资讯动态

ArduPilot 脚本驱动实战:ANX CAN 电池监测驱动(BattMon_ANX)参数配置与源码原理

发布时间:2026/9/15 19:42:09 来源:尧图企业网站定制
ArduPilot 脚本驱动实战ANX CAN 电池监测驱动BattMon_ANX参数配置与源码原理【免费下载链接】ardupilotArduPlane, ArduCopter, ArduRover, ArduSub source项目地址: https://gitcode.com/GitHub_Trending/ar/ardupilot导读ANX CAN 电池协议是一种基于 CAN 总线的智能电池通信协议ArduPilot 通过 Lua 脚本驱动 BattMon_ANX.lua 在飞控侧接收并解析 ANX 电池上报的电压、电流、剩余容量、温度与单体电芯电压。本文以驱动文档 BattMon_ANX.md 为骨架逐项讲解BATT_ANX_*系列参数的含义与设置方法并结合 Lua 驱动源码与 C 电池监控后端源码说明 CAN 帧组装、CRC 校验、数据解析到BATT_MONITOR脚本后端的完整链路。读完本文你将掌握在 ArduPilot 上启用 ANX 电池监测驱动的完整配置步骤并理解其底层工作原理便于部署与排障。一、驱动概述与适用场景ANX 电池驱动运行在 ArduPilot 的 Lua 脚本运行时之上属于 libraries/AP_Scripting/drivers 目录下的外设驱动脚本。它实现的是 ANX CAN 电池协议通过飞控的 CAN 总线接口接收智能电池的遥测数据并把解析结果写入 ArduPilot 的电池监控BattMonitor系统从而复用飞控已有的电压/电流告警、剩余电量计算、低电量保护等能力。该驱动适用于以下场景采用 ANX 智能电池支持 ANX CAN 电池协议的固定翼、多旋翼或地面车辆平台飞控具备 CAN 总线接口CAN1/CAN2且固件开启了脚本Scripting与 CAN 传感器支持希望通过脚本方式扩展电池后端而不需要为特定电芯/协议修改 C 固件源码。驱动本体是一个纯 Lua 文件 BattMon_ANX.lua与同目录下的CircuitStatus.lua、EFI_Halo6000.lua等驱动脚本一样通过参数表动态注册自身参数实现了不改固件、只改脚本的外设接入方式。二、启用脚本功能前置条件运行该驱动前需要确认固件已具备脚本能力。根据 libraries/AP_Scripting/README.md 的说明所有 Flash 空间大于 1MB 的板卡默认自动启用脚本支持需要将参数SCR_ENABLE设为 1 并重启飞控以激活脚本运行时脚本文件需放入 SD 卡APM目录下的scripts文件夹SITL 环境下则放入工作目录飞控启动时会自动加载执行。配置完成后将BattMon_ANX.lua放置到上述scripts目录飞控即会自动加载该驱动驱动启动时会在 GCS 上发送BATT_ANX: Started的文本消息MAV_SEVERITY.INFO可作为加载成功的判断依据。三、驱动参数详解驱动在 Lua 侧通过param:add_table注册了一张以BATT_ANX_为前缀的参数表表键为 45、预留 15 个参数位见 BattMon_ANX.lua。以下三个参数即文档 BattMon_ANX.md 中描述的配置项。参数名说明取值默认值BATT_ANX_ENABLE驱动总开关必须设为 1 才会运行0禁用1启用0BATT_ANX_CANDRV选择脚本 CAN 驱动通道0无1第 1 个 CAN 驱动2第 2 个 CAN 驱动1BATT_ANX_INDEX电池监测实例索引范围 1101对应 BATT1、2对应 BATT2依此类推13.1 BATT_ANX_ENABLE驱动总开关。脚本启动时首先读取该参数若值为 0脚本直接打印BATT_ANX: disabled并退出BattMon_ANX.lua不会注册任何 CAN 回调。因此启用驱动时该参数必须显式设为 1。3.2 BATT_ANX_CANDRV选择脚本层使用的 CAN 驱动。脚本绑定bindings.desc暴露了两个获取 CAN 设备的接口CAN:get_device(buffer_len)对应第 1 个 CAN 驱动CAN:get_device2(buffer_len)对应第 2 个 CAN 驱动。驱动脚本据此决定从哪条 CAN 总线接收 ANX 电池帧local CAN_BUF_LEN 25 if BATT_ANX_CANDRV:get() 1 then driver CAN.get_device(CAN_BUF_LEN) elseif BATT_ANX_CANDRV:get() 2 then driver CAN.get_device2(CAN_BUF_LEN) end缓冲区长度固定为 25 帧用于缓存组装一个完整报文的多帧数据若获取设备失败例如固件未启用 CAN 脚本支持驱动会打印BATT_ANX: Failed to load driver并退出该 CAN 设备接口ScriptingCANBuffer依赖编译宏AP_SCRIPTING_CAN_SENSOR_ENABLED即固件构建时必须启用脚本 CAN 传感器支持文档建议该参数取 1 或 2源码中同时允许 0无驱动此时脚本因拿不到设备会直接失败退出因此实际使用时务必设为 1 或 2。3.3 BATT_ANX_INDEX指定该驱动把数据写入哪个电池监控实例。脚本最终通过battery:handle_scripting(BATT_ANX_INDEX:get()-1, state)把状态写入对应的实例BattMon_ANX.lua索引从 0 开始因此在 Lua 层要减去 1。取值 1 对应 BATT1、2 对应 BATT2最大支持到第 10 个实例参数范围为 110。该值必须与BATT_MONITOR参数配置的Scripting类型实例序号保持一致否则数据不会出现在预期的电池槽位中。四、与 BATT_MONITOR 参数的配合脚本驱动的数据要进入 ArduPilot 电池监控系统还需要把目标实例的BATT_MONITOR参数设为 Scripting 类型。从源码看电池类型枚举定义在 AP_BattMonitor_Params.h其中enum class Type { NONE 0, ... Scripting 29, ... };即BATT_MONITOR 29表示该电池实例由脚本提供数据。在 AP_BattMonitor.cpp 中固件初始化时对Type::Scripting实例分配AP_BattMonitor_Scripting后端驱动随后 Lua 脚本中每次调用battery:handle_scripting()时AP_BattMonitor.cpp 会把脚本状态透传给该实例的后端handle_scripting()最终在 AP_BattMonitor_Scripting.cpp 中更新内部状态供电压告警、容量计算、MAVLink 上报等模块使用。因此完整的启用步骤为将SCR_ENABLE设为 1 并重启将BattMon_ANX.lua放入 SD 卡APM/scripts目录SITL 则为工作目录scripts目录设置BATT_MONITOR 29Scripting将对应电池实例交给脚本驱动设置BATT_ANX_ENABLE 1根据 ANX 电池实际挂接的总线设置BATT_ANX_CANDRV 1或2按需设置BATT_ANX_INDEX默认 1对应 BATT1重启或重载脚本确认 GCS 收到BATT_ANX: Started。五、CAN 报文解析原理源码级驱动核心逻辑在read_can()与process_frames()两个函数中理解它可以更好地配置参数与排查通信问题。5.1 帧过滤与 ID 字段拆解驱动只接收扩展帧isExtended()非扩展帧会被丢弃。对收到的扩展帧按位拆解 29 位标识符BattMon_ANX.lualocal id frame:id_signed() local last_pkt_id (id3) 1 -- 是否为报文最后一帧 local pkt_count (id4) 0x3F -- 帧序号用于帧连续性检测 local msg_type_id (id19) 0x3FF -- 报文类型 IDlast_pkt_id标识该帧是否为当前报文的最后一帧多帧报文由若干 CAN 帧拼接而成pkt_count提供帧序号若与当前已组装帧数不一致说明帧不连续驱动会重置组装缓冲保证跨报文的数据不会串扰msg_type_id标识报文类型用于决定如何解析负载。5.2 帧重组与 CRC 校验一个完整报文由多帧数据拼装而来帧载荷按序拼接成字节串后前 2 字节为 CRC其后为实际负载BattMon_ANX.lua。CRC 采用 XMODEM CRC16 算法但初始种子为0xa635区别于标准 XMODEM 的 0x0000查表实现内嵌在脚本中local function crc_ANX(bytes) local crc 0xa635 for i1,#bytes do local b string.byte(bytes,i,i) crc ((crc8) 0xffff) ~ XMODEMCRC16Lookup[(((crc8)~b) 0xff) 1] end return crc end若crc ~ crc_ANX(payload)则不接受该报文。这是脚本侧对总线噪声、错帧的第一道防线也是排查数据不刷新问题时的重要检查点——CRC 不匹配的报文会被静默丢弃。5.3 电压报文解析当msg_type_id落在 721727 区间时说明该报文携带电压数据包含单体电芯电压驱动调用parse_volt_frame()解析BattMon_ANX.lua。负载按小端序解包字段类型原始值换算系数总电压uint1610 位×0.01 V电流int1610 位×(−0.01) A放电为负剩余容量uint1610 位×0.1 %温度int1610 位×0.1 ℃单体电压uint16×N每电芯 2 字节mV 级原始值负载前 10 字节解析出总电压、电流、剩余容量、温度四项其后每 2 字节为一个单体电芯电压电芯数量由(payload_len - 10) / 2推算上限截断为 32 节超过后按 32 处理因为电池后端接口对电芯数有更严格的限制。5.4 状态写入后端解析完成后构造BattMonitorScript_State状态对象并逐项填充local state BattMonitorScript_State() state:healthy(true) state:voltage(total_volt) state:cell_count(num_cells) state:capacity_remaining_pct(math.floor(rem_cap)) for i 1, num_cells do state:cell_voltages(i-1, cells[i]) end state:current_amps(current) state:temperature(temperature) battery:handle_scripting(BATT_ANX_INDEX:get()-1, state)脚本绑定中bindings.descBattMonitorScript_State还支持cycle_count、consumed_mah、consumed_wh、state_of_health_pct等字段但 ANX 协议当前只填充健康状态、电压、电芯数、剩余容量、单体电压、电流和温度。handle_scripting接口依赖编译宏AP_BATTERY_SCRIPTING_ENABLED即固件需同时启用电池脚本后端支持。5.5 周期调度驱动通过返回update, 10注册每 10ms 执行一次的周期回调BattMon_ANX.lua每次回调会尝试读取 CAN 缓冲区内所有可用帧并逐一处理实现接近 100Hz 的遥测刷新率满足电池数据实时性要求。六、常见问题排查要点结合源码行为可整理出以下排查路径GCS 未出现BATT_ANX: Started检查SCR_ENABLE是否为 1、脚本是否放在APM/scripts目录、BATT_ANX_ENABLE是否设为 1若提示BATT_ANX: disabled说明开关未打开。提示BATT_ANX: Failed to load driverBATT_ANX_CANDRV取值无效或固件未启用脚本 CAN 传感器支持依赖AP_SCRIPTING_CAN_SENSOR_ENABLED需要重新构建固件。能启动但数据不刷新优先怀疑总线接线/波特率与帧过滤问题——驱动只接收扩展帧同时报文 CRC 校验失败会被静默丢弃可通过 CAN 总线分析工具确认 ANX 电池上报的报文类型是否落在 721727以及帧 ID 各字段位分布是否符合驱动拆分逻辑。数据出现在错误的电池槽位核对BATT_ANX_INDEX与BATT_MONITOR参数是否为同一实例注意 Lua 层索引减 1 的对应关系。七、小结ANX 电池驱动是 ArduPilot Lua 脚本外设生态的一个典型示例通过BATT_ANX_ENABLE、BATT_ANX_CANDRV、BATT_ANX_INDEX三个参数即可完成总线选择、实例绑定与启停控制而协议解析帧组装、XMODEM CRC、电芯电压拆解全部在脚本层完成最终通过battery:handle_scripting()汇入统一的电池监控后端。理解 BattMon_ANX.lua 的实现不仅可以正确配置 ANX 电池也为阅读其他脚本驱动如同目录的CircuitStatus.lua、torqeedo-torqlink.lua与自行编写 CAN 总线外设驱动提供了可复用的范本。【免费下载链接】ardupilotArduPlane, ArduCopter, ArduRover, ArduSub source项目地址: https://gitcode.com/GitHub_Trending/ar/ardupilot创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价