首页 > 其他分享 >【FreeRTOS】事件组实验-改进姿态控制

【FreeRTOS】事件组实验-改进姿态控制

时间:2024-09-05 21:24:34浏览次数:6  
标签:姿态控制 FreeRTOS 中断 void WriteRegister MPU6050 改进 事件

目录


0 前言

学习视频:
【FreeRTOS 入门与工程实践 --由浅入深带你学习 FreeRTOS(FreeRTOS 教程 基于 STM32,以实际项目为导向)】 【精准空降到 00:28】 https://www.bilibili.com/video/BV1Jw411i7Fz/?p=43&share_source=copy_web&vd_source=8af85e60c2df9af1f0fd23935753a933&t=28

参考《FreeRTOS 入门与工程实践(基于 DshanMCU-103).pdf》

  • 《第 10 章 同步互斥与通信》
  • 《第 14 章 事件组(event group)》

1 事件组实验_改进姿态控制

本节源码:在"25_eventgroup_and"的基础上,改出:26_eventgroup_mpu6050

2 改进思路

以前的程序框图

在这里插入图片描述

  • 这里的思路不是使用中断来操作MPU6050,我们是创建了一个任务,读取I2C,但是读取I2C这个操作很耗时间,就需要放到任务里去完成,这没有问题的
  • 那我们怎么样让这个任务及时获得我们摇晃的动作呢?
  • 我们用的是vTaskDelay,使其50ms

改进思路如下:

  • 我们可以使用中断,在中断里唤醒任务,在任务里读取I2C,读到数据之后再写队列,把数据写到队列3去,这里会同时写队列集,这个InputTask就会获得队列3的句柄,然后读取队列3得到摇晃的数据,最后去控制游戏。
  • 现在我们需要增加一个中断在中断里怎么唤醒任务?
  • 我们可以用事件组来唤醒:在中断里设置事件,在读I2C之前等待事件(读不到事件就一直阻塞)

这样和之前的程序相比较,现在就少了很多无谓的操作了

在这里插入图片描述

2.1 创建事件

static EventGroupHandle_t g_xEventMPU6050;  //定义MPU6050事件


/* 然后再到MPU6050_Init创建事件 */
int MPU6050_Init(void)
{
	MPU6050_WriteRegister(MPU6050_PWR_MGMT_1, 0x00);	//解除休眠状态
	MPU6050_WriteRegister(MPU6050_PWR_MGMT_2, 0x00);
	MPU6050_WriteRegister(MPU6050_SMPLRT_DIV, 0x09);
	MPU6050_WriteRegister(MPU6050_CONFIG, 0x06);
	MPU6050_WriteRegister(MPU6050_GYRO_CONFIG, 0x18);
	MPU6050_WriteRegister(MPU6050_ACCEL_CONFIG, 0x18);

	g_xQueueMPU6050 = xQueueCreate(MPU6050_QUEUE_LEN, sizeof(struct mpu6050_data));
	g_xEventMPU6050 = xEventGroupCreate();	
	return 0;
}

2.2 等待事件

然后在任务里等待事件

void MPU6050_Task(void *params)
{	
    int16_t AccX;
	struct mpu6050_data result;
	int ret;

    extern void GetI2C(void);
    extern void PutI2C(void);
    while (1)
    {    
        
        /* 等待事件 */
        /* 等待bit0 and bit1事件 */
        xEventGroupWaitBits(g_xEventMPU6050, (1<<0),    // 等待bit0 and bit1事件
                            pdTRUE,                 //  pdTRUE: 清除uxBitsToWaitFor指定的位
                            pdTRUE,                 // 都为1才可以 
                            portMAX_DELAY);         // 一定等到成功才返回
        
		/* 读数据 */
        
        GetI2C();   // 使用LCD之前,先获得互斥量。会一直等待
        ret = MPU6050_ReadData(&AccX, NULL, NULL, NULL, NULL, NULL);
        PutI2C();   // 使用LCD之后,再释放互斥量
		
        if (0 == ret)
		{
			/* 解析数据 */
			MPU6050_ParseData(AccX, 0, 0, 0, 0, 0, &result);

			/* 写队列 */
			xQueueSend(g_xQueueMPU6050, &result, 0);
		}
		
		/* delay */
		vTaskDelay(50);
	}
}


加入必要的头文件

#include "FreeRTOS.h"                   // ARM.FreeRTOS::RTOS:Core
#include "task.h"                       // ARM.FreeRTOS::RTOS:Core
#include "event_groups.h"               // ARM.FreeRTOS::RTOS:Event Groups

2.3 设置事件

在这里插入图片描述
根据原理图,我们使用PB5的外部中断用来触发,设置事件。

MPU6050的INT引脚是外部中断引脚,触发中断是高电平信号,INT引脚静息状态为低电平。所以这里我们配置上升沿触发,上拉输入

在这里插入图片描述

在这里插入图片描述

void EXTI9_5_IRQHandler(void)
{
    /* 设置事件组:bit0 */
    xEventGroupSetBits(g_xEventMPU6050, (1<<0));
}

2.4 Debug

编译下载程序,发现不能运行,我们先来检查是否使能了中断,再检查是否进入了中断,打开CubeMX发现确实没使能中断,

在这里插入图片描述
然后就报错了,说我们重复定义了

01_freertos_template\01_freertos_template.axf:
 Error: L6200E: Symbol EXTI9_5_IRQHandler multiply defined 
 (by driver_mpu6050.o and stm32f1xx_it.o).

然后编写MPU6050的设置事件组的代码

void MPU6050_Callback(void)
{
    /* 设置事件组:bit0 */
    xEventGroupSetBitsFromISR(g_xEventMPU6050, (1<<0), NULL);   //在中断里设置事件
}

声明这个文件,并且在中断回调函数里添加 case GPIO_PIN_5的情况!

extern void MPU6050_Callback(void);


void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    switch (GPIO_Pin)
    {
        case GPIO_PIN_5:
        {
            MPU6050_Callback();
            break;
        }
        case GPIO_PIN_10:
        {
            IRReceiver_IRQ_Callback();
            break;
        }

        case GPIO_PIN_12:
        {
            RotaryEncoder_IRQ_Callback();
            break;
        }

        default:
        {
            break;
        }
    }
}

2.5 设置MPU6050寄存器

设置寄存器,做初始化工作:配置中断引脚使能中断

#define	MPU6050_INT_PIN_CFG		0x37    //引脚配置
#define	MPU6050_INT_ENABLE		0x38    //中断使能

int MPU6050_Init(void)
{
	MPU6050_WriteRegister(MPU6050_PWR_MGMT_1, 0x00);	//解除休眠状态
	MPU6050_WriteRegister(MPU6050_PWR_MGMT_2, 0x00);
	MPU6050_WriteRegister(MPU6050_SMPLRT_DIV, 0x09);
	MPU6050_WriteRegister(MPU6050_CONFIG, 0x06);
	MPU6050_WriteRegister(MPU6050_GYRO_CONFIG, 0x18);
	MPU6050_WriteRegister(MPU6050_ACCEL_CONFIG, 0x18);
    
    /* 配置中断引脚 */
    MPU6050_WriteRegister(MPU6050_INT_PIN_CFG, 0);
    /* 使能中断 */
    MPU6050_WriteRegister(MPU6050_INT_ENABLE, 0xFF);

	g_xQueueMPU6050 = xQueueCreate(MPU6050_QUEUE_LEN, sizeof(struct mpu6050_data));
	g_xEventMPU6050 = xEventGroupCreate();	//创建事件
	return 0;
}

烧录程序,现在就能正常运行了,但是运行的特别快,我们在MPU6050_Task的最后取消注释vTaskDelay(50);
现在就很丝滑了

3 总结

我们实现了在中断里使用事件组改造这个程序,这个任务只有当中断写了事件之后,得到了事件,才会读取I2C,避免了一直读取I2C的数据,节省资源。

标签:姿态控制,FreeRTOS,中断,void,WriteRegister,MPU6050,改进,事件
From: https://blog.csdn.net/weixin_63135906/article/details/141938759

相关文章

  • 语义分块:改进 AI 信息检索
    RAG系统及其挑战检索增强生成的流行是有充分理由的。它允许AI系统通过结合信息检索和语言生成来回答问题。标准的RAG管道通过摄取数据、检索相关信息并使用它来生成响应来实现这一点。然而,随着数据变得越来越复杂,查询也越来越复杂,传统的RAG系统可能会面临限制。这就是语......
  • YOLOv8改进 | 注意力篇 | YOLOv8引入MSCAAttention(MSCA)注意力机制
    1. MSCA介绍1.1 摘要:我们提出了SegNeXt,一种用于语义分割的简单卷积网络架构。由于自注意力在编码空间信息方面的效率,最近基于变压器的模型在语义分割领域占据了主导地位。在本文中,我们证明卷积注意力是一种比Transformer中的自注意力机制更高效、更有效的编码上下文......
  • YOLOv8改进:CA注意力机制【注意力系列篇】(附详细的修改步骤,以及代码,CA目标检测效果由
    如果实验环境尚未搭建成功,可以参考这篇文章->【YOLOv8超详细环境搭建以及模型训练(GPU版本)】文章链接为:http://t.csdnimg.cn/8ZmAm---------------------------------------------------------------------------​------------------------------------------------------1......
  • freeRTOS源码解析4--task.c 2
    4、task.c解析时隔两年,还是决定继续把这个系统解析完成,有始有终。不过这次源码又从官网上下载了最新的,可能和我以前看的略有区别,但应该基本不影响理解。接下来正式开始。4.1.3新增或是遗漏的两个宏1/*ReturnspdTRUEifthetaskisactivelyrunningandnotsch......
  • PointNet++改进策略 :模块改进 | PAConv,位置自适应卷积提升精度
    题目:PAConv:PositionAdaptiveConvolutionwithDynamicKernelAssemblingonPointClouds来源:CVPR2021机构:香港大学论文:https://arxiv.org/abs/2103.14635代码:https://github.com/CVMI-Lab/PAConv前言PAConv,全称为位置自适应卷积(PositionAdaptiveConvolution),是一种......
  • 【FreeRTOS】事件组的本质
    目录0前言1事件组讲解2事件组概念与操作2.1事件组的概念2.2事件组的操作3事件组函数3.1创建3.2删除3.3设置事件3.4等待事件3.5同步点4示例:广播5示例:等待任意一个事件6示例:等待多个事件都发生0前言学习视频:【FreeRTOS入门与工程实践--由浅......
  • 【算法改进】离散分数阶Caputo方法克服局部最优陷阱:蝠鲼觅食优化算法案例研究
    目录1.摘要2.离散分数阶Caputo方法3.基于Caputo定义的分数阶蝠鲼觅食优化算法4.结果展示5.参考文献6.代码获取1.摘要增强元启发式(MH)优化算法的探索和开发阶段是避免局部最优的关键,本工作提出了一种新的蝠鲼觅食优化算法变体,用于全局优化问题、工程设计优化问题和......
  • YOLOv10改进系列,YOLOv10替换主干网络为ShuffleNetV2
    原论文摘要目前,神经网络架构设计主要依赖于计算复杂度的间接指标,即浮点运算次数(FLOPs)。然而,直接指标(如速度)还取决于其他因素,如内存访问成本和平台特性。因此,本研究建议在目标平台上评估直接指标,而不仅仅考虑FLOPs。基于一系列受控实验,本研究提出了若干高效网络设计的实用......
  • 如何改进yolov8网络-结合代码从模型结构改进(附源码)
    第一天:挖掘YOLOv8的潜力:从创新角度分析关键瓶颈引言YOLOv8作为最新一代的目标检测框架,在性能上有了显著提升。然而,为了进一步挖掘其潜力,我们需要从模型的创新点出发,结合代码,详细分析可能存在的瓶颈。这不仅有助于理解YOLOv8的局限性,也为后续优化提供了具体的方向。1.模......
  • 全网歌词搜索自动下载工具(改进版)
    利用python获取酷我音乐歌词,实现搜索、自动下载:输入搜索关键词,返回格式化搜索结果:选择目标歌曲,自动搜索、输出歌词:回车即可自动保存歌词(lrc文件)到本地:保存本地效果:.lrc(.srt、.ass等)文件可以在本地有对应的音频文件时提供对应字幕,实现本地离线带字幕听歌。exe获取......