ArduPilot开源飞控之AP_Relay

news/2024/7/10 19:24:13 标签: 开源, ardupilot

ArduPilot开源飞控之AP_Relay

  • 1. 源由
  • 2. 框架设计
    • 2.1 启动代码
    • 2.2 任务代码
      • 2.2.1 AP_Camera_Relay::update
      • 2.2.2 AP_Parachute::update
      • 2.2.3 MAVLink命令
  • 3. 重要例程
    • 3.1 AP_Relay::AP_Relay
    • 3.2 AP_Relay::init
    • 3.3 AP_Camera_Relay::update
    • 3.4 AP_Parachute::update
    • 3.5 AP_Parachute::arming_checks
    • 3.6 AP_Camera_Relay::trigger_pic
    • 3.7 AP_ServoRelayEvents::update_events
  • 4. 总结
  • 5. 参考资料

1. 源由

开关动作基本上都是Relay来完成的。

从工作原理上来说,就是控制GPIO的高低电平,触发后续机械动作,比如:伺服开关/相机拍照等。

2. 框架设计

2.1 启动代码

Copter::init_ardupilot
 └──> AP_Relay::init

2.2 任务代码

2.2.1 AP_Camera_Relay::update

SCHED_TASK_CLASS(AP_Camera,            &copter.camera,              update,          50,  75, 111)
 └──> AP_Camera::update
     └──> AP_Camera_Relay::update

2.2.2 AP_Parachute::update

FAST_TASK(update_land_and_crash_detectors),
 └──> Copter::update_land_and_crash_detectors
     └──> Copter::parachute_check
         └──> AP_Parachute::update

2.2.3 MAVLink命令

  • AP_Parachute::arming_checks
  • AP_Camera_Relay::trigger_pic
  • AP_ServoRelayEvents::update_events
SCHED_TASK_CLASS(GCS,                  (GCS*)&copter._gcs,          update_receive, 400, 180, 102)
 └──> GCS::update_receive
     └──> GCS_MAVLINK::update_receive
         └──> GCS_MAVLINK::packetReceived
             └──> GCS_MAVLINK_Copter::handleMessage
                 └──> GCS_MAVLINK::handle_common_message
                     ├──> GCS_MAVLINK::handle_command_long
                     │   └──> GCS_MAVLINK_Copter::handle_command_long_packet
                     │       └──> GCS_MAVLINK::handle_command_long_packet
                     │           ├──> GCS_MAVLINK::handle_command_run_prearm_checks
                     │           │   └──> AP_Arming_Copter::pre_arm_checks
                     │           │       └──> AP_Arming::pre_arm_checks
                     │           │           └──> AP_Arming::system_checks
                     │           │               └──> AP_Parachute::arming_checks
                     │           └──> GCS_MAVLINK::handle_command_camera
                     │               └──> AP_Camera::handle_command_long
                     │                   └──> AP_Camera::take_picture
                     │                       └──> AP_Camera_Backend::take_picture
                     │                           └──> AP_Camera_Relay::trigger_pic
                     └──> GCS_MAVLINK::handle_command_int
                         └──> GCS_MAVLINK::handle_command_int_packet
                             └──> GCS_MAVLINK::handle_servorelay_message
                                 ├──> AP_ServoRelayEvents::do_repeat_servo
                                 │   └──> AP_ServoRelayEvents::update_events
                                 └──> AP_ServoRelayEvents::do_repeat_relay
                                     └──> AP_ServoRelayEvents::update_events

3. 重要例程

3.1 AP_Relay::AP_Relay

SITL和Linux板子有特殊默认引脚,其他板子默认没有pin脚定义。

AP_Relay::AP_Relay(void)
 ├──> AP_Param::setup_object_defaults(this, var_info)
 ├──> <CONFIG_HAL_BOARD == HAL_BOARD_SITL> <singleton != nullptr>
 │   └──> AP_HAL::panic("AP_Relay must be singleton")
 └──> singleton = this

3.2 AP_Relay::init

默认启动Relay IO配置为0输出,可通过RELAY_DEFAULT配置。

ValueMeaning
0off
1on
2no change
AP_Relay::init
 ├──> <_default != 0 && _default != 1>
 │   └──> return
 └──> <for (uint8_t i=0 i<AP_RELAY_NUM_RELAYS i++)>
     └──> set(i, _default)

3.3 AP_Camera_Relay::update

// update - should be called at 50hz
AP_Camera_Relay::update
 │
 │  /********************************************************************************
 │   * Trigger delay                                                                *
 │   ********************************************************************************/
 ├──> <trigger_counter > 0>
 │   └──> trigger_counter--
 │
 │  /********************************************************************************
 │   * On/Off                                                                       *
 │   ********************************************************************************/
 ├──> < else >
 │   ├──> AP_Relay *ap_relay = AP::relay()
 │   ├──> <ap_relay == nullptr>
 │   │   └──> return
 │   ├──> <_params.relay_on>
 │   │   └──> ap_relay->off(0)
 │   └──> < else >
 │       └──> ap_relay->on(0)
 │
 │  /********************************************************************************
 │   * call parent update                                                           *
 │   ********************************************************************************/
 └──> AP_Camera_Backend::update()

3.4 AP_Parachute::update

降落伞状态控制。

/// update - shuts off the trigger should be called at about 10hz
AP_Parachute::update
 │
 │  /********************************************************************************
 │   * exit immediately if not enabled or parachute not to be released              *
 │   ********************************************************************************/
 ├──> <_enabled <= 0>
 │   └──> return
 │
 │   // calc time since release
 ├──> uint32_t time_diff = AP_HAL::millis() - _release_time
 ├──> uint32_t delay_ms = _delay_ms<=0 ? 0: (uint32_t)_delay_ms
 │
 ├──> bool hold_forever = (_options.get() & uint32_t(Options::HoldOpen)) != 0
 │
 │   // check if we should release parachute
 ├──> <(_release_time != 0) && !_release_in_progress>
 │   │/********************************************************************************
 │   │ * release parachute                                                            *
 │   │ ********************************************************************************/
 │   ├──> <time_diff >= delay_ms>
 │   │   ├──> <_release_type == AP_PARACHUTE_TRIGGER_TYPE_SERVO> 
 │   │   │   │   // PWM output
 │   │   │   └──> SRV_Channels::set_output_pwm(SRV_Channel::k_parachute_release, _servo_on_pwm)  // move servo
 │   │   └──> < else if (_release_type <= AP_PARACHUTE_TRIGGER_TYPE_RELAY_3)> <AP_RELAY_ENABLED>
 │   │       │   // High voltage output
 │   │       ├──> AP_Relay*_relay = AP::relay() // set relay
 │   │       └──> <_relay != nullptr> _relay->on(_release_type)
 │   ├──> _release_in_progress = true
 │   └──> _released = true
 └──> < else if ((_release_time == 0) || (!hold_forever && time_diff >= delay_ms + AP_PARACHUTE_RELEASE_DURATION_MS))>
     │/********************************************************************************
     │ * release parachute end                                                        *
     │ ********************************************************************************/
     ├──> <_release_type == AP_PARACHUTE_TRIGGER_TYPE_SERVO>
	 │   │   // PWM output
     │   └──> SRV_Channels::set_output_pwm(SRV_Channel::k_parachute_release, _servo_off_pwm) // move servo back to off position
     ├──> < else if (_release_type <= AP_PARACHUTE_TRIGGER_TYPE_RELAY_3)> <AP_RELAY_ENABLED>
	 │   │   // Low voltage output
     │   ├──> AP_Relay*_relay = AP::relay()  // set relay back to zero volts
     │   └──> <_relay != nullptr> _relay->off(_release_type)
     │
     │   // reset released flag and release_time
     ├──> _release_in_progress = false
     ├──> _release_time = 0
     │
     │   // update AP_Notify
     └──> AP_Notify::flags.parachute_release = 0

3.5 AP_Parachute::arming_checks

解锁降落山配置检查。

// check settings are valid
AP_Parachute::arming_checks
 ├──> <_enabled > 0>
 │   │/********************************************************************************
 │   │ * Parachute Configuration Check                                                *
 │   │ ********************************************************************************/
 │   ├──> <_release_type == AP_PARACHUTE_TRIGGER_TYPE_SERVO) {
 │   │   └──> <!SRV_Channels::function_assigned(SRV_Channel::k_parachute_release)>
 │   │       ├──> hal.util->snprintf(buffer, buflen, "Chute has no channel")
 │   │       └──> return false
 │   ├──> < else >
 │   │   ├──> <AP_RELAY_ENABLED>
 │   │   │   ├──> AP_Relay*_relay = AP::relay()
 │   │   │   └──> <_relay == nullptr || !_relay->enabled(_release_type)>
 │   │   │       ├──> hal.util->snprintf(buffer, buflen, "Chute invalid relay %d", int(_release_type))
 │   │   │       └──> return false
 │   │   └──> <else>
 │   │       └──> hal.util->snprintf(buffer, buflen, "AP_Relay not available")
 │   └──> <_release_initiated>
 │       ├──> hal.util->snprintf(buffer, buflen, "Chute is released")
 │       └──> return false
 │
 │  /********************************************************************************
 │   * No Parachute Configuration                                                   *
 │   ********************************************************************************/
 └──> return true

3.6 AP_Camera_Relay::trigger_pic

拍照控制。

// entry point to actually take a picture.  returns true on success
AP_Camera_Relay::trigger_pic
 │   // fail if have not completed previous picture
 ├──> <trigger_counter > 0>
 │   └──> return false
 │
 │  /********************************************************************************
 │   * On/Off                                                                       *
 │   ********************************************************************************/
 │   // exit immediately if no relay is setup
 ├──> AP_Relay *ap_relay = AP::relay()
 ├──> <ap_relay == nullptr>
 │   └──> return false
 ├──> <_params.relay_on>
 │   └──> ap_relay->on(0)
 ├──> < else >
 │   └──> ap_relay->off(0)
 │
 │  /********************************************************************************
 │   * set counter to move servo to off position                                    *
 │   * after this many iterations of update (assumes 50hz update rate)              *
 │   ********************************************************************************/
 ├──> trigger_counter = constrain_float(_params.trigger_duration * 50, 0, UINT16_MAX)
 └──> return true

3.7 AP_ServoRelayEvents::update_events

/*
  update state for MAV_CMD_DO_REPEAT_SERVO and MAV_CMD_DO_REPEAT_RELAY
*/
AP_ServoRelayEvents::update_events
 │
 │  /********************************************************************************
 │   * repeat condition check                                                       *
 │   ********************************************************************************/
 ├──> <repeat == 0 || (AP_HAL::millis() - start_time_ms) < delay_ms>
 │   └──> return
 │
 ├──> start_time_ms = AP_HAL::millis()
 │
 │  /********************************************************************************
 │   * EVENT_TYPE_SERVO                                                             *
 │   ********************************************************************************/
 ├──> <case EVENT_TYPE_SERVO>
 │   ├──> SRV_Channel *c = SRV_Channels::srv_channel(channel-1)
 │   └──> <c != nullptr>
 │       ├──> <repeat & 1>
 │       │   └──> c->set_output_pwm(c->get_trim())
 │       └──> < else >
 │           ├──> c->set_output_pwm(servo_value)
 │           └──> c->ignore_small_rcin_changes()
 │
 │  /********************************************************************************
 │   * EVENT_TYPE_RELAY                                                             *
 │   ********************************************************************************/
 ├──> <case EVENT_TYPE_RELAY> <AP_RELAY_ENABLED>
 │   ├──> AP_Relay *relay = AP::relay()
 │   └──> <relay != nullptr>
 │       └──> relay->toggle(channel)
 │
 │  /********************************************************************************
 │   * set counter to move servo to off position                                    *
 │   ********************************************************************************/
 ├──> <repeat > 0>
 │   └──> repeat--
 └──> < else > // toggle bottom bit so servos flip in value
     └──> repeat ^= 1

4. 总结

Relay目前有以下几个应用场景:

  1. AP_Parachute
  2. AP_Camera_Relay
  3. AP_ServoRelayEvents

配置参数:

  • RELAY_ Parameters
  • BTN_ Parameters
  • ADSB_ Parameters
  • CHUTE_ Parameters
  • RC Parameters
  • SERVO Parameters

5. 参考资料

【1】ArduPilot开源飞控系统之简单介绍
【2】ArduPilot之开源代码Task介绍
【3】ArduPilot飞控启动&运行过程简介
【4】ArduPilot之开源代码Library&Sketches设计
【5】ArduPilot之开源代码Sensor Drivers设计


http://www.niftyadmin.cn/n/5109089.html

相关文章

2023年中国车用冲压模具行业特征、竞争现状及行业市场规模分析[图]

汽车冲压件模具具有尺寸大、型面复杂、精度要求高等特点&#xff0c;属于技术密集型产品。汽车冲压模具能快速精密地把材料直接加工成零件或半成品并通过焊接、铆接、拼装等工艺装配成零部件&#xff0c;冲压模具的设计开发和加工能力对汽车冲压零部件产品总制造成本、质量及性…

easyphoto 妙鸭相机

AIGC专栏7——EasyPhoto 人像训练与生成原理详解-CSDN博客如何训练一个高品质的人像Lora与应用高品质Lora的链路对于写真生成而言非常重要。由《LoRA: Low-Rank Adaptation of Large Language Models》 提出的一种基于低秩矩阵的对大参数模型进行少量参数微调训练的方法&#x…

用 Python 这样去创建词云不是更美嘛?

什么是词云&#xff1f;在网络上我们经常可以看到一张图片&#xff0c;上面有一大堆大小不一的文字&#xff0c;这便是词云。词云一般是根据输入的大量词语生成的&#xff0c;如果某个词语出现的次数越多&#xff0c;那么相应的大小就会越大。 Python 中有一个专门用来生成词云…

PixCakeAI人像处理技术修图软件:打造你的完美像素之境

在当今这个数字时代&#xff0c;我们的形象&#xff0c;无论是在社交媒体上&#xff0c;还是在日常生活中&#xff0c;都显得尤为重要。有没有想过&#xff0c;你可以自己动手&#xff0c;轻松打造出独一无二的像素艺术作品&#xff1f;现在&#xff0c;让我们一同探索一个全新…

C语言之排序

1.冒泡排序 冒泡排序就不多说了&#xff0c;只需要两层循环嵌套&#xff0c;两两比较确定相对正确的顺序即可。 2.插入排序 插入排序的思想就是每一次向后寻找一个再将其与前面有序的部分进行对比&#xff0c;寻找合适位置插入。 这里关键要避免让前移超出目前读取的数字&…

PHP基础学习

PHP是什么&#xff1f; PHP&#xff08;全称&#xff1a;PHP&#xff1a;Hypertext Preprocessor&#xff0c;即"PHP&#xff1a;超文本预处理器"&#xff09;是一种通用开源脚本语言。PHP 脚本在服务器上执行。PHP 可免费下载使用。 基础的PHP语法 PHP 脚本可以放…

CentOS7.9离线安装Docker环境

1. 下载合适的Docker安装包 Docker安装包下载地址&#xff1a;Index of linux/static/stable/x86_64/https://download.docker.com/linux/static/stable/x86_64/ 进入地址页面&#xff0c;如下图&#xff1a; 我下载的是&#xff1a;docker-23.0.1.tgz 版本 2. 将下载好的Do…

4795: 【PY】【C1】【分支】寄快递

题目描述 快递每件10元&#xff0c;如果加急加收5元&#xff0c;根据快递数量和加急情况&#xff0c;计算快递费。 输入 第1行&#xff0c;快递数量 第2行&#xff0c;是否加急&#xff08;Y表示加急&#xff0c;N表示不加急&#xff09; 输出 快递费用 样例输入 5 Y 样…