如果有io芯片,且使用了io作为输出PWM的设备
则fmu将mixer传输给io,io进行混控计算并输出PWM,将pwm结果传递回fmu,此时无app订阅acuator_outpus,就是给人看的。
// src/drivers/px4io/px4io.cpp
/* fetch PWM outputs from IO */
io_publish_pwm_outputs();
在px4iofirmware和pwm_out中
都使用函数up_pwm_servo_set进行PWM输出
// src/modules/px4iofirmware/mixer.cpp
if (mixer_servos_armed
&& (should_arm || should_arm_nothrottle || (source == MIX_FAILSAFE))
&& !(r_setup_arming & PX4IO_P_SETUP_ARMING_LOCKDOWN)) {
/* update the servo outputs. */
for (unsigned i = 0; i < PX4IO_SERVO_COUNT; i++) {
up_pwm_servo_set(i, r_page_servos[i]);
}
/* set S.BUS1 or S.BUS2 outputs */
if (r_setup_features & PX4IO_P_SETUP_FEATURES_SBUS2_OUT) {
sbus2_output(_sbus_fd, r_page_servos, PX4IO_SERVO_COUNT);
} else if (r_setup_features & PX4IO_P_SETUP_FEATURES_SBUS1_OUT) {
sbus1_output(_sbus_fd, r_page_servos, PX4IO_SERVO_COUNT);
}
} else if (mixer_servos_armed && (should_always_enable_pwm
|| (r_setup_arming & PX4IO_P_SETUP_ARMING_LOCKDOWN))) {
/* set the disarmed servo outputs. */
for (unsigned i = 0; i < PX4IO_SERVO_COUNT; i++) {
up_pwm_servo_set(i, r_page_servo_disarmed[i]);
/* copy values into reporting register */
r_page_servos[i] = r_page_servo_disarmed[i];
}
/* set S.BUS1 or S.BUS2 outputs */
if (r_setup_features & PX4IO_P_SETUP_FEATURES_SBUS1_OUT) {
sbus1_output(_sbus_fd, r_page_servo_disarmed, PX4IO_SERVO_COUNT);
}
if (r_setup_features & PX4IO_P_SETUP_FEATURES_SBUS2_OUT) {
sbus2_output(_sbus_fd, r_page_servo_disarmed, PX4IO_SERVO_COUNT);
}
}
如果有io芯片但没作为PWM输出,或者无io芯片
则在fmu的PWM输出设备上进行PWM输出
// src/drivers/pwm_out/PWMOut.cpp
// _interface可以指fmu的PWM,也可以是IO的PWM,也可以是UAVCAN等
/* now return the outputs to the driver */
// updateOutputs函数就输出到PWM设备了
if (_interface.updateOutputs(stop_motors, _current_output_value, mixed_num_outputs, n_updates)) {
actuator_outputs_s actuator_outputs{};
setAndPublishActuatorOutputs(mixed_num_outputs, actuator_outputs);
// 发布了actuator_outputs主题
publishMixerStatus(actuator_outputs);
updateLatencyPerfCounter(actuator_outputs);
}
输出函数是
bool PWMOut::updateOutputs()
调用:
int up_pwm_servo_set(unsigned channel, servo_position_t value)
其再调用:
// platforms/nuttx/src/px4/nxp/imxrt/io_pins/io_timer.c
int io_timer_set_ccr(unsigned channel, uint16_t value)
而CCR就是产生PWM的寄存器。