2022 electric racing car open source code explanation open source

I think there are several main problems with the 2022 electric racing car, and I will explain it in these parts

Table of contents

1. Tracking

2. Bluetooth communication, dual-vehicle data transmission

3. Identification of starting intersections

4. Recognition of fork intersections

Five, source code


 2022 electric race, two cars drive stably_哔哩哔哩_bilibili

1. Tracking

Tracking Our group uses five-way grayscale, the effect of grayscale and infrared on the tube is similar, you can buy it on Taobao, and input a high level when a black line is detected, then you need to capture it on the microcontroller The level of this IO port can know which grayscale detects the black line.

The steps are very simple. Initialize the IO port -> capture the IO port. The code is as follows:

#ifndef __GRAY_H_
#define __GRAY_H_
//主函数定义
#include "sys.h"
void GRAY_Init(void);
int Gray_values(void);

#endif
#include "gray.h"
void GRAY_Init(void)//初始化IO口
{
	 GPIO_InitTypeDef  GPIO_InitStructure;
	 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	 //使能PA,PD端口时钟
		
	 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
	 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 		 			//上拉输入
	 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		  //IO口速度为50MHz
	 GPIO_Init(GPIOA, &GPIO_InitStructure);				//根据设定参数初始化
}


u8 Gray_values()//得到IO口的值并返回
{
   static u8 Gray_Value;
   Gray_Value=GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_4);//获得GPIO的值
   return Gray_Value;
}

You can configure the IO port according to your own needs, and finally use an array to store these IO values.

2. Bluetooth communication, dual-vehicle data transmission

First pair the Bluetooth of the two cars, and set one Bluetooth as the master and the other as the slave mode. For the specific pairing method, click here . Then the bluetooth is initialized. The initialization is relatively simple and the source code can be found everywhere.

#ifndef __USART2_H
#define __USART2_H
#include "sys.h"



#define USART2_MAX_RECV_LEN		37					//最大接收缓存字节数
#define USART2_MAX_SEND_LEN		3					//最大发送缓存字节数
#define USART2_RX_EN 			1					//0,不接收;1,接收.

#define	DATA1			12550
#define	DATA2			12806
#define	DATA3			13062

extern u8  USART2_RX_BUF[USART2_MAX_RECV_LEN]; 		//接收缓冲,最大USART3_MAX_RECV_LEN字节
extern u8  USART2_TX_BUF[USART2_MAX_SEND_LEN]; 		//发送缓冲,最大USART3_MAX_SEND_LEN字节
extern vu16 USART2_RX_STA;   						//接收数据状态
void dataSend(u8 *sendArry);
void usart2_init(u32 bound);				//串口2初始化
void u2_printf(char* fmt, ...);
#endif

#include "delay.h"
#include "usart2.h"
#include "stdarg.h"	 	 
#include "usart.h"
#include "timer.h"
#include "stdio.h"	 	 
#include "string.h"	



//串口接收缓存区
u8 USART2_RX_BUF[USART2_MAX_RECV_LEN]; 				//接收缓冲,最大USART3_MAX_RECV_LEN个字节.
u8 USART2_TX_BUF	[USART2_MAX_SEND_LEN];		//发送缓冲,最大USART3_MAX_SEND_LEN字节

u16 uart2rec;
u8 END_FLAG1;

u8	RECEIVE_FLAG = 0; 

//初始化IO 串口3
//pclk1:PCLK1时钟频率(Mhz)
//bound:波特率
void usart2_init(u32 bound)
{

    NVIC_InitTypeDef NVIC_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	// GPIOB时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); //串口3时钟使能
    USART_DeInit(USART2);  //复位串口3
    //USART2_TX   PA2
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PB10
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
    GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PB10
    //USART2_RX	  PA3
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
    GPIO_Init(GPIOA, &GPIO_InitStructure);  //初始化PB11
	 //设置中断优先级
    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3 ; //抢占优先级3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
	
    USART_InitStructure.USART_BaudRate = bound;//波特率一般设置为9600;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
    USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
    USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式

    USART_Init(USART2, &USART_InitStructure); //初始化串口	
    //使能接收中断
    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启中断
		USART_Cmd(USART2, ENABLE);                    //使能串口
 
}

void dataSend(u8 *sendArry) {//发送数据函数,注意这里发的是一个数组,3位数组,第一个与第三个用于判断
	int i;
   for(i=0;i<3;i++)   		
   {
	   USART_SendData(USART2,sendArry[i]);
     while((USART2->SR&0x40)==0);
	}

}


void USART2_IRQHandler(void)//接收数据中断
{
static  u8 i = 0;
    u8 res;
    if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
    {
        
      res = USART_ReceiveData(USART2);
			if(res == 0x01 )//帧头判断
			{
				i = 0;
			}
			USART2_RX_BUF[i] = res;//将接收到的数据放在数组中
			i++;
			if(i == 2 && USART2_RX_BUF[2] == 0x06)//帧尾判断
			{
				uart2rec = (u16)((u16)USART2_RX_BUF[1]<<8 | (u16)USART2_RX_BUF[2]);//将接收到的数据进行移位操作
		
		 }
    }

}


//串口2,printf 函数
//确保一次发送数据不超过USART3_MAX_SEND_LEN字节
void u2_printf(char* fmt, ...)
{
    u16 i, j;
    va_list ap;
    va_start(ap, fmt);
    vsprintf((char*)USART2_TX_BUF, fmt, ap);
    va_end(ap);
    i = strlen((const char*)USART2_TX_BUF);		//此次发送数据的长度

    for(j = 0; j < i; j++)							//循环发送数据
    {
        USART_SendData(USART2, USART2_TX_BUF[j]);

        while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET); //循环发送,直到发送完毕

       

    }
}

It is mainly to make good use of the sending function and receiving interrupt. The shift operation is to convert the last two digits of hexadecimal into decimal.

Column: send array data[3]={0x01,0x31,0x06} then 0x31,0x06->12550 uart2rec=12550

 Change the value of uartrec by changing the middle value to determine which question to take.

3. Identification of starting intersections

It can be judged according to the on and off of the gray scale. When passing the parking position, if the three lights in the middle are off, let it make an instruction.

4. Recognition of fork intersections

There are many methods here. The method we use is to judge according to the fact that the first three lights are off. If the three lights are off, if you go to the outer circle, use the delay to rush forward for a while, and you can use the outermost Gray scale is judged. It sounds abstract, let's go directly to the code.

Five, source code

Using a lot of flags makes reading uncomfortable. Forgive everyone, the main thing is that this code was written a month ago and I don’t want to change it anymore. The main thing is to provide you with an idea. Welcome to discuss and learn in the comment area.

Link: https://pan.baidu.com/s/1X8O7z_afGnofAl8y89iRAQ?pwd=1234 Extraction code: 1234 

#include "test.h"
#include "control.h"
#include "gray.h"
#include "tb6612.h"
#include "led.h"
#include "usart2.h"
#include "test.h"
#include "encoder.h"
u8 TRACE_FLAG = 1,STOP_FLAG ,START_FLAG = 1;

u8 send_data5[3] = {0x01,0x35,0x06};//13574
u8 send_data6[3] = {0x01,0x36,0x06};//13574
u8 Instruction_Flag;
int cross_num;
void test1()
{
	Basic_Speed = 2600;				//2400   0.3
	Gray_values();
	Encoder4();
	if(START_FLAG)
	{
		trace(Basic_Speed);
		if(TURN_FLAG == 1)
		{
			Direction(10,10,0,1);			//0  外圈
		}
		if(Gray_Number >= 3  && Gray_Number < 5 && TURN_FLAG == 0)
		{
			TURN_FLAG = 1;
			Qingling = 0;
		}
		if(cross_num == 2)
		{
			START_FLAG = 0;
			END_FLAG = 1;
		}
	}
			//停止行进标志位
	if(END_FLAG == 1)
	{
		LED0 = 1;
		STOP;	
		dataSend(send_data5);
		if(delay(40))
		{
			LED0 = 0;
			END_FLAG = 0;
			START_FLAG = 0;
			TRACE_FLAG = 0;
		}
	}
}


void test2()
{
	Basic_Speed = 3300;				//3100   0.5	
	Gray_values();
	Encoder4();
	if(START_FLAG)
	{
		trace(Basic_Speed);
		if(TURN_FLAG == 1)
		{
			Direction(10,10,0,1);
		}
		if(Gray_Number >= 3 && Gray_Number < 5 && TURN_FLAG == 0 )
		{
			TURN_FLAG = 1;
			Qingling = 0;
		}

		if(cross_num == 3)
		{
			START_FLAG = 0;
			END_FLAG = 1;
		}
	}
	
	if(END_FLAG == 1)/结束
	{
		dataSend(send_data5);
		LED0 = 1;
		BACKWORD;	
		PWM_L = 0;
		PWM_R = 0;
		if(delay(30))
		{
			START_FLAG = 0;
			LED0 = 0;
			END_FLAG = 0;
			DELAY_FLAG = 1;
		}
	}
}


void test3()
{
	Basic_Speed = 2600;
	Gray_values();
	Encoder4();
	if(START_FLAG)
	{
		trace(Basic_Speed);
		if(TURN_FLAG == 1)
		{
			switch(cross_num)
			{
				case 0:
							 Direction(10,10,0,1);     break;
				case 1:
							 Direction(10,10,0,1);     break;
				case 2:
							 Direction(10,10,0,1);     break;
				case 3:
							 Direction(10,10,1,1);     
								LED1 = 1;								 break;
				case 4:
							 Direction(10,10,1,1);     break;
			}
		}
		if(Gray_Number >= 3 && Gray_Number < 5 && TURN_FLAG == 0)
		{
			TURN_FLAG = 1;
			Qingling = 0;
		}
		if(cross_num == 4)
		{
			START_FLAG = 0;
			END_FLAG = 1;
		}
	}
	if(END_FLAG == 1)/结束
	{
		dataSend(send_data5);
		LED0 = 1;
		BACKWORD;	
		PWM_L = 0;
		PWM_R = 0;
		if(delay(30))
		{
			START_FLAG = 0;
			LED0 = 0;
			END_FLAG = 0;
			DELAY_FLAG = 0;
		}
	}
}


void test4()
{
	Basic_Speed = 4000;
	Gray_values();
	Encoder4();
	if(START_FLAG)
	{
		if(Instruction_Flag == 0  && Gray_Number >= 3 && TURN_FLAG == 0)
		{
			TURN_FLAG = 1;
		}
		if(TURN_FLAG == 1)
		{
			if(delay(20))
			{
				Instruction_Flag  = 1;
				TURN_FLAG = 2;
				DELAY_FLAG = 0;
			}
		}

		if(Instruction_Flag  == 1 && TURN_FLAG == 2 && Gray_Number >= 3)
		{
			TURN_FLAG = 3;
		}
		if(TURN_FLAG == 3)
		{
				BACKWORD;
				PWM_L = 0;
				PWM_R = 0;
				Instruction_Flag  = 2;
				if(delay(150))
				{
					TURN_FLAG = 4;
					Instruction_Flag  = 3;
					FORWARD;
					DELAY_FLAG = 0;
					TIM_SetCounter(TIM2,0);
				}	
		}
			
		if(Instruction_Flag == 3 && Gray_Number >= 3 && Read_Encoder(2) > 1000)
		{
			START_FLAG = 0;
			END_FLAG = 1;
		}
		if(Instruction_Flag != 2)
		{
			trace(Basic_Speed);
		}
	}

	if(END_FLAG)
	{
		START_FLAG = 0;
		BACKWORD;
		PWM_L = 0;
		PWM_R = 0;	
		LED0 = 1;
		dataSend(send_data5);
		if(delay(50))
		{
			LED0 = 0;
			END_FLAG = 0;
			START_FLAG = 0;
			TRACE_FLAG = 0;
			DELAY_FLAG = 0;
		}
	}
	
}
	

Guess you like

Origin blog.csdn.net/qq_62392385/article/details/130000308