首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >手搓电流表-实时检测锂电池状态

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

作者头像
逍遥子大表哥
发布2026-02-12 09:44:03
发布2026-02-12 09:44:03
1470
举报
文章被收录于专栏:kali blogkali blog

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

设备清单

  • esp8266
  • INA219模块
  • 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 <Wire.h>
#include <Adafruit_INA219.h>
#include <U8g2lib.h>

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 国际协议进行许可,转载引用文章应遵循相同协议。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2026-02-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 设备清单
  • 线路连接
    • 效果
  • 后期改进
  • 源码
    • 相关计算公式
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档