ESP32+MCP2515读取Netgain Hyper9 CAN总线word及位掩码求助
ESPHome读取Netgain Hyper9电机CAN数据的修正方案
核心错误说明
原有代码存在两个核心逻辑错误:
- 2字节小端序WORD解析错误:将字节转为十进制字符串拼接的方式完全不符合数值组合规则,会得到完全错误的结果
- 系统标志位解析错误:标志位是16位位图,每个比特位独立对应一个状态,可能同时触发多个状态,不能用switch判断整数值
修正后的完整配置
canbus: - platform: mcp2515 id: my_mcp2515 spi_id: McpSpi cs_pin: GPIO14 can_id: 2 use_extended_id: false bit_rate: 250KBPS clock: 8MHZ mode: NORMAL on_frame: - can_id: 0x301 #[canbus:066]: received can message std can_id=0x301 size=8 use_extended_id: false then: - lambda: |- // 电池SOC,原有逻辑正常 int soc = x[2]; id(motor_battery_soc).publish_state(soc); // RPM解析:小端序2字节拼16位整数,x[0]是低字节,x[1]是高字节 uint16_t rpm = (static_cast<uint16_t>(x[1]) << 8) | x[0]; id(motor_rpm).publish_state(rpm); // 系统标志位解析:先拼16位掩码 uint16_t flag_mask = (static_cast<uint16_t>(x[4]) << 8) | x[3]; std::vector<std::string> active_flags; // 逐位判断标志是否触发,位序号从0到15对应给出的16个状态 if (flag_mask & (1 << 0)) active_flags.push_back("牵引电池SOC过低"); if (flag_mask & (1 << 1)) active_flags.push_back("液压系统SOC过低"); if (flag_mask & (1 << 2)) active_flags.push_back("倒车档激活"); if (flag_mask & (1 << 3)) active_flags.push_back("前进档激活"); if (flag_mask & (1 << 4)) active_flags.push_back("驻车制动激活"); if (flag_mask & (1 << 5)) active_flags.push_back("踏板制动激活"); if (flag_mask & (1 << 6)) active_flags.push_back("控制器过热"); if (flag_mask & (1 << 7)) active_flags.push_back("钥匙开关过压"); if (flag_mask & (1 << 8)) active_flags.push_back("钥匙开关欠压"); if (flag_mask & (1 << 9)) active_flags.push_back("车辆运行中"); if (flag_mask & (1 << 10)) active_flags.push_back("牵引系统已启用"); if (flag_mask & (1 << 11)) active_flags.push_back("液压系统已启用"); if (flag_mask & (1 << 12)) active_flags.push_back("供电已启用"); if (flag_mask & (1 << 13)) active_flags.push_back("供电就绪"); if (flag_mask & (1 << 14)) active_flags.push_back("预充电中"); if (flag_mask & (1 << 15)) active_flags.push_back("主接触器闭合中"); std::string flag_output; if (active_flags.empty()) { flag_output = "无系统告警"; } else { // 多个激活的标志用顿号拼接 for (size_t i = 0; i < active_flags.size(); i++) { if (i > 0) flag_output += "、"; flag_output += active_flags[i]; } } id(motor_system_flags).publish_state(flag_output); // 故障码,原有逻辑正常 int fault_code = x[5]; id(motor_fault_code).publish_state(fault_code); // 电机温度,原有逻辑正常 int temp = x[6] - 40; id(motor_temp).publish_state(temp); text_sensor: - platform: template id: motor_system_flags name: "电机系统标志" sensor: - platform: template id: motor_battery_soc name: "电机电池SOC" accuracy_decimals: 0 - platform: template id: motor_fault_code name: "电机故障码" - platform: template id: motor_temp name: "电机温度" accuracy_decimals: 0 # 原RPM是数值,修改为sensor类型,不再用文本传感器 - platform: template id: motor_rpm name: "电机转速" accuracy_decimals: 0
修改点说明
- 将RPM从文本传感器改为数值传感器,用位运算直接拼接16位小端序整数,得到正确的转速数值
- 系统标志位改为逐位判断的位图解析逻辑,支持同时显示多个激活的状态
- 保留原有正常工作的SOC、故障码、温度解析逻辑
内容的提问来源于stack exchange,提问作者Dennis
相关产品推荐
相关产品推荐

