PX4飞控的PPM接收机

2023-05-16

(一)原理图:

      PX4飞控的PPM输入捕获由协处理器完成,接在A8引脚,对应Timer1的通道1。

(二)PPM协议:

      PPM的每一帧数据间隔为20ms,用两个上升沿之间的时间间隔表示一个通道的值,如图所示是一个6通道信号。在每一帧的结束会有较长时间的持续低电平,两次上升沿时间间隔要大于5ms,可以用于辨别下一帧数据的到来。

(三)相关代码

定时器1配置:

/* timer1 config */
void Bsp_Timer1_Config(void)
{
    TIM_ICInitTypeDef       TIM_ICInitStructure;
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    NVIC_InitTypeDef        NVIC_InitStructure;
    GPIO_InitTypeDef        GPIO_InitStructure;

    /* Clock Enable */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    /* Enable global Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    /* TIM1 channel 1 pin (PA.08) configuration */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* Time Base configuration, 1us every tick */
    TIM_TimeBaseStructure.TIM_Prescaler = SystemCoreClock / 1000000;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseStructure.TIM_Period = 0xFFFF;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;

    TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

    TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
    TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
    TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
    TIM_ICInitStructure.TIM_ICFilter = 0x0;

    TIM_ICInit(TIM1, &TIM_ICInitStructure);

    /* TIM enable counter */
    TIM_Cmd(TIM1, ENABLE);

    /* Enable the CC1 Interrupt Request */
    TIM_ITConfig(TIM1, TIM_IT_CC1, ENABLE);
}

PPM处理程序:

#define GET_GAP(x, y)	(x > y ? (x - y) : (0xFFFF - y + x))

ST_PPM machine_param;

static uint8_t PPM_Recv = 0;        /* ppm received flag */ 
static uint8_t PPM_Send_Freq = 0;   /* freq of sending ppm to fmu */ 

/* status turn to the next one */ 
static void ppm_next_status(ST_PPM *param)
{
    static uint8_t max_ch = STA_EDGE_9 + 1;

    param->status = (param->status + 1) % max_ch;
}

/* reset the ppm machine state */
void reset_machine_state(ST_PPM *param)
{
    param->status = STA_EDGE_1;
    param->bad_frame = 0;
    param->last_ic = 0;
}

/* the function will be called back by the timer1 interrupt */
void App_PPM_Status_Machine(uint16_t ic)
{
    static uint16_t temp_val[8];
    uint16_t gap;

    gap = GET_GAP(ic, machine_param.last_ic);

    /* each ppm frame has a 5.5ms start puls, each tick is 1us */
    if (gap > 5000)
    {
        reset_machine_state(&machine_param);
    }
    else if (gap < 800 || gap > 2200)
    {
        /* bad signal, drop frame */
        machine_param.bad_frame = 1;
    }

    if (machine_param.status == STA_EDGE_1)
    {
        /* do nothing */
    }
    else if (machine_param.status == STA_EDGE_9)
    {
        uint8_t i;

        temp_val[STA_EDGE_9 - 1] = gap;
        /* we know next we have a 5.5ms gap, so we can do some time-cost task here */
        /* If it's bad frame, we drop it */
        if (!machine_param.bad_frame)
        {
            for (i = 0; i < 8; i++)
            {
                machine_param.ppm_val[i] = temp_val[i];
            }
            PPM_Recv = 1;
        }
    }
    else
    {
        temp_val[machine_param.status - 1] = gap;
    }

    machine_param.last_ic = ic;
    ppm_next_status(&machine_param);
}

/* received a wholed ppm frame */
uint8_t App_PPM_Ready(void)
{
    static uint32_t prev_time = 0;
    uint32_t time = Sys_Tick_Time;

    if (!PPM_Send_Freq)
    {
        return 0;
    }

    if (time - prev_time > 1000 / PPM_Send_Freq && PPM_Recv)
    {
        prev_time = time;
        return 1;
    }

    return 0;
}

/* copy the ppm frame to the buff when the ppm frame will be used */
void App_Get_PPM_Value(uint16_t ppm[8])
{
    memcpy(ppm, machine_param.ppm_val, 8);
    PPM_Recv = 0;
}

/* set the frequency of sending ppm buff to fmu */
uint8_t App_Set_PPM_Send_Freq(uint8_t freq)
{
    if (freq <= 50)
    {
        PPM_Send_Freq = freq;
        return 1;
    }
    else
    {
        return 0;
    }
}	(x > y ? (x - y) : (0xFFFF - y + x))

ST_PPM machine_param;

static uint8_t PPM_Recv = 0;        /* ppm received flag */ 
static uint8_t PPM_Send_Freq = 0;   /* freq of sending ppm to fmu */ 

/* status turn to the next one */ 
static void ppm_next_status(ST_PPM *param)
{
    static uint8_t max_ch = STA_EDGE_9 + 1;

    param->status = (param->status + 1) % max_ch;
}

/* reset the ppm machine state */
void reset_machine_state(ST_PPM *param)
{
    param->status = STA_EDGE_1;
    param->bad_frame = 0;
    param->last_ic = 0;
}

/* the function will be called back by the timer1 interrupt */
void App_PPM_Status_Machine(uint16_t ic)
{
    static uint16_t temp_val[8];
    uint16_t gap;

    gap = GET_GAP(ic, machine_param.last_ic);

    /* each ppm frame has a 5.5ms start puls, each tick is 1us */
    if (gap > 5000)
    {
        reset_machine_state(&machine_param);
    }
    else if (gap < 800 || gap > 2200)
    {
        /* bad signal, drop frame */
        machine_param.bad_frame = 1;
    }

    if (machine_param.status == STA_EDGE_1)
    {
        /* do nothing */
    }
    else if (machine_param.status == STA_EDGE_9)
    {
        uint8_t i;

        temp_val[STA_EDGE_9 - 1] = gap;
        /* we know next we have a 5.5ms gap, so we can do some time-cost task here */
        /* If it's bad frame, we drop it */
        if (!machine_param.bad_frame)
        {
            for (i = 0; i < 8; i++)
            {
                machine_param.ppm_val[i] = temp_val[i];
            }
            PPM_Recv = 1;
        }
    }
    else
    {
        temp_val[machine_param.status - 1] = gap;
    }

    machine_param.last_ic = ic;
    ppm_next_status(&machine_param);
}

/* received a wholed ppm frame */
uint8_t App_PPM_Ready(void)
{
    static uint32_t prev_time = 0;
    uint32_t time = Sys_Tick_Time;

    if (!PPM_Send_Freq)
    {
        return 0;
    }

    if (time - prev_time > 1000 / PPM_Send_Freq && PPM_Recv)
    {
        prev_time = time;
        return 1;
    }

    return 0;
}

/* copy the ppm frame to the buff when the ppm frame will be used */
void App_Get_PPM_Value(uint16_t ppm[8])
{
    memcpy(ppm, machine_param.ppm_val, 8);
    PPM_Recv = 0;
}

/* set the frequency of sending ppm buff to fmu */
uint8_t App_Set_PPM_Send_Freq(uint8_t freq)
{
    if (freq <= 50)
    {
        PPM_Send_Freq = freq;
        return 1;
    }
    else
    {
        return 0;
    }
}

定时器1中断程序:

/* timer1 interrupt */
void TIM1_CC_IRQHandler(void)
{
    uint16_t ic = 0;

    if (TIM_GetITStatus(TIM1, TIM_IT_CC1) == SET) 
    {
        /* Clear TIM1 Capture compare interrupt pending bit */
        TIM_ClearITPendingBit(TIM1, TIM_IT_CC1);

        ic = TIM_GetCapture1(TIM1);
        App_PPM_Status_Machine(ic);
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PX4飞控的PPM接收机 的相关文章

  • PX4/Pixhawk---uORB深入理解和应用

    The Instructions of uORB PX4 Pixhawk 软件体系结构 uORB 主题发布 主题订阅 1 简介 1 1 PX4 Pixhawk的软件体系结构 PX4 Pixhawk的软件体系结构主要被分为四个层次 xff0c
  • PX4 SITL Gazebo 仿真时 libgazebo_multirotor_base_plugin 插件运行时出错

    PX4 SITL Gazebo 仿真时 libgazebo multirotor base plugin 插件运行时出错 问题描述原因分析解决办法总结 问题描述 在 Gazebo 中进行 PX4 的软件在环仿真时 xff0c 执 make
  • PX4无人机 - 键盘控制飞行代码

    PX4无人机 键盘控制飞行代码 仿真效果 实机效果 由于图片限制5M以内 xff0c 只能上传一小段了 xff0c 整段视频请点击链接 Pixhawk 6c 无人机 键盘控制无人机 Offboard模式 核心 xff1a 发布 mavros
  • PX4 Bootloader下载及编译过程中的问题解决

    买来的雷迅的板子都是Bootloader已经烧进去了 xff0c Fireware也已经刷进去了 如果是自制的板子 xff0c 上位机根本没法识别板子 xff0c 必须先烧写下载Bootloader后编译好的bin文件 这篇记一下自己下载及
  • Ubuntu下构建PX4软件

    本搭建过程基于http dev px4 io starting building html xff0c 希望大家互相交流学习 原文 xff1a Building PX4 Software xff08 构建PX4软件 xff09 PX4 ca
  • 从Simulink到PX4——Simulink-PX4插件安装与环境搭建

    从Simulink到PX4 Simulink PX4插件安装与环境搭建 前言0 准备工作1 安装WSL2 Setting up the PX4 Toolchain on Windows3 Setting up the PX4 Tool Ch
  • PX4 ---- Mixer

    文章目录 Mixer 混合控制 作用输入输出装载混控文件MAVROS代码解析总结示例MAINAUX Mixer 混合控制 作用 经过位置控制和姿态控制后 xff0c 控制量通过 actuator controls发布 xff0c 其中 co
  • PX4模块设计之六:PX4-Fast RTPS(DDS)简介

    64 TOC PX4模块设计之六 xff1a PX4 Fast RTPS DDS 简介 基于PX4开源软件框架简明简介的框架设计 xff0c 逐步分析内部模块功能设计 PX4 Fast RTPS DDS 具有实时发布 订阅uORB消息接口
  • PX4模块设计之九:PX4飞行模式简介

    PX4模块设计之九 xff1a PX4飞行模式简介 关于模式的探讨1 需求角度1 1 多旋翼 MC multi copter 1 1 1 RC控制模式1 1 1 1 Position Mode1 1 1 2 Altitude Mode1 1
  • PX4模块设计之十六:Hardfault模块

    PX4模块设计之十六 xff1a Hardfault模块 1 Hardfault模块初始化2 Hardfault模块主程序3 Hardfault命令3 1 hardfault check status3 2 hardfault rearm3
  • PX4模块设计之二十四:内部ADC模块

    PX4模块设计之二十四 xff1a 内部ADC模块 1 内部ADC模块简介2 模块入口函数2 1 主入口board adc main2 2 自定义子命令custom command 3 内部ADC模块重要函数3 1 task spawn3
  • 接收机PPM与SBUS

    最开始是自己弄ACfly的飞控时发现插接收机有两个位置 xff0c 一个PPM一个SBUS xff0c 我想直接移植Pixhawk的接收机或者无名的接收机到ACfly模块上 我最后发现Pixhawk和无名的也是留了两个给接收机 xff08
  • 关于github px4 gps 驱动的开发的总结

    源码编译上边已经写过文章了 遇到的几个问题 1 解决虚拟机不能共享文件夹的问题 一开始虚拟机的更新 vmware tools 是灰色的 xff0c 不能点 xff0c 然后通过关掉虚拟机 xff0c 然后再开启的时候 xff0c 在没有启动
  • px4_simple_example和uorb机制

    px4 simple app PX4 Autopilot src exampes px4 simple app xff0c 这个程序是用c语言调用orb API和poll机制订阅和发布通讯数据 xff0c 但是这个例子并不是既有接收又有发送
  • 【px4】运行mavsdk中的offboard example

    运行MAVSDK中的offboard例子时无人机不执行 想控制无人机前后左右移动 xff0c 在按照官方教程实现offboard 插件的时候 发现用action插件能正常起飞和降落 但是一旦执行到offboard的插件代码的时候就会自动降落
  • px4下载指定版本的固件、git用法

    https hub fastgit org PX4 PX4 Autopilot git describe tag 查看当前版本号 git tag l 查看所有版本 xff0c 也就是打个tag git checkout v1 9 1 跳转到
  • PX4中自定义MAVLink消息(记录)

    简单记录一下这个过程 一 自定义uORB消息 这一步比较简单 xff0c 首先在msg 中新建ca trajectory msg文件 uint64 timestamp time since system start span class t
  • 四、无人机知识笔记(初级:基本运动原理)

    笔记来源于 沈阳无距科技 工业级无人机的中国名片 编程外星人 目录 一 多旋翼直升机 二 基本飞行姿态 三 多旋翼飞行原理 四 反扭力与偏航运动 五 螺旋桨 六 有刷电机和无刷电机 七 电调与PWM信号 八 动力电池 九 遥控器 十 机架设
  • 大神浅谈无人机飞控软件设计 系统性总结

    写在前面 深感自己对飞控软件 算法的知识点过于杂乱 很久没有进行系统的总结了 因此决定写几篇文章记录一些飞控开发过程的知识点 主要是针对一些软件 算法部分进行讨论 如内容有错误 欢迎指出 1 飞控软件的基本模块 无人机能够飞行主要是依靠传感
  • 在 C 中将 PPM 从 RGB 转换为 HSL [关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我需要有关 RGB 图像文件中的直方图均衡化的帮助来完成我的学术课程 我检查了之前有关直方图均衡的代码示例 但没有找到有关此问题的任何线索

随机推荐

  • VS2019 C#开发手机App环境配置和开发

    参考链接 xff1a https www dianyuan com eestar article 1284 html 上位机开发人员 xff0c 想开发APP xff0c 从头学Java xff0c 需要花的时间成本太大 xff0c 最近网
  • 华为手机通过ADB禁止系统更新和卸载自带软件

    参考链接 xff1a 电源网 刚买华为手机最烦的是每天都提示系统更新 xff0c 就算设置不提醒 xff0c 过两天又开始提醒 xff0c 不死不休 xff0c 最后还是一次手误最终还是让它得逞了 xff0c 自动更新了 xff0c 下面就
  • C#利用Socket实现C/S模式通信

    参考链接 xff1a https www dianyuan com eestar article 1330 html 首先我们要了解一下几点内容 xff1a 1 Tcp IP协议是什么 xff1f 2 Socket是什么 xff1f 3 s
  • OpenCV 图像处理 灰度化、二值化与加噪

    参考链接 xff1a https www dianyuan com eestar article 1414 html 因为要自动检测裂缝 xff0c 就考虑到了图像的二值化处理 xff0c 虽然C 可以实现二值化处理 xff0c 但是是逐个
  • ROC-RK3328-CC 开发板开箱和上手指南

    参考链接 xff1a https www dianyuan com eestar article 1424 html RK3328处理器采用了64位A53架构四核处理器 xff0c 主频为1 5GHz xff0c GPU则采用了Mali 4
  • C#中AForge库调节视频亮度、饱和度等属性

    参考链接 xff1a https www dianyuan com eestar article 1479 html 之前工作中需要调节摄像头的亮度 饱和度调节 xff0c 之前一直通过调用AForge的调节控件才能调节 xff0c 虽然可
  • Ubuntu下安装和配置Qtcreator5.15版本

    Qt选择 在官方的声明中 xff0c Qt5 15是Qt5 x的最后一个LTS版本 xff0c 增加了即将在2020年底推出的Qt6的部分新特性 xff0c 为了之后的新版本有更好的兼容性 xff0c 选择了Qt5 15 下载Qt 对于普通
  • python 获取文件夹下的文件名操作(两种)

    一 相对路径 文件存储的想对路径路径 path 61 39 data 0 39 os walk 是一个生成器 xff0c 返回三个值 xff1a 根目录 xff0c 根目录下的目录和文件列表 folder 61 os walk path 3
  • 1、串口(UART/COM/TTL/RS232/RS485)

    目录 串口简介 串行通讯制式 UART 2 1 简介 2 2 电平标准 TTL RS232 RS485 2 3 电平转换 xff08 重点讲解RS232 TTL xff09 USB转TTL USB转RS232 USB转RS485 RS232
  • 集成Python和QML

    Qt包括QML作为一种声明性地描述用户界面并使用JavaScript作为其中的脚本语言的手段 可以编写完整的独立QML应用程 序 xff0c 或将它们与C 43 43 结合使用 PyQt5允许QML以完全相同的方式与Python集成 特别是
  • 个人小型管理服务器 SVN的安装和使用方法

    1 下载TortoiseSVN客户端 官网下载地址 Downloads TortoiseSVN 注意下载跟你电脑位数匹配 64位 32位 的安装包 在页面的下面你还可以找到语言包 如图 下载完成后 应该有这些安装包 如图 接下来我们安装To
  • Ubuntu20.04下安装QtCreator 5.14.2(安装/卸载/创建快捷键/添加收藏)

    原文链接 xff1a https www dianyuan com eestar article 2864 html 都是自己原创 xff0c 发这里提高下知名度 xff0c 也帮助需要的人 一 Qt和Qt Creator的区别 Qt是C
  • WPF中自定义双滑块Slider

    项目中遇到需要双滑块的情况 xff0c 可以网上的基本都是单滑块的样式和例子 xff0c 但是双滑块的很少 xff0c 后来终于在网上找到一个大神的帖子 xff0c 通过修改和完善终于符合自己的需求 xff0c 可后来再查看代码的时候好像又
  • C#通过API对硬件进行禁用和启用

    慢慢的随着年龄的增长 xff0c 脑子越来越不够用 xff0c 而自己的收藏栏也越来越杂乱 xff0c 虽然现在的网上要啥都有 xff0c 但是没有经过自己亲手实验和整理总结 xff0c 下次需要的时候一切又要从头开始 xff0c 而电子星
  • Ubuntu下如何获取usb相机的PID/VID并打开指定的相机

    项目需求控制和打开两个USB摄像头 xff0c 并且根据相机的PID和VID来打开指定的相机 xff0c 来区分主副相机 xff0c 在Windows下可以通过AForge Video DirectShow库来实现 xff0c 但是Ubun
  • ubuntu在arm平台下编译安装opencv(亲测可用)

    X86平台安装很多软件一句话就可以搞定 xff0c 非常方便 xff0c 但是在arm平台一个简单的软件安装起来都非常费尽 xff0c 一个软件安装就要折腾好几天 下面就把安装opencv的过程记录下来 一 通过pip安装opencv xf
  • ubuntu在arm平台下编译安装Qt5.15.2和PySide2(亲测可用)

    一 安装Qt5 15 2 1 下载源码首先在官网下载Qt5 15 2的源码 xff1a https download qt io archive qt 5 15 5 15 2 single 2 先安装编译qt的环境 sudo apt get
  • ubuntu20.04安装cmake详细教程

    一 命令行安装 xff08 这种直接安装cmake xff0c 其实安装的版本都太老了 xff0c 这种方式不推荐 xff09 sudo apt install cmake 二 Cmake源码编译安装 1 更新一下g 43 43 已经安装请
  • ubuntu20.04编译安装qt5.14.2和qtcreator4.12.0

    编译qt5 14 2 本来编译安装的是qt5 15 2 xff0c 编译安装ok xff0c 一切就绪 xff0c 安装qtcreator安装后一直报错 xff0c 以下插件有错误 xff0c 无法载入 xff1a QmlDesigner
  • PX4飞控的PPM接收机

    xff08 一 xff09 原理图 xff1a PX4飞控的PPM输入捕获由协处理器完成 xff0c 接在A8引脚 xff0c 对应Timer1的通道1 xff08 二 xff09 PPM协议 xff1a PPM的每一帧数据间隔为20ms