花 1 小时,开源设计 LoRa 检测电池容量

提示1:锐米所有 LoRa 产品严格遵循国标标准的 LoRaWAN 协议
提示2:您可以免费复制,修改和商用本项目,请注明锐米原创
提示3:如果您有其他 LoRa 需求或建议,欢迎联系锐米 [email protected]

电池容量

LoRa 检测电池容量

测量电池电压,计算电池容量,基于 LoRa 传送到服务器,App 可实时演示。
LoRa LoRaWAN Arduino 物联网 开源设计

组件和材料

LoRa 扩展板LoRa 扩展板 x 1 采购链接


Arduino Pro MiniArduino Pro Mini x 1 采购链接


电池盒电池盒 x 1 采购链接


南孚 7 号电池7 号电池 x 2 采购链接


天线天线 x 1 采购链接


杜邦线杜邦线 x 6 采购链接


下载烧录器下载烧录器 采购链接


数字万用表数字万用表 采购链接

扫描二维码关注公众号,回复: 8961725 查看本文章

软件和网络

LoRa网关 LoRa网关 采购链接


LoRaServerLoRaServer 下载链接


LoRaAppLoRaApp 下载链接


Arduino IDEArduino IDE 下载链接

项目介绍

超过 80% 的 LoRa 终端基于电池供电,尽管我们最大化降低功耗,然而电池终将有耗尽的那一天。计算电池容量,对于 LoRa 终端的维保意义重大。

相比传统的检测技术,LoRa 检测电池容量的优点为:

  • 零额外成本,基于 MCU 自身的 ADC 计算
  • 无接线工作,直接测量电池电压
  • 简单直观,App 实时查看电池容量
  • 精度高,误差小于 1%

本项目开源设计 LoRa检测电池容量的核心—软件和硬件,用户可以直接使用在自己的 LoRa 终端产品中。
同时,简介了 LoRa 网络组件,轻松构建一个商用的物联网。

技术细节

元器件介绍

LoRa 扩展板
这是专为 Arduino 而设计的 LoRa 扩展板,既可以安装在 Arduino UNO 上,也能使用杜邦线连接到 Arduino Pro Mini。

它能达到空旷 10km 的通信距离,休眠电流仅 1.3uA。精心设计的软件库,使其开发极为容易:

  • 发送数据
LoRa.write("123", 3);
  • 接收数据
if (LoRa.availabe()) { 
    len = LoRa.read(buf, MAX_LEN); 
}

Arduino Pro Mini

Arduino Pro Mini 是最小的开发板,它功耗极低(休眠 0.1uA),便宜简单,接线方便。


天线
470MHz 胶棒天线,增益 3.5dB,特别适合中国 LoRa 频段范围(470~510MHz)。

硬件接线

如下图所示,使用杜邦线连接 Arduino Pro Mini,LoRa 扩展板和电池盒。
ArduinoProMiniLoRaBattery

通信逻辑

如下图所示,LoRa 检测电池电压和容量,App 实时显示。

为此,需要配置如下的网络组件:

运行效果

如下图所示,LoRa 终端每分钟检测电池电压和容量,通过 LoRa 发送消息,App 显示电池电压和容量。
运行效果

行业第一的超低功耗—休眠仅 1.4uA

如下图所示(实物拍摄),ArduinoLoRa+ 的低功耗可达 1.4uA,这不仅是行业第一的超低功耗,而且达到了器件极限
低功耗可达 1.4uA
如下图所示,2 节 5 号碱性电池容量约 2890mAH,在典型的采集应用中(设每 10 分钟采集)电池可工作近 6 年。
终端电池寿命计算器
在这里插入图片描述

Arduino 代码

给 Arduino Pro Mini 下载程序请参考 《ArduinoLoRa 休眠极限 1.4uA参考链接

编译本工程需要添加 LoRa 驱动库 下载链接

使用 Arduino IDE 打开工程,点击"Sketch -> Include Library -> Add .ZIP Library…"

Arduino 的 zip 库安装路径一般为:C:\Users\Administrator\Documents\Arduino\libraries

Arduino 的代码简洁,容易理解,下载链接

  • DEBUG 设置为 0 禁止调试功能;设置为 1 它将通过 8 和 9 两个引脚打印调试信息(使用“USB转串口”连接到 PC)
  • getVccVoltage() 通过 ADC 将 Vcc 与内部 1.1 参考电压进行比较来计算Vcc 的电压。
  • getBatteryCapacity() 将 Vcc 电压转换成电池容量
#include <lora.h>

lora LoRa;
const int ledPin = 13;  // choose the pin for the LED

#define DEBUG    0

#if DEBUG
#include <SoftwareSerial.h>
SoftwareSerial debugSerial(8, 9);  // 8=RX, 9=TX
#endif

/* results are Vcc * 100, So for example, 3V would be 30 */
int getVccVoltage() 
{
  /* Adjust this value to your board's specific internal BG voltage */
  static const long InternalReferenceVoltage = 1075;  // 1.075V measured on the AREF pin 

 /* REFS0: Selects AVcc external reference
  * MUX3 MUX2 MUX1: Selects 1.1V (VBG)
  */
  bitSet(ADMUX, REFS0);
  bitSet(ADMUX, MUX3);
  bitSet(ADMUX, MUX2);
  bitSet(ADMUX, MUX1);

 /* START and WAIT for ADC conversion to complete
  *  
  * ADC start conversion when set the ADSC to 1
  * ADSC will read as 1 as long as a conversion in progress
  * when the conversion is complete, the ADSC returns to 0
  * 
  * add dead time to avoid ENDLESS LOOP if the ADC failed
  * ADC conversion is 115us in normal, so set MAX is 200us
  */
  unsigned long duration = 0;
  unsigned long microseconds = micros();
  bitSet(ADCSRA, ADSC);  // start conversion
  while(bitRead(ADCSRA, ADSC) && (duration < 200))  
  {
    duration = micros() - microseconds;
  }
  int results = (((InternalReferenceVoltage * 1024) / ADC) + 5) / 10; 

  return results;
}

/* argument are Vcc * 100, So for example, 3V would be 300 */
int getBatteryCapacity(int VccVoltage)
{
  /* Adjust this value to your board's specific battery voltage */
  #define BATTERY_MAX_VOLTAGE    300  // 3.0V
  #define BATTERY_MIN_VOLTAGE    180  // 1.8V

  int capacity;

  capacity = (VccVoltage - BATTERY_MIN_VOLTAGE) * 100L / (BATTERY_MAX_VOLTAGE - BATTERY_MIN_VOLTAGE);
  capacity = constrain(capacity, 0, 100);  // constrained between 0 and 100

  return capacity;
}

void setup() 
{
  pinMode(ledPin, OUTPUT);  // declare LED as output
  Serial.begin(115200);  // for LoRa Node
#if DEBUG
  debugSerial.begin(115200); // start software serial port at 115200-8-N-1
#endif  
}

void loop()
{
  int voltage, capacity;
  int array[2];  // voltage, capacity

  voltage = getVccVoltage();
  capacity = getBatteryCapacity(voltage);

#if DEBUG
  debugSerial.print("Vcc: ");
  debugSerial.print(voltage);
  debugSerial.print("V, Battery Capacity: ");
  debugSerial.print(capacity);
  debugSerial.println("%");
#endif  

  array[0] = voltage;
  array[1] = capacity;
  LoRa.write(array, sizeof(array));

  digitalWrite(ledPin, HIGH);  // indicate that have send a LoRa message
  delay(100);
  digitalWrite(ledPin, LOW);

  delay(60000);  // 60 seconds
}

算法原理

测量内部基准电压

为了获得更准确的结果,这需要测量 MCU 内部基准电压。 为此,请运行以下代码:

// Find internal 1.1 reference voltage on AREF pin
void setup ()
{
  analogReference(INTERNAL);
  analogRead(A0);  // force voltage reference to be turned on
}
void loop () { }

然后使用电压表测量处理器的 AREF 引脚上的电压。 将该值乘以1000,并将其用作 Arduino 代码的 InternalReferenceVoltage 变量。
如下图,测量得到1.075V,那么设置 InternalReferenceVoltage 为 1075
测量 MCU 基准电压
因为 MCU 的个体差异,它们的基准电压有细微不同。如果要求非常精确测量 Vcc 电压,这需要将参考电压存储在每个 MCU 的 EEPROM 中。这样,程序可以参考该值以找到计算电压时要使用的确切数字。

计算 Vcc 电压

当 ADC 用于测量 Vcc 电压时,模拟读数代表的数值含义为:

模拟读数 / 模拟总长 = 基准电压 / Vcc 电压

模拟总长为 1024(Arduino Pro Mini 的 ADC 是 10 位),基准电压和模拟读数是已知量,求 Vcc 电压需要转换公式为:

Vcc 电压 = 基准电压 * 模拟总长 / 模拟读数

计算电池容量

下图是实验用的南孚电池放电曲线,电压从 1.5V 到 0.9V,分别代表 95% 到 5% 的电量。为简化计算,我们拟定电量和电压为线性函数,即:电量(Capacity) 和电压(Voltage)为

Capacity = (Voltage - 0.9V) / (1.5V - 0.9V) * 100%

考虑 MCU 计算浮点数代价大,我们使用定点数,将电压放大 100 倍。同时,防止整数除法的精度丢失,先乘法,后除法,因此有:

Capacity = (Voltage - 90) * 100 / (150 - 90)
电池电压曲线图

实际应用中,需要根据电池电压调整下面 2 个数值:BATTERY_MAX_VOLTAGE(最高电压) 和BATTERY_MIN_VOLTAGE(最低电压)。在本次实验中,2 节 7 号电池的最高电压为 3.0V,最低电压为 1.8V

发布了139 篇原创文章 · 获赞 347 · 访问量 94万+

猜你喜欢

转载自blog.csdn.net/jiangjunjie_2005/article/details/104070668
今日推荐