一、前言
复盘一下2023年的工训赛,分享一下比赛经验。现在回顾依然会觉得遗憾,但面对遗憾的最好方式就是努力走好现在的路,事事遗憾,事事也值得。希望此文章可以帮助到你,祝比赛顺利。
二、比赛场地与流程
三、材料选型与结构
3.1、选材
主控:STM32F103ZET6
机械臂:升降式滑轨
视觉:OpenMV4
底盘:麦克纳姆轮,直流减速编码电机,维特智能陀螺仪
3.2、机械结构
滑轨的底盘和物料盘采用的是幻尔的总线舵机,我们将传统的机械臂改装成升降梯的结构,控制简单、便利。通过编码器电机控制同步带的滑动去控制机械爪的升降,滑轨的顶部与底部分别放置一个限位开关,再配合PID算法可实现机械爪升降到任意位置。
四、视觉识别部分
OpenMv与K210入门简单,低成本,功能强大,但受光线影响很大,和OpenCV对比起来,会被秒杀。建议有经济和能力的同学可以选择CV。我们选择的是OpenMv,关于它的入门有很多文章,可以自己去查找学习,我就不多做介绍了,直接上代码。
此部分是寻找三个色环的代码
def ring(a):
global flag
global send_num
if a=="r":
img = sensor.snapshot()
img.binary([ring_thresholds[0]])
img.dilate(1)
for blob in img.find_blobs(graythreshold,area_threshold=7000, pixels_threshold=100, area_threshold=2000, merge=True):
img.draw_rectangle(blob.rect())
img.draw_cross(blob.cx(), blob.cy())
lcd.display(img)
print("red:(",blob.cx(),",",blob.cy(),")")
uart.write("R")
uart.write(str(trans_Three(blob.cx()))+str(trans_Three(blob.cy()))+'\r\n')
if blob.area() >5000 :
print("RED")
return 'r'
if a=="g":
img = sensor.snapshot()
img.binary([ring_thresholds[2],ring_thresholds[1]])
img.dilate(1)
if flag==0:
send_num = send_num+1
if send_num>15 :
send_num = 0
if flag == 1 :
send_num = send_num+1
if send_num > 20 :
send_num = 0
flag =0
for blob in img.find_blobs(graythreshold,area_threshold=3000, pixels_threshold=2000, area_threshold=1000, merge=True):
img.draw_rectangle(blob.rect())
img.draw_cross(blob.cx(), blob.cy())
lcd.display(img)
print("green:(",blob.cx(),",",blob.cy(),")")
uart.write("R")
uart.write(str(trans_Three(blob.cx()))+str(trans_Three(blob.cy()))+'\r\n')
if blob.area() >3000 :
flag =1
if a=="b":
img = sensor.snapshot()
img.binary([ring_thresholds[2]])
img.dilate(1)
for blob in img.find_blobs(graythreshold,area_threshold=7000, pixels_threshold=100, area_threshold=2000, merge=True):
img.draw_rectangle(blob.rect())
img.draw_cross(blob.cx(), blob.cy())
lcd.display(img)
print("blue:(",blob.cx(),",",blob.cy(),")")
uart.write("R")
uart.write(str(trans_Three(blob.cx()))+str(trans_Three(blob.cy()))+'\r\n')
return 'b'
img.binary([grayscale_thres])
#对图像边缘进行侵蚀,去除边缘相邻处多余的点。threshold用来设置去除相邻点的个数,
#threshold数值越大,被侵蚀掉的边缘点越多,边缘旁边白色杂点少;数值越小,
#被侵蚀掉的边缘点越少,边缘旁边的白色杂点越多。
img.dilate(1)
#对图像边缘进行膨胀,膨胀函数image.dilate(size, threshold=Auto)
#threshold用来设置去除相邻点的个数,threshold数值越大,边缘越膨胀;数值越小,边缘膨胀的小。
此部分是寻找色块的代码
if color=="red":
img = sensor.snapshot()#拍照
img.binary([cir_thresholds[0]])
img.dilate(1)
if flag_R==0:
send_num_R_T = 0 #找到色块的话就运行此函数
send_num_R_F = send_num_R_F+1
if send_num_R_F>5 :
send_num_R_F = 0
uart.write("@")
uart.write(str(trans_Three(000))+str(trans_Three(002))+'\r\n')
print("not")
if flag_R == 1 :
send_num_R_F = 0 #找到色块的话就运行此函数
send_num_R_T = send_num_R_T+1
if send_num_R_T > 10 :
send_num_R_T = 0
uart.write("@") #发送其他识别标志位的包头是@
uart.write(str(trans_Three(000))+str(trans_Three(001))+'\r\n')
print("yes")
flag_R =0
#trans_Three()是强转成三位数的发送,配合主代码里的解包使用,也就是只有1的话也会转换为001
for blob in img.find_blobs(graythreshold,area_threshold=2600, pixels_threshold=100, area_threshold=1000, merge=True):
img.draw_rectangle(blob.rect())
img.draw_cross(blob.cx(), blob.cy())
lcd.display(img)
#print("red:(",blob.cx(),",",blob.cy(),")")
uart.write("R") #发送色块坐标的包头是R
uart.write(str(trans_Three(blob.cx()))+str(trans_Three(blob.cy()))+'\r\n')
#return 'r'
if blob.area() >3000 :
flag_R =1
主函数部分
根据单片机下发的任务,去寻找所需颜色的色块或者色环
while(True):
while(1):
get_data()#接收数据
if(mission == 1):
find_cir("red"
if(mission == 2):
find_cir("green")
if(mission == 3):
find_cir("blue")
if(mission == 4):
ring("r")
if(mission == 5):
ring("g")
if(mission == 6):
ring("b")
if(mission == 7):
uart.write("@")
uart.write(str(trans_Three(000))+str(trans_Three(002))+'\r\n')