单K210模块低成本实现21电赛题送药小车

这篇具有很好参考价值的文章主要介绍了单K210模块低成本实现21电赛题送药小车。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

博主已经大三,想着暑假参加电赛,于是将21电赛的控制题尝试做了一下,由于成本有限,想着能不能仅使用一块k210完成这个项目,但是看网上查找资料都没人这样做,于是博主就按照自己的想法实现了这个,为了让更多和博主一样的小白能够简单制作这个项目,博主决定写一下这个项目,顺便记录一下自己的学习过程,顺便希望暑假电赛一切顺利。
因为代码还没有注释整理好,所以博主暂时只分享出数字识别模型(当初博主想找网上现成的模型,由于营销号都限制收费获取,博主一怒之下暴训500张图,实现了0.97的识别率)
k210模块,单片机,stm32,嵌入式硬件

博主的车还是很慢的
小车的结构照片和实现功能视频博主还没拍,之后添加链接补上~

实现成本

  1. K210——实现循迹+数字识别
  2. stm32f103c8t6——实现小车主控
  3. 小车底盘+两个直流减速编码电机+万向轮
  4. M3型号铜柱,螺丝若干
  5. 电池,电机驱动,oled,稳压模块

赛题要求

赛题要求

赛题分析

题目基础部分要求使用一辆小车实现近端,中端,和远端的送药过程
并且给出了红线用于循迹,那么比赛的需求就是重点考察以下几个功能

  • 1 红线循迹功能
  • 2 数字识别功能

首先对于红线循迹,由于寻常传感器大多是寻黑线,大多对于红线识别效果不好,市面大多采用多路灰度传感器循迹,但是由于成本较高,有些朋友会望而却步,经济实力足够的朋友采用这种方法循迹效果自然更好。同时,也具备另一种解决方法摄像头循迹,本人采用的就是这个方法;另一个功能数字识别也有两种常用解决方法:1、使用opemmv的模板匹配;2、使用K210训练识别模型,本人采用的也是第二个选项。(博主也是刚入门的菜鸟,如果还有博主没想到的实现方法,请大佬指点)
那么这里很明显,要想实现低成本制作,我们可以把循迹和数字识别结合在一起解决,这样成本当然最低,同时opemmv价格上是大于K210的,所以博主决定使用K210实现这两个功能
ps:由于赛题为直线,有的大佬不采用循迹,而是使用编码器和电机搭配位置环控制,做到行走固定路线,实在是很牛逼的想法啊。
k210模块,单片机,stm32,嵌入式硬件这种灰度传感器就不需要使用了,本人亲测排雷,还浪费了我一个礼拜,贪小便宜吃大亏。

k210任务

我的做法是将k210的需求分解成4个任务

  • 开机识别数字
  • 循迹加路口识别
  • 循迹加终端识别
  • 匹配数字并给出转向结果

至于什么时候执行对应的任务,则由stm32通过串口给出指令。这里有个细节就是K210并没有串口中断,但是你又不可能定时接收,这样做即浪费及时间和资源,实时性也没有保障,所以我选择使用stm32和k210连接一条外部中断线,这样stm32发送数据前将那条线拉低或者拉高实现K210在中断里面执行。实现伪串口中断,当时博主也是灵光一闪想到的,还是挺机智的。
解决了通信问题,接下来就是K210的重点功能实现。

  • 红线循迹+路口识别+终点识别采用寻色块法
    k210模块,单片机,stm32,嵌入式硬件
    将三个色块的中心坐标经过给不同的权重,计算平均加权后的横坐标和目标直线的横坐标的差值作为误差,给到小车的转向环pid。当然方法还是很多的,网上常见的还有使用库函数实现线性回归拟合成一条直线。
    ps:博主在实现这个模块的过程中遇到了一个问题,那就是颜色阈值的确定,博主实际条件惨烈,使用的是胶布实现的赛道布置,并且不知道是不是由于反光,使用阈值编辑器自己得出看似效果不错的阈值实际效果很差,最后博主也没有找到解决方法,而是询问chatgpt使用它大概提供的阈值范围,在阈值编辑器效果不好,但是实际效果绝佳。也是一件玄学的事,希望有大佬能指点有什么找阈值的好方法。
    言归正传,既然循迹使用的是寻色块,那么为了简单化,博主将识别终点和识别路口都使用色块法,识别终点的逻辑是当视野中没有了红线视为终点,识别路口则是因为普通循迹状态下的色块识别的宽度和路口的宽度差距大,作为判断条件。当识别到宽度大于某个值的色块,视为识别路口
    k210模块,单片机,stm32,嵌入式硬件
    以上方法略微取巧,当然识别路口也可以使用识别黑色个数,但是那样又需要在弄一次黑色阈值,相当浪费时间,同时识别路口也有别的方法,不过博主这样是为了方便和循迹模块连接。下面是博主的代码部分,没写注释,代码细碎,看不懂没关系,博主之后将写好注释的代码整理出来。
ROIS={
'down':   (0, 164, 220, 20),
'middle': (0, 144, 220, 20),
'up':	  (0, 124, 220, 20)
}
state_1=(0,120,224,10)
#判断是什么状态的循迹 2是识别十字路口 3是识别终点
def track():
    global route_num
    global code_flag
    m=0#记录识别的数量
    n=0#记录路程
    img = sensor.snapshot()#.binary([(61, 19, 18, 91, 62, -21)])
    #img.draw_rectangle(10,20,100,60,color = (255, 0, 0))(100, 0, 18, 91, 62, -21)
    #img.draw_rectangle(170, 50 , 30, 50,color = (255, 0, 0))
    # img =img.binary([(0, 25)])
    if(code_flag==2):   #路口循迹还是终点循
       #for area in state_1:#路口识别
       a=img.find_blobs([(22, 100, 36, 100, -8, 67)],roi=state_1,merge=True,pixels_area=100)
       tmp=find_max(a)
       if(tmp):
                #m=m+1
           if(tmp[2]>60):
                uart_A.write(send_data_packet(0,1,0))#检测到了路口
                print('ok1')
                code_flag=0
                return None
    '''
    if(code_flag==3):   #终点循迹
       a=img.find_blobs([(22, 100, 36, 100, -8, 67)],roi=[0, 164, 220, 20],merge=True,pixels_area=60)#识别红线
       if (a==None):
#            for b in a:
#                m=m+1 #统计检测到的黑色色块的数量
#       if(m>6): #统计到五块以上
            uart_A.write(send_data_packet(0,1,0))#检测到了终点
            print('ok2')
            print(m)
            code_flag=0
            return None
    '''

    m=0
    for area in ROIS:
       a=img.find_blobs([(22, 100, 36, 100, -8, 67)],roi=ROIS[area],merge=True,pixels_area=25)
       tmp=find_max(a)
       if(tmp):
           img.draw_rectangle(tmp[0:4])
           img.draw_cross(tmp[5], tmp[6])
           n=n+tmp[5]
           m=m+1
           print(tmp[5])

    if((m==0)and (code_flag==3)):
        uart_A.write(send_data_packet(0,1,0))#检测到了终点
        print('ok2')
        code_flag=0
        return None
    #print(m)

    code_flag=0
    uart_A.write(send_data_packet(((n/m-115+200)*0.16-12),0,0))
    print(n/m)
    print(send_data_packet(((n/m-115+200)*0.15-10),0,0))


    lcd.display(img)

以上是识别路口+循迹+识别终点模块代码。
另外接下贴出K210串口识别指令和数据帧格式

#数据帧格式 	    | x-循迹偏移量 |y-检测成功 成功1,不成功0  | z-作为判断识别到的数字  或者   作为左右转向的0左,1右,2直行
def send_data_packet(x, y,z):
    data='ba'+str('%03d'%x)+str(y)+str(z)+'\r\n'
    return data
#串口中断 判断下一次是否发送数据
def fun(uart_flag):
    global code_flag
    text=uart_A.read(2) #读取数据
    #print(1)
    if text: #如果读取到了数据
        text=text.decode('utf-8')
        if(text[0]=='b'):
            if(text[1]=='1'):  #数字识别请求
                code_flag=1
            elif(text[1]=='2'): #循迹+路口识别请求
                code_flag=2
            elif(text[1]=='3'): #循迹+终点识别请求
                code_flag=3
            elif(text[1]=='4'): #数字匹配请求
                code_flag=4
            elif(text[1]=='0'): #停止运行,等待指令
                code_flag=0
        print(text)
uart_flag.irq(fun, GPIO.IRQ_BOTH)#使能外部中断,执行串口处理

至此实现了四个任务中的两个;
还剩下两个功能,由于都涉及数字识别,所以博主把他们放一起。
首先对于k210如果你想要长时间跑模型还想使用找色块等部分库函数,你就需要使用内存略微小点的固件,我使用的是这个固件,具体怎么烧录固件和接下来的识别模型教程不懂得大家可以去看别的博主的文章或者b站视频。
k210模块,单片机,stm32,嵌入式硬件

下载网站,和模型都放在文章结尾处,有需要的自取。
使用这个模型就可以实现保留部分找色块这种的基本图像功能,也能较长时间运行模型。识别部分反而更加简单,训练出一个好模型,基本就实现了功能,具体思路就是匹配数字,同时发送识别到的数字给单片机,单片机判断是否为近端,如果为近端,就不需要功能4了,如果为非近端,就让单片机发送对应的指令就i行了。任务4的实现就是简单将识别的数字和我们开机识别的数字比对,匹配成功则判断坐标是坐标还是右边,将结果发送给单片机处理。

def recog(task):
    global labels
    global anchors
    global num_goal
    global code_flag
    img = sensor.snapshot()
    objects = kpu.run_yolo2(task, img)
    if objects:
        if(code_flag==1):
            max_value=objects[0]
            for obj in objects:
                pos = obj.rect()
                img.draw_rectangle(pos)
                img.draw_string(pos[0], pos[1], "%s : %.2f" %(labels[obj.classid()], obj.value()), scale=2, color=(255, 0, 0))
                if(max_value.value()<obj.value()):
                     max_value=obj
            num_goal=labels[max_value.classid()]
            uart_A.write(send_data_packet(0,0,int(num_goal)))
            print(int(int(num_goal)))
            code_flag=0

        if(code_flag==4):
             for obj in objects:
                 pos = obj.rect()
                 img.draw_rectangle(pos)
                 img.draw_string(pos[0], pos[1], "%s : %.2f" %(labels[obj.classid()], obj.value()), scale=2, color=(255, 0, 0))
                 if(num_goal==labels[obj.classid()]):
                    if(pos[0]>80):
                        uart_A.write(send_data_packet(0,1,1))#检测到了右行
                    elif(pos[0]<80):
                        uart_A.write(send_data_packet(0,1,0))#检测到了左行
                 else:
                    uart_A.write(send_data_packet(0,0,2))#未检测到,直行
             code_flag=0
    lcd.display(img)

代码稀碎,感兴趣的我之后把整理好的代码放到文件末。

stm32控制任务

这里要处理的比较简单,具体需要的功能如下

实现与K210的通信

这里有两段功能

  • stm32发送指令给k210,每次发送指令前都将K120设置的外部中断对应的端口电平反转,使得K210及时响应串口数据。
  • 解析K210发送的数据帧,根据当前的stm32处于第几个状态去进行对应数据帧的解析
    下面是部分代码,老样子后续详细代码整理好会发到github仓库和百度网盘。
#include"fun.h"
#include"OLED.h"
#include"UART.h"
extern char num_goal;//需要检测的目标数字
extern uint8_t recog_flag;//检测是否成功
extern uint8_t turn_err;//转向误差
extern uint8_t K210_state;//设置K210的状态
extern uint8_t turn;//转向
extern uint8_t turn_stack[4];//转向栈
extern uint8_t top;//栈顶指针
extern uint8_t send_flag;
extern uint8_t start_flag;//开始标志
extern uint8_t recog_count;
/*
 *功能:将信息发送给K210
 *参数:K210_state 选择要设置的K210的状态 
 *返回值:无
*/
void usart_pack(uint8_t K210_state)
{
	GPIO_WriteBit(GPIOC,GPIO_Pin_13,!GPIO_ReadOutputDataBit(GPIOC,GPIO_Pin_13));
	Send_Byte(USART1,'b');//发送帧头数据
	switch(K210_state)
	{
		case 0:Send_Byte(USART1,'0');break;
		case 1:Send_Byte(USART1,'1');break;
		case 2:Send_Byte(USART1,'2');break;
		case 3:Send_Byte(USART1,'3');break;
		case 4:Send_Byte(USART1,'4');break;
	}
}

/*
 *功能:解析接受的数据
 *参数:需要解析的数据
 *返回值:无
*/
void data_deal(char *buffer)
{
	if(buffer[0]=='b'&&buffer[1]=='a')//接受的数据无误
	{
		send_flag=1;
		if(K210_state==1)
			num_goal=buffer[6];
		else if(K210_state==2)
		{
			if(buffer[5]=='1') //检测成功
				recog_flag=1,turn_err=-1;
			else recog_flag=0,turn_err=(buffer[2]-0x30)*100+(buffer[3]-0x30)*10+(buffer[4]-0x30);
			
		}
		else if(K210_state==3)
		{
			if(buffer[5]=='1') //检测成功
				recog_flag=1,turn_err=-1;
			else recog_flag=0,turn_err=(buffer[2]-0x30)*100+(buffer[3]-0x30)*10+(buffer[4]-0x30);
		}
		else if(K210_state==4)
		{
			if(buffer[5]=='1')//识别成功数字
			{
				recog_flag=1;
				turn=buffer[6]-0x30;
			}
			else
			{
				if(recog_count==9)
				{
					turn=0;
				}
				recog_count++;
			}
		}
		else if(K210_state==0)
		{
			start_flag=1;
		}
	}
}

控制电机实现小车运动

小车的运动其实无非两点

  • 控制小车基本运动,前进,后退,左转,右转建议大家写的时候把代码好好封装一下,做到这四个运动方式可以根据自己传入的参数去执行大概需要的运动幅度大小,另外可以作为一些固定运动作为小车偏移的一个补偿
  • 控制小车循迹部分,我采用的是K210将pid转向环的速度结果直接传入stm32解析数据获得,但是当然也可以自己将K210的误差作为数据,在stm32中进行pid计算

对于这部分,我都是在pid速度环的基础上实现的,另外,这里我的转向环其实也是可以作为速度环的参数,其实也算是串级pid了吧。我也不太清楚,但是总的来说使用了速度环和转向环两种

ps:对于速度环的调参,也没什么经验,网上大佬都有,这里只是建议大家可以使用串口做到上位机显示波形的模式,这里博主使用的是vofa,很多大佬是使用匿名上位机,当然也是可以的,博主的速度环和转向环其实效果还是属于比较差的,因为调参太麻烦了,很是消磨耐心,没有队友帮忙调实在是太累了。至于这部分代码就不贴了,以来还是可读性不强,另一方面这部分代码网上应该有很多了,没必要贴出来丢人。
给大家瞅瞅我速度环波形
k210模块,单片机,stm32,嵌入式硬件
低速还是挺好的,抖动不大,所以博主也是让车的速度是低速走,是在没耐心调参了。相信各位的效果比我强。

其他

其他也没什么好说的,毕竟小白一枚,做出这个项目纯属侥幸。希望各位的项目能比我的更稳,更快!

资料获取

[数字识别模型及openmv固件]
链接: https://pan.baidu.com/s/1APhRB1pNWLSt-NwvMtKmZQ 提取码: faiz
代码
链接:https://pan.baidu.com/s/1f7gOiSKLh-ZcFvK_8mshAA
提取码:faiz
剩余资料等博主整理完上传github仓库和百度网盘~文章来源地址https://www.toymoban.com/news/detail-600318.html

到了这里,关于单K210模块低成本实现21电赛题送药小车的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 智能送药小车(二)——K210物体检测,训练模型与部署

    线上训练模型参考这篇: Maixhub模型训练平台整体流程 下面仅介绍利用Mx-yolov3训练模型并部署在k210上的整体流程。 利用K210采集数据集 使用说明:插上合适的SD卡(最大32GB),采集不同类别图像时要在代码相应位置进行修改(有注释提示),程序运行后按下KEY会进行图像采集

    2024年02月14日
    浏览(30)
  • 2023 电赛 E 题 K210 方案

    K210芯片是一款基于RISC-V架构的嵌入式人工智能芯片,具备低功耗、高性能的特点。它拥有强大的图像处理和机器学习能力,适用于边缘计算设备和物联网应用。为了方便开发者,K210芯片提供了丰富的外设接口,包括摄像头接口、显示接口、WiFi、蓝牙等,同时支持多种编程语

    2024年02月14日
    浏览(22)
  • 2023 电赛 E 题 K210方案

    K210芯片是一款基于RISC-V架构的嵌入式人工智能芯片,具备低功耗、高性能的特点。它拥有强大的图像处理和机器学习能力,适用于边缘计算设备和物联网应用。为了方便开发者,K210芯片提供了丰富的外设接口,包括摄像头接口、显示接口、WiFi、蓝牙等,同时支持多种编程语

    2024年02月14日
    浏览(25)
  • 分享21年电赛F题-智能送药小车-做题记录以及经验分享

    自己是今年准备电赛的同学一名,电赛结束了,想把自己之前刷过的题目,通过这篇文章,来分享一波做这道题的思路和调试方法 自己在做之前的电赛题目时,也苦苦没有思路,不知道该怎么去下手,面对题目的要求和限制,应该如何去分析和实现 由于我们主要是准备小车

    2024年02月13日
    浏览(26)
  • 电赛备赛日记(一):K210与STM32串口通信

       拖更了n久的备赛日记终于来啦,最近实现了关于K210图像识别并将所需数据(即目标类别,目标在图像中的加权坐标)其中,加权坐标指K210识别到的目标并框出的框的宽和高与框左上顶点的坐标加权,希望以此来判断目标所处的位置并方便后续进行诸如寻迹,目标跟随等

    2024年02月04日
    浏览(46)
  • 亚博k210视觉模块与stm32双向通信

    【K210模块】使用UART模块发送和接收数据_KevinGuo457的博客-CSDN博客 K210的串口_uart_a.write_飞鸟211的博客-CSDN博客 ①每隔1s终端以及串口助手收到消息并显示 ②通过串口助手发送123,K210收到数据并显示 这里如果想要指定K210接收的数据,判断条件不能直接用==(原因参考上面的链接

    2024年04月23日
    浏览(82)
  • k210实现麦克风阵列声源定位

    import sensor import image import lcd import time import KPU as kpu from fpioa_manager import * from Maix import GPIO # 设置麦克风阵列 fm.register(board_info.MIC_ARRAY_DATA, fm.fpioa.I2S0_IN_D0, force=True) fm.register(board_info.MIC_ARRAY_WS, fm.fpioa.I2S0_WS, force=True) fm.register(board_info.MIC_ARRAY_BCK, fm.fpioa.I2S0_SCLK, force=True) # 初始化

    2024年02月14日
    浏览(32)
  • STM32通过K210进行PID巡线,使用蓝牙模块与电脑通信从而进行P,I,D参数的调节

    目录 一.前言部分(废话部分) 二.K210色块识别 1.必要知识 2.色块识别 3.单片机的接收代码 三.通过蓝牙连接在电脑上实现PID的调参 我使用的是HAL库,如果你使用的是标准库的话可以根据对应标准库的函数进行更改即可 因为之前使用灰度传感器进行巡线,即使用上PID,最后的效果也

    2024年02月14日
    浏览(32)
  • 【电子系统综合实践】--2021电赛F题智能送药小车

    主要内容     设计并制作智能送药小车,模拟完成在医院药房与病房间药品的送取作业。院区结构示意如图1所示。院区走廊两侧的墙体由黑实线表示。走廊地面上画有居中的红实线,并放置标识病房号的黑色数字可移动纸张。药房和近端病房号(1、2号)如图1所示位置固定

    2024年02月15日
    浏览(32)
  • 智能送药小车完整版【电赛、课设】开源(含源代码)

    目录 任务要求 摘要 1、前言 2、系统方案设计 3、理论分析与计算 3.1 病房选择: 3.2 电机引脚及状态 3.3 灰度传感器及电机状态 4、系统电路设计与仿真 4.1系统硬件框图 4.2 单片机最小板电路 4.3 驱动电路设计 4.4 灰度传感器设计 5、系统软件设计 6、系统测试及结果分析 6.1 系

    2024年02月09日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包