辅助行走机器人开发 —— 下位机控制

news2024/11/15 4:17:10

文章目录

  • 总体设计
  • 硬件选型
  • 控制模式
  • 程序流程
    • 1 初始化
    • 2 FreeRTOS
      • Balance_task
      • MPU6050_task
      • Show_task
      • Led_task
      • Ps2_task
      • Data_task
    • 3 中断
      • 串口中断


辅助行走机器人开发项目总结

总体设计

项目分为语音模式、导航模式和手动模式。

  • 语音模式、导航模式为ROS下发控制指令;
  • 手动模式由手柄下发运动指令。

在这里插入图片描述

硬件选型

工控机:NUC11
传感器:单线雷达rplidar a1、Kinect
MCU: STM32F407
IMU: MPU6050
电机驱动:D50A(单片机通过电机驱动电路输出PWM波对电机速度进行控制)
编码器

控制模式

  • 手柄控制
  • APP控制
  • ROS控制(串口通信)

关闭JTAG接口 提高鲁棒性
打开SWD接口调试

中断优先级分组设置
初始化LED、蜂鸣器、OLED
使能开关初始化(车辆是否接收控制开关)
复位按键和用户按键初始化(更新陀螺仪零点)
串口2、3(ROS使用串口3)初始化

uart3_init(115200);

程序流程

1 初始化

硬件初始化:

systemInit();

中断初始化

  1. 串口2:APP(蓝牙)
  2. 串口3:ROS控制命令获取

2 FreeRTOS

目的:
创建多个任务并行运行,并分配频率和优先级(单片机资源有限,使用RTOS框架)单片机本身中断的优先级最高。

FreeRTOS初始化task

// 创建任务
xTaskCreate((TaskFunction_t )start_task,            
			(const char*    )"start_task",             
			(uint16_t       )START_STK_SIZE,        // 任务堆栈大小
			(void*          )NULL,                  // 传递参数
			(UBaseType_t    )START_TASK_PRIO,       // 优先级   
			(TaskHandle_t*  )&StartTask_Handler);   // 任务句柄				
vTaskStartScheduler();  // 开启任务调度


void start_task(void *pvParameters)
{
    taskENTER_CRITICAL(); //Enter the critical area 
	
    //Create the task 
	xTaskCreate(Balance_task,  "Balance_task",  BALANCE_STK_SIZE,  NULL, BALANCE_TASK_PRIO,  NULL);	
	xTaskCreate(MPU6050_task,  "MPU6050_task",  MPU6050_STK_SIZE,  NULL, MPU6050_TASK_PRIO,  NULL);	
    xTaskCreate(show_task,     "show_task",     SHOW_STK_SIZE,     NULL, SHOW_TASK_PRIO,     NULL); 
    xTaskCreate(led_task,      "led_task",      LED_STK_SIZE,      NULL, LED_TASK_PRIO,      NULL);	
    xTaskCreate(pstwo_task,    "PSTWO_task",    PS2_STK_SIZE,      NULL, PS2_TASK_PRIO,      NULL);	
    xTaskCreate(data_task,     "DATA_task",     DATA_STK_SIZE,     NULL, DATA_TASK_PRIO,     NULL);	
   
    vTaskDelete(StartTask_Handler); 
    taskEXIT_CRITICAL();          
}

子任务(如Balance_task、MPU6050_task等)不会被直接删除。它们会在任务执行完毕后自动退出,或者由其他任务或中断删除。

Balance_task

运动控制任务
10ms 4级优先

获取编码器的数据Get_Velocity_Form_Encoder(),通过运动学正解算转换为速度,之后发送给上位机进行里程计解算。

以上任何一个地方获取控制命令后,都会进入Balance_task()中进行控制
将控制命令转换为三轴的目标速度,输入Drive_Motor()运动学分析函数,之后运动学逆解算计算出车轮所需速度(pwm)。

// 解算计算得出的pwm
Set_Pwm(-MOTOR_A.Motor_Pwm,-MOTOR_B.Motor_Pwm, 0);
// 设置pwm
void Set_Pwm(int motor_a,int motor_b,int servo)
{

	if(motor_a<0)		AIN2=0,		AIN1=1;   
	else 	            AIN2=1,		AIN1=0;

	TIM_SetCompare4(TIM8,myabs(motor_a));
	
	if(motor_b>0)		BIN2=0,		BIN1=1;   
	else 	            BIN2=1,		BIN1=0;

	TIM_SetCompare3(TIM8,myabs(motor_b));
}

TIM_SetCompare3()用来设置定时器的比较值,从而控制对应通道的PWM信号的占空比。

MPU6050_task

加速度角速度获取任务
100Hz 3级优先

使用I2C通信读取MPU6050的X、Y、Z轴加表和陀螺仪的原始数据,分别保存在acc、gyro数组中。读取过程中,高位和低位数据通过位移操作进行合并。
获取陀螺仪数据

gyro[0]=(I2C_ReadOneByte(devAddr,MPU6050_RA_GYRO_XOUT_H)<<8)+I2C_ReadOneByte(devAddr,MPU6050_RA_GYRO_XOUT_L);    
gyro[1]=(I2C_ReadOneByte(devAddr,MPU6050_RA_GYRO_YOUT_H)<<8)+I2C_ReadOneByte(devAddr,MPU6050_RA_GYRO_YOUT_L);   
gyro[2]=(I2C_ReadOneByte(devAddr,MPU6050_RA_GYRO_ZOUT_H)<<8)+I2C_ReadOneByte(devAddr,MPU6050_RA_GYRO_ZOUT_L);   

之后将加表和陀螺仪数据发送给上位机进行里程计解算。

Show_task

OLED显示和串口3(默认开启,与ROS通信)发送数据任务、蜂鸣器叫任务
50Hz 3级优先

显示当前控制模式,默认ROS

Led_task

LED闪烁
3级优先

Ps2_task

获取手柄控制任务
100Hz 4级优先

读取按键值,读取遥感的模拟量

Data_task

串口3(ROS)发送给上位机
20Hz 4级优先

发送数据:
帧头1byte、底盘使能标识1byte、三轴速度23byte、三轴加速度23byte、三轴角速度2*3byte、数据校验位1byte、帧尾1byte。
串口一次只能发送一个 8 位(1 个字节)的数据,2 个字节(short)的数据会拆分成高 8 位和低 8 位发送。

Send_Data.buffer[n]=Send_Data.Sensor_Str.Gyroscope.X_data>>8;
Send_Data.buffer[n+1]=Send_Data.Sensor_Str.Gyroscope.X_data;

之后发送22byte的数据:

void USART3_SEND(void)
{
  unsigned char i = 0;	
	for(i=0; i<22; i++)
	{
		usart3_send(Send_Data.buffer[i]);
	}	 
}

// 子函数
void usart3_send(u8 data)
{
	USART3->DR = data;
	while((USART3->SR&0x40)==0);	
}

USART3->DR = data;: 这行代码将传递给函数的 data 值写入 USART3 外设的数据寄存器 DR(Data Register)。这会将数据加载到 USART3 的发送缓冲区中,准备发送。

while((USART3->SR&0x40)==0);: 这是一个循环,用于等待 USART3 外设发送完成。在 STM32 的串口通信中,发送完成时,SR(Status Register)寄存器的第6位(0x40)会被置为1。这个循环不断检查 SR 寄存器的状态,直到发送完成。

它将数据存储到 USART3 的数据寄存器,然后等待发送完成,以确保数据成功发送出去。

浮点数成1000,并强制转换位short(保留3位小数)。之后上位机端在接收到数据后,将接收到两个 8 位数据合并后转换为 short 型,在缩小一千倍来进行单位的转换。

3 中断

串口中断

usartx.c
串口2中断
APP控制
判断是否接收到数据
之后判断帧头来选择电机操作

串口3中断
生成x,z轴的目标速度
之后提供给balace_task()中的Drive_Motor()

int USART3_IRQHandler():
判断是否接收到数据

if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)

读取数据

Usart_Receive = USART_ReceiveData(USART3);

检查帧头

if(Usart_Receive == FRAME_HEADER||Count>0) 
			Count++; 
		else 
			Count=0;

数据包的长度为11

if (Count == 11){
	Count = 0;
	帧尾验证
	
}

在 7 种控制机器人方式中,ROS 的控制优先级是最高的,在任意时候 串口 3 接收到数据,则强制进入 ROS 控制模式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/713782.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java.lang.UnsupportedOperationException 异常处理

通过 json 字符串转化成的 asList &#xff0c;对该 List 进行 add 时&#xff0c;抛出异常 java.lang.UnsupportedOperationException 处理方案 List string new ArrayList<>(asList);

企业邮箱的多重用途:了解企业邮箱在工作中的重要作用

邮箱已经成为商务交流不可或缺的一部分。在企业界&#xff0c;邮箱被用于各种各样的任务&#xff0c;从内部沟通到客户服务。虽然许多组织已经转向更现代的通信方式&#xff0c;如即时消息&#xff0c;企业邮箱仍然是任何成功的商业运作的重要组成部分。以下是公司邮箱的一些主…

【小程序上传报错】message:Error: 系统错误,错误码:80058,desc of scope.userLocation is empty

根据错误信息 “Error: 系统错误&#xff0c;错误码&#xff1a;80058,desc of scope.userLocation is empty”&#xff0c;这是一个系统错误&#xff0c;错误码为80058。错误信息中提到了 scope.userLocation 的描述为空。 可能是因为在小程序中使用了 scope.userLocation 权…

5.4 服务器编程基本框架和两种高效的事件处理模式

5.4 服务器编程基本框架和两种高效的事件处理模式 服务器编程基本框架 虽然服务器种类繁多&#xff0c;但其基本框架都一样&#xff0c;不同之处在于逻辑处理&#xff08;比如开发Web服务器项目&#xff0c;浏览器客户端向服务端发送http请求&#xff0c;服务器对请求报文进行…

高压线路零序电流方向保护程序逻辑原理(三)

四、零序保护故障处理程序原理 零序保护逻辑程序可分为三个模块&#xff1a;快速动作部分、全相循环和非全相循环模块。这是根据零序保护的特点而设计的。任何一种高压线路保护都要求快速处理I段范围内的严重故障&#xff0c;所以零序保护与距离保护一样配有快速动作部分程序模…

分不清楚蝴蝶的种类,让AI来告诉你,基于YOLOv5开发构建轻量级蝴蝶细粒度目标检测识别系统

小时候有时间就很喜欢趁着下课放学的时间去抓蝴蝶玩&#xff0c;五彩多样的蝴蝶让人应接不暇&#xff0c;现在早就过了那个天真玩耍的年纪了&#xff0c;如今看到蝴蝶的第一反应就是这是什么蝴蝶&#xff0c;没有专业的知识支撑很难识别出来具体的种类&#xff0c;本文的主要目…

电脑bios使用的uefi启动,系统盘使用的mbr格式,为什么安装完系统无法进入?

概要 在电脑的安装系统过程中&#xff0c;我们会遇到一些问题&#xff0c;比如说使用UEFI启动但是磁盘分区使用MBR格式&#xff0c;导致系统安装完成之后无法引导。这是因为UEFI启动只支持GPT格式的磁盘分区。 在本文中&#xff0c;我们将探讨如何将磁盘转换成GPT格式&#xf…

一种新的程序在线升级的实现(学习)

介绍一种新的程序在线升级方法&#xff0c;以及程序在线升级在嵌入式系统中的应用和实现。设计将从系统原理和实现介绍该程序在线升级方法。利用串口作为通讯方式&#xff0c;自定义通讯协议。 上位机将升级文件传给下位机&#xff0c;下位机将数据解析后存储在内部Flash中。解…

用矩阵处理3D变换

Rotation 也可以把三个旋转矩阵合并为一个综合旋转矩阵: 平移和旋转结合 有时我们想要将平移和旋转结合起来&#xff0c;这样我们就可以在一次操作中同时进行两者&#xff0c;但是我们不能用3x3矩阵来做3D平移&#xff0c;只能用4x4矩阵来做&#xff0c;如下所定义&#xff1a…

尚硅谷Docker实战教程-笔记07【Docker常规安装简介】

尚硅谷大数据技术-教程-学习路线-笔记汇总表【课程资料下载】视频地址&#xff1a;尚硅谷Docker实战教程&#xff08;docker教程天花板&#xff09;_哔哩哔哩_bilibili 尚硅谷Docker实战教程-笔记01【理念简介、官网介绍、平台入门图解、平台架构图解】尚硅谷Docker实战教程-笔…

嵌入式基础知识-总线带宽

带宽&#xff0c;最容易想到的是上网用的网络带宽&#xff0c;在嵌入式软件开发中&#xff0c;也会用到带宽&#xff0c;这个带宽的含义就不一样了&#xff0c;区别是什么&#xff1f;本篇就来介绍一下&#xff0c;并通过一些例子来进行带宽的计算。 先来简单看下不同领域的带…

交叉熵和softmax

交叉熵cross-entropy loss 最大化似然函数&#xff0c;最小化负的似然对数函数 最终的交叉熵损失函数&#xff0c;最小化该loss&#xff1a; nn.BCELoss def criterion(yhat, y):out -1 * torch.mean(y*torch.log(yhat) (1-y) * torch.log(1-yhat))return outsoftmax

51单片机一氧化碳烟雾报警器mq2MQ7ADC0832采集

实践制作DIY- GC0152--- 一氧化碳烟雾报警器 基于51单片机设计------- 一氧化碳烟雾报警器 二、功能介绍&#xff1a; STC89C52单片机lcd1602adc0832mq2烟雾传感器mq7烟雾传感器蜂鸣器2个按键设定烟雾报警阈值 2个按键设定一氧化碳报警阈值 1.通过ADC0832采集MQ2烟雾输出的电…

嵌入式系统中STM32时钟系统详解

1. STM32的时钟源主要有&#xff1a; 内部时钟 外部时钟 锁相环倍频输出时钟 1.1 详细介绍 HSI(内部高速时钟) 它是RC振荡器&#xff0c;频率可以达到8MHZ&#xff0c;可作为系统时钟和PLL锁相环的输入 HSE&#xff08;外部高速时钟&#xff09; 接入晶振范围是4-16MHZ&a…

数据结构--线性表(顺序表、单链表、双链表、循环链表、静态链表)

前言 学习所记录&#xff0c;如果能对你有帮助&#xff0c;那就泰裤辣。 目录 1.线性表概念 定义 基本操作 2.顺序表 定义 顺序表的实现--静态分配 动态分配 顺序表的特点 顺序表的插入和删除 顺序表的查找 按位查找 按值查找 3.单链表 定义 单链表的初始化 不带…

112.(cesium篇)cesium地球自转+文字上下滚动

地图之家总目录(订阅之前必须详细了解该博客) 地图之家:cesium+leaflet+echart+地图数据+地图工具等相关内容的介绍 文章末尾处提供保证可运行完整代码包,运行如有问题,可“私信”博主。 效果如下所示: 112.(cesium篇)cesium地球自转+文字上下滚动 下面献上完整代码…

Kubernetes(k8s)集群搭建,完整无坑,不需要科学上网~

文章目录 写在前面一、准备三个centos7虚拟机1、创建Vagrantfile2、启动三台虚拟机3、配置centos7支持ssh登录&#xff08;所有机器&#xff09;4、修改 linux 的 yum 源&#xff08;所有机器&#xff09;5、更新并安装依赖&#xff08;所有机器&#xff09;6、安装docker&…

SPI硬件实现-GD32

SPI硬件实现-GD32 #include "w25qxx_spi.h"void w25qxx_init(void){// 使能外设时钟w25qxx_rcu_init();// IO口进行配置,使之复用为SPI0, PA4\PA5\PA6\PA7,NSS\SCK\MISO\MOSIw25qxx_io_init();// SPI0初始化w25qxx_spi_init();spi_enable(SPI0); }// 使能外设时钟…

HTTP/HTTPS 简介||HTTP 消息结构

HTTP/HTTPS 简介 HTTP 协议是 Hyper Text Transfer Protocol&#xff08;超文本传输协议&#xff09;的缩写&#xff0c;是用于从万维网&#xff08; WWW:World Wide Web &#xff09;服务器传输超文本到本地浏览器的传送协议。 HTTP 是一个基于 TCP/IP 通信协议来传递数据&a…

〖动态规划60题〗泰波纳契数列模型

文章目录 1.第N个泰波那契数&#xff08;简单&#xff09;解题流程1. 状态表示2. 状态转移方程3. 初始化dp表4. 填表顺序5. 返回值 代码编写 2.三步问题解题流程1. 状态表示2. 状态转移方程3. 初始化dp表4. 填表顺序5. 返回值 代码编写 3.使用最小花费爬楼梯解题流程1. 状态表示…