#ifndef PMOTOR_CAN_H #define PMOTOR_CAN_H #include #include #include namespace motor { //============================================================================ // 推进电机控制器 CAN 通信协议(docs/推进电机通信协议20260321.docx) // // 数据来源:pCanBridge 透传的 MOOS 消息 // 变量名 CAN_0x%08X = CAN ID(29 位扩展帧),m_sVal = 二进制数据域(8 字节), // m_dfVal2 = 原始帧信息字节。本模块只负责按报文 ID 解析/编码数据域字段。 // // 物理/链路层:CAN2.0B 扩展帧,250kbps(默认),数据域 8 字节, // 多字节数值采用 Intel 编码(低字节在前,高字节在后)。 // // 【报文清单】 // 下行(pMotor -> 电机控制器,周期 500ms): // 0x18EF2010 主控指令帧(冗余 CAN 0x18EF2011) // 0x18EF2110 主控限制帧(冗余 CAN 0x18EF2111,全预留,暂不发送) // 上行(电机控制器 -> pMotor): // 0x18EF1020 支路一故障报警状态帧1(200ms,冗余 CAN 0x18EF1021) // 0x18EF1120 支路二故障报警状态帧2(200ms,冗余 CAN 0x18EF1121) // 0x18EF1220 状态帧3:反馈转速/母线电压(100ms,冗余 0x18EF1221) // 0x18EF1320 状态帧4:温度(100ms,冗余 0x18EF1321) // // 【指令帧 0x18EF2010】数据域 8 字节: // byte0 bit0 = 使能命令(0 无效 1 有效,IGBT 开关;需先预充后使能) // byte0 bit1 = 复位命令(0 无效 1 有效,仅故障状态下有效,故障支路复位) // byte0 bit2 = 支路一通信状态(0 正常 1 中断) // byte0 bit3 = 支路二通信状态(0 正常 1 中断) // byte0 bit4~7 / byte1 / byte4~7 = 预留(发 0) // byte2/3 = (转速模式)期望转速 s16(偏移 0,分辨率 1,Intel) // 文档示例:启动并给定 1000 转速 -> 01 00 E8 03 00 00 00 00 // 停机 -> 00 00 00 00 00 00 00 00 // 复位 -> 02 00 00 00 00 00 00 00 // // 【状态帧3 0x18EF1220】byte0/1 反馈转速 s16(Intel),byte2/3 母线电压 u16(Intel) // // 【状态帧4 0x18EF1320】byte0~5 依次为 A/B/C 相绕组、逆变组件底板、 // 输出滤波器、筒内空气温度,均为 s8(偏移 0,分辨率 1) // // 【故障帧 0x18EF1020/0x18EF1120】4 个 16 位字(byte0|1、byte2|3、byte4|5、byte6|7), // 字内 bit 定义见 MotorCan.cpp 中描述表;前两帧仅支路一/支路二 // byte0|1 的 bit7 不同(支路一=筒内空气过温故障,支路二=预留)。 //============================================================================ // CAN ID 定义(29 位扩展帧) enum MotorCanId : uint32_t { MOTOR_CAN_CMD = 0x18EF2010u, // 主控指令帧(pMotor -> 电机) MOTOR_CAN_CMD_RED = 0x18EF2011u, // 主控指令帧 冗余 CAN MOTOR_CAN_LIMIT = 0x18EF2110u, // 主控限制帧(全预留,暂不使用) MOTOR_CAN_LIMIT_RED = 0x18EF2111u, // 主控限制帧 冗余 CAN MOTOR_CAN_FAULT1 = 0x18EF1020u, // 支路一故障报警状态帧1 MOTOR_CAN_FAULT1_RED = 0x18EF1021u, // 支路一 冗余 CAN MOTOR_CAN_FAULT2 = 0x18EF1120u, // 支路二故障报警状态帧2 MOTOR_CAN_FAULT2_RED = 0x18EF1121u, // 支路二 冗余 CAN MOTOR_CAN_STATE3 = 0x18EF1220u, // 状态帧3(转速/母线电压) MOTOR_CAN_STATE3_RED = 0x18EF1221u, // 状态帧3 冗余 CAN MOTOR_CAN_STATE4 = 0x18EF1320u, // 状态帧4(温度) MOTOR_CAN_STATE4_RED = 0x18EF1321u, // 状态帧4 冗余 CAN }; // 指令动作(网页 /api/motor_cmd -> 队列 -> Iterate 应用) // 与协议指令帧字段一一对应,独立下发、无联动: enum MotorAction { MOTOR_ACT_ENABLE = 1, // 使能命令=1(Byte0 bit0,保持当前期望转速) MOTOR_ACT_DISABLE = 2, // 使能命令=0(Byte0 bit0,协议"停机"示例:期望转速清 0) MOTOR_ACT_SPEED = 3, // 期望转速(Byte2/3,speed 参数,使能状态保持不变) MOTOR_ACT_RESET = 4, // 复位命令=1(Byte0 bit1,保持高 resetHold 秒,仅故障态有效) }; // 网页下发的控制指令 struct MotorCmd { int action = 0; // MotorAction int16_t speed = 0; // MOTOR_ACT_SPEED / MOTOR_ACT_START 有效 }; // 单条电机上行消息的新鲜度 + 原始数据 struct MotorBranchState { int branch = 0; // 1 / 2 uint16_t word[4] = {0, 0, 0, 0}; // 4 个 16 位字(故障1/故障2/故障3/报警) std::vector faults; // 当前置位的故障描述(word0~2) std::vector alarms; // 当前置位的报警描述(word3) bool valid = false; // 是否收到过该支路故障帧 double lastRxTime = 0; // 最近收到时刻(MOOSTime,调用方设置) }; // 电机最新合成状态(各帧部分更新合并) struct MotorState { // 状态帧3 0x18EF1220 int16_t feedbackSpeed = 0; // 反馈转速 uint16_t busVoltage = 0; // 母线电压 bool state3Valid = false; double state3LastRx = 0; // 状态帧4 0x18EF1320(s8,偏移 0) int8_t tempA = 0, tempB = 0, tempC = 0; // A/B/C 相绕组温度 int8_t tempInv = 0, tempFilter = 0, tempAir = 0; // 逆变底板/滤波器/筒内空气 bool state4Valid = false; double state4LastRx = 0; // 故障/报警 MotorBranchState branch1; MotorBranchState branch2; // 计数 uint32_t rxCount = 0; // 命中电机报文的帧计数 }; // 是否为电机协议定义的 CAN ID(含冗余 CAN 变体) inline bool isCanMotorId(uint32_t canId) { switch (canId) { case MOTOR_CAN_CMD: case MOTOR_CAN_CMD_RED: case MOTOR_CAN_LIMIT: case MOTOR_CAN_LIMIT_RED: case MOTOR_CAN_FAULT1: case MOTOR_CAN_FAULT1_RED: case MOTOR_CAN_FAULT2: case MOTOR_CAN_FAULT2_RED: case MOTOR_CAN_STATE3: case MOTOR_CAN_STATE3_RED: case MOTOR_CAN_STATE4: case MOTOR_CAN_STATE4_RED: return true; default: return false; } } // 故障/报警字索引(帧内):0=byte0|1 1=byte2|3 2=byte4|5 3=byte6|7(报警) extern const char* kMotorWordName[4]; // 按支路(1/2)与字索引查故障/报警描述表,把 bits 中置位的描述填入 out; // 返回描述条数。wordIdx 非法或无置位返回 0。 int motorFaultTexts(int branch, int wordIdx, uint16_t bits, std::vector& out); // 编码指令帧数据域(8 字节,经 MOOS CAN_TX_0x%08X 下发 pCanBridge 发送): // [0] = enable(bit0) | reset(bit1)(支路通信状态位恒 0) // [1] = 0 [2]/[3] = speed s16 Intel(停用时调用方传 0) [4..7] = 0 void buildMotorCmdData(bool enable, bool reset, int16_t speed, uint8_t out[8]); // 解析一帧 CAN 数据域;命中电机上行报文返回 true 并部分更新 st: // 故障帧 -> 对应支路 word[4] + 故障/报警描述 // 状态帧3 -> feedbackSpeed / busVoltage // 状态帧4 -> 6 路温度 // 非电机报文或 data/dlc 非法返回 false。lastRxTime 由调用方设置。 bool decodeMotorFrame(uint32_t canId, const uint8_t* data, int dlc, MotorState& st); } // namespace motor #endif // PMOTOR_CAN_H