APM使用LUA脚本发送实现遥控器PWM信号输出CAN协议信号

需求:由于舵机是CAN总线舵机,需实现APM开源飞控遥控器输入PWM通道到CAN的发送。

方法1:修改APM固件源码,编译,运行,测试。实现复杂。

方法2:使用lua脚本。实现简单

目前采用方法2,使用lua脚本:

几乎所有运行ArduPilot 4.5及以上固件、并且有足够存储空间的飞控,理论上都支持Lua脚本

一定要升级飞控版本到4.5以上。早期的支持比较差,各种运行不通。

✅ 运行Lua PWM→CAN 的必要设置(完整清单)

一、固件版本要求

项目 要求 说明

ArduPilot版本 ≥ 4.5.0 4.6.3验证可用,4.5以上才完整支持Lua CAN API

飞控硬件 有足够Flash/MCU CUAV V5+/X7、Pixhawk系列、H7系列等

二、参数设置(必须)

  1. Lua脚本总开关

    参数 设置值 说明

    SCR_ENABLE 1 启用Lua脚本引擎

    SCR_DIR_DISABLE 0 确保scripts目录被读取(默认0)

  2. CAN接口参数(以CAN1为例)

    参数 设置值 说明

    CAN_P1_DRIVER 1 启用CAN1硬件接口

    CAN_D1_PROTOCOL 12 (Scripting2) 关键! 让Lua脚本接管CAN口

    CAN_P1_BITRATE 按需(如250000) 与你的CAN设备匹配

    如果是用第二个CAN口,对应参数为 CAN_P2_DRIVER、CAN_D2_PROTOCOL

  3. 修改参数后的关键操作

    操作 说明

    写入参数 点击"写入参数"保存

    完全断电重启 拔掉USB线和电池,等30秒再上电

    只点"重启飞控"可能不够,彻底冷启动才能让CAN驱动正确初始化

三、脚本文件要求

项目 要求 说明

存放路径 /APM/scripts/ 必须严格区分大小写

文件名后缀 .lua(小写) 不能是 .lua.txt

文件编码 UTF-8 无BOM 推荐用VS Code/Notepad++编辑

上传新脚本前,快速过一遍:

固件版本 ≥ 4.5(当前4.6.3 ✅)

SCR_ENABLE = 1

CAN_P1_DRIVER = 1

CAN_D1_PROTOCOL = 12(关键!)

已完全断电重启(拔USB+电池)

脚本放在 /APM/scripts/ 目录

文件名以 .lua 结尾

代码中用 CAN:get_device2(5)(Protocol 12专用)

定时用 update 函数(最兼容)

CAN ID用 uint32_t() 包裹

CAN分析仪已监听或设备已连接

lua 复制代码
-- pwm_to_can_template.lua
-- 稳定版模板(Protocol 12 + update函数)

```lua
local driver = CAN:get_device2(5)
if not driver then
    gcs:send_text(0, "CAN init failed")
    return
end

gcs:send_text(0, "PWM→CAN script started")

local last_send = 0
local TX_INTERVAL = 20  -- ms
local frame_count = 0

local function send_frames()
    frame_count = frame_count + 1
    
    for ch = 1, 9 do
        -- 读取PWM
        local pwm = rc:get_pwm(ch) or 1500
        pwm = math.min(math.max(pwm, 1000), 2000)
        
        -- 构建数据(根据你的协议修改)
        local data = { 0x22, 0x03, 0x60, 0x00,
                      pwm % 256, math.floor(pwm/256),
                      0x00, 0x00 }
        
        -- 发送CAN帧
        local msg = CANFrame()
        msg:id(uint32_t(0x0600 + ch))
        msg:dlc(8)
        for i = 0, 7 do
            msg:data(i, data[i+1])
        end
        driver:write_frame(msg, 10000)
    end
    
    -- 调试输出(每秒一次)
    if frame_count % (1000/TX_INTERVAL) == 0 then
        gcs:send_text(0, string.format("Running: %d Hz", 1000/TX_INTERVAL))
    end
end

local function update()
    local now = millis()
    if now - last_send >= TX_INTERVAL then
        send_frames()
        last_send = now
    end
    return update, TX_INTERVAL
end

return update()

保存代码,然后在mission planner中拷贝到这里,如果没有SCRIPTS文件夹,就自己建立一个。

最后的效果:```

相关推荐
SeaTunnel2 小时前
从 Python Script 地狱到标准化数据集成框架
大数据·开发语言·python·程序员·代码·seatunnel
碎光拾影2 小时前
ARM交叉工具链各工具作用及IMX6ULL平台LED+蜂鸣器裸机程序实现
java·开发语言·数据库
Marst Code3 小时前
(python)2026Plotly 库评估:交互式可视化到底值不值得引入?
开发语言·python
Miao121313 小时前
微服务 API 测试实践:海外某民宿平台如何构建模式驱动测试基础设施
java·开发语言
CRMEB系统商城4 小时前
开源自建还是SaaS订阅?算一笔3年经济账
java·大数据·开发语言·开源
keyipatience5 小时前
线程栈与TLS和线程互斥
java·linux·服务器·开发语言·ubuntu
我的xiaodoujiao5 小时前
快速学习Python基础知识详细图文教程9--函数进阶
开发语言·python·学习·测试工具
爱喝水的鱼丶6 小时前
SAP-ABAP:ALV通用封装实践——搭建可复用的ALV开发工具类,减少80%重复代码
开发语言·性能优化·sap·abap·erp·alv
脱胎换骨-军哥6 小时前
C++/Rust无缝互操作:混合系统新常态
开发语言·c++·rust
songroom7 小时前
Kimi K3:Rust封装XTP接口详细教程实践
开发语言·后端·rust