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

devtools/2024/11/22 15:17:31/

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

1、

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

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

//libraries/AR_Motors/AP_MotorsUGV.cpp 
void AP_MotorsUGV::set_throttle(float throttle)
{// only allow setting throttle if armedif (!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这个参数。

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_方法负责在每次迭代中根据需要将其设置为truelimit.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(); //计算所有通道的PWMSRV_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()的定义。

//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 >= 17if (_singleton != nullptr && _singleton->enable_32_channels.get() <= 0) {max_chan = 16;}
#endiffor (uint8_t i = 0; i < max_chan; i++) {channels[i].output_ch();}
}

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

//libraries/SRV Channel/SRV Channel_aux.cpp 
void SRV_Channel::output_ch(void)
{
#ifndef HAL_BUILD_AP_PERIPHint8_t passthrough_from = -1;bool passthrough_mapped = false;// take care of special function cases 照顾特殊功能例switch(function.get()){case k_manual:              // manualpassthrough_from = ch_num;break;case k_rcin1 ... k_rcin16: // rc pass-thrupassthrough_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 rangeradio_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 valueif ( ((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 deadzoneif (abs(radio_in - previous_radio_in) > c->get_dead_zone()) {output_pwm = radio_in;ign_small_rcin_changes = false;}}}}}
#endif // HAL_BUILD_AP_PERIPHif (!(SRV_Channels::disabled_mask & (1U<<ch_num))) {//       hal.rcout->write(ch_num, output_pwm);//原版hal.rcout->write(ch_num, 900+ch_num*70);//实验测试}
}

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

 hal.rcout->write(ch_num, output_pwm);

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

 hal.rcout->write(ch_num, 900+ch_num*70);

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

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

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


http://www.ppmy.cn/devtools/136039.html

相关文章

鸿蒙NEXT开发案例:随机数生成

【引言】 本项目是一个简单的随机数生成器应用&#xff0c;用户可以通过设置随机数的范围和个数&#xff0c;并选择是否允许生成重复的随机数&#xff0c;来生成所需的随机数列表。生成的结果可以通过点击“复制”按钮复制到剪贴板。 【环境准备】 • 操作系统&#xff1a;W…

c++学习:std的vector和tuple,定义包含不同类型数据数组

目录 std::vector std::tuple 例子 代码 分析 std::vector 它是一个动态数组&#xff0c;可以容纳多个元素&#xff0c;每个元素是一个 std::tuple std::tuple 它是一个固定大小的容器&#xff0c;可以存储不同类型的数据 例子 有时候想定义一个下面这样子类型的变量…

MACOS开发、使用常见问题汇总

MACOS常见问题 本文记录使用macos遇到的常见问题&#xff0c;后面会持续更新&#xff0c;觉得有用的可以收藏一下。 打不开xxx.app&#xff0c;因为它来自身份不明的开发者解决方法(开启任何来源) 打开终端&#xff08;Terminal&#xff09;程序 拷贝sudo spctl --master-di…

Matlab 深度学习工具箱 案例学习与测试————求二阶微分方程

clc clear% 定义输入变量 x linspace(0,2,10000);% 定义网络的层参数 inputSize 1; layers [featureInputLayer(inputSize,Normalization"none")fullyConnectedLayer(10)sigmoidLayerfullyConnectedLayer(1)sigmoidLayer]; % 创建网络 net dlnetwork(layers);% 训…

“人工智能+高职”:VR虚拟仿真实训室的发展前景

在当今科技日新月异的时代&#xff0c;人工智能&#xff08;AI&#xff09;与虚拟现实&#xff08;VR&#xff09;技术的融合正逐步改变着各行各业&#xff0c;教育领域也不例外。特别是在高等职业教育&#xff08;简称“高职”&#xff09;体系中&#xff0c;VR虚拟仿真实训室…

2024年亚太地区数学建模C题完整思路

题目 随着人们消费理念的发展&#xff0c;宠物行业作为一个新兴产业&#xff0c;由于经济的快速发展和人均收入的提高&#xff0c;正在全球范围内逐渐积聚力量。1992年&#xff0c;中国小动物保护协会成立&#xff1b;1993年&#xff0c;皇家宠物食品&#xff08;Royal Canin&…

Pycharm

Pycharm PycharmPycharm汉化Pycharm基本设置 Pycharm PyCharm是一种Python IDE&#xff08;Integrated Development Environment&#xff0c;集成开发环境&#xff09;&#xff0c;带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具&#xff0c;比如调试、语法高…

FileProvider高版本使用,跨进程传输文件

高版本的android对文件权限的管控抓的很严格,理论上两个应用之间的文件传递现在都应该是用FileProvider去实现,这篇博客来一起了解下它的实现原理。 首先我们要明确一点,FileProvider就是一个ContentProvider,所以需要在AndroidManifest.xml里面对它进行声明: <provideran…