PIXHAWK(ardupilot4.52)单ic通道输出pwm

可以看到飞控具有16个ic输出通道,理论上每一个通道都可以单独输出pwm,那么怎样才能在固件中让每个通道都单独输出pwm呢?

1、

手动模式下油门控制可以直观的控制pwm输出,

在void ModeManual::update()中可以看到g2.motors.set_throttle(desired_throttle); 就是油门处理函数。可以根据这个函数寻址找到void AP_MotorsUGV::set_throttle(float throttle)函数

cpp 复制代码
//libraries/AR_Motors/AP_MotorsUGV.cpp 
void AP_MotorsUGV::set_throttle(float throttle)
{
    // only allow setting throttle if armed
    if (!hal.util->get_soft_armed()) {
        return;
    }
    // check throttle is between -_throttle_max and  +_throttle_max
    _throttle = constrain_float(throttle, -_throttle_max, _throttle_max);
}

在这个函数中可以看到形参desired_throttle最终是递给了_throttle这个参数。接下来就是在该文件下找哪里使用了_throttle这个参数。

cpp 复制代码
void AP_MotorsUGV::output(bool armed, float ground_speed, float dt)
{
    // soft-armed overrides passed in armed status 以武装状态通过软武装覆盖
    if (!hal.util->get_soft_armed()) {
        armed = false;
        _throttle = 0.0f;
    }

    // clear limit flags
    // output_ methods are responsible for setting them to true if required on each iteration
    //清除限制标志
    //output_方法负责在每次迭代中根据需要将其设置为true
    limit.steer_left = limit.steer_right = limit.throttle_lower = limit.throttle_upper = false;

    // sanity check parameters 健全性检查参数
    sanity_check_parameters();

    // slew limit throttle 回转限制节流阀
    slew_limit_throttle(dt);

    // output for regular steering/throttle style frames 常规转向/油门式车架的输出
    output_regular(armed, ground_speed, _steering, _throttle);

    // output for skid steering style frames 滑移转向式车架的输出
    output_skid_steering(armed, _steering, _throttle, dt);

    // output for omni frames 全帧输出
    output_omni(armed, _steering, _throttle, _lateral);

    // output to sails 输出到帆
    output_sail();

    // send values to the PWM timers for output 将值发送到PWM定时器进行输出
    SRV_Channels::calc_pwm(); //计算所有通道的PWM
    SRV_Channels::cork();
    SRV_Channels::output_ch_all(); //控制pwm输出
    SRV_Channels::push();
}

搜索查找后可以找到void AP_MotorsUGV::output(bool armed, float ground_speed, float dt)这个函数,看名称可以判断为输出函数。_throttle在这个函数中使用了,但是最终都汇聚在SRV_Channels::output_ch_all();函数中,这个就是控制pwm输出函数。

继续寻址。找到SRV_Channels::output_ch_all()的定义。

cpp 复制代码
//libraries/SRV Channel/SRV Channel_aux.cpp 
void SRV_Channels::output_ch_all(void)
{
    uint8_t max_chan = NUM_SERVO_CHANNELS;
#if NUM_SERVO_CHANNELS >= 17
    if (_singleton != nullptr && _singleton->enable_32_channels.get() <= 0) {
        max_chan = 16;
    }
#endif
    for (uint8_t i = 0; i < max_chan; i++) {

        channels[i].output_ch();
    }
}

在函数的末尾可以看到channels[i].output_ch();这个函数,这个函数还不能直接输出定值的pwm,继续寻址。

cpp 复制代码
//libraries/SRV Channel/SRV Channel_aux.cpp 
void SRV_Channel::output_ch(void)
{
#ifndef HAL_BUILD_AP_PERIPH
    int8_t passthrough_from = -1;
    bool passthrough_mapped = false;

    // take care of special function cases 照顾特殊功能例
    switch(function.get())
    {
    case k_manual:              // manual
        passthrough_from = ch_num;
        break;
    case k_rcin1 ... k_rcin16: // rc pass-thru
        passthrough_from = int8_t((int16_t)function - k_rcin1);
        break;
    case k_rcin1_mapped ... k_rcin16_mapped:
        passthrough_from = int8_t((int16_t)function - k_rcin1_mapped);
        passthrough_mapped = true;
        break;
    }
    if (passthrough_from != -1) {
        // we are doing passthrough from input to output for this channel 我们正在为这个通道进行从输入到输出的直通
        RC_Channel *c = rc().channel(passthrough_from);
        if (c) {
            if (SRV_Channels::passthrough_disabled()) {
                output_pwm = c->get_radio_trim();
            } else {
                // non-mapped rc passthrough 非映射rc透传
                int16_t radio_in = c->get_radio_in();
                if (passthrough_mapped) {
                    if (rc().has_valid_input()) {
                        switch (c->get_type()) {
                        case RC_Channel::ControlType::ANGLE:
                            radio_in = pwm_from_angle(c->norm_input_dz() * 4500);
                            break;
                        case RC_Channel::ControlType::RANGE:
                            // convert RC normalised input from -1 to +1 range to 0 to +1 and output as range
                            radio_in = pwm_from_range((c->norm_input_ignore_trim() + 1.0) * 0.5 * 4500);
                            break;
                        }
                    } else {
                        // no valid input.  If we are in radio
                        // failsafe then go to trim values (if
                        // configured for this channel).  Otherwise
                        // use the last-good value
                        if ( ((1U<<passthrough_from) & SRV_Channels::get_rc_fs_mask()) && rc().in_rc_failsafe()) {
                            radio_in = pwm_from_angle(0);
                        } else {
                            radio_in = previous_radio_in;
                        }
                    }
                }
                if (!ign_small_rcin_changes) {
                    output_pwm = radio_in;
                    previous_radio_in = radio_in;
                } else {
                    // check if rc input value has changed by more than the deadzone
                    if (abs(radio_in - previous_radio_in) > c->get_dead_zone()) {
                        output_pwm = radio_in;
                        ign_small_rcin_changes = false;
                    }
                }
            }
        }
    }
#endif // HAL_BUILD_AP_PERIPH
    if (!(SRV_Channels::disabled_mask & (1U<<ch_num))) {
 //       hal.rcout->write(ch_num, output_pwm);//原版

        hal.rcout->write(ch_num, 900+ch_num*70);//实验测试

    }
}

该函数下,前面的都是验证每个通道分别需要多少的pwm输出,函数的最后才是控制单独通道的单独输出。

cpp 复制代码
 hal.rcout->write(ch_num, output_pwm);

其中ch_num即对应通道,output_pwm即需要输出的pwm,在这里修改代码测试一下:

cpp 复制代码
 hal.rcout->write(ch_num, 900+ch_num*70);

修改后,理论上第一个通道输出900,然后后面的通道逐个递增70。

编译完成后下载到飞控中查看ic通道输出。

可以看到ic通道确实是根据设定输出,但是只有前8个通道输出,后面8个却没有输出,这是为啥?

相关推荐
怀旧6662 分钟前
Java List 集合
java·数据结构·后端·list·个人开发
Peter_chq3 分钟前
【计算机网络】多路转接之poll
linux·c语言·开发语言·网络·c++·后端·poll
陈小于1 小时前
springboot集成shiro和前后端分离配置
java·spring boot·后端
Adolf_19931 小时前
Flask 基于wsgi源码启动流程
后端·python·flask
@逆风微笑代码狗1 小时前
136.flask内置jinja2模版使用
后端·python·flask
lix的小鱼2 小时前
Scala之Array数组
java·开发语言·后端·python·scala
anqi272 小时前
Scala 的Array 和 ArrayBuffer 集合
开发语言·后端·scala
柔弱女子爱java2 小时前
XML文件(超详细):XML文件概念、作用、写法、如何用程序解析XML、写入XML、dom4j框架、DTD文档、schema文档
xml·java·开发语言·后端
2402_857589362 小时前
SpringBoot在线课程系统:教育行业的数字化转型
spring boot·后端·mfc
老A技术联盟2 小时前
基于syslog实现项目的日志收集
后端