尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

深入解析 PX4 的 PwmInput uORB 消息:PWM 输入捕获的字段语义、驱动实现与典型应用

发布时间:2026/9/29 5:24:21

资讯中心
01
ARTICLE

深入解析 PX4 的 PwmInput uORB 消息:PWM 输入捕获的字段语义、驱动实现与典型应用

深入解析 PX4 的 PwmInput uORB 消息:PWM 输入捕获的字段语义、驱动实现与典型应用
嵌入式物联网机器人自动驾驶智能硬件【免费下载链接】PX4-AutopilotPX4 Autopilot Software项目地址https://gitcode.com/gh_mirrors/px/PX4-Autopilot点击查看免费下载PwmInput是 PX4 Autopilot 中专门承载「PWM 输入脉冲测量结果」的 uORB 话题由pwm_input驱动通过定时器输入捕获中断ISR在 AUX5或 MAIN5管脚上测量脉冲宽度与信号周期并以微秒精度对外发布。本文以 docs/en/msg_docs/PwmInput.md 定义的消息结构为骨架逐字段讲解其语义并结合 src/drivers/pwm_input 驱动源码、板级配置以及ll40ls_pwm、rpm_capture等下游订阅者讲清「硬件管脚 → 定时器捕获 → uORB 消息 → 应用模块」的完整数据链路。读完本文你将能准确理解每个字段的取值来源与单位换算知道如何启用、观测该话题并掌握基于pwm_input实现 PWM 测距、转速捕获等功能的底层原理。一、消息定义一张表看懂 PwmInputPwmInput消息由 4 个字段组成全部为无符号整型单位为微秒µs。其话题名为pwm_input单一 TOPIC无多实例别名。字段名类型单位说明timestampuint64µs系统启动以来的时间微秒即采样时刻error_countuint64—定时器过捕获overcapture错误计数AUX5 或 MAIN5 管脚pulse_widthuint32µs脉冲宽度定时器计数微秒perioduint32µs信号周期定时器计数微秒对应的原始消息定义位于 msg/PwmInput.msg全文仅 4 行uint64 timestamp # Time since system start (microseconds) uint64 error_count # Timer overcapture error flag (AUX5 or MAIN5) uint32 pulse_width # Pulse width, timer counts (microseconds) uint32 period # Period, timer counts (microseconds)该文件已被纳入 msg/CMakeLists.txt 的 uORB 消息生成流程构建时由Tools/msg下的生成脚本如 Tools/msg/px_generate_uorb_topic_files.py自动生成对应的 C/C 结构体pwm_input_s与话题定义。二、四个字段的完整语义与取值来源1.timestamp采样时间戳uint64类型单位微秒表示「系统启动以来的时间」。在 pwm_input.cpp 的publish()中由hrt_absolute_time()填充_pwm.timestamp hrt_absolute_time();该时间戳是 ISR 触发时刻的高精度硬件时间下游模块如测距传感器可直接基于它计算数据年龄或做时间同步无需关心 uORB 发布本身引入的延迟。2.error_count定时器过捕获错误计数字段注释写作「Timer overcapture error flag」语义上是累计的错误次数而非单次标志位。驱动在发布前检查定时器状态寄存器rSR中的溢出标志位SR_OVF_PWMIN即 CC1OF / CC2OF 捕获溢出标志// if we missed an edge, we have to give up if (status SR_OVF_PWMIN) { _error_count; return; }也就是说一旦某次边沿到来时上一次捕获尚未被读取过捕获驱动认为该样本不可靠丢弃本次数据并递增错误计数而不是发布错误数值。因此error_count是衡量输入信号质量 / 驱动健康度的重要指标——若持续增长说明 PWM 信号频率过高、定时器配置不当或系统中断响应不及时。3.pulse_width脉冲宽度uint32单位微秒表示一个 PWM 周期内高电平持续的时间。它来自定时器捕获比较寄存器 BrCCR_PWMIN_B在 ISR 中直接读出uint32_t period rCCR_PWMIN_A; uint32_t pulse_width rCCR_PWMIN_B;对典型的 RC 遥控器接收机或舵机类 PWM 信号脉宽通常位于 1000–2000 µs 区间如 1500 µs 为中立点对 Lidar-Lite 这类 PWM 测距传感器脉宽则直接编码了距离信息详见下文下游应用章节。4.period信号周期uint32单位微秒表示相邻两次上升沿之间的时间间隔即整个 PWM 信号的周期。RC 接收机通常以 50 Hz 更新对应周期约 20000 µs。period与pulse_width组合可计算占空比也可用于判断输入是否丢失例如rpm_capture以超时阈值区分「有信号」与「无信号」状态。三、数据来源pwm_input 驱动与定时器捕获原理驱动整体结构pwm_input是一个基于ModuleBase的 NuttX 平台驱动源码仅两个文件src/drivers/pwm_input/pwm_input.cppsrc/drivers/pwm_input/pwm_input.h模块的官方描述为Measures the PWM input on AUX5 (or MAIN5) via a timer capture ISR and publishes via the uORB pwm_input message.即通过定时器捕获中断在 AUX5或 MAIN5具体取决于板卡管脚上测量 PWM 输入并通过 uORBpwm_input话题发布。启动流程与首个样本task_spawn()创建PWMIN实例并调用start()pwm_input.cppvoid PWMIN::start() { // NOTE: must first publish here, first publication cannot be in interrupt context _pwm_input_pub.update(); // Initialize the timer isr for measuring pulse widths. Publishing is done inside the isr. timer_init(); }这里有一个值得注意的细节驱动在初始化定时器之前先主动发布一次空样本_pwm_input_pub.update()。注释明确指出首次发布不能发生在中断上下文提前发布可确保 uORB 话题已正确注册为后续在 ISR 内发布铺路。此后真正的测量与发布全部在定时器 ISR 中完成。定时器初始化微秒分辨率如何实现timer_init()pwm_input.cpp完成以下关键步骤预留管脚与定时器遍历DIRECT_PWM_OUTPUT_CHANNELS找到与GPIO_PWM_IN端口/管脚匹配的输出通道调用io_timer_allocate_channel()与io_timer_allocate_timer()以IOTimerChanMode_PWMIn模式独占该定时器通道配置输入管脚px4_arch_configgpio(GPIO_PWM_IN)挂接中断向量irq_attach(PWMIN_TIMER_VECTOR, PWMIN::pwmin_tim_isr, NULL)预分频换算微秒/* for simplicity scale by the clock in MHz. This gives us * readings in microseconds which is typically what is needed * for a PWM input driver */ uint32_t prescaler PWMIN_TIMER_CLOCK / 1000000UL; ... rPSC prescaler - 1;预分频器把定时器时钟按 MHz 缩放到 1 MHz 计数频率使每个计数器 tick 恰好等于 1 µs——这就是为什么pulse_width与period的注释写作「timer counts (microseconds)」两者在数值上直接就是微秒计数器满量程rARR UINT16_MAX让计数器跨越完整 16 位量程避免在长周期信号下过早溢出所有 PX4 使用的定时器均支持 uint16 计数使能定时器与中断生成更新事件后置位GTIM_CR1_CEN退出临界区后up_enable_irq(PWMIN_TIMER_VECTOR)。ISR 中的数据采集与发布中断服务程序 pwmin_tim_isr 非常精简——读取状态与两个捕获寄存器清中断标志然后直接在中断上下文发布int PWMIN::pwmin_tim_isr(int irq, void *context, void *arg) { uint16_t status rSR; uint32_t period rCCR_PWMIN_A; uint32_t pulse_width rCCR_PWMIN_B; /* ack the interrupts we just read */ rSR 0; auto obj get_instancePWMIN(desc); if (obj ! nullptr) { obj-publish(status, period, pulse_width); } return PX4_OK; }从 pwm_input.h 中的寄存器位定义可以推断其捕获原理定时器工作于从模式复位SMS 0x04的 PWM 输入模式——通道 A 捕获信号作为触发源CH1 配置使用TS TI1FP1CH2 配置使用TI2FP2上升沿使计数器复位并锁存周期值到捕获寄存器 A下降沿则把脉宽锁存到捕获寄存器 BCCxP 极性位与 CCxE 使能位的组合配置即为此服务。这正是一般通用定时器如 STM32 GTIM标准的 PWM 输入测量方案。publish()pwm_input.cpp在确认无过捕获后按序填充timestamp/error_count/period/pulse_width四个字段并发布同时更新_last_period、_last_width、_pulses_captured统计量供status命令输出。编译期硬约束src/drivers/pwm_input/pwm_input.h 对板级集成提出了明确约束任何一条不满足都会直接编译失败HRT_TIMER与PWMIN_TIMER不能共用同一个定时器#error cannot share timer between HRT and PWMIN板卡必须在board_config.h中定义GPIO_PWM_IN、PWMIN_TIMER、PWMIN_TIMER_CHANNEL三个宏PWMIN_TIMER_CLOCK必须大于 1 MHz保证预分频后分辨率可用PWMIN_TIMER_CHANNEL仅允许取 1 或 2。以 boards/ark/fmu-v6x/src/board_config.h 为例#define PWMIN_TIMER 4 #define PWMIN_TIMER_CHANNEL /* T4C2 */ 2 #define GPIO_PWM_IN /* PD13 */ GPIO_TIM4_CH2IN_2即该板卡使用定时器 TIM4 的通道 2PD13 管脚作为 PWM 输入。类似的定义还存在于 boards/px4/fmu-v6x/src/board_config.h、boards/cuav/7-nano/src/board_config.h、boards/mro/ctrl-zero-h7/src/board_config.h 等众多板卡中AUX5/MAIN5 的具体物理管脚由各板卡的board_config.h决定。四、如何启用与使用 pwm_input 驱动编译开关驱动由 Kconfig 开关控制默认关闭src/drivers/pwm_input/Kconfigmenuconfig DRIVERS_PWM_INPUT bool pwm_input default n构建模块定义见 src/drivers/pwm_input/CMakeLists.txt模块名drivers__pwm_input入口pwm_input。板卡需要在自己的.px4board配置CONFIG_DRIVERS_PWM_INPUTy中启用后pwm_input命令才会被编译进固件。命令行用法根据 docs/en/modules/modules_system.md驱动支持三条标准命令pwm_input command [arguments...] Commands: start stop status print status infopwm_input start启动驱动执行定时器初始化并开始发布pwm_input stop停止驱动pwm_input status打印统计信息。status命令的输出格式在 pwm_input.cpp 中定义形如count已捕获脉冲数 period最近周期(µs) width最近脉宽(µs)自动启动时机在真实固件中pwm_input通常由系统启动脚本按参数自动拉起。ROMFS/px4fmu_common/init.d/rc.sensors 中的逻辑如下# Sensors on the PWM interface bank if param compare -s SENS_EN_LL40LS 1 then if pwm_input start then ll40ls_pwm start fi fi # External automatic trigger system if param compare FD_EXT_ATS_EN 1 then pwm_input start fi即两种情况会触发pwm_input startSENS_EN_LL40LS1启用 PWM 接口的 Lidar-Lite 测距传感器先启动pwm_input再启动ll40ls_pwmFD_EXT_ATS_EN1启用外部自动触发系统External Automatic Trigger System直接启动pwm_input。观测消息固件运行后可通过 PX4 自带的listener系统命令源码位于 src/systemcmds/listener实时查看该话题的发布内容例如在 NuttShell 中执行listener pwm_input输出会循环打印timestamp、error_count、pulse_width、period的最新值是验证捕获链路是否工作的最直接手段。五、谁在消费 PwmInput下游订阅与典型应用pwm_input话题本身只是测量结果的载体真正有价值的是消费它的应用模块。仓库中有多处典型的上下游关系。1. Lidar-Lite PWM 测距ll40ls_pwmsrc/drivers/distance_sensor/ll40ls_pwm/LidarLitePWM.cpp 的文件头注释直接说明了二者关系Driver for the PulsedLight Lidar-Lite range finders connected via PWM. This driver accesses the pwm_input published by the pwm_input driver.其collect()LidarLitePWM.cpp订阅pwm_input话题int LidarLitePWM::collect() { pwm_input_s pwm_input; if (_sub_pwm_input.update(pwm_input)) { _pwm pwm_input; return PX4_OK; } return EAGAIN; }随后在measure()LidarLitePWM.cpp中完成脉宽到距离的换算并发布distance_sensorconst float current_distance static_castfloat(_pwm.pulse_width) * 1e-3f; // 1us 1mm distance for LIDAR-Lite ... _px4_rangefinder.update(timestamp_sample, current_distance);1 µs 脉宽 1 mm 距离即pulse_width字段被直接当作测距结果使用。这正是「PWM 输入测量 → 应用级传感器」的经典案例也解释了为何pwm_input的发布频率与信号同步、时间戳精度至关重要。2. 转速输入捕获rpm_capturesrc/drivers/rpm_capture/RPMCapture.cpp 是pwm_input话题的另一个生产者兼消费者——它通过参数系统查找被配置为RPM_Input输出功能编号 2070见mixer_module/output_functions.yaml参数元数据的输出通道用 GPIO 外部中断捕获转速脉冲并在 Run() 中同时发布rpm与pwm_input两个话题pwm_input_s pwm_input{}; pwm_input.timestamp now; pwm_input.period _period; pwm_input.error_count _error_count; _pwm_input_pub.publish(pwm_input);这里period即相邻两次转速脉冲的时间间隔µs进而换算转速rpm_raw 60.f * 1e6f / static_castfloat(_param_rpm_puls_per_rev.get() * _period);值得注意的是与定时器捕获方案不同rpm_capture走的是「GPIO EXTI 高优先级工作队列」路径调用px4_arch_gpiosetevent并通过io_timer_channel_get_as_pwm_input()把输出通道复用为输入体现了 PX4 输入捕获体系的灵活性。3. PPS 秒脉冲捕获pps_capturesrc/drivers/pps_capture/PPSCapture.cpp 用于捕获 GNSS 模块的 PPSPulse Per Second信号并计算 PPS 与实时时钟的漂移。它与rpm_capture采用相同的基础设施——通过io_timer_channel_get_as_pwm_input(_channel)获取输入 GPIOPPSCapture.cpp并注册外部中断回调最终发布独立的pps_capture话题。它证明了「把 PWM 输出通道当作高精度输入捕获使用」这一模式在 PX4 中已被广泛复用。4. 外部自动触发系统如前所述FD_EXT_ATS_EN1时系统会单独启动pwm_input不启动测距驱动此时pwm_input话题成为外部自动触发如相机触发信号测量通道供触发/同步相关逻辑使用。六、总结PwmInput 的设计要点微秒级精度通过预分频把定时器时钟缩放到 1 MHzpulse_width/period的计数单位即微秒字段无需额外换算即可直接使用中断内发布数据在定时器捕获 ISR 中填充并发布保证测量与发布之间的延迟最小首次发布提前到非中断上下文完成规避 uORB 在中断中的初始化限制错误可观测过捕获溢出时样本被丢弃并累计error_count下游可据此判断输入信号质量板级可配置输入管脚、定时器与通道由各板卡board_config.h中的GPIO_PWM_IN、PWMIN_TIMER、PWMIN_TIMER_CHANNEL决定编译期即校验约束多场景复用同一话题被 PWM 测距Lidar-Lite、转速捕获rpm_capture等模块消费是 PX4 中「通用 PWM 脉冲测量」的标准数据接口。从消息定义msg/PwmInput.msg到驱动实现src/drivers/pwm_input/pwm_input.cpp再到下游应用LidarLitePWM.cpp、RPMCapture.cpppwm_input展示了一条完整、可追踪的传感器数据链路——这也正是阅读 uORB 消息文档时最值得延伸的视角。赞分享嵌入式物联网机器人自动驾驶智能硬件【免费下载链接】PX4-AutopilotPX4 Autopilot Software项目地址https://gitcode.com/gh_mirrors/px/PX4-Autopilot点击查看免费下载相关推荐PX4-Autopilot HeaterStatus UORB 消息详解字段定义、常量与加热器驱动源码实现PX4 Autopilot HeaterStatus UORB 消息详解字段定义、常量与加热器驱动源码实现 本文以 PX4 Autopilot 仓库中的 He嵌入式物联网机器人自动驾驶智能硬件PX4-Autopilot ControlAllocatorStatus uORB 消息从字段语义到控制分配器实现PX4 Autopilot ControlAllocatorStatus uORB 消息从字段语义到控制分配器实现 本篇技术指南以 PX4 Autopilot嵌入式物联网机器人自动驾驶智能硬件PX4 uORB 消息 AirspeedValidatedV0 全解析字段语义、数据来源与下游消费链路PX4 uORB 消息 AirspeedValidatedV0 全解析字段语义、数据来源与下游消费链路 airspeed_validated_v0 是 PX4嵌入式物联网机器人自动驾驶智能硬件上一篇Wand-Enhancer 使用指南给 WeMod 加个远程控制面板还能解锁这些本地功能下一篇如何快速修复Windows更新老旧系统的完整解决方案指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。