2021年电赛F题综合回顾与分析

关于这次2021年的电子设计大赛F题(智能送药小车)的比赛历程,经过一段时间的学习和准备,前后面对了8月份的延迟比赛和11月份的亚克力球消失之谜,怀着忐忑不安的心情开始三天四夜紧张又充实的比赛。

回顾赛题,个人认为本赛题对控制的要求比较低,由于题中有着时间限制,所以让传统控制的核心PID调节显得可有可无,反而着重考察了对于图像的处理,系统的整合以及多任务的切换。

整体思路设计:


首先是小车的搭建。本次比赛小车搭建了三层板,第一层固定了四个直流减速电机以及给小车供电的四节3.7V的18650动力电池,前端安装了用于寻迹的七路灰度传感器。第二层固定了L298N电机驱动,使用PWM调节控制小车的转速,小车两边固定两个稳压模块分别调节电压给电机驱动和单片机供电,第三层放置STM32单片机,图像处理系统OPENMV,自己制作的集成了OLED,三色LED灯,蜂鸣器等等的电路板以及固定了红外对光关管的放置药品盒子。
图像的识别处理部分,利用OPENMV固定对地距离,通过改变角度偏差对每一个数字以及每一种道路情况进行不少于1500次的数据采集,利用Edge Impulse网站搭建出网络模型。数字识别时,将看到的图像画面分为左右两个部分,寻找到黑色矩形框后,对矩形里的数字进行识别,取十次识别结果中的众数作为最终识别数字。道路识别部分添加了七路灰度传感器,保证小车不会偏差道路,其余识别部分与上述同理。
对于远端的T字道路,由于没有使用广角摄像头,所以无法同时将四个数字放到镜头中,设计的解决方法是通过T字路口直接左转,循迹到达第二个T字路口时,开始识别数字,如果并没有识别到,掉头全速冲到右侧的T字路口寻找目标数字。小车到达病房,检测到拿走药品开始返回时,运用堆栈原理,小车可以原路返回。

两车通过蓝牙技术无线通信,小车1到达病房后向小车2发送指令,小车2开始循迹直行,并到达暂停点,小车1卸载药品开始返回时向小车2发送指令,小车2开始识别数字到达病房。

部分代码:

# 道路识别所需文件
net_load = "trained_load.tflite"
labels_load = [line.rstrip('\n') for line in open("labels_load.txt")]
# 道路列表
load_list=[]

# 数字识别(0背景,1到8数字)
def number_classes(img,net,labels,roi_rects):
    for r in img.find_rects(threshold = 20000,roi=roi_rects):
        img.draw_rectangle(r.rect(), color = (255, 0, 0))
        roi=r.rect()
        for obj in tf.classify(net, img, roi=roi,min_scale=1.0, scale_mul=0.8, x_overlap=0.5, y_overlap=0.5):
            sorted_list = sorted(zip(labels, obj.output()), key = lambda x: x[1], reverse = True)
            if(sorted_list[0][1]>0.8):
                img.draw_string(r.rect()[0] + 20, r.rect()[1]-20, sorted_list[0][0],color = (255,0,0), scale = 2,mono_space=False)
        blue_led.toggle()
        return sorted_list[0][0]

# 数字识别所需文件
net_number = "trained_number.tflite"
labels_number = [line.rstrip('\n') for line in open("labels_number.txt")]

# 把整个屏幕分成左右两个部分
roi_left =(0,0,155,180)
roi_right=(140,0,180,180)

# 数字列表
number_left_list=[]
number_right_list=[]

# 检测十次中出现最多的元素并返回
def get_maxtimes(list):
    maxtimes=max(list,key=list.count)
    return maxtimes

# 外部受控引脚
p6_in = Pin('P6', Pin.IN, Pin.PULL_UP)#设置p_in为输入引脚,并开启上拉电阻
p7_in = Pin('P7', Pin.IN, Pin.PULL_UP)#设置p_in为输入引脚,并开启上拉电阻

clock = time.clock()
# 检测次数
limit_times=10

while(True):
    clock.tick()
    img = sensor.snapshot()
    value_p6 = p6_in.value()
    value_p7 = p7_in.value()
    if(value_p6==0):
        result_load=load_classes(img,net_load,labels_load)
        green_led.toggle()
        if(result_load!=None):#识别到的路属于直线、十字、T字和黑色虚线中一个
            load_list.append(result_load)
            if(len(load_list)>2):
                rd=get_maxtimes(load_list)
                print('load:',str(rd))
                connect(rl,rr,rd)
                load_list.clear()
                rd=0
            else:
                continue
    if(value_p7==0):
        result_number_left=number_classes(img,net_number,labels_number,roi_left)
        result_number_right=number_classes(img,net_number,labels_number,roi_right)
        blue_led.toggle()
        if(result_number_left!=None): #识别到有效数字
            number_left_list.append(result_number_left)
            if(len(number_left_list)>limit_times):
                rl=get_maxtimes(number_left_list)
                print('left number:',str(rl))
                number_left_list.clear()
        if(result_number_right!=None): #识别到有效数字
            number_right_list.append(result_number_right)
            if(len(number_right_list)>limit_times):
                rr=get_maxtimes(number_right_list)
                print('right number:',str(rr))
                connect(rl,rr,rd)
                number_right_list.clear()
                rr=0
                rl=0

总结与思考:

小车整体的设计思路没有明显错误,但有些地方会显的力不从心。由于本次设计只用了OPENMV进行图像处理,尽管我们从一开始的OPENMV3升级到OPENMV4 PLUS,但在图像识别和处理方面依然不是很理想,在车身倾斜后,识别的正确率会下降很多。如果使用K210或者树莓派等处理起来会轻松一些。还有便是小车的转弯方面,虽然“DELAY大法”是不错,但毕竟还是存在一部分不确定因素,对于这点,我们可以添加一个陀螺仪,精确控制转弯角度,尽量减少不确定因素,同时在小车两侧添加红外对光管,图像处理和数字循迹双重保障。
通过这次电赛,还是感觉到应当平时多多积累,多做一些往年的电赛的题目练手,一步一步来,把各个模块调通,确保需要用到东西可以直接往里植入,提前测试无误。

物联沃分享整理
物联沃-IOTWORD物联网 » 2021年电赛F题综合回顾与分析

发表回复