写在前面

调试完光电传感器之后就把他装到车子的前部和后部,在这篇文章里我将分享STM32F427IIH6芯片(RoboMaster A型)上运行的FreeRTOS系统通过串口+DMA方式接收传感器数据并且根据反馈数据调整机器人姿态的方法

场地图如下:

 机器人后面的光电传感器:

b

机器人前面的光电传感器: 


流程概述

流程图上图是数据感知和姿态调整的大致流程图,接下来我将结合程序来为大家进行介绍


程序介绍

首先最重要的就是数据的感知了,在整个工程中总共跑了2个线程,分别是StartDefaultTaskStartCalcucrossTask,StartCalcucrossTask里面主要是数白线的交叉点,这个我会在后续的博客中进行分享,StartDefaultTask完成了机器人底盘的大部分功能,包括开发板和树莓派的通信,CAN总线驱动c620电调,接收光电传感器的反馈数据等,因为芯片设置的时候是用串口+DMA接收光电传感器数据,因此在初始化串口的时候设置了DMA中断,一旦开发板接受到了光电传感器反馈的数据之后,开发板的DMA模块会自动把数据写到对应的模块里面,这在程序里面对应的回调函数是下列代码段:

这部分主要参考的是这篇文章:

STM32 Uart @调试命令的实现

uint8_t RxLenHi, RxLenlo;  
void HAL_UART_IdleCpltCallback(UART_HandleTypeDef *huart)
{//uart6Rx和uart7Rx是2个数组,分别用来存储前后光电传感器传回来的数据
    __HAL_UART_CLEAR_IDLEFLAG(huart);
 
		if( huart == &huart8)
		{
			test3++;
			HAL_UART_Receive_DMA(&huart8, uart8Rx, buffer_size);  
		
			uart8RxLength = buffer_size-__HAL_DMA_GET_COUNTER(&hdma_uart8_rx);     
			if(uart8Rx[0]=='@'
			&&uart8Rx[1]=='c'
			&&uart8Rx[2]=='m'
			&&uart8Rx[3]=='d') 
			{
				if(!SERDEB_CmdValid())
					SERDEB_PushCmd(uart8Rx, uart8RxLength);
			}
			__HAL_DMA_DISABLE(&hdma_uart8_rx);
			HAL_GPIO_TogglePin(GPIOG,GPIO_PIN_8);    
		}
		
                if( huart == &huart7)
		{		
			__HAL_DMA_DISABLE(&hdma_uart7_rx);  
			HAL_UART_Receive_DMA(&huart7, uart7Rx, buffer_size); 
			__HAL_DMA_DISABLE(&hdma_uart7_rx);
		}
			
		if( huart == &huart6)
		{
			__HAL_DMA_DISABLE(&hdma_usart6_rx);
			HAL_UART_Receive_DMA(&huart6, uart6Rx, buffer_size); 
			__HAL_DMA_DISABLE(&hdma_usart6_rx);
		}
                                
}

上述代表表示了uart6和uart7就是分别接收前后2个光电传感器数据的串口,uart8是跟树莓派通信的串口,暂时不去管他。可以很明显的看到uart6和uart7都是通过DMA方式将数据从外围设备搬运到芯片里的 在接收到数据之后就是对于数据的处理了,让我们先来看一下这个示意图 

虽然一个光电传感器会传回来16个循迹灯的数据,但是并不是所有的都是有用的数据,因为我只选了4个灯做为我纠正机器人姿态的依据 S1和S2

上面5个灯最里面那个都是不用的,而是通过S1和S2两组灯来进行机器人的姿态纠正,接下来我通过举例子来进行说明

当车子向左偏离航线的时候,S1左边的灯会亮,S2右边的灯会灭,此时左轮加速,右轮减速,后面2个轮速度不变,以纠正姿态

当车子向右偏离航线的时候,S2左边的灯会灭,S1右边的灯会亮,此时右轮加速,左轮减速,后轮2个轮速度不变,以纠正姿态

函数的调用是这样的:set_speed(motor_b_r,mid_sen1,motor_b_l,mid_sen2); 那么上述这些变量是从哪里来的呢?

		mid_sen1[motor_f_r]=((~uart7Rx[1])&0x40)>>6;
		mid_sen1[motor_f_l]=((~uart7Rx[1])&0x10)>>4;	
		mid_sen1[motor_b_l]=((~uart6Rx[0])&0x08)>>3;
		mid_sen1[motor_b_r]=((~uart6Rx[0])&0x02)>>1;	
		
		mid_sen2[motor_f_r]=(uart7Rx[1]&0x80)>>7;	
		mid_sen2[motor_f_l]=(uart7Rx[1]&0x08)>>3;	
		mid_sen2[motor_b_l]=(uart6Rx[0]&0x10)>>4;	
		mid_sen2[motor_b_r]=(uart6Rx[0]&0x01);	

uartRx6和uartRx7就是接收光电传感器的数据的数组,uartRx6[0]是后面那个光电传感器数据的低8位,uart6Rx[1]是后面那个光电传感器数据的高8位,uart7Rx是前面的光电传感器,数据格式相同。mid_sen1数组就是S1,mid_sen2数组就是S2


效果展示

走直线


                                               (づ ̄3 ̄)づ╭❤~一键三连,这次一定(๑•̀ㅂ•́)و✧ QQ图片20210126200222