diyBMS I2C通信协议深度解析:命令表、地址设计与自动分配机制
2026/8/24 8:43:00 网站建设 项目流程

diyBMS I2C通信协议深度解析:命令表、地址设计与自动分配机制

【免费下载链接】diyBMSDo it yourself battery management system for Lithium ion battery packs/cells项目地址: https://gitcode.com/gh_mirrors/diy/diyBMS

diyBMS是一款自制的锂离子电池(18650)电池组电池管理系统(BMS):ESP8266 作为主控制器,通过隔离 I2C 总线轮询连接在每串电池包上的 ATTINY85 从机模块,实现逐节电压/温度监测与被动均衡。本文完整讲解这套 diyBMS I2C 通信协议:地址如何分配、19 个命令 ID 各自做什么、新模块如何被自动"编址",以及协议内置的容错机制——即使没写过嵌入式代码,也能看懂整套设计。

1️⃣ 系统架构:hub-and-spoke 的 I2C 主从拓扑

上面是电池模块 PCB 背面:左右两组接口分别为I2C INI2C OUT(SDA/SCL 两线),说明多个模块像菊花链一样级联在同一条 I2C 总线上;每块板上有一颗 ATTINY85 主芯片,电池接口支持 1.8~4.35V。

整套系统采用"轮毂-辐条"(hub and spoke)结构:

  • 主机(Master):ESP8266 控制器,负责 WiFi 监控、数据上报与均衡决策,I2C 总线初始化 在 SDA=GPIO4、SCL=GPIO5 上以 100kHz 时钟通信,并设置了 1000ms 超时:
Wire.setTimeout(1000); // 1000ms 超时 Wire.setClock(100000); // 100kHz Wire.begin(4, 5); // SDA/SCL
  • 从机(Slave):每个电池包模块上的一颗 ATTINY85,通过板上的 ADUM1250 数字隔离芯片与主总线隔离,负责本串电压、温度的采集与均衡负载开关。

I2C 天然是"两级寻址"协议:7 位从机地址找到是哪块板,随后发送的命令字节决定"做什么"。理解 diyBMS 协议,本质上就是理解这两级设计。

2️⃣ I2C 地址设计:默认地址 21 与 24~48 号段

diyBMS 的地址规划非常克制,见 地址定义:

地址用途说明
21出厂默认地址新模块全部"挤"在这个地址上,绿灯闪烁特定图案提示"未配置"
24 ~ 48已配置模块号段最多容纳 24 个模块(对应 24S 电池组)

为什么需要两个号段?因为出厂时所有模块地址相同(21),上电后不可能同时工作——必须有一套机制把它们"拆开"。这正是下文自动分配机制要解决的问题。

3️⃣ 命令总表:第 6 位是"命令标志位"

协议中最巧妙的一笔在 bms_values.h:命令字节复用第 6 位(COMMAND_BIT)作为"我是一条命令"的标记。这样同一个 1 字节既能表示"执行命令",又能表示"读取数据":

uint8_t cmdByte(uint8_t cmd) { bitSet(cmd, COMMAND_BIT); // 置位第6位 → 命令字节 return cmd; }

模块端收到字节后检查该位:置位 → 按命令处理(后面通常还跟着参数);未置位 → 按读取请求处理(主机随后会来收数据)。

写入类命令(ID 1~9)

ID常量参数作用
1COMMAND_green_led_pattern1 字节位图自定义绿灯闪烁图案(诊断用)
3COMMAND_factory_default恢复出厂设置并重启
4COMMAND_set_slave_address1 字节新地址自动分配的核心命令,写入 EEPROM 后重启生效
5COMMAND_green_led_default恢复默认绿灯图案
6COMMAND_set_voltage_calibration4 字节浮点设置电压校准系数(默认 4.430)
7COMMAND_set_temperature_calibration4 字节浮点设置温度校准系数(默认 1.080)
8COMMAND_set_bypass_voltage2 字节 mV下发均衡目标电压(0 = 关闭均衡)
9COMMAND_set_load_resistance4 字节浮点设置均衡负载电阻值(默认 10.0Ω)

完整实现见 i2c_cmds.cpp 命令封装。

读取类命令(ID 10~18)

ID常量返回作用
10read_voltage2 字节 mV校准后的电池电压(均衡进行中时返回负载断开瞬间的读数)
11read_temperature2 字节板载温度(NTC 热敏电阻)
12read_voltage_calibration4 字节浮点读出电压校准系数
13read_temperature_calibration4 字节浮点读出温度校准系数
14read_raw_voltage2 字节原始 ADC 值(验证校准是否合理的依据)
15read_error_counter2 字节通信错误计数器(I2C 异常、总线卡死都会累加)
16read_bypass_enabled_state1 字节均衡负载当前是否开启
17read_bypass_voltage_measurement2 字节 mV均衡负载开启时的电压采样
18read_load_resistance4 字节浮点读出均衡负载电阻值

模块端对应的分发逻辑在 requestEvent() 请求应答。

4️⃣ 自动地址分配机制:新模块如何"对上号"

这是 diyBMS 协议最实用的设计——新增电池模块无需任何跳线设置,流程如下(provision() 源码):

  1. 在控制器网页管理界面点击添加模块,Web 处理器 置位runProvisioning标志;
  2. 控制定时器检测到标志后调用provision():先探测地址 21 上是否有模块(testModuleExists即发一个空 I2C 事务看返回值是否为 0);
  3. 从 24 开始逐个探测到 48,找到第一个空闲地址
  4. 向地址 21 下发COMMAND_set_slave_address(值 = 空闲地址);
  5. 模块端校验新地址必须落在 24~48 区间且不同于当前地址(地址写入与重启),通过则写入 EEPROM、重启
  6. 重启后模块以新地址上线,控制器把它加入轮询数组cell_array

控制器每次上电还会执行一次全总线扫描 scani2cBus():遍历 24~48,发现存在的模块就读取电压、温度与全部校准参数,并顺手把残留的均衡状态关闭——所以控制器重启不需要重新配置,模块侧 EEPROM 里保存着完整状态。

5️⃣ 数据格式:大端序与 4 字节浮点

命令和数据之外,协议对字节序也有明确约定(字节拆分实现):

  • 2 字节数值(mV 电压、温度等):高字节先发,低字节后发,主机端用word(high, low)合并;
  • 4 字节浮点(校准系数等):C 的unionfloatuint8_t buffer[4]共享同一块内存,直接按字节流传输,两端字节序一致即可还原;
  • 一次典型读取 = "主机发 1 字节命令 → 主机再向该地址请求 N 字节数据",N 由命令决定(1/2/4)。

6️⃣ 容错设计:恐慌模式、看门狗与 EEPROM 校验

一个可靠的 BMS 协议必须假设"总会出错"。diyBMS 的对策(loop 主循环):

  • 恐慌模式(Panic):模块用last_i2c_request倒计时(每次收到请求重置为 150),一旦超时说明主机失联——绿灯切换为恐慌闪烁图案B01010101、重建 I2C 接口、累加error_counter;主机恢复通信后自动退出恐慌。用 ID 15 读错误计数器就能远程判断链路质量;
  • 看门狗定时器:4 秒超时硬重启,兜底所有软件死锁;
  • 配置完整性:地址、电压/温度校准、负载电阻存于 EEPROM 并带 CRC32 校验(配置加载),校验失败即回落到出厂默认值;
  • 安全边界:均衡目标电压被硬件端限制在 3000~4200mV 且必须低于当前实测电压,越界参数直接拒绝。

7️⃣ 相关源码文件

文件职责
Arduino-ESP8266-BMS-Controller/Arduino-ESP8266-BMS-Controller.inoESP8266 主控制器:总线扫描、模块轮询、均衡策略
Arduino-BMS-Cell-Module/Arduino-BMS-Cell-Module.inoATTINY85 模块固件:ADC 采集、命令处理、EEPROM 存储
Arduino-ESP8266-BMS-Controller/i2c_cmds.cppI2C 命令封装、provision()自动分配、模块探测
Arduino-ESP8266-BMS-Controller/bms_values.h全部命令 ID 定义与cell_module数据结构
Arduino-ESP8266-BMS-Controller/settings.cpp控制器侧 EEPROM 配置(WiFi、均衡阈值等)
Arduino-BMS-Controller-Test/Arduino-BMS-Controller-Test.ino协议测试工程
docs/homePage.html控制器 Web 监控页面

小结:diyBMS 用"7 位从机地址 + 1 字节命令"完成了全部通信,第 6 位命令标志区分读写,大端序 + 4 字节浮点保证数据无歧义,而"默认地址 21 + 24~48 空闲探测 + 写 EEPROM 重启"三步曲让 24 块电池板免去了任何人工配置——这是一个教科书级的轻量 I2C 多从机管理方案,值得所有 DIY 电池项目参考。

⚠️ 提示:本项目为 DIY 设计,不适用于安全关键场景;README 亦注明该设计已被作者的 v4 版本取代,本文仅作 I2C 协议原理学习之用。

【免费下载链接】diyBMSDo it yourself battery management system for Lithium ion battery packs/cells项目地址: https://gitcode.com/gh_mirrors/diy/diyBMS

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询