手搓电流表-实时检测锂电池状态

手搓电流表-实时检测锂电池状态

如何获取锂电池的电压、电流、电量等信息呢?本文基于ESP8266 + INA219 实现电池监测。喜欢就收藏吧!

设备清单esp8266INA219模块18650锂电池5v充电模块0.96Oled屏幕设备清单线路连接连接类别

设备/引脚端

连接至

esp8266-INA219

GPIO4 OLED (D2)

INA219 SDA

esp8266-INA219

GPIO5 OLED(D1)

INA219 SCL

esp8266-INA219

3.3V

INA219 VCC

esp8266-INA219

GND

INA219 GND

锂电池连接

18650 正极

INA219 (vim -)

锂电池连接

18650 负极

esp8266 (GND)

充电模块

正极

INA219 (vim +)

充电模块

负极

锂电池负极

用电器(负载)

设备正极

INA219 (vim +)

用电器(负载)

设备负极

esp8266 (GND)

​

效果类似电流表,可实时测量电池的电压,电流、容量、充放电状态等。

后期改进后期,我们可以通过MQTT协议,将电池信息通过json发送。这样我们便可以远程查看电池的信息了。

源码代码语言:javascript复制#include

#include

#include

Adafruit_INA219 ina219;

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);

const float BATTERY_CAPACITY = 3.5;

const float FULL_VOLTAGE = 4.15;

const float EMPTY_VOLTAGE = 3.0;

const float CURRENT_THRESHOLD = 5.0;

const int FILTER_WINDOW_SIZE = 10;

float batteryVoltage = 0.0;

float shuntVoltage_mV = 0.0;

float current_mA = 0.0;

float filteredCurrent = 0.0;

float power_mW = 0.0;

float batterySOC = 50.0;

float totalCharge = 0.0;

String batteryState = "";

float currentBuffer[FILTER_WINDOW_SIZE];

int filterIndex = 0;

unsigned long lastTime = 0;

void setup() {

Serial.begin(115200);

while (!Serial) {

delay(1);

}

Serial.println("ESP8266 + INA219 电池监测系统启动中...");

if (!ina219.begin()) {

Serial.println("INA219初始化失败!请检查接线");

while (1);

}

ina219.setCalibration_32V_2A();

u8g2.begin();

u8g2.clearBuffer();

u8g2.setFont(u8g2_font_ncenB10_tr);

u8g2.setCursor(20, 35);

u8g2.print(F("Starting..."));

u8g2.sendBuffer();

delay(2000);

for (int i = 0; i < FILTER_WINDOW_SIZE; i++) {

currentBuffer[i] = 0.0;

}

lastTime = millis();

Serial.println("INA219初始化成功!");

Serial.println("使用滑动窗口滤波 + 库仑计法");

Serial.println("----------------------------------------");

Serial.println("电压(V) | 分流电压 | 电流(mA) | 功率(mW) | 电量(%) | 状态");

Serial.println("----------------------------------------");

}

void loop() {

unsigned long currentTime = millis();

float deltaTime = (currentTime - lastTime) / 3600000.0;

readBatteryData();

filteredCurrent = filterCurrentValue(current_mA);

calculateSOC(deltaTime);

determineState();

displayData();

displayOnOLED();

lastTime = currentTime;

delay(1000);

}

void readBatteryData() {

batteryVoltage = ina219.getBusVoltage_V();

shuntVoltage_mV = ina219.getShuntVoltage_mV();

current_mA = ina219.getCurrent_mA();

power_mW = ina219.getPower_mW();

}

float filterCurrentValue(float newValue) {

currentBuffer[filterIndex] = newValue;

filterIndex = (filterIndex + 1) % FILTER_WINDOW_SIZE;

float sum = 0.0;

for (int i = 0; i < FILTER_WINDOW_SIZE; i++) {

sum += currentBuffer[i];

}

return sum / FILTER_WINDOW_SIZE;

}

void calculateSOC(float deltaTime) {

if (deltaTime > 0) {

float chargeChange = (filteredCurrent / 1000.0) * deltaTime;

totalCharge += chargeChange;

float voltageSOC;

if (batteryVoltage >= 4.15) {

voltageSOC = 100.0;

} else if (batteryVoltage <= 2.7) {

voltageSOC = 0.0;

} else {

voltageSOC = ((batteryVoltage - 2.7) / (4.15 - 2.7)) * 100.0;

}

float estimatedSOC = (totalCharge / BATTERY_CAPACITY) * 100.0;

if (batteryVoltage >= 4.1) {

batterySOC = voltageSOC;

} else if (batteryVoltage <= 3.2) {

batterySOC = (estimatedSOC * 0.1) + (voltageSOC * 0.9);

} else {

batterySOC = (estimatedSOC * 0.2) + (voltageSOC * 0.8);

}

batterySOC = constrain(batterySOC, 0.0, 100.0);

if (batterySOC >= 99.5) {

batterySOC = 100.0;

}

}

}

void determineState() {

if (filteredCurrent > CURRENT_THRESHOLD) {

batteryState = "充电中";

} else if (filteredCurrent < -CURRENT_THRESHOLD) {

batteryState = "放电中";

} else if (filteredCurrent > 1.0 && batteryVoltage >= 4.0) {

batteryState = "充电中";

} else {

batteryState = "待机";

}

}

void displayData() {

Serial.print(batteryVoltage, 2);

Serial.print("V | ");

Serial.print(shuntVoltage_mV, 1);

Serial.print("mV | ");

Serial.print(filteredCurrent, 0);

Serial.print("mA | ");

Serial.print(power_mW, 0);

Serial.print("mW | ");

Serial.print(batterySOC, 1);

Serial.print("% | ");

Serial.println(batteryState);

}

void displayOnOLED() {

u8g2.clearBuffer();

u8g2.setFont(u8g2_font_ncenB08_tr);

u8g2.setCursor(0, 10);

u8g2.print(F("Voltage: "));

u8g2.print(batteryVoltage, 2);

u8g2.print(F(" V"));

u8g2.setCursor(0, 24);

u8g2.print(F("Current: "));

u8g2.print(filteredCurrent, 0);

u8g2.print(F(" mA"));

u8g2.setCursor(0, 38);

u8g2.print(F("Power: "));

u8g2.print(power_mW, 0);

u8g2.print(F(" mW"));

u8g2.setCursor(0, 52);

u8g2.print(F("SOC: "));

u8g2.print(batterySOC, 1);

u8g2.print(F(" %"));

u8g2.setCursor(0, 64);

u8g2.print(F("Status: "));

if (batteryState == "充电中") {

u8g2.print(F("Charging"));

} else if (batteryState == "放电中") {

u8g2.print(F("Discharging"));

} else {

u8g2.print(F("Idle"));

}

u8g2.sendBuffer();

}相关计算公式容量(mAh) = \sum |I(t)| \times \Delta t(h) ----

版权属于:逍遥子大表哥

本文链接:https://cloud.tencent.com/developer/article/2629638

按照知识共享署名-非商业性使用 4.0 国际协议进行许可,转载引用文章应遵循相同协议。

❈ ❈ ❈

相关文章

✧ ✧ ✧
宝来后视镜折叠方法分享
365英超

宝来后视镜折叠方法分享

📅 02-04 👁️ 2878
我理解的前端发展方向
365英超

我理解的前端发展方向

📅 08-07 👁️ 8649
美国公开赛冠军杯:费城联合 VS 纽约红牛