diyBMS I2C通信协议深度解析:命令表、地址设计与自动分配机制
diyBMS I2C通信协议深度解析命令表、地址设计与自动分配机制【免费下载链接】diyBMSDo it yourself battery management system for Lithium ion battery packs/cells项目地址: https://gitcode.com/gh_mirrors/diy/diyBMSdiyBMS是一款自制的锂离子电池18650电池组电池管理系统BMSESP8266 作为主控制器通过隔离 I2C 总线轮询连接在每串电池包上的 ATTINY85 从机模块实现逐节电压/温度监测与被动均衡。本文完整讲解这套 diyBMS I2C 通信协议地址如何分配、19 个命令 ID 各自做什么、新模块如何被自动编址以及协议内置的容错机制——即使没写过嵌入式代码也能看懂整套设计。1️⃣ 系统架构hub-and-spoke 的 I2C 主从拓扑上面是电池模块 PCB 背面左右两组接口分别为I2C IN和I2C OUTSDA/SCL 两线说明多个模块像菊花链一样级联在同一条 I2C 总线上每块板上有一颗 ATTINY85 主芯片电池接口支持 1.8~4.35V。整套系统采用轮毂-辐条hub and spoke结构主机MasterESP8266 控制器负责 WiFi 监控、数据上报与均衡决策I2C 总线初始化 在 SDAGPIO4、SCLGPIO5 上以 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~9ID常量参数作用1COMMAND_green_led_pattern1 字节位图自定义绿灯闪烁图案诊断用3COMMAND_factory_default无恢复出厂设置并重启4COMMAND_set_slave_address1 字节新地址自动分配的核心命令写入 EEPROM 后重启生效5COMMAND_green_led_default无恢复默认绿灯图案6COMMAND_set_voltage_calibration4 字节浮点设置电压校准系数默认 4.4307COMMAND_set_temperature_calibration4 字节浮点设置温度校准系数默认 1.0808COMMAND_set_bypass_voltage2 字节 mV下发均衡目标电压0 关闭均衡9COMMAND_set_load_resistance4 字节浮点设置均衡负载电阻值默认 10.0Ω完整实现见 i2c_cmds.cpp 命令封装。读取类命令ID 10~18ID常量返回作用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() 源码在控制器网页管理界面点击添加模块Web 处理器 置位runProvisioning标志控制定时器检测到标志后调用provision()先探测地址 21 上是否有模块testModuleExists即发一个空 I2C 事务看返回值是否为 0从 24 开始逐个探测到 48找到第一个空闲地址向地址 21 下发COMMAND_set_slave_address值 空闲地址模块端校验新地址必须落在 24~48 区间且不同于当前地址地址写入与重启通过则写入 EEPROM、重启重启后模块以新地址上线控制器把它加入轮询数组cell_array。控制器每次上电还会执行一次全总线扫描 scani2cBus()遍历 24~48发现存在的模块就读取电压、温度与全部校准参数并顺手把残留的均衡状态关闭——所以控制器重启不需要重新配置模块侧 EEPROM 里保存着完整状态。5️⃣ 数据格式大端序与 4 字节浮点命令和数据之外协议对字节序也有明确约定字节拆分实现2 字节数值mV 电压、温度等高字节先发低字节后发主机端用word(high, low)合并4 字节浮点校准系数等C 的union让float和uint8_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),仅供参考