2024电子设计大赛(自动行驶小车H题)嘉立创地猛星分享

16af03e4eeeb49648bc5fdcdf8bc832a.png

一、第一个难点在于使用mspm0作为主控芯片

        不像历年来使用的msp430或者msp432,我们是直接使用的b站up主我的代码没问题的库,这个up主封装了自己的ml库,帮助我们封装好了寄存器,提供了上层接口,单片机外设的常用函数都可以很方便的直接调用。

2024电赛小白入门 手把手教你做一辆电赛小车|STM32|MSP432|PID|MPU6050_哔哩哔哩_bilibili

        关于ml库的bug问题:当时遇到的是程序编译过了,下载不进去,最离谱的是删掉一行程序就能下载进去,加上一行程序就下不进去了,当时想了很多办法,最后竟然是keil版本的问题,更新了keil版本之后就没遇到这种问题了,更新之后的版本是5.39。

二、这个题第二个难点是陀螺仪传感器的问题

        1.使用g3507芯片解算mpu6050传感器会影响编码器的测速,因为不管使用定时器中断还是使用外部中断(mpu6050的int引脚)去解算数据,因为解算数据会占用长时间的cpu,而这个长时间占用cpu会导致定时器中断那里来不及清零数据,导致速度计算出问题,从而无法使用速度环pid去调整正确的占空比。

        2.使用mpu6050传感器会产生误差,比如上电之后规定一个方向为0,旋转传感器一圈之后他会有几度的飘逸,这会产生累计误差,影响到第四问的跑四圈。产生误差的原因有温度的影响,网上流传的解决方案是使用5883磁力计,并融合卡尔曼滤波,来进行补偿。因为涉及到一些深度算法,对于没有准备过得队伍,四天三夜的时间比较紧张。

        所以我们使用的是维特的陀螺仪维特智能六轴加速度计电子陀螺仪模块姿态角度传感器高精度JY61P-tmall.com天猫

d0c6323b38ae4740a32ae39652ad441f.png

这款陀螺仪自带mcu解算,数据特别精准,而且误差  特别小,并且使用串口传递数据,通信比较简单,关于jy61的解算,可以使用串口中断来解包,依靠的这个表:

8ee2947b8c95433f8930222fc902a590.png

 三、有关小车尺寸和传感器排布。限制宽度15cm,长度25cm,要把小车做的尽量宽,可以排布巡线传感器尽量宽,我们当时使用了一个八路巡线,旁边加了两个单路巡线,总共十路巡线。其实可以十二路巡线。巡线越宽,第三问斜着走的时候越容易识别到黑线。而且,每个巡线传感器之间的间隔必须离得近,再走弯道的时候,不会出现传感器都识别不到黑线的情况,这样会大大减少代码检测的难度,直接检测不到黑线就代表出巡线区域了,不用结合定时器再来判断是否出巡线区域。巡线传感器必须用灰度传感器,红外传感器一是需要调节,二是对于红外传感器哑光布不一定能识别出来。

b805c1378990471ba568999dbd390259.png

八路灰度传感器 白黑红黄蓝绿线循迹模块 光电传感器 感为科技-淘宝网 (taobao.com)

102c0105a9804312a19de7894260780a.png

智能小车灰度巡线传感器可见白光非红外 支持arduino0 1路模拟输-淘宝网 (taobao.com)

 四、代码部分

使用状态机,仅仅使用一个标志位就能完成每个状态的转换,附上第三问shi山代码,使用一个标志位step1的不同数值,来完成状态之间的切换,大概就是这样的思路

#define middle 16500
#define error1 3000
void track_mode3()
{		
	     oled_printf(4,1,"yaw%.4f",yaw);
	     gray=track_read();
				if(step1==0)//a->c矫正
				{		
							if((yaw > 324 && yaw < 360) || (yaw > 0 && yaw < 30) )// ,第一步a-》c矫正修正yaw=321斜线预备角, 偏移时提供PWM 
							{
									motorA_dir=1;
									motorB_dir=0;
									motorA_duty(sp);					
   								motorB_duty(sp+2000);								
							}
							
							else if(yaw > 315 && yaw <= 324)
							{ 
								step1=1;// 角度修正完成 ,进入第二步
							}
							else if(yaw > 30 && yaw <= 324)
							{
								motorA_dir=0;
								motorB_dir=1;		
								motorA_duty(sp+2000);
								motorB_duty(sp);	}							
				}
				if(step1==1) // 约定脉冲数road_a < 1880//a-》c直走
				{		
					
					gray=track_read(); //进行一次灰线传感读取
					go_on(3); // go on @ mode 3				
				}	
				if((gray!=0)&&step1==1) // 到c了蜂鸣器响,并往前走
				{																		 
					step1=2	;				
					motorA_duty(0);
					motorB_duty(0);
					gpio_set(GPIOA,DL_GPIO_PIN_28,1);
					gpio_set(GPIOB,DL_GPIO_PIN_8,1);
					delay_ms(250);
					gpio_set(GPIOB,DL_GPIO_PIN_8,0);
					gpio_set(GPIOA,DL_GPIO_PIN_28,0);		
					delay_ms(1000);
            	}
				
				if(step1==2)
				{
					gray=track_read();
					if(gray!=0)
					{step1=3;}
					else
					{
						motorA_dir=0;
						motorB_dir=1;		
						motorA_duty(sp+2000);
						motorB_duty(sp);		
					}	
				}
				if(step1==3)	//矫正完成开始巡线c-》b
				{
						gray=track_read();                    
						switch (gray) {                          
							case 0:								
									step1 = 4; 
									break;		
							case 1:
									motorA_duty(0);//20000
									motorB_duty(middle+error1);//0
									break;

							case 2:
									motorA_duty(0);//25000
									motorB_duty(middle+error1);//0
									break;

							case 3:
									motorA_duty(middle);
									motorB_duty(middle);
									break;

							case 4:
									motorA_duty(middle+error1);//25500
									motorB_duty(0);//25500
									break;

							case 5:
									motorA_duty(middle);//21500
									motorB_duty(middle);//12500
									break;
							case 6:
									motorA_duty(middle);
									motorB_duty(middle);
									break;
							case 7:
									motorA_duty(middle);
									motorB_duty(middle);
									break;
							case 8:
									motorA_duty(middle+error1);
									motorB_duty(0);
									break;
							case 9:
									motorA_duty(middle+error1);
									motorB_duty(0);
									break;
							case 10:
									motorA_duty(middle+error1);
									motorB_duty(0);
									break;
								default:
										motorA_duty(16000);
										motorB_duty(16000);
										break;
										
										}//switch
						
				}
				if(step1==4)//蜂鸣器和led
				{
					step1=5;
					motorA_duty(0);//小车停止
					motorB_duty(0);
					gpio_set(GPIOA,DL_GPIO_PIN_28,1);
					gpio_set(GPIOB,DL_GPIO_PIN_8,1);
					delay_ms(1000);
					gpio_set(GPIOB,DL_GPIO_PIN_8,0);
					gpio_set(GPIOA,DL_GPIO_PIN_28,0);
		  	    }
		  		
				if(step1==5)//到b->d矫正角度并直走,中心角度219
				{						
							if(yaw>single+2) // ,第一步a->c矫正修正yaw=219斜线预备角, 偏移时提供PWM @ duty cycle = sp 
							{
									motorA_dir=1;//小车左转
									motorB_dir=0;
									motorA_duty(17000-2000);			
									motorB_duty(17000);
							}
							else if(yaw<single)
							{ 
								oled_printf(2,1,"yaw=%d",yaw);
								motorA_dir=0;//小车右转
								motorB_dir=1;		
								motorA_duty(17000);
								motorB_duty(17000-2000);	
							}
							else 
								{
								motorA_duty(0);
								motorB_duty(0);	
								step1=6;//矫正完成
								}				
					}
				if(step1==6)
				{
					gray=track_read();
					if(gray==0)
					{
						go_on(4);
					}													
					else
					   step1=7;//找到黑线,直走结束
					}	
				if(step1==7)
				{		motorA_duty(0);
						motorB_duty(0);		
						gpio_set(GPIOA,DL_GPIO_PIN_28,1);
						gpio_set(GPIOB,DL_GPIO_PIN_8,1);			
  					delay_ms(1000);
						gpio_set(GPIOA,DL_GPIO_PIN_28,0);
						gpio_set(GPIOB,DL_GPIO_PIN_8,0);
						step1=8;			
				}							
		        if(step1==8)//完成最后巡线
				{
						#define middle2 14000
						gray=track_read();
							switch (gray) {
							case 0:								
									step1 = 10;
									break;

			        case 1:
									motorA_duty(0);//20000
									motorB_duty(20000);//0
									break;
							case 2:
									motorA_duty(0);//25000
									motorB_duty(middle2+error1);//0
									break;
							case 3:
									motorA_duty(0);
									motorB_duty(middle2+error1);
									break;

							case 4:
									motorA_duty(middle2);//25500
									motorB_duty(middle2);//25500
									break;

							case 5:
									motorA_duty(middle2+error1);
									motorB_duty(0);
									break;
							case 6:
									motorA_duty(middle2+error1);
									motorB_duty(0);
									break;
							case 7:
									motorA_duty(middle2+error1);
									motorB_duty(0);
									break;
							case 8:
									motorA_duty(middle2+error1);
									motorB_duty(0);
									break;
							case 9:
									motorA_duty(middle2+error1);
									motorB_duty(0);
									break;
							case 10:
									motorA_duty(middle2+error1);
									motorB_duty(0);
									break;
							default:
									motorA_duty(middle2+error1);
							    	motorB_duty(0);
									break;
								}
		            if(step1==10)//到d点停止
				   {
						gpio_set(GPIOA,DL_GPIO_PIN_28,1);//蜂鸣器和led
						gpio_set(GPIOB,DL_GPIO_PIN_8,1);
						motorA_duty(0);//小车停止
						motorB_duty(0);		
						delay_ms(1000);
					    gpio_set(GPIOA,DL_GPIO_PIN_28,0);
						gpio_set(GPIOB,DL_GPIO_PIN_8,0);
				
		            }
				
       }
}
### STM32 八路循迹使用 CubeMX 开发教程 #### 一、硬件准备 为了实现八路循迹功能,需要准备如下材料: - 主控芯片:STM32F103C8T6 或其他支持的型号。 - 循迹传感器模块:通常由八个红外发射接收管组成的一体化模块[^1]。 #### 二、软件配置 通过CubeMX初始化项目设置,具体操作包括但不限于: - 打开STMCubeMX工具并新建工程; - 配置时钟树使系统频率达到72MHz以提高响应速度; - 初始化GPIO端口用于连接外部设备如LED指示灯、按键以及最重要的循迹传感器接口; - 启用USART串行通信以便调试信息输出; 对于八路循迹而言,在Pinout&Configuration界面下需特别注意定义好对应数量的ADC通道来读取各传感器状态值。由于大多数情况下单片机自带资源有限,可能还需要外扩多路模拟开关或者采用分时采样的方式处理多个信号源的数据采集工作[^2]。 #### 三、程序设计思路 核心算法围绕着如何判断当前车辆所处位置相对于黑线的位置关系展开,进而决定前进方向。当所有探测器都检测到白色地面时表示已经偏离轨道太远,则应立即停止运动重新校准方位;反之如果全部感应黑色则说明正处于转弯阶段要适当减速慢行以免冲出边界之外。除此之外还需考虑特殊情况下的避障逻辑,比如遇到障碍物自动绕行等功能扩展。 ```c // 定义全局变量存储各个传感器的状态 uint8_t sensor_values[8]; void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){ if(htim->Instance==TIM2){ // 假设定时器中断周期为5ms ADC_Channel_Conversion(); // 轮询获取一次AD转换结果 /* 处理循迹逻辑 */ Track_Process(); Motor_Control(sensor_values); // 控制电机动作 } } /* 获取AD转换后的数值存入数组中 */ void ADC_Channel_Conversion(void){ for(int i=0;i<8;i++){ __HAL_ADC_ENABLE(&hadc); while(__HAL_ADC_GET_FLAG(&hadc, ADC_FLAG_EOC)==RESET); sensor_values[i]=__HAL_ADC_GET_VALUE(&hadc); __HAL_ADC_DISABLE(&hadc); } } ``` 上述代码片段展示了基于定时器触发的循环扫描机制,每隔固定时间间隔就去查询一遍所有传感器的工作情况,并据此调整行驶策略。实际应用当中还可以加入更多细节优化,例如PID调节使得转向更加平稳自然等高级特性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值