2021电赛国赛F小车题总结——附源码,源工程文件

2021年电赛结束了,这里分享一下F小车题代码和方案。
多少个通宵不眠夜,只能说已经全力以赴,结束了现在已经问心无愧了。
@山东赛区 组内成员:大三*3

目录

    • 部分
    • 开始前的碎碎念
    • 方案设计
      • 硬件连线表:(没更新,可能啊可能有点点问题)
        • 蓝牙:
        • openMV:
        • 灰度 循迹:
        • OLED : 3.3or5V
        • L298N-stm32(motor.h)
        • L298N-电机
        • 电机编码器-stm32
        • 红外(药品放置、到达检测)-stm32
    • stm32 代码,逻辑
      • 1车
      • 2车
      • openMV识别
      • 总结

部分

  1. 方案设计
  2. 硬件连接
  3. stm32巡线、控制(我实现部分 有源代码、工程文件)
  4. openMV识别数字、识别终点停止
  5. 总结反思

开始前的碎碎念

出来题目的时候觉得还行,没什么特别奇怪不会的部分。之前因为赛题准备器材里面有很奇怪的角度测量、透明空心球,一直以为会是控制器用,搞得我们准备控制题的很紧张……当时各种预测都有,结果今年出了小车题

在暑假准备的时候准备了stm32和430控制的小车(需要代码可以留言,有几次还是跑的很稳的。当然当时学430上手的时候还是挺难搞的,以后有空再写一个文档。)
暑假准备的……只准备了相关模块,但是小车供电啊之类的硬件连接设计没有自己想好(12V转5V等,我们天真的以为随便用一个12-5的模块就行,结果没有稳压没有保护,模块电流限制等等问题都没有考虑……竞赛的时候用了坏的再换就很痛苦……)
2021电赛国赛F小车题总结——附源码,源工程文件_第1张图片

暑假准备的时候问了一个已经毕业的大佬学长,大佬:学会Verilog、FPGA……我:??? 数电模电可再见吧,我不行。

我:啊这,然后我们准备的时候就定了选控制题……(忘了这个大佬打的是什么题了,应该可能不是控制题)

方案设计

emm发题前我们还在忙一些课业之类的事情,属实是忙的没空在11月怎么准备。11.3我们还在期待明天延期吧……

11.4早上有点睡过了,发题了我还在睡觉

来了实验室就开始讨论方案: 主要实现以下方面:

  1. 循迹 (红外不行灰度传感器)
  2. 识别数字(openMV) 我们有一块3 一块4 4的处理速度更快

stm32部分是我实现
openMV部分我一点不会(暑假懒了),由队友实现
硬件弄车另一个队友 (暑假弄了个半成品车模,不太行 准备的还是不太够)

2021电赛国赛F小车题总结——附源码,源工程文件_第2张图片
当时想着之前轮速有问题显示以下用PID控制,但是嘛,时间不太够,最后没用PID…… PWM单控制速度慢点也非常稳

晚上九点多老师回去了我们还在吵是3个红外还是2个红外

然后给老师发消息问,然后开了个腾讯会议问(为什么当时不直接通话……)

硬件连线表:(没更新,可能啊可能有点点问题)

3个灰度(老师建议保证抓住线,我们临时就买了6个)
2个附加的红外 防止撞到墙
1个红外识别药品

蓝牙:

(PA2 3)

PB10 TX
PB11 RX

openMV:

PA9 RXD

PA10 TXD

灰度 循迹:

灰度 PA3) 左 PA4 中 PA5 右
stm32 PA5 PA6 PA7

白色)的时候输出低电平


OLED : 3.3or5V

OLED SCL SDA
stm32 PB0 PB1

RES 接PB11 如果是用4针iic接口这个脚可以不接


L298N-stm32(motor.h)

L298N PWA(左) IN1 IN2 PWMB(右) IN3 IN4
stm32 PA8 PB14 PB15 PA11 PB13 PB12

PA8驱动力弱?

L298N-电机

L298N M1(左) M2 M1(右) M2
电机 OUT1 OUT2 OUT1 OUT2

电机编码器-stm32

电机编码器 C1(左) C2 C1(右) C2
stm32 PB7 PB6 PA0 PA1

电机 :【 M1 GND C1 C2 3.3V M2 】


红外(药品放置、到达检测)-stm32

printf("%d,%d,drug%d\r\n",xunji_1,xunji_2,drug);

白色是0 (接受0)

黑色(未接收1)

红外传感器 药品检测 是否到达检测1 是否到达检测2
stm32 PC8 PC6 PC7

**LED ** (调试方便、显示)

LED LED_left LED_straight LED_right
stm32 PA0 PA1 PA2

stm32 代码,逻辑

1车

  1. 读openMV数据:
  • 0:直走
  • 1:左转
  • 2:右转
  • 3:停止
  1. 循迹 (一定要走的稳不然晃动太大会对openMV读数造成很大影响)
  2. 控制电机(跑、掉头、转弯)
  3. 放药去,取药返回

2021电赛国赛F小车题总结——附源码,源工程文件_第3张图片

main里面代码不多,都在引用

int main(void)
{ 
	u8 i;
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable,ENABLE);
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);//禁用JTAG 启用 SWD
	
// 
	TIM5_PWM_Init(1000,9); //PWM初始化 8KHz	
	MY_NVIC_PriorityGroupConfig(2);	//=====设置中断分组
	
	delay_init();	    	        //=====延时函数初始化
	LED_Init();                     //=====LED初始化    程序灯	
	usart3_init(9600);              //=====串口3初始化  蓝牙 发送调试信息
	uart_init(115200);  

	
	Motor_Init();             //=====初始化驱动电机 如需初始化驱动器接口
	Xj_Init();										//灰度循迹初始化
	infrared_INIT();
	LED_straight = 0;
	LED_right = 0;
	LED_left = 0;
//	Set_Pwm(rightspeedinit,rightspeedinit); //左,右 右边速度会快一点
	//速度控制
	while(1)
	{

		read_openMV();
		if(start_flag==1) //读到数据 DS1亮绿灯
		{
			if(!drug&&(go_des==0))   {go_des=1;delay_ms(5);}//&&go_des==0 取到药 add&&(go_des==0))
			if(go_des ==1)   //无论返回还是去
			{ 
				if(!i) {i=1;CarForward();delay_ms(100);}//前冲一段
				Xj_read();
				hongwai_avoid();
				if(state_arrive==1){hongwai_avoid();} //Xj_read_stead();
			}
		while(state_arrive==2){LED_left=1;//要求绿灯
				delay_ms(400);CarStop();}
		}
	}
}

openMV控制部分和下面的循迹是我写的自己满意的地方

void read_openMV()
{
	u8 back;
//	u16 times=0;
	if(USART_RX_STA&0x8000) //收到数据
		{					
			recived =1;
			LED_g=0;
			if(!start_flag)
			{
			start_flag=1;
			}
			
			len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
			for(t=0;t<len;t++)
			{
				 if(USART_RX_BUF[t]==0xb3)     //判断帧头,即我们加的两个数
					 if(USART_RX_BUF[t+1]==0xb3)
						  n=t+2;    //记录我们需要数据的位置
			}
			for(t=0;n<len;t++,n++)
			UsartDisPlay[t] = USART_RX_BUF[n];  // 将我们需要的数据在oled上面显示,便于观察是否正确

			USART_RX_STA=0;
			
			
			if(go_des)//拿到药,开始走
			{
				if(UsartDisPlay[0]=='0')
				{
//					LED_left=0;
//					LED_right = 0;
//					LED_straight = 1;
					CarForward();	 
					switch(turn_car2) //多次发送
					{
						case(1):printf("1/r/n");break;  //告诉2车左转
						case(2):printf("2/r/n");break;  //告诉2车右转
						default:break;
					}

				} 
				else if(UsartDisPlay[0]=='1') //左转
				{
//					LED_right = 0;
//					LED_straight = 0;
//					LED_left = 1;
					turn_car2=2;
//					printf("2/r/n");  //告诉2车右转
					if(!state_arrive){delay_ms(300+100+100+200);}
					if(state_arrive){delay_ms(50);} //回来的时候延时一段  延时很长   有点长 4:42
					
					CarBigLeft();	
				}
				else if(UsartDisPlay[0]=='2')
				{
//					LED_straight = 0;
//					LED_left = 0;
//					LED_right = 1;
					turn_car2=1;
//					printf("1/r/n");  //告诉2车左转
					if(!state_arrive){delay_ms(300+100+100+200);}
					if(state_arrive){delay_ms(50);} //回来的时候延时一段
					CarBigRight();
				}		
				else if(UsartDisPlay[0]=='3')
				{
					state_arrive+=1;
					if(drug==0) //送达  有药未取
						{
//						LED_straight=1;
//						LED_left=1;	
						CarForward();
						delay_ms(400+200+200);//再向前
						LED_right = 1;//题目要求指示灯 红灯亮 
							
						
						while(!drug){
							switch(turn_car2) //多次发送
							{
								case(1):printf("1/r/n");break;  //告诉2车左转
								case(2):printf("2/r/n");break;  //告诉2车右转
								default:break;
							}
						CarStop();
						} 
						LED_right = 0;//题目要求指示灯 红灯灭
						CarFaceBack();
						delay_ms(50); //
						}

				}
		}
	}
}

循迹,速度慢的时候很稳~

void Xj_read()
{
	u16 i;
	if(XJ_MEDIUM)// while |(XJ_LEFT&&XJ_RIGHT)
	{
		CarForward();  
	}

	if(XJ_LEFT==1)//左边压线 左小转弯
		{
			if(!XJ_MEDIUM) //中间只要没巡线
			{
					LED_left=1;
					LED_right = 0;
					LED_straight = 0;
			Set_Pwm(0,leftspeedinit+100);i = 1;} //delay_ms(1);
			if(XJ_MEDIUM)//寻到了红线,这时车头稍微歪斜向左 
//			if(i)
			{i = 0;Set_Pwm(leftspeedinit-50+30,rightspeedinit-50-50); }
		}
	else if(XJ_RIGHT==1)    //右边压线 右小转弯
		{
			if(!XJ_MEDIUM) //中间白色
			{
					LED_left=0;
					LED_right = 1;
					LED_straight = 0;
				Set_Pwm(leftspeedinit+100,0);
//				delay_ms(1);
				i = 1;
			}
			if(XJ_MEDIUM)//寻到了红线,这时车头稍微歪斜向右
//			if(i)
			{
			i=0;Set_Pwm(leftspeedinit-50-50,rightspeedinit-50+30); } //delay_ms(1);
		}
		

//	else if(XJ_LEFT==1&&XJ_RIGHT==1&&turn_flag)    //到达药房、病房
//	{
//	CarStop();
//	}
}

只放关键代码,工程文件晚点再发吧……

2车

2车实际没太多时间测 可能代码不好


int main(void)
{ 
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable,ENABLE);
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);//禁用JTAG 启用 SWD
	
//	Encoder_Init_TIM2();
//	Encoder_Init_TIM4();
	TIM5_PWM_Init(1000,9); //PWM初始化 8KHz	
	MY_NVIC_PriorityGroupConfig(2);	//=====设置中断分组
	
	delay_init();	    	        //=====延时函数初始化
	LED_Init();                     //=====LED初始化    程序灯	
	usart3_init(9600);              //=====串口3初始化  蓝牙 发送调试信息
	uart_init(115200);  
//	printf("ok");
	
	Motor_Init();             //=====初始化驱动电机 如需初始化驱动器接口
	Xj_Init();										//灰度循迹初始化
	infrared_INIT();
//	usart3_init(9600);
//	Set_Pwm(rightspeedinit,rightspeedinit); //左,右 右边速度会快一点
	//速度控制
	while(1)
	{
		u16 i,t;
		u8 flag;
		if(USART3_RX_STA&0X8000)			//接收到一次数据了 可以收到
		{
			flag =1;
			LED_g=0;
		if(USART3_RX_BUF[0]=='1'){turn_car2 = 1;}
		if(USART3_RX_BUF[0]=='2'){turn_car2 = 2;}
			USART3_RX_STA=0;
		}
		
		while(flag)
		{	
			read_openMV();
			if(start_flag==1)
			{
				if(!drug)   {go_des=1;delay_ms(5);}//&&go_des==0 取到药
				if(go_des ==1)   //无论返回还是去
				{ 
					if(!i) {i=1;CarForward();delay_ms(100);}//前冲一段
					Xj_read();
					hongwai_avoid();
				}
			}	
		}
	} 
}


openMV

void read_openMV()
{
	u8 back;
//	u16 times=0;
	if(USART_RX_STA&0x8000) //收到数据
		{					
			recived =1;
			LED_g=0;
			if(!start_flag)
			{
			start_flag=1;
			}
			
			len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
			for(t=0;t<len;t++)
			{
				 if(USART_RX_BUF[t]==0xb3)     //判断帧头,即我们加的两个数
					 if(USART_RX_BUF[t+1]==0xb3)
						  n=t+2;    //记录我们需要数据的位置
			}
			for(t=0;n<len;t++,n++)
			UsartDisPlay[t] = USART_RX_BUF[n];  // 将我们需要的数据在oled上面显示,便于观察是否正确

			USART_RX_STA=0;
			
			
			if(go_des)//拿到药,开始走
			{
				if(UsartDisPlay[0]=='0')
				{
					LED_left=0;
					LED_right = 0;
					LED_straight = 1;
					CarForward();	 
				} 
				else if(UsartDisPlay[0]=='1') //转
				{
					switch(turn_car2)
							{
								case(1):{
									LED_right = 0;
									LED_straight = 0;
									LED_left = 1;CarBigLeft();}break;  //告诉2车左转
								case(2):{
									LED_straight = 0;
									LED_left = 0;
									LED_right = 1;
									CarBigRight();
								}break;  //告诉2车右转
								default:break;
							}
					CarBigLeft();	
				}
				else if(UsartDisPlay[0]=='3')
				{
					while(1)
					{
					CarStop();
					LED_right = 1;
					LED_straight = 1;
					LED_left = 1;
					}
						
				}
		}
	}
}

openMV识别

这部分不是我做的hhh,一直在看队友录模板、调整精度

总结

  1. 和老师交流不够(比完赛微信和老师总结了下,比赛前都不太认识这个老师, )
  2. 进度太慢,开始我折腾什么oled显示,简单点不好吗
  3. 方案讨论的不充分,讨论的自以为差不多就开始莽(经验积累不够,过程把握不充分
  4. 什么都想要最后就会什么都得不到(过于理想化
  5. 调试花了挺多时间的,控制嘛……
  6. 硬件太不稳了,花了我们很多时间(前期准备不足
    1. 杜邦线、端子连接、和电池连接
    2. 电池,我买的航模电池80多一个,后来我们整了5大块航模电池。电池电压一遍,之前测的参数就gg
    3. ……很多很多问题
  7. 持续更新

老师:很多经验教训需要总结,先休息好,进入学习状态,以后机会很多。

代码:
蓝牙1车:链接:https://pan.baidu.com/s/1gIsHPX7HccK6Uns2c_B_qg
提取码:ji9d

蓝牙2车:链接:https://pan.baidu.com/s/18MaYlvZyOE6h7lEjkp6DNQ
提取码:fzwf
2021电赛国赛F小车题总结——附源码,源工程文件_第4张图片
2021电赛国赛F小车题总结——附源码,源工程文件_第5张图片
吃饭的时候在操场摸到了学校的猫猫(好像他叫桶桶来着)
2021电赛国赛F小车题总结——附源码,源工程文件_第6张图片

你可能感兴趣的:(stm32,单片机,嵌入式硬件,stm32,opencv,硬件工程)