当前位置: 首页 > article >正文

[项目]基于FreeRTOS的STM32四轴飞行器: 八.遥控器摇杆

基于FreeRTOS的STM32四轴飞行器: 八.遥控器摇杆

  • 一.摇杆数据的扫描
  • 二.处理摇杆数据
  • 三.微调按键处理

一.摇杆数据的扫描

下面摇杆初始化时,启动了ADC-DMA进行了采集,已经开始转换直接将数据通过DMA存入buff数组中:

static uint16_t buff[4] = {0};
/*** @description: 摇杆初始化* @return {*}*/
void Inf_JoyStickAndKey_Init(void)
{debug_printfln("摇杆和按键数据的初始化 开始");/* 1. ADC校准 */HAL_ADCEx_Calibration_Start(&hadc1);/* 2. 启动ADC转换 */HAL_ADC_Start_DMA(&hadc1, (uint32_t *)buff, 4);debug_printfln("摇杆和按键数据的初始化 结束");
}

扫描摇杆数据时,直接从缓冲区中扫描就行了:
注意取数据要根据配置的Rank。
在这里插入图片描述
定义摇杆数据:
com_config.h使用int16防止数据突变。

typedef struct
{int16_t THR; /* 油门 */int16_t PIT; /* 俯仰 */int16_t ROL; /* 横滚 */int16_t YAW; /* 偏航 */uint8_t isPowerDown; /* 是否关机: 1:关机 0:不关机 */uint8_t isFixHeight; /* 是否翻转定高的状态 */
} JoyStick_Struct;

扫描摇杆数据:

/**
* @description: 扫描摇杆数据
* @return {*}
*/
void Inf_JoyStickAndKey_JoyStickScan(void)
{joyStick.THR = buff[0];joyStick.YAW = buff[1];joyStick.PIT = buff[2];joyStick.ROL = buff[3];
}

创建摇杆处理任务:
先定义一些任务参数。

/* 4. 摇杆处理任务 */
void joyStickTask(void *args);
#define JOY_STICK_TASK_NAME "joy_stick_task"
#define JOY_STICK_TASK_STACK 256
#define JOY_STICK_TASK_PRIORITY 7
TaskHandle_t joyStickTaskHandle;
#define JOY_STICK_EXEC_CYCLE 4/* 4. 摇杆处理任务 */
xTaskCreate(joyStickTask,JOY_STICK_TASK_NAME,JOY_STICK_TASK_STACK,NULL,JOY_STICK_TASK_PRIORITY,&joyStickTaskHandle);

测试打印摇杆数据:
在这里插入图片描述

/* 4. 摇杆处理 */
void joyStickTask(void *args)
{vTaskDelay(500);debug_printfln("摇杆处理任务开始调度");uint32_t preTime = xTaskGetTickCount();while(1){Inf_JoyStickAndKey_JoyStickScan();Com_Config_PrintJoyStick("a");vTaskDelayUntil(&preTime, JOY_STICK_EXEC_CYCLE);}
}

观察打印数据全部为0:
因为要先启动ADC采集数据。
在这里插入图片描述
在启动任务前启动处理模块:
在这里插入图片描述
在这里插入图片描述
这时可以打印数据:
观察发现数据有一些极性相反。
在这里插入图片描述

二.处理摇杆数据

摇杆极性和范围的处理
处理摇杆数据范围0-4095转换为0-1000

/*** @description: 处理摇杆数据的极性和范围* @return {*}*/
static void App_DataProcess_JoyStickPolarityAndRange(void)
{/* 1. 处理极性   [4095, 0]  => [0, 1000](4095 -  [4095, 0]) / 4.095(4095 -  [4095, 0]) / (4095 / 1000)(4095 -  [4095, 0]) * 1000 / 40951000 - [4095, 0] * 1000 / 4095*/joyStick.THR = 1000 - joyStick.THR * 1000 / 4095;joyStick.ROL = 1000 - joyStick.ROL * 1000 / 4095;joyStick.PIT = 1000 - joyStick.PIT * 1000 / 4095;joyStick.YAW = 1000 - joyStick.YAW * 1000 / 4095;
}

处理摇杆数据:

/*** @description: 处理摇杆数据* @return {*}*/
void App_DataProcess_JoyStickDataProcess(void)
{/* 1. 扫描摇杆 */Inf_JoyStickAndKey_JoyStickScan();/* 2. 极性和范围处理 */App_DataProcess_JoyStickPolarityAndRange();Com_Config_PrintJoyStick("2");}

观察发现该数据在默认情况下会有误差值,需要进行校准
在这里插入图片描述
摇杆数据校准:
想办法求出数据偏移量长按按键减去偏移量进行校准。
在Config.c中定义存储摇杆偏移量的结构体:
在这里插入图片描述
计算偏移量:

/*** @description: 计算摇杆的偏移量* @return {*}*/
static void App_DataProcess_JoyStickCaclBias(void)
{joyStickBias.THR = 0;joyStickBias.ROL = 0;joyStickBias.YAW = 0;joyStickBias.PIT = 0;for(uint8_t i = 0; i < 100; i++){Inf_JoyStickAndKey_JoyStickScan();App_DataProcess_JoyStickPolarityAndRange();joyStickBias.THR += (joyStick.THR - 0);   /* 0值校准 */joyStickBias.PIT += (joyStick.PIT - 500); /* 中值校准 */joyStickBias.YAW += (joyStick.YAW - 500);joyStickBias.ROL += (joyStick.ROL - 500);vTaskDelay(10);}joyStickBias.THR /= 100;joyStickBias.PIT /= 100;joyStickBias.ROL /= 100;joyStickBias.YAW /= 100;// Com_Config_PrintJoyStickBias("bias 2");
}

校准:

/*** @description: 对摇杆数据做校准* @return {*}*/
static void App_DataProcess_JoystickWithBias(void)
{/* 叠加偏移量 */joyStick.THR -= joyStickBias.THR;joyStick.PIT -= joyStickBias.PIT;joyStick.ROL -= joyStickBias.ROL;joyStick.YAW -= joyStickBias.YAW;/* 对校准后的数据做限幅处理 */joyStick.THR = LIMIT(joyStick.THR, 0, 1000);joyStick.PIT = LIMIT(joyStick.PIT, 0, 1000);joyStick.ROL = LIMIT(joyStick.ROL, 0, 1000);joyStick.YAW = LIMIT(joyStick.YAW, 0, 1000);
}

在打印数据时出现BUG,数值不正确:
在这里插入图片描述
原因是扫描摇杆值后未对极性和范围处理,数值错误。
在这里插入图片描述
解决:
在执行完扫描后执行极性和范围处理函数,之后再计算偏移量。
在这里插入图片描述
在按键处理时,将该函数放在临界区中可以避免在长按时,任务调度到摇杆扫描:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

三.微调按键处理

在摇杆结构体中添加isPowerDown和isFixHeight:
在这里插入图片描述
在按键处理函数中继续添加关机和定高功能:
在这里插入图片描述
继续添加微调按钮:
保持飞行稳定不偏,将需要微调的数据直接加到偏移量中,之后减去偏移量可以达到效果。
在这里插入图片描述

相关文章:

[项目]基于FreeRTOS的STM32四轴飞行器: 八.遥控器摇杆

基于FreeRTOS的STM32四轴飞行器: 八.遥控器摇杆 一.摇杆数据的扫描二.处理摇杆数据三.微调按键处理 一.摇杆数据的扫描 下面摇杆初始化时&#xff0c;启动了ADC-DMA进行了采集&#xff0c;已经开始转换直接将数据通过DMA存入buff数组中&#xff1a; static uint16_t buff[4] …...

附下载 | 2024 OWASP Top 10 基础设施安全风险.pdf

《2024 OWASP Top 10 基础设施安全风险》报告&#xff0c;由OWASP&#xff08;开放网络应用安全项目&#xff09;发布&#xff0c;旨在提升企业和组织对基础设施安全风险、威胁与漏洞的意识&#xff0c;并提供高质量的信息和最佳实践建议。报告列出了2024年最重要的10大基础设施…...

Pytorch的一小步,昇腾芯片的一大步

Pytorch的一小步&#xff0c;昇腾芯片的一大步 相信在AI圈的人多多少少都看到了最近的信息&#xff1a;PyTorch最新2.1版本宣布支持华为昇腾芯片&#xff01; 1、 发生了什么事儿&#xff1f; 在2023年10月4日PyTorch 2.1版本的发布博客上&#xff0c;PyTorch介绍的beta版本…...

C语言操作MySQL从入门到精通

大家好&#xff0c;我是 V 哥。今天给大家整理的内容是关于使用 C 语言操作 MySQL 数据库的详细介绍&#xff0c;从入门到精通&#xff0c;并配有案例代码和注释&#xff0c;帮助小白快速上手。 基本操作 1. 环境准备 在开始之前&#xff0c;你需要安装 MySQL 数据库和 MySQ…...

【从零开始学习计算机科学】编译原理(五)语法制导翻译

【从零开始学习计算机科学】编译原理(五)语法制导翻译 语法制导翻译语法制导定义SDDSDD的求值顺序两类重要的SDD语法制导的翻译方案SDTSDT的实现L属性定义的SDT左递归翻译方案语法制导翻译 语法表述的是语言的形式,或者说是语言的样子和结构。而程序设计语言中另一方面,是…...

uniapp uview 1.0 跨域h5配置多个代理、如何请求接口

参考文章&#xff1a;uniapp uView1.0跨域h5配置多个代理 官方手册&#xff1a;http 请求 项目中使用&#xff1a; 参考其他博主的文章是在manifest.json中配置代理&#xff0c;但在官方的手册中是直接在script请求的&#xff0c;我尝试请求了下没问题&#xff0c;上线后也不…...

化工厂防爆气象站:为石油化工、天然气等领域提供安全保障

【TH-FB02】在石油化工、天然气等高危行业中&#xff0c;安全生产是至关重要的。这些行业常常面临着易燃易爆、有毒有害等潜在风险&#xff0c;因此&#xff0c;对气象条件的监测和预警显得尤为重要。化工厂防爆气象站作为一种专门设计用于这些特殊环境的气象监测设备&#xff…...

Android Glide 缓存模块源码深度解析

一、引言 在 Android 开发领域&#xff0c;图片加载是一个极为常见且关键的功能。Glide 作为一款被广泛使用的图片加载库&#xff0c;其缓存模块是提升图片加载效率和性能的核心组件。合理的缓存机制能够显著减少网络请求&#xff0c;降低流量消耗&#xff0c;同时加快图片显示…...

Mac安装Neo4j图数据库

通过Homebrew 安装&#xff08;推荐&#xff09; 打开mac终端&#xff1a; 1. 安装 Homebrew&#xff08;如果尚未安装&#xff09; /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"2. 安装 Neo4j brew insta…...

《A Gentle Introduction to Graph Neural Networks》-GNN的综述性论文

目录 一、什么数据可以表示成一张图 &#xff08;1&#xff09;什么是图&#xff1f; &#xff08;2&#xff09;如何表示图的属性 &#xff08;3&#xff09;images as graphs&#xff08;将图片表示为图&#xff09; &#xff08;4&#xff09;text as graphs&#xff08…...

[023-01-40].第40节:组件应用 - OpenFeign与 Sentinel 集成实现fallback服务降级

SpringCloud学习大纲 一、需求说明&#xff1a; 需求1&#xff1a;通过fallback属性进行统一配置 a.问题分析&#xff1a; 1.需要实现cloudalibaba-consumer-nacos-order83模块通过OpenFeign调用cloudalibaba-provider-payment9001 83服务通过OpenFeign调用 9001微服务&…...

设计模式-结构型模式-装饰器模式

概述 装饰器模式 : Decorator Pattern : 是一种结构型设计模式. 作用 &#xff1a; 允许你动态地给对象添加功能或职责&#xff0c;而无需修改其原始类的代码,非常的符合 开闭原则。 实现思路 &#xff1a;通过创建一个包装对象&#xff08;即装饰器&#xff09;&#xff0c;来…...

RK3588 编译 openssl

在编译 OpenSSL 时,你需要确保你的系统环境已经配置好了所有必要的依赖和编译工具。下面是一般步骤和一些常见问题的解决方案,特别是在使用 RK3588 这类的 ARM 处理器上。 1. 安装依赖 首先,你需要安装编译 OpenSSL 所需的依赖。这通常包括编译器(如 GCC)、make 工具、Per…...

Git前言(版本控制)

1.Git 目前世界上最先进的分布式版本控制系统。 git官网&#xff1a;https://git-scm.com/ 2.版本控制 2.1什么是版本控制 版本控制(Revision control)是一种在开发的过程中用于管理我们对文件、目录或工程等内容修改历史&#xff0c;方便查看更改历史记录备份以便恢复以前…...

visual studio配置opencv

文章目录 step1 下载opencvstep2 配置包含目录step 3 配置链接器step4 配置环境变量并重启vs2022step5 检查代码 step1 下载opencv 下载 opencv-4.8.0-windows.exe https://cloud.189.cn/web/share?codefUnqEb7naUra step2 配置包含目录 step 3 配置链接器 step4 配置环境变…...

docker修改daemon.json文件后无法启动

1.问题描述 使用阿里云docker镜像安装的docker&#xff0c;安装成功后默认可以启动。但是修改daemon.json配置后docker服务无法启动&#xff0c;提示如下错误&#xff1a; 从上图发现&#xff0c;docker服务默认使用阿里docker镜像仓库 2.解决方法 根据提示找到docker服务目…...

Linux网络:网络与操作系统1

本文是介绍网络的基本结构&#xff0c;以及和OS之间有什么关系 OSI七层模型 引入 使用网络是为了解决信息的长距离传送&#xff0c;那就需要解决四个问题&#xff1a; 接收方如何使用数据传输的可靠性主机如何定位数据包在局域网如何转发 人们选择用网络协议&#xff08;t…...

Manus(一种AI代理或自动化工具)与DeepSeek(一种强大的语言模型或AI能力)结合使用任务自动化和智能决策

一、Manus与DeepSeek差异 十分好奇DeepSeek和Manus究竟谁更厉害些&#xff0c;DeepSeek是知识型大脑&#xff0c;Manus则是全能型执行者。即DeepSeek专注于语言处理、知识整合与专业文本生成。其核心优势在于海量参数支持的深度学习和知识推理能力&#xff0c;例如撰写论文、润…...

Python个人学习笔记(14):函数(匿名函数、内置函数(下)、三元表达式)

九、匿名函数 lambda表达式 语法规则&#xff1a; 变量 lambda 参数1,参数2,…:返回值 例&#xff1a;用lambda简化下述操作 def func(a,b):return ab ret func(1, 2) print(ret)代码&#xff1a; fn lambda a,b:ab print(fn) print(fn(12,13))结果&#xff1a; <fun…...

姚安娜新剧瘦了一圈,《仁心俱乐部》急诊医生顾诗宜在线上岗

《仁心俱乐部》在芒果 TV 播出&#xff0c;湖南卫视金鹰独播剧场也随之播出&#xff0c;这一剧集受到了不少观众的关注。姚安娜在剧中饰演的急诊科医生顾诗宜&#xff0c;她为患者检查身体时动作娴熟&#xff0c;与患者沟通时展现出的耐心和专注&#xff0c;都展现出很高的专业…...

【PyCharm】Python和PyCharm的相互关系和使用联动介绍

李升伟 整理 Python 是一种广泛使用的编程语言&#xff0c;而 PyCharm 是 JetBrains 开发的专门用于 Python 开发的集成开发环境&#xff08;IDE&#xff09;。以下是它们的相互关系和使用联动的介绍&#xff1a; 1. Python 和 PyCharm 的关系 Python&#xff1a;一种解释型、…...

【ES6】基础特性总结

概述 仅个人使用&#xff0c;复习ES6的笔记&#xff0c;比较粗糙&#xff0c;仅适用于浏览器端。 数据类型 ES6&#xff08;ECMAScript 2015&#xff09;引入了一些新的数据类型和对现有数据类型的扩展。以下是ES6中数据类型的一个简要总结表格&#xff1a; 数据类型描述Nu…...

串口数据记录仪DIY,体积小,全开源

作用 产品到客户现场出现异常情况&#xff0c;这个时候就需要一个日志记录仪、黑匣子&#xff0c;可以记录产品的工作情况&#xff0c;当出现异常时&#xff0c;可以搜集到上下文的数据&#xff0c;从而判断问题原因。 之前从网上买过&#xff0c;但是出现过丢数据的情况耽误…...

无障碍阅读(Web Accessibility)NVDA打开朗读查看器后,enter键不生效的原因

用NVDA测试Web Accessibility时&#xff0c;打开朗读查看器&#xff0c;enter键会无效&#xff0c;而不打开测试器&#xff0c;就没有问题&#xff0c;很大原因是被应用的元素不是可聚焦的&#xff0c;解决方法尝试&#xff1a; 将标签改为可聚焦的语义化标签&#xff0c;如 b…...

基于docker+python+paddleocr构建自己本地化ocr服务

1、使用FastAPI创建服务实例 1.1、正常程序 from fastapi import FastAPI, UploadFile, File, HTTPException from typing import List from paddleocr import PaddleOCR import numpy as np from PIL import Image import io import loggingapp FastAPI(title"游戏截图…...

【视频】V4L2、ffmpeg、OpenCV中对YUV的定义

1、常见的YUV格式 1.1 YUV420 每像素16位 IMC1:YYYYYYYY VV-- UU– IMC3:YYYYYYYY UU-- VV– 每像素12位 I420: YYYYYYYY UU VV =>YUV420P YV12: YYYYYYYY VV UU =>YUV420P NV12: YYYYYYYY UV UV =>YUV420SP(最受欢迎格式) NV21: YYYYYYYY VU VU =>YUV420SP…...

歌词相关实现

歌词相关 歌词数据模型&#xff1a; // Lyric.swift class Lyric: BaseModel {/// 是否是精确到字的歌词var isAccurate:Bool false/// 所有的歌词var datum:Array<LyricLine>! }// LyricLine.swift class LyricLine: BaseModel {/// 整行歌词var data:String!/// 开始…...

51单片机Proteus仿真速成教程——P1-软件与配置+Proteus绘制51单片机最小系统+新建程序模版

前言&#xff1a;本文主要围绕 51 单片机最小系统的绘制及程序模板创建展开。首先介绍了使用 Proteus 绘制 51 单片机最小系统的详细步骤&#xff0c;包括软件安装获取途径、工程创建、器件添加&#xff08;如单片机 AT89C51、晶振、电容、电阻、按键等&#xff09;、外围电路&…...

使用 pytesseract 进行 OCR 识别:以固定区域经纬度提取为例

引言 在智能交通、地图定位等应用场景中&#xff0c;经常会遇到需要从图像中提取经纬度信息的需求。本篇文章将介绍如何利用 Python 的 pytesseract 库结合 PIL 对图像进行预处理&#xff0c;通过固定区域裁剪&#xff0c;来有效地识别出图像上显示的经纬度信息。 1. OCR 与 …...

【18】单片机编程核心技巧:变量赋值与高位填充机制

【18】单片机编程核心技巧&#xff1a;变量赋值与高位填充机制 七律 变量赋值探秘 单字赋多字疑云开&#xff0c;高位零填自天来。 清零保守虽稳妥&#xff0c;强制转换更悠哉。 实验验证真章显&#xff0c;编译器间无异态。 嵌入式海行舟稳&#xff0c;类型分明避坑台。 注释…...