2022年電気レーシングカーのオープンソースコードの説明オープンソース

2022年の電気レーシングカーにはいくつかの主な問題があると思います。それについては次の部分で説明します

目次

1. 追跡

2.Bluetooth通信、二台車データ送信

3. 開始交差点の特定

4. 分岐交差点の認識

5、ソースコード


 2022年の電気レース、2台の車両が安定走行_哔哩哔哩_bilibili

1. 追跡

追跡 私たちのグループは5方向のグレースケールを使用しており、チューブに対するグレースケールと赤外線の効果は似ています。淘宝網で購入でき、黒い線が検出されたときに高レベルを入力し、それをマイクロコントローラーでキャプチャする必要があります。この IO ポートのレベルによって、どのグレースケールが黒線を検出したかを知ることができます。

手順は非常に簡単で、IO ポートの初期化 -> IO ポートのキャプチャ コードは次のとおりです。

#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;
}

独自のニーズに応じて IO ポートを構成し、最終的に配列を使用してこれらの IO 値を保存できます。

2.Bluetooth通信、二台車データ送信

まず2台の車のBluetoothをペアリングし、一方のBluetoothをマスターモード、もう一方のBluetoothをスレーブモードに設定します。具体的なペアリング方法については、ここをクリックしてください次にBluetoothが初期化されます。初期化は比較的簡単で、ソース コードはどこにでもあります。

#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); //循环发送,直到发送完毕

       

    }
}

主に送信関数と受信割り込みを活用するためのもので、シフト演算とは16進数の下2桁を10進数に変換する演算です。

列: 配列データ [3]={0x01,0x31,0x06} を送信し、次に 0x31,0x06->12550 uart2rec=12550

 中央の値を変更して uartrec の値を変更し、どの質問を受けるかを決定します。

3. 開始交差点の特定

グレースケールのオンオフで判断でき、駐車位置を通過する際、中央の3つのライトが消灯していれば指示を出します。

4. 分岐交差点の認識

方法は色々ありますが、最初の3灯が消えていることを基準に判断する方法で、3灯消えたら外周に行ったらディレイを利用してしばらく突進し、一番外側のグレースケールを判定して使用できます。抽象的に聞こえるので、コードに直接進みましょう。

5、ソースコード

フラグを多用すると読むのが不快になります。皆さん、申し訳ありませんが、重要なことは、このコードは 1 か月前に書かれたものであり、これ以上変更したくないということです。重要なことは、アイデアを提供することです。コメント エリアでの議論や学習を歓迎します。

リンク: https://pan.baidu.com/s/1X8O7z_afGnofAl8y89iRAQ?pwd=1234 抽出コード: 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;
		}
	}
	
}
	

おすすめ

転載: blog.csdn.net/qq_62392385/article/details/130000308