2021年电赛结束了,这里分享一下F小车题代码和方案。
多少个通宵不眠夜,只能说已经全力以赴,结束了现在已经问心无愧了。
@山东赛区 组内成员:大三*3
出来题目的时候觉得还行,没什么特别奇怪不会的部分。之前因为赛题准备器材里面有很奇怪的角度测量、透明空心球,一直以为会是控制器用,搞得我们准备控制题的很紧张……当时各种预测都有,结果今年出了小车题
在暑假准备的时候准备了stm32和430控制的小车(需要代码可以留言,有几次还是跑的很稳的。当然当时学430上手的时候还是挺难搞的,以后有空再写一个文档。)
暑假准备的……只准备了相关模块,但是小车供电啊之类的硬件连接设计没有自己想好(12V转5V等,我们天真的以为随便用一个12-5的模块就行,结果没有稳压没有保护,模块电流限制等等问题都没有考虑……竞赛的时候用了坏的再换就很痛苦……)
暑假准备的时候问了一个已经毕业的大佬学长,大佬:学会Verilog、FPGA……我:??? 数电模电可再见吧,我不行。
我:啊这,然后我们准备的时候就定了选控制题……(忘了这个大佬打的是什么题了,应该可能不是控制题)
emm发题前我们还在忙一些课业之类的事情,属实是忙的没空在11月怎么准备。11.3我们还在期待明天延期吧……
11.4早上有点睡过了,发题了我还在睡觉
来了实验室就开始讨论方案: 主要实现以下方面:
stm32部分是我实现
openMV部分我一点不会(暑假懒了),由队友实现
硬件弄车另一个队友 (暑假弄了个半成品车模,不太行 准备的还是不太够)
当时想着之前轮速有问题显示以下用PID控制,但是嘛,时间不太够,最后没用PID…… PWM单控制速度慢点也非常稳
晚上九点多老师回去了我们还在吵是3个红外还是2个红外
然后给老师发消息问,然后开了个腾讯会议问(为什么当时不直接通话……)
3个灰度(老师建议保证抓住线,我们临时就买了6个)
2个附加的红外 防止撞到墙
1个红外识别药品
(PA2 3)
PB10 TX
PB11 RX
PA9 RXD
PA10 TXD
灰度 | ( |
PA4 中 | PA5 右 |
---|---|---|---|
stm32 | PA5 | PA6 | PA7 |
白色)的时候输出低电平
OLED | SCL | SDA |
---|---|---|
stm32 | PB0 | PB1 |
RES 接PB11 如果是用4针iic接口这个脚可以不接
L298N | PWA(左) | IN1 | IN2 | PWMB(右) | IN3 | IN4 |
---|---|---|---|---|---|---|
stm32 | PA8 | PB14 | PB15 | PA11 | PB13 | PB12 |
PA8驱动力弱?
L298N | M1(左) | M2 | M1(右) | M2 |
---|---|---|---|---|
电机 | OUT1 | OUT2 | OUT1 | OUT2 |
电机编码器 | C1(左) | C2 | C1(右) | C2 |
---|---|---|---|---|
stm32 | PB7 | PB6 | PA0 | PA1 |
电机 :【 M1 GND C1 C2 3.3V M2 】
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 |
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车实际没太多时间测 可能代码不好
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;
}
}
}
}
}
这部分不是我做的hhh,一直在看队友录模板、调整精度
老师:很多经验教训需要总结,先休息好,进入学习状态,以后机会很多。
代码:
蓝牙1车:链接:https://pan.baidu.com/s/1gIsHPX7HccK6Uns2c_B_qg
提取码:ji9d
蓝牙2车:链接:https://pan.baidu.com/s/18MaYlvZyOE6h7lEjkp6DNQ
提取码:fzwf
吃饭的时候在操场摸到了学校的猫猫(好像他叫桶桶来着)