2024年电赛H题解析_电赛循迹带mcu
一、硬件选择
这里不是打广告
(一)电机驱动
TB6612双路驱动模块带稳压版接口
(二)红外循迹
幻尔机器人4路循迹传感器(GPIO通信)
(三)小车车模以及电机
R1系列三轮小车+带铰链高度角度可调相机支架+mg310电机两个
(四)陶晶驰串口屏4.3英寸
(五)角度传感器
MPU6050模块 串口6轴加速度计电子陀螺仪JY61
(六)MCU
嘉立创MSPM0G3507(咸鱼买二手)
二、硬件链接
(一)电机驱动
1.电机驱动
MCU的PA14连电机驱动的AIN1,PA13连电机驱动的AIN2,PA15连电机驱动的BIN1,PA16连电机驱动的BIN2。TB6612上的STAY直接置3.3v高电平。
MCU的PA21是左轮电机的pwm引脚连到TB6612的PWMA,PA22是右轮电机的pwm引脚连到TB6612的PWMB。
电机A是小车左边的电机,电机B是小车右边的电机
2.霍尔编码器
MCU的PB18连电机驱动的E1A,MCU的PB19连电机驱动的E1B。
3.红外循迹
红外循迹模块左2(最左边的红外管)连MCU的PA2,左1(中间靠左)连PA7,右1(中间靠右)连PA8,右2(最右边的红外管)连PA9。
4.蜂鸣器
蜂鸣器的IO口连接MCU的PB7。
5.串口
MCU的PA1连接到MPU6050的TX,PA0连接到MPU6050的RX(串口0,波特率:115200bps,注意:此串口协议为:RS485,不是常规的RS232)
MCU的PA18连接到串口屏的TX,PA17连接到串口屏的RX(串口1,波特率:115200bps)
6.其他
除此之外,还要把MCU的主频提高到80MHz,定时器每隔50ms中断,外部中断
三、软件代码编写思路
题目切换思路
-
如果接受的串口1的数据为 \'1\' ,则进入题目1程序
-
如果接受的串口1的数据为 \'0\' ,则继续发送有关题目1程序的小车参数,但让小车停止
-
如果接受的串口1的数据为 \'2\' 并且已完成mpu6050角度初始化,则进入题目2程序,这里的角度初始化完成状态为 ‘N’
-
如果接受的串口1的数据为 \'3\' ,则继续发送有关题目2程序的小车参数,但让小车停止
-
如果接受的串口1的数据为 \'4\' 并且已完成mpu6050角度初始化,则进入题目3程序 这里的角度初始化完成状态为 ‘C’
-
如果接受的串口1的数据为 \'5\' ,则继续发送有关题目3程序的小车参数,但让小车停止
-
如果接受的串口1的数据为 \'6\', 小车行驶的圈数小于4圈,并且已完成mpu6050角度初始化,则进入题目3程序 这里的角度初始化完成状态为 ‘D’
-
如果接受的串口1的数据为 \'7\' 或小车行驶的圈数大于等于4圈,则继续发送有关题目4程序的小车参数,但让小车停止
题目切换状态机图
题目一
题目一的思路很简单,就是使小车按0度行驶,当小车检测到有黑线时,则认为到达B点,题目1完成
void qustion1(void) { if(IT.Infraed_Tracking_State == 11 && car_state == \'A\')//小车红外循迹为全白 { PID_Control(18, 3 , 7 , Value[2] , 0 , yaw_old ,&PID_left.pwm,car_state); PID_Control(18, 3 , 7 , 0 , Value[2] , yaw_old ,&PID_right.pwm,car_state); } else if(IT.Infraed_Tracking_State != 11) //小车红外循迹不为全白 { car_state = \'B\'; PID_left.pwm = PID_right.pwm = 0; } if(car_state == \'B\') { if(Buzzer_count <=20)//蜂鸣器工作1s { Buzzer_count++; DL_GPIO_setPins(GPIO_Buzzer_PORT,GPIO_Buzzer_PIN_0_PIN); } else { DL_GPIO_clearPins(GPIO_Buzzer_PORT,GPIO_Buzzer_PIN_0_PIN); } } DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm, DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm, DL_TIMER_CC_1_INDEX); }
题目二
题目二,先让小车按0度行驶,检测到黑线就正常循迹。当小车状态为‘B’时,红外循迹模块检测为全白,判断偏航角是否大于170度或小于-170度,是的话,小车状态为‘C’,小车按+-180度行驶。当小车状态为‘C’时,红外循迹模块检测到黑线,则认为小车到达D点,再正常循迹。当小车状态为‘D’时,红外循迹模块检测为全白,判断偏航角是否处于[-10,10]区间,如是,则认为到达A点,题目二完成
void question2(void){ if(IT.Infraed_Tracking_State == 11 && car_state == \'A\')//红外循迹为全白 { PID_Control(15, 1 , 5 , Value[2] , 0 , yaw_old ,&PID_left.pwm,car_state); PID_Control(15, 1 , 5 , 0 , Value[2] , yaw_old ,&PID_right.pwm,car_state); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm, DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm, DL_TIMER_CC_1_INDEX); yaw_old=Value[2]; } else if(IT.Infraed_Tracking_State !=11 && car_state == \'A\')//红外循迹不为全白 { car_state = \'B\'; Buzzer_count = 0; yaw_old=0; PID_left.pwm = PID_right.pwm=0; DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm, DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm, DL_TIMER_CC_1_INDEX); } else if(car_state == \'B\')//小车进入红外循迹 { Judge_pwm_duty_difference(IT.Infraed_Tracking_State,&pwm_duty_difference); PID_left.pwm = 520 + (pwm_duty_difference * 40); PID_right.pwm = 520 - (pwm_duty_difference * 40); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm , DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm , DL_TIMER_CC_1_INDEX); if(Buzzer_count <=20) { Buzzer_count++; DL_GPIO_setPins(GPIO_Buzzer_PORT,GPIO_Buzzer_PIN_0_PIN); } else { DL_GPIO_clearPins(GPIO_Buzzer_PORT,GPIO_Buzzer_PIN_0_PIN); } if(IT.Infraed_Tracking_State == 11 && car_state == \'B\' && (Value[2] = 170))//如果红外循迹为全白,小车偏航角大于170度小于-170,则认为小车进入C点 { car_state = \'C\'; Buzzer_count = 0; pwm_duty_difference = 0; PID_left.pwm = PID_right.pwm=0; DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm, DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm, DL_TIMER_CC_1_INDEX); } } else if(car_state == \'C\') { if(Buzzer_count <=25) { Buzzer_count++; DL_GPIO_setPins(GPIO_Buzzer_PORT,GPIO_Buzzer_PIN_0_PIN); } else { DL_GPIO_clearPins(GPIO_Buzzer_PORT,GPIO_Buzzer_PIN_0_PIN); } if(Value[2] = 0) { PID_Yaw = -180 + Value[2]; } PID_Control(15, 2 , 0 , PID_Yaw , 0 , 0,&PID_left.pwm,car_state); PID_Control(15, 2 , 0 , 0 , PID_Yaw , 0 ,&PID_right.pwm,car_state); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm , DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm , DL_TIMER_CC_1_INDEX); yaw_old=PID_Yaw; if(IT.Infraed_Tracking_State !=11 && car_state == \'C\')//红外循迹不为全白 ,则小车到达D点 { car_state = \'D\'; Buzzer_count = 0; yaw_old=0; PID_left.pwm = PID_right.pwm=0; DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm, DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm, DL_TIMER_CC_1_INDEX); } } else if(car_state == \'D\') { if(Buzzer_count = -15 && Value[2] <= 15))//红外循迹为全白,小车偏航角为[-15,15],小车进入\'E\'状态 { car_state = \'E\'; Buzzer_count = 0; pwm_duty_difference = 0; PID_left.pwm = PID_right.pwm = 0; DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm , DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm , DL_TIMER_CC_1_INDEX); } } else if(car_state == \'E\') { if(Buzzer_count <=25) { Buzzer_count++; DL_GPIO_setPins(GPIO_Buzzer_PORT,GPIO_Buzzer_PIN_0_PIN); } else { DL_GPIO_clearPins(GPIO_Buzzer_PORT,GPIO_Buzzer_PIN_0_PIN); } }}
题目三
小车在A点,原地向右转,当偏航角为[-30,-40]时,小车进入 ‘a’状态。
-
小车为 ‘a’状态,向-37度行驶,当小车循迹状态不为全白时,小车进入C点。
-
小车进入C点,开始红外循迹 , 当循迹状态为全白并且(偏航角大于170度或小于-170度) ,小车到达B点。
-
小车进入B点,原地向左转,当偏航角为[-130,-150]时,小车进入\'b\'状态。
-
小车进入\'b\'状态,当红外循迹状态不为全白,小车进入\'D\'点。
-
小车进入\'D\'点,当红外循迹状态为全白并且偏航角为[-10,10],小车状态为 \'E\',题目三完成。
-
题目三状态机图
-
void question3(void){ if(car_state == \'A\')//小车在A点,原地向右转,当偏航角为[-30,-40]时,小车进入 ‘a’状态 { DL_GPIO_setPins(GPIO_Motor_PORT,GPIO_Motor_PIN_E2_AIN2_PIN); DL_GPIO_clearPins(GPIO_Motor_PORT,GPIO_Motor_PIN_E2_AIN1_PIN); PID_left.pwm = 450; PID_right.pwm = 400; DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm, DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm, DL_TIMER_CC_1_INDEX); if(Value[2] >= -40.0f && Value[2] <= -30.0f) { car_state = \'a\'; PID_left.pwm = PID_right.pwm = 0; DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm, DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm, DL_TIMER_CC_1_INDEX); DL_GPIO_setPins(GPIO_Motor_PORT,GPIO_Motor_PIN_E2_AIN1_PIN); DL_GPIO_clearPins(GPIO_Motor_PORT,GPIO_Motor_PIN_E2_AIN2_PIN); } } else if(car_state == \'a\')//小车为 ‘a’状态,向-37度行驶,当小车循迹状态不为全白时,小车进入C点 { PID_Yaw = 37 + Value[2]; PID_Control(18, 3 , 2 , PID_Yaw , 0 , 0,&PID_left.pwm,car_state); PID_Control(18, 3 , 2 , 0 , PID_Yaw , 0 ,&PID_right.pwm,car_state); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm , DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm , DL_TIMER_CC_1_INDEX); yaw_old = PID_Yaw; if(IT.Infraed_Tracking_State != 11) { car_state = \'C\'; Buzzer_count = 0; yaw_old =0; PID_left.pwm = PID_right.pwm = 0; DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm, DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm, DL_TIMER_CC_1_INDEX); } } else if(car_state == \'C\')//小车进入C点 开始红外循迹 , 当循迹状态为全白并且(偏航角大于170度或小于-170度) ,小车到达B点 { if(Buzzer_count <=10) { Buzzer_count++; DL_GPIO_setPins(GPIO_Buzzer_PORT,GPIO_Buzzer_PIN_0_PIN); } else { DL_GPIO_clearPins(GPIO_Buzzer_PORT,GPIO_Buzzer_PIN_0_PIN); } Judge_pwm_duty_difference(IT.Infraed_Tracking_State,&pwm_duty_difference); PID_left.pwm = 520 + (pwm_duty_difference * 40); PID_right.pwm = 520 - (pwm_duty_difference * 40); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm , DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm , DL_TIMER_CC_1_INDEX); if(IT.Infraed_Tracking_State == 11 && (Value[2] = 170)) { car_state = \'B\'; Buzzer_count = 0; pwm_duty_difference = 0; PID_left.pwm = PID_right.pwm=0; DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm, DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm, DL_TIMER_CC_1_INDEX); } } else if(car_state == \'B\')//小车进入B点 原地向左转 , 当偏航角为[-130,-150]时,小车进入\'b\'状态 { if(Buzzer_count = -150.0f && Value[2] <= -130.0f) { car_state = \'b\'; PID_left.pwm = PID_right.pwm = 0; DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm, DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm, DL_TIMER_CC_1_INDEX); DL_GPIO_setPins(GPIO_Motor_PORT,GPIO_Motor_PIN_E1_AIN1_PIN); DL_GPIO_clearPins(GPIO_Motor_PORT,GPIO_Motor_PIN_E1_AIN2_PIN); } } else if(car_state == \'b\')//小车进入\'b\'状态,当红外循迹状态不为全白,小车进入\'D\'点 { PID_Yaw = 144 + Value[2]; PID_Control(18, 3 , 2 , PID_Yaw , 0 , 0,&PID_left.pwm,car_state); PID_Control(18, 3 , 2 , 0 , PID_Yaw , 0 ,&PID_right.pwm,car_state); yaw_old = PID_Yaw; DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm , DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm , DL_TIMER_CC_1_INDEX); if(IT.Infraed_Tracking_State != 11) { car_state = \'D\'; Buzzer_count = 0; yaw_old = 0; PID_left.pwm = PID_right.pwm = 0; DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm, DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm, DL_TIMER_CC_1_INDEX); } } else if(car_state == \'D\')//小车进入\'D\'点 ,当红外循迹状态为全白并且偏航角为[-10,10],小车状态为 \'E\' { if(Buzzer_count <=10) { Buzzer_count++; DL_GPIO_setPins(GPIO_Buzzer_PORT,GPIO_Buzzer_PIN_0_PIN); } else { DL_GPIO_clearPins(GPIO_Buzzer_PORT,GPIO_Buzzer_PIN_0_PIN); } Judge_pwm_duty_difference(IT.Infraed_Tracking_State,&pwm_duty_difference); PID_left.pwm = 520 + (pwm_duty_difference * 40); PID_right.pwm = 520 - (pwm_duty_difference * 40); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm , DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm , DL_TIMER_CC_1_INDEX); if(IT.Infraed_Tracking_State == 11 && Value[2] = -10) { car_state = \'E\'; Buzzer_count = 0; pwm_duty_difference = 0; PID_left.pwm = PID_right.pwm=0; DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm, DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm, DL_TIMER_CC_1_INDEX); } } else if(car_state == \'E\')//蜂鸣器工作 { if(Buzzer_count <=10) { Buzzer_count++; DL_GPIO_setPins(GPIO_Buzzer_PORT,GPIO_Buzzer_PIN_0_PIN); } else { DL_GPIO_clearPins(GPIO_Buzzer_PORT,GPIO_Buzzer_PIN_0_PIN); } }}
题目四
若小车在状态‘E’到C点偏右,就加上Value_yaw_old1,若偏左,则减去Value_yaw_old1。
/*因为mpu6050有累积误差,在小车在每次一圈结束时记录最后的偏航角,让新的偏航角减去这个乘个系数的最后的偏航角 一般最后一题在这调参*/ Value[2] = Value[2] + Value_yaw_old1 * 0.12f;
小车状态为 ‘A’ ,让原地向右转。如果小车偏航角为[-70,-80],则小车进入‘a’状态 。
小车状态为 ‘a’ ,向-75度行驶。小车左轮的竖直位移的计数值大于1170,进入到 \'E\'状态。在此状态下,进行对小车的左轮编码器计数求竖直方向的位移
因为减小角度误差对竖直位移计算的影响,小车要按-75度行驶,竖直位移计算公式为 :
左轮总竖直位移 = 左轮上一时刻的总竖直位移 + (左轮位移 - 上一刻左轮位移) * cos(偏航角)
cos(X)在+-90度附近的导数(-sin(X))较小,能减小角度误差对竖直位移计算的影响,故小车向-75度行驶。
if(car_state == \'a\')//小车状态为 ‘a’ ,向-75度行驶 { PID_Yaw = 75 + Value[2]; //进行小车竖直位移的测量 E1.Left_Wheel_Vertical_displacement_Value = E1.Left_Wheel_Vertical_displacement_Value + (E1.Left_Wheel_Value - E1.Left_Wheel_Value_old) * cos(Value_yaw_old) ; PID_Control(20, 3 , 2 , PID_Yaw , 0 , 0,&PID_left.pwm,car_state); PID_Control(20, 3 , 2 , 0 , PID_Yaw , 0 ,&PID_right.pwm,car_state); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm , DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm , DL_TIMER_CC_1_INDEX); yaw_old = PID_Yaw; Value_yaw_old = (-90 - Value[2] ) * (M_PI / 180.00f);//小车上一刻的偏航角 E1.Left_Wheel_Value_old = E1.Left_Wheel_Value;//小车上一刻的左轮计数值 }
小车进入到‘E’状态 进行转向,如果偏航角为(-3,3) ,小车进入‘F’状态。
小车进入到‘F’状态 向0度行驶,如果小车循迹状态不为全白,则小车到C点。
小车进入到‘C’状态,进行黑线循迹。如果小车循迹状态为全白并且(偏航角大于172 或小于-172),则认为小车到了B点。
小车进入到‘B’点,原地向左转,如果小车偏航角为[-100,-110],则小车为‘b’状态。
小车进入到‘b’状态,向-105度行驶,如果小车左轮竖直方向计数值大于1170,则小车进入到‘G’状态。向-105度行驶的原因与状态‘a’的小车向-75度行驶的原因相同,故不做解释。
小车进入到‘G’状态 原地向右转向,如果小车偏航角大于-175度或小于175度,则进入到H状态。
小车进入到‘H’状态 向+-180度行驶,如果小车循迹状态不为全白,则进入到D点。
小车进入到‘D’状态 进行红外循迹,如果小车循迹状态为全白并且偏航角为[-10,10],小车进入到‘I’状态。
小车进入到‘I’状态 等蜂鸣器工作0.5s之后,再跳转到‘A’状态,小车行驶圈数自加1。若小车行驶圈数大于等于4圈(初始圈数为0),则题目4完成
题目四状态机图
void question4(void) { /*因为mpu6050有累积误差,在小车在每次一圈结束时记录最后的偏航角,让新的偏航角减去这个乘个系数的最后的偏航角 一般最后一题在这调参*/ Value[2] = Value[2] + Value_yaw_old1 * 0.12f; if(car_state == \'A\')//小车状态为 ‘A’ ,让原地向右转 { DL_GPIO_setPins(GPIO_Motor_PORT,GPIO_Motor_PIN_E2_AIN2_PIN); DL_GPIO_clearPins(GPIO_Motor_PORT,GPIO_Motor_PIN_E2_AIN1_PIN); PID_left.pwm = 550; PID_right.pwm = 450; DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm, DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm, DL_TIMER_CC_1_INDEX); if(Value[2] >= -80.0f && Value[2] 1170 ) //小车左轮的竖直位移的计数值大于1170,进入到 \'E\'状态 { Buzzer_count = 0; yaw_old =0; PID_left.pwm = 0; PID_right.pwm = 0; E1.Left_Wheel_Vertical_displacement_Value =0; E1.Left_Wheel_Value_old = 0; E1.Left_Wheel_Value = 0; DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm, DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm, DL_TIMER_CC_1_INDEX); DL_GPIO_setPins(GPIO_Motor_PORT,GPIO_Motor_PIN_E1_AIN2_PIN); DL_GPIO_clearPins(GPIO_Motor_PORT,GPIO_Motor_PIN_E1_AIN1_PIN); car_state = \'E\'; } } else if(car_state == \'C\')//小车进入到‘C’状态 进行黑线循迹 { if(Buzzer_count <=10) { Buzzer_count++; DL_GPIO_setPins(GPIO_Buzzer_PORT,GPIO_Buzzer_PIN_0_PIN); } else { DL_GPIO_clearPins(GPIO_Buzzer_PORT,GPIO_Buzzer_PIN_0_PIN); } Judge_pwm_duty_difference(IT.Infraed_Tracking_State,&pwm_duty_difference);//根据小车循迹状态 给出小车的左右轮pwm差值 PID_left.pwm = 470 + (pwm_duty_difference * 40); PID_right.pwm = 470 - (pwm_duty_difference * 40); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm , DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm , DL_TIMER_CC_1_INDEX); if(IT.Infraed_Tracking_State == 11 && (Value[2] = 172))//如果小车循迹状态为全白并且(偏航角大于172 或小于-172),则认为小车到了B点 { car_state = \'B\'; Buzzer_count = 0; pwm_duty_difference = 0; PID_left.pwm = PID_right.pwm=0; DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm, DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm, DL_TIMER_CC_1_INDEX); } } else if(car_state == \'E\') //小车进入到‘E’状态 进行转向,如果偏航角为(-3,3) ,小车进入‘F’状态 { PID_left.pwm = 550; PID_right.pwm = 450; DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm, DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm, DL_TIMER_CC_1_INDEX); if(Value[2] > -3 && Value[2] < 3) { car_state = \'F\'; PID_left.pwm = 0; PID_right.pwm = 0; DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm, DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm, DL_TIMER_CC_1_INDEX); DL_GPIO_setPins(GPIO_Motor_PORT,GPIO_Motor_PIN_E1_AIN1_PIN); DL_GPIO_clearPins(GPIO_Motor_PORT,GPIO_Motor_PIN_E1_AIN2_PIN); } } else if(car_state == \'F\')//小车进入到‘F’状态 向0度行驶,如果小车循迹状态不为全白,则小车到C点 { PID_Control(20, 1 , 8 , Value[2] , 0 , yaw_old ,&PID_left.pwm,car_state); PID_Control(20, 1 , 8 , 0 , Value[2] , yaw_old ,&PID_right.pwm,car_state); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm, DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm, DL_TIMER_CC_1_INDEX); yaw_old = Value[2]; if(IT.Infraed_Tracking_State != 11) { car_state = \'C\'; yaw_old =0; PID_left.pwm = PID_right.pwm = 0; DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm, DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm, DL_TIMER_CC_1_INDEX); } } else if(car_state == \'B\')//小车进入到‘B’点 原地向左转,如果小车偏航角为[-100,-110],则小车为‘b’状态 { if(Buzzer_count = -110.0f && Value[2] 1170 ) { Buzzer_count = 0; yaw_old =0; PID_left.pwm = 0; PID_right.pwm = 0; E1.Left_Wheel_Vertical_displacement_Value = 0;E1.Left_Wheel_Value_old = 0; E1.Left_Wheel_Value =0; DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm, DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm, DL_TIMER_CC_1_INDEX); DL_GPIO_setPins(GPIO_Motor_PORT,GPIO_Motor_PIN_E2_AIN2_PIN); DL_GPIO_clearPins(GPIO_Motor_PORT,GPIO_Motor_PIN_E2_AIN1_PIN); car_state = \'G\'; } } else if(car_state == \'G\')//小车进入到‘G’状态 原地向右转向,如果小车偏航角大于-175度或小于175度,则进入到H状态 { PID_left.pwm = 550; PID_right.pwm = 450; DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm, DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm, DL_TIMER_CC_1_INDEX); if(Value[2] 175) { car_state = \'H\'; PID_left.pwm = 0; PID_right.pwm = 0; DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm, DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm, DL_TIMER_CC_1_INDEX); DL_GPIO_setPins(GPIO_Motor_PORT,GPIO_Motor_PIN_E2_AIN1_PIN); DL_GPIO_clearPins(GPIO_Motor_PORT,GPIO_Motor_PIN_E2_AIN2_PIN); } } else if(car_state == \'H\')//小车进入到‘H’状态 向+-180度行驶,如果小车循迹状态不为全白,则进入到D点 { if(Value[2] = 0) { PID_Yaw = -180 + Value[2]; } PID_Control(20, 3 , 8 , PID_Yaw , 0 , 0,&PID_left.pwm,car_state); PID_Control(20, 3 , 8 , 0 , PID_Yaw , 0 ,&PID_right.pwm,car_state); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm, DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm, DL_TIMER_CC_1_INDEX); yaw_old=PID_Yaw; if(IT.Infraed_Tracking_State != 11) { car_state = \'D\'; yaw_old =0; DL_GPIO_setPins(GPIO_Motor_PORT,GPIO_Motor_PIN_E2_AIN1_PIN); DL_GPIO_clearPins(GPIO_Motor_PORT,GPIO_Motor_PIN_E2_AIN2_PIN); PID_left.pwm = PID_right.pwm = 0; DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm, DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm, DL_TIMER_CC_1_INDEX); } } else if(car_state == \'D\')//小车进入到‘D’状态 进行红外循迹,如果小车循迹状态为全白并且偏航角为[-10,10],小车进入到‘I’状态 { if(Buzzer_count <=10) { Buzzer_count++; DL_GPIO_setPins(GPIO_Buzzer_PORT,GPIO_Buzzer_PIN_0_PIN); } else { DL_GPIO_clearPins(GPIO_Buzzer_PORT,GPIO_Buzzer_PIN_0_PIN); } Judge_pwm_duty_difference(IT.Infraed_Tracking_State,&pwm_duty_difference); PID_left.pwm = 470 + (pwm_duty_difference * 40); PID_right.pwm = 470 - (pwm_duty_difference * 40); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm , DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm , DL_TIMER_CC_1_INDEX); if(IT.Infraed_Tracking_State == 11 && Value[2] = -10 ) { car_state = \'I\'; Buzzer_count = 0; pwm_duty_difference = 0; PID_left.pwm = PID_right.pwm=0; DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_left.pwm, DL_TIMER_CC_0_INDEX); DL_TimerG_setCaptureCompareValue(PWM_0_INST, PID_right.pwm, DL_TIMER_CC_1_INDEX); } } else if(car_state == \'I\')//小车进入到‘I’状态 等蜂鸣器工作之后 再跳转到‘A’状态,小车行驶圈数自加1 { Value_yaw_old1 = Value[2]; if(Buzzer_count <=10) { Buzzer_count++; DL_GPIO_setPins(GPIO_Buzzer_PORT,GPIO_Buzzer_PIN_0_PIN); } else { DL_GPIO_clearPins(GPIO_Buzzer_PORT,GPIO_Buzzer_PIN_0_PIN); car_state = \'A\'; laps_number++; } } }
四、代码文件
通过百度网盘分享的文件:empty_LP…
链接:https://pan.baidu.com/s/1N5vi2J0HFzZ_0mV7JbqbyQ?pwd=98zd
提取码:98zd
复制这段内容打开「百度网盘APP 即可获取
五、总结
填补在电赛的遗憾,就重做24年电赛题, 从2024年十月初到10月30日,耗时一个月完成(挤出课余时间,其实不是每天都写代码),除了MPU6050串口接收的部分代码是商家资料提供,其他均是本人所写。由于本人才疏学浅,代码和解析的不足挺多的,比如多余的变量,中断服务函数代码过多,状态机图有些状态转换没画出以及部分文字口语化等。作者已经大三了,留给我的大学生活时间已经不多,接下来我要学FPGA(因为我是集成专业的)和一些未来的打算。在此,特别鸣谢帮助我的同学和老师(特别鸣谢高老师)。最后希望读者都有充实的大学生活。与君共勉。
作者于2024年10月31日编写完成