Apm飞控学习笔记之-RC_Channel遥控器数据获取-Cxm
前言
这一篇分析APM的遥控器数据获取
ArduCopter\Copter.cpp中rc_loop遥控器线程
const AP_Scheduler::Task Copter::scheduler_tasks[] = {SCHED_TASK(rc_loop, 100, 130),SCHED_TASK(throttle_loop, 50, 75),SCHED_TASK(update_GPS, 50, 200),
void Copter::rc_loop()
{// Read radio and 3-position switch on radio// -----------------------------------------read_radio();rc().read_mode_switch();
}
read_radio();
这里开始跳转ArduCopter\Copter.h
// radio.cppvoid default_dead_zones();void init_rc_in();void init_rc_out();void enable_motor_output();void read_radio();void set_throttle_and_failsafe(uint16_t throttle_pwm);void set_throttle_zero_flag(int16_t throttle_control);void radio_passthrough_to_motors();int16_t get_throttle_mid(void);
这一步不能直接跳转了 看了一下注释找一下radio.cpp文件在ArduCopter\radio.cpp中
void Copter::read_radio()
{const uint32_t tnow_ms = millis();if (rc().read_input()) {ap.new_radio_frame = true;set_throttle_and_failsafe(channel_throttle->get_radio_in());set_throttle_zero_flag(channel_throttle->get_control_in());// RC receiver must be attached if we've just got inputap.rc_receiver_present = true;// pass pilot input through to motors (used to allow wiggling servos while disarmed on heli, single, coax copters)radio_passthrough_to_motors();const float dt = (tnow_ms - last_radio_update_ms)*1.0e-3f;rc_throttle_control_in_filter.apply(channel_throttle->get_control_in(), dt);last_radio_update_ms = tnow_ms;return;}// No radio input this timeif (failsafe.radio) {// already in failsafe!return;}const uint32_t elapsed = tnow_ms - last_radio_update_ms;// turn on throttle failsafe if no update from the RC Radio for 500ms or 2000ms if we are using RC_OVERRIDEconst uint32_t timeout = RC_Channels::has_active_overrides() ? FS_RADIO_RC_OVERRIDE_TIMEOUT_MS : FS_RADIO_TIMEOUT_MS;if (elapsed < timeout) {// not timed out yetreturn;}if (!g.failsafe_throttle) {// throttle failsafe not enabledreturn;}if (!ap.rc_receiver_present && !motors->armed()) {// we only failsafe if we are armed OR we have ever seen an RC receiverreturn;}// Nobody ever talks to us. Log an error and enter failsafe.AP::logger().Write_Error(LogErrorSubsystem::RADIO, LogErrorCode::RADIO_LATE_FRAME);set_failsafe_radio(true);
}
这里重点关注read_input()这个是通道信号输入的刷新
bool RC_Channels::read_input(void)
{if (!hal.rcin->new_input() && !has_new_overrides) {return false;}has_new_overrides = false;bool success = false;for (uint8_t i=0; i<NUM_RC_CHANNELS; i++) {success |= channel(i)->update();}return success;
}
直接关注hal.rcin->new_input()
bool RC_Channels::read_input(void)
{if (!hal.rcin->new_input() && !has_new_overrides) {return false;}has_new_overrides = false;bool success = false;for (uint8_t i=0; i<NUM_RC_CHANNELS; i++) {success |= channel(i)->update();}return success;
}
channel(i)
RC_Channel_Copter *channel(const uint8_t chan) override {if (chan >= NUM_RC_CHANNELS) {return nullptr;}return &obj_channels[chan];}
channel(i)->update()信号的读取
radio_in保存读取到的PWM值
bool RC_Channel::update(void)
{if (has_override() && !rc().ignore_overrides()) {radio_in = override_value;} else if (!rc().ignore_receiver()) {radio_in = hal.rcin->read(ch_in);} else {return false;}if (type_in == RC_CHANNEL_TYPE_RANGE) {control_in = pwm_to_range();} else {//RC_CHANNEL_TYPE_ANGLEcontrol_in = pwm_to_angle();}return true;
}
float rcin[8]; // RC input 0..1
read_mode_switch()
此函数的作用是判断飞行器当前的模式和飞行模式的设置
void RC_Channel::read_mode_switch()
{// calculate position of flight mode switchconst uint16_t pulsewidth = get_radio_in();if (pulsewidth <= 900 || pulsewidth >= 2200) {return; // This is an error condition}modeswitch_pos_t position;if (pulsewidth < 1231) position = 0;else if (pulsewidth < 1361) position = 1;else if (pulsewidth < 1491) position = 2;else if (pulsewidth < 1621) position = 3;else if (pulsewidth < 1750) position = 4;else position = 5;if (!debounce_completed(position)) {return;}// set flight mode and simple mode setting//设置飞行模式和简单模式设置mode_switch_changed(position);
}
这里的重点是void RC_Channel_Copter::mode_switch_changed(modeswitch_pos_t new_pos) 函数
ArduCopter\RC_Channel.cpp
void RC_Channel_Copter::mode_switch_changed(modeswitch_pos_t new_pos)
{if (new_pos < 0 || (uint8_t)new_pos > copter.num_flight_modes) {// should not have been calledreturn;}if (!copter.set_mode((Mode::Number)copter.flight_modes[new_pos].get(), ModeReason::RC_COMMAND)) {// alert user to mode change failureif (copter.ap.initialised) {AP_Notify::events.user_mode_change_failed = 1;}return;}// play a tone// alert user to mode change (except if autopilot is just starting up)if (copter.ap.initialised) {AP_Notify::events.user_mode_change = 1;}if (!rc().find_channel_for_option(AUX_FUNC::SIMPLE_MODE) &&!rc().find_channel_for_option(AUX_FUNC::SUPERSIMPLE_MODE)) {// if none of the Aux Switches are set to Simple or Super Simple Mode then// set Simple Mode using stored parameters from EEPROMif (BIT_IS_SET(copter.g.super_simple, new_pos)) {copter.set_simple_mode(2);} else {copter.set_simple_mode(BIT_IS_SET(copter.g.simple_modes, new_pos));}}
}
判断一下是否有模式输入
if (new_pos < 0 || (uint8_t)new_pos > copter.num_flight_modes) {
// should not have been called
// const uint8_t num_flight_modes = 6;
return;
}
更改模式和判断模式是否更改成功
if (!copter.set_mode((Mode::Number)copter.flight_modes[new_pos].get(), ModeReason::RC_COMMAND)) {
// alert user to mode change failure
if (copter.ap.initialised) {
AP_Notify::events.user_mode_change_failed = 1;
}
return;
}
其中set_mode有两个重载函数
第一个传参很好理解就是设置成当前的模式而第二个传参modereason 则是接口相当于你模式的来源,我是这么理解的
// interface to set the vehicles mode
enum class ModeReason : uint8_t {UNKNOWN,RC_COMMAND,GCS_COMMAND,RADIO_FAILSAFE,BATTERY_FAILSAFE,GCS_FAILSAFE,EKF_FAILSAFE,GPS_GLITCH,MISSION_END,THROTTLE_LAND_ESCAPE,FENCE_BREACHED,TERRAIN_FAILSAFE,BRAKE_TIMEOUT,FLIP_COMPLETE,AVOIDANCE,AVOIDANCE_RECOVERY,THROW_COMPLETE,TERMINATE,TOY_MODE,CRASH_FAILSAFE,SOARING_FBW_B_WITH_MOTOR_RUNNING,SOARING_THERMAL_DETECTED,SOARING_THERMAL_ESTIMATE_DETERIORATED,VTOL_FAILED_TRANSITION,VTOL_FAILED_TAKEOFF,FAILSAFE, // general failsafes, prefer specific failsafes over this as much as possibleINITIALISED,SURFACE_COMPLETE,BAD_DEPTH,LEAK_FAILSAFE,SERVOTEST,STARTUP,SCRIPTING,UNAVAILABLE,AUTOROTATION_START,AUTOROTATION_BAILOUT,
};
后续更新
Apm飞控学习笔记之-RC_Channel遥控器数据获取-Cxm相关推荐
- Apm飞控学习笔记之悬停loiter模式-Cxm
文章汇集 PX4/APM/飞控的学习笔记前言-Cxm_CHENxiaomingming的博客-CSDN博客_apm和px4哪个好 前言 时隔一段时间又开始琢磨APM飞控了,在上一篇中写了姿态控制,经过 ...
- Apm飞控学习笔记-姿态控制-Cxm
目录 PX4/APM/飞控的学习笔记前言-Cxm_chen_taifu的博客-CSDN博客开始了 开始了终于有时间可以学习飞控了此文章是用来当目录,我会持续更新我的学习之旅,希望能对各位有所帮助如果有 ...
- Apm飞控学习笔记之添加我的设备或单片机串口通信-Cxm
目录 PX4/APM/飞控的学习笔记前言-Cxm_chen_taifu的博客-CSDN博客开始了 开始了终于有时间可以学习飞控了此文章是用来当目录,我会持续更新我的学习之旅,希望能对各位有所帮助如果有 ...
- Apm飞控学习笔记之添加我的飞行模式-Cxm
目录 PX4/APM/飞控的学习笔记前言-Cxm_chen_taifu的博客-CSDN博客开始了 开始了终于有时间可以学习飞控了此文章是用来当目录,我会持续更新我的学习之旅,希望能对各位有所帮助如果有 ...
- Apm飞控学习笔记之如何添加自己的功能-Cxm
目录: PX4/APM/飞控的学习笔记前言-Cxm_chen_taifu的博客-CSDN博客开始了 开始了终于有时间可以学习飞控了此文章是用来当目录,我会持续更新我的学习之旅,希望能对各位有所帮助如果 ...
- APM飞控学习笔记——自动模式下一分钟自动降落
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.自动模式简介 二.添加自动降落功能 1.飞控主循环调用逻辑 2.功能添加 总结 前言 APM是一款功能齐全的开源多 ...
- 第一篇——APM飞控学习笔记
关于什么是APM? 可能有很多玩航模或者是向我这样混迹于实验室的垃圾佬(bushi)看到过这个玩意--->>> 从狭义上来说,这个就是APM开源飞控. APM又叫ArduPilot- ...
- 基于tiva的匿名飞控学习笔记(1)
基于tiva的匿名飞控学习笔记(1) 开关状态任务 遥控器数据处理任务 数传数据交换 延时存储任务 开关状态任务 匿名飞控的开关状态任务为函数Swtich_State_Task(u8 dT_ms),定 ...
- APM飞控学习之路:1 无人机的分类与发展
"旧时王谢堂前燕,飞入寻常百姓家".无人机也像那堂前燕,从以前为军事所专属,负责侦查和战斗,飞入民用领域,在航拍.植保.快递.救灾.巡检.拍摄等行业大显身手,无人机+的应用遍地开花 ...
最新文章
- spacy spaCy主要功能包括分词、词性标注、词干化、命名实体识别、名词短语提取等等
- 光伏电站清扫机器人_轻型光伏电站清扫机器人的制作方法
- Winform控件扩展
- android发送点击事件,Android 模拟发送事件
- 算法-----python实现
- [MSP430DriverLib-2]使用延时让LED闪烁
- 两个相同矩形脉冲卷积_两个矩形脉冲的卷积
- 20个开源Flutter项目推荐
- 等保要求的 linux 系统扫描脚本
- python isinstance()方法的使用
- Python 身份证校验代码
- HDU2030-汉字机内码
- VMware Fusion CentOS7 下载安装及手动配置静态IP
- 近期币圈与美股的相关性
- linux创建用户和组
- win10启动文件夹在哪 如何设置随系统自动启动
- QMS-云质-质量管理软件-闲聊霍尼韦尔用13亿美元收购一家质量管理软件(QMS)小公司
- VS Code中将自定义的Snippets绑定到自定义的快捷键上
- IDA的详细使用指南以及核心功能讲解
- 机器学习之Matplotlib
热门文章
- sobel算子梯度 matlab,sobel算子,matlab实现 | 学步园
- Codeforces Round #849 (Div. 4) F. Range Update Point Query
- js 判断数组中是否存在某个元素(字符串,类等)
- php xpath注入工具,科普:XPATH注入
- 如何使用Latex将四幅图跨栏排列
- 非常受用:HP大中华区总裁孙振耀退休十五天后九大感言
- Android SDK Platform Tools
- 计算机无法跳转登录页面,电脑连接校园网后CMCC登录界面不能弹出的解决方法...
- php setinc,ThinkPHP 数字字段 更新 setInc 与 setDec 方法
- Django Q对象