日常·唠嗑

     小师弟说在广东省工科赛跟电赛拿奖了,听了很开心,那个腼腆的男孩,也能开始自己独挡一面了。我个人认为,在大学中参与竞赛,并不是要蛮干,而是要在竞赛中,实践,查漏补缺,进行总结,所以今天邀请小师弟写写自己的心得,分享给大家。

前言

     经过大一 1年的学习,我和我的两个队友组队参加了上大学以来的第一个比赛——电赛,经过了漫长的准备,不断发现问题,不断解决问题,虽然过程很坎坷,但是最终也顺利完成并获奖。这为我后面比赛积累了经验和提高了自信,有了电赛的基础后,我开始准备我的第二个比赛——广东省工科赛。

一、实验效果

直接先上成果视频,全程16秒完成。

2022年广东省工科赛(省一,开源7天)

二、赛题分析及方案

1、赛题内容:

初赛:

  • (1)自行设计和制作一台参赛全地形越障排爆小车,可采用轮式、履带式结 构,轮式底盘最大轮径不超过 105mm,履带式底盘的轮径不超过 45mm。具体 设计、材料、零件的选用(可采用现场提供的标准套件)及加工制作均由参赛学 生自主完成,整车的装配调试在现场完成,现场提供相关套件供参赛队选用。
  • (2)全地形越障排爆小车的主体基板(底盘)需要现场采用激光加工设备进 行加工,非金属材料,厚度 3mm 或 5mm。所用设备:北京正天恒业数控技术有 限公司(多功能激光雕刻机 D90M)或广州华之尊光电科技有限公司(i.Laser3000 精密型二氧化碳非金属激光切雕一体机)。
  • (3)全地形越障排爆小车必须是完全自主的(禁止各种形式的无线通讯);
  • (4)全地形越障排爆小车的长宽高分别不超过 300mm× 230mm×200mm。
  • (5)电控装置:主控电路的设计及制作、检测元器件、电机(舵机)及驱动 电路自行选定。电控装置所用电池自备,比赛时须安装到车上并随车行走,场内 赛程中不得更换,供电电源额定电压不超过 9V。
  • (6)车上电机需使用不大于 5kgf.cm 的直流减速电机或扭力不超过 30kg 的 舵机。
  • (7)比赛场地中设定三种四个不同特点、不同难度的障碍物和一个气球排爆区, 每种障碍物和气球排爆均有一定的分值,参赛队根据比赛规则自主设计制作全地 形越障排爆小车。场地整体效果图和尺寸如图所示

决赛:

     第二阶段(决赛)规则如下:

  • 1、在起点处,选手把弹珠放进小车的载盘后,启动小车进行比赛。小 车把弹珠进行搬运,并正确卸进相应的收纳盒。载盘装载弹珠数量为4个, 小车把弹珠正确卸进相应的收纳盒时,每个弹珠得5分。该单项满分为20分。 此环节代替初赛阶段的扎气球环节。
  • 2、在小车上安装一个弹珠载盘,弹珠载盘由参赛学生赛前自行设计制 作。也可采用现场提供的标准套件,加工制作由参赛学生自主完成。收纳盒 与弹珠由竞赛现场提供。
  • 3、参赛队携带在本校制作完成并调试好的全地形越障定点搬运小车及 相关的零部件参加竞赛。在第二阶段(决赛)时,小车启动后自动行驶并跨 越三种四个障碍物后,需识别颜色板上色卡的颜色,并将弹珠卸进对应颜色 收纳盒中。
  • 4、色卡签由选手进入赛道时,在现场抽取并向裁判出示后,由裁判放 置色卡。收纳盒相应颜色的顺序,在比赛开始前由裁判随机放置。

2、实施方案:

     分析赛题,我们用灰度传感器进行循迹和黑色十字的识别和记数,识别部分则采用openmv进行颜色识别,openmv资源丰富,容易上手,简单的颜色识别完全够用,弯道部分的通过我们则利用结构,在小车车头的左右两侧安装导向轮来辅助过弯,扎气球排爆任务利用一个舵机带动带针的自制杆完成排爆,决赛部分则是把带针的自制杆改成管道即可,方法有很多,用管道可以不需要改代码直接换装置就可以。

三、材料选择

器件选择:
主控芯片:STM32f103rct6 x1
电池:2s航模锂电池 x1
稳压模块:自主设计的PCB集成板
机器视觉:openmv x1
循迹模块:七路灰度循迹模块 x1
舵机:SG90舵机 x1 20kg舵机 x1
显示屏:OLED显示屏 x1
电机:直流减速电机 x4
电机驱动模块TB6612fng电机驱动模块 x2

 


     另外自主设计了两块PCB板,一块为电源稳压板,给多个模块所需对应电压进行供电,另一块将openmv、四个直流减速电机、两个电机驱动模块、灰度循迹模块、OLED显示屏、舵机组装成一个控制系统,七路灰度循迹模块用于对地面黑线进行循迹,当其七路同时识别到黑线时,执行对应的操作进行避障,OLED的作用是用于小车调试,显示黑线记录数据,以及颜色识别等信息数据,方便对小车参数的调试。

四、程序设计

程序思路

  • 1.开始将系统初始化;
  • 2.小车利用读取灰度传感器每一路的电平进行判断,从而进行循迹,利用7路灰度循迹模块进行循迹,可以有效提高寻迹的精确度;
  • 3.设定一个变量每到达一个十字路口变量发生变化,该变量对应一个数值,到达不同的十字路口会对应执行不同的程序,该变量只有在七路灰度传感器全部识别到黑线时才会发生变化,所以在避障过程中,七路灰度传感器也是全部识别到黑线,也会使该变量发生改变,对应相应的避障任务执行相应的程序,
  • 4.根据比赛场地得知,当识别到色卡前的十字黑线时,累计识别到3个十字黑线,该变量为3,程序跳到串口中断,即开启openmv进行颜色识别,进行识别结果的数据发送给单片机;
  • 5.单片机通过接收openmv发送的信息执行对应操作,定义一个新的变量开始记录;
  • 6.再识别到与色卡颜色相同的颜色时,新设定的变量发生改变,小车执行进行排爆或分拣动作;
  • 7.小车完成后排爆或分拣任务后,小车直行行驶至终点,即结束。

PID:

     电机随着使用时间的增加,电机的性能会发生改变,输出相同的PWM值。速度会跟最开始测的值是不一样的,会使小车无法稳定的直行,PID算法用来应对这一问题,用小车后轮电机上带的两个编码器来读取电机的速度,把电机转动的速度转化为一个数字量传到微处理器,使速度稳定在一个数值。

void TIM4_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
	{
		int cnt_left,cnt_right;
		cnt_left = abs((TIM2->CNT)-0X7FFF);
		cnt_right = abs((TIM3->CNT)-0X7FFF);
		
		TIM2->CNT = 0X7FFF;
		TIM3->CNT = 0X7FFF;
		
		//左电机	
		spd_now1 = cnt_left;
		err_now1 = target_left - spd_now1;
		jisuan1 = Kp*(err_now1-err_last1) + Ki*err_now1 + Kd*(err_now1+err_last_last1-2*err_last1);
		out_left += jisuan1;
		if(out_left<0)
			out_left = 0;
		if(out_left>100) 
			out_left = 100; 
		TIM_SetCompare1(TIM1,out_left);	
		TIM_SetCompare2(TIM1,out_left);	
		err_last_last1 = err_last1;
		err_last1 = err_now1;
		
		//右电机
		spd_now2 = cnt_right;
		err_now2 = target_right - spd_now2;
		jisuan2 = Kp*(err_now2-err_last2) + Ki*err_now2 + Kd*(err_now2+err_last_last2-2*err_last2);
		out_right += jisuan2;
		if(out_right<0)
			out_right = 0;
		if(out_right>100) 
			out_right = 100; 	
		TIM_SetCompare3(TIM1,out_right);	
		TIM_SetCompare4(TIM1,out_right);
		err_last_last2 = err_last2;
		err_last2 = err_now2; 
		
		TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
	}
 
}

 

越障部分:

while((L == 1 && M11 == 1 && M1 == 1&& M == 1 && M2 == 1 && M22 == 1&& R == 1)&&(a==0))  //开局第一条线(只是识别一下记个数)
		     {
					 forward (5);
					 Delay_ms (100);
					 a=1;
			     break ;
		     }
			
				while((L == 1 && M11 == 1 && M1 == 1&& M == 1 && M2 == 1 && M22 == 1&& R == 1)&&(a==1))  //冲上坡
				{
					forward(15);
	        Delay_ms (1600);
					forward(10);//下坡减速
					Delay_ms (1000);
					Delay_ms (415);
					a=2;
					break ;
				}
				while((L == 1 && M11 == 1 && M1 == 1&& M == 1 && M2 == 1 && M22 == 1&& R == 1)&&(a==2))  //识别到台阶前黑线,可以冲台阶了
				{
					forward (10);
	        Delay_ms (3600);
					a=3;
					break ;
			
				}
 

颜色识别部分:

# LOTS OF Blob Detection
import sensor, image, time
from pyb import UART
from pyb import LED
pink_threshold =(46, 63, 57, 80, 18, 66)
blue_threshold =(21, 65, 1, 46, -75, -30)
green_threshold =(51, 78, -59, -28, -15, 50)
pink_color_code = 1 # code = 2^0 = 1
blue_color_code = 4# color_code_3 = 2^2 = 4
green_color_code = 2# color_code_4 = 2^3 = 8
sensor.reset() # 初始化摄像头
sensor.set_pixformat(sensor.RGB565) # 选择像素模式 RGB565.
sensor.set_framesize(sensor.QVGA) # use QQVGA for speed.
sensor.set_auto_whitebal(False) #关闭白平衡。白平衡是默认开启的,在颜色识别中,需要关闭白平衡。
sensor.set_vflip(True)
sensor.skip_frames(time = 2000) # Let new settings take affect.
clock = time.clock() # Tracks FPS.
left_roi = [53,86,129,80]
uart = UART(3, 115200)#P4、5  TX、RX
while(True):
    clock.tick() # Track elapsed milliseconds between snapshots().
    img = sensor.snapshot()#.lens_corr(1.8)#.chrominvar()
    blobs = img.find_blobs([pink_threshold , green_threshold,  blue_threshold], area_threshold=400,blobs = img.find_blobs,roi=left_roi)
    if blobs:
        for blob in blobs:
            x = blob[0]
            y = blob[1] #
            width = blob[2] # 色块矩形的宽度
            height = blob[3] # 色块矩形的高度
            center_x = blob[5] # 色块中心点x值
            center_y = blob[6] # 色块中心点y值
            color_code = blob[8] # 颜色代码
            if color_code == pink_color_code:
                img.draw_string(x, y - 10, "red", color = (0xFF, 0x00, 0x00))
            elif color_code == blue_color_code:
                img.draw_string(x, y - 10, "blue", color = (0xFF, 0x00, 0x00))
            elif color_code == green_color_code:
                img.draw_string(x, y - 10, "green", color = (0xFF, 0x00, 0x00))
            img.draw_rectangle([x, y, width, height])
            img.draw_cross(center_x, center_y)
    else:
        color_code=0
    output_str="[%d]" % (color_code)
    uart.write(output_str+'\r\n')
    print(clock.fps())
    print(color_code)

 

五、竞赛心得

     我认为工科赛全地形避障小车的设计不仅仅需要学会单片机编程控制和电路板的绘制,还需要设计好小车的结构,在调试中发现小车避障是会抖动,一开始以为是轮子打滑的原因,后面换了其他轮子发现问题还是解决不了,最后无意中发现是结构的原因。另外,小车的控制思路可能在自己理想中是可行的,但在实际中却出现了很多问题,然后又重新开始改思路,检测是否数据采集到,是否执行到对应的程序,需要不断尝试,不断地调试,在确保小车能稳定完成全程后再提升小车的速度追求更好的成绩。

六、工程获取

方式1:
直接点击链接进行下载
2022广东省工科赛省一(越障组,程序+PCB+3D打印)

方式2:
关注“不眠者科技”公众号,免费获取(需要发推文pyq)

资料内容:

  • 1、PCB文件
  • 2、3D打印文件
  • 3、程序工程