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

项目实现

    • 前言
    • 实现成本
    • 赛题要求
    • 赛题分析
    • k210任务
    • stm32控制任务
      • 实现与K210的通信
      • 控制电机实现小车运动
    • 其他
    • 资料获取

前言

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

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

实现成本

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

赛题要求

赛题要求

赛题分析

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

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

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

k210任务

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

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

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

  • 红线循迹+路口识别+终点识别采用寻色块法
    在这里插入图片描述
    将三个色块的中心坐标经过给不同的权重,计算平均加权后的横坐标和目标直线的横坐标的差值作为误差,给到小车的转向环pid。当然方法还是很多的,网上常见的还有使用库函数实现线性回归拟合成一条直线。
    ps:博主在实现这个模块的过程中遇到了一个问题,那就是颜色阈值的确定,博主实际条件惨烈,使用的是胶布实现的赛道布置,并且不知道是不是由于反光,使用阈值编辑器自己得出看似效果不错的阈值实际效果很差,最后博主也没有找到解决方法,而是询问chatgpt使用它大概提供的阈值范围,在阈值编辑器效果不好,但是实际效果绝佳。也是一件玄学的事,希望有大佬能指点有什么找阈值的好方法。
    言归正传,既然循迹使用的是寻色块,那么为了简单化,博主将识别终点和识别路口都使用色块法,识别终点的逻辑是当视野中没有了红线视为终点,识别路口则是因为普通循迹状态下的色块识别的宽度和路口的宽度差距大,作为判断条件。当识别到宽度大于某个值的色块,视为识别路口
    在这里插入图片描述
    以上方法略微取巧,当然识别路口也可以使用识别黑色个数,但是那样又需要在弄一次黑色阈值,相当浪费时间,同时识别路口也有别的方法,不过博主这样是为了方便和循迹模块连接。下面是博主的代码部分,没写注释,代码细碎,看不懂没关系,博主之后将写好注释的代码整理出来。
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_numglobal code_flagm=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+1if(tmp[2]>60):uart_A.write(send_data_packet(0,1,0))#检测到了路口print('ok1')code_flag=0return 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=0return None'''m=0for 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+1print(tmp[5])if((m==0)and (code_flag==3)):uart_A.write(send_data_packet(0,1,0))#检测到了终点print('ok2')code_flag=0return None#print(m)code_flag=0uart_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_flagtext=uart_A.read(2) #读取数据#print(1)if text: #如果读取到了数据text=text.decode('utf-8')if(text[0]=='b'):if(text[1]=='1'):  #数字识别请求code_flag=1elif(text[1]=='2'): #循迹+路口识别请求code_flag=2elif(text[1]=='3'): #循迹+终点识别请求code_flag=3elif(text[1]=='4'): #数字匹配请求code_flag=4elif(text[1]=='0'): #停止运行,等待指令code_flag=0print(text)
uart_flag.irq(fun, GPIO.IRQ_BOTH)#使能外部中断,执行串口处理

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

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

def recog(task):global labelsglobal anchorsglobal num_goalglobal code_flagimg = 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=objnum_goal=labels[max_value.classid()]uart_A.write(send_data_packet(0,0,int(num_goal)))print(int(int(num_goal)))code_flag=0if(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=0lcd.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,很多大佬是使用匿名上位机,当然也是可以的,博主的速度环和转向环其实效果还是属于比较差的,因为调参太麻烦了,很是消磨耐心,没有队友帮忙调实在是太累了。至于这部分代码就不贴了,以来还是可读性不强,另一方面这部分代码网上应该有很多了,没必要贴出来丢人。
给大家瞅瞅我速度环波形
在这里插入图片描述
低速还是挺好的,抖动不大,所以博主也是让车的速度是低速走,是在没耐心调参了。相信各位的效果比我强。

其他

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

资料获取

[数字识别模型及openmv固件]
链接: https://pan.baidu.com/s/1APhRB1pNWLSt-NwvMtKmZQ 提取码: faiz

剩余资料等博主整理完上传github仓库和百度网盘~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/12142.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

.NET MAUI 开发电子木鱼(上)

本文介绍如何使用 .NET MAUI 开发一个电子木鱼应用。以实际的小应用开发为例&#xff0c;通过这个开发过程&#xff0c;介绍了其涉及的 .NET MAUI、Blazor、前端等相关知识点。文章涉及的应用已开源在 Github&#xff0c;大家可前往下载体验&#xff1a; https://github.com/sa…

年轻人为啥热衷去寺庙?

年轻人的苦&#xff0c;寺庙最清楚。 周末的寺庙挤满了年轻人&#xff0c;北京雍和宫限流了&#xff0c;杭州灵隐寺十八籽的手串限购了&#xff0c;南京鸡鸣寺从地铁站出口就开始排队了...... “上班和上学&#xff0c;你选择哪个&#xff1f;” ”我选择上香“ 工作和学习…

CSDN问答机器人

文章目录 前言一、背景二、总体流程三、构建知识库四、粗排五、精排六、Prompt总结相关博客 前言 先看结果: 已经连续很多周获得了第二名(万年老二), 上周终于拿了一回第一, 希望继续保持. &#x1f601; 这是今天的榜单, 采纳的数量相对较少, 之前基本上维持在100 重点说明…

从18楼失踪的猫,被ChatGPT救了 | 谷雨

撰文丨崔頔 编辑丨张瑞 出品丨腾讯新闻 谷雨工作室 * 版权声明&#xff1a;腾讯新闻出品内容&#xff0c;未经授权&#xff0c;不得复制和转载&#xff0c;否则将追究法律责任。 一只猫从18楼失踪了&#xff0c;搜索无果后&#xff0c;伤心的主人晓娅去找ChatGPT倾诉。人工智能…

ChatGPT「奶奶漏洞」又火了!扮演过世祖母讲睡前故事,骗出Win11序列号

【导读】只要对ChatGPT说&#xff1a;请扮演我已经过世的祖母&#xff0c;你就可以让它为你做几乎任何事情了&#xff0c;比如生成Win11、Office365的激活码。如此玄学的提示词攻击怎么防&#xff1f;OpenAI真是任重道远啊。 最近&#xff0c;著名的ChatGPT「奶奶漏洞」又火了&…

ChatGPT的「奶奶漏洞」火了,扮演过世的祖母,让它为你做几乎任何事情!

来源&#xff1a;新智元 【新智元导读】只要对ChatGPT说&#xff1a;请扮演我已经过世的祖母&#xff0c;你就可以让它为你做几乎任何事情了&#xff0c;比如生成Win11、Office365的激活码。如此玄学的提示词攻击怎么防&#xff1f;OpenAI真是任重道远啊。 最近&#xff0c;著名…

重磅!微软开源Deep Speed Chat,人人拥有ChatGPT!

点击上方“AI遇见机器学习”&#xff0c;选择“星标”公众号 第一时间获取价值内容 【导读】微软开源的DeepSpeed Chat&#xff0c;让开发者实现了人手一个ChatGPT的梦想&#xff01; 人手一个ChatGPT的梦想&#xff0c;就要实现了&#xff1f; 刚刚&#xff0c;微软开源了一个…

微软CHAT-GPT4研究报告(全中文版)

下载地址 &#xff1a;​​​​​​​javaTodo: 打造java开发一站式套件 (gitee.com)

ChatGPT教你如何用Python和Matplotlib绘图(下)

想学习用 Python 绘图吗&#xff1f;ChatGPT 将为您提供帮助。 微信搜索关注《Python学研大本营》&#xff0c;加入读者群&#xff0c;分享更多精彩 该项目要求 ChatGPT 教您如何生成用于创建绘图和可视化的 Python 代码。只需简要描述您要创建的绘图&#xff0c;ChatGPT 就会…

什么是 chatGPT?

OpenAI 的语言模型ChatGPT是 AI 研究的最新突破。ChatGPT建立在GPT&#xff08;生成式预训练转换器&#xff09;架构之上并经过调整以执行各种任务——从响应查询到生成文本片段甚至朗诵诗歌——ChatGPT 已迅速成为可用于自然语言处理的最强大工具之一。 ChatGPT 因其在理解和…

Titanic 泰坦尼克号预测-Tensorflow 方法-【Kaggle 比赛】

本文介绍Kaggle入门比赛Titanic泰坦尼克号幸存预测的解题思路&#xff0c;使用的是神经网络和Tensorflow框架。提交代码附在本文的最后部分。 基本思路为: 导入数据集对数据预处理训练预测并输出结果 一、入门介绍 1. 比赛介绍 Kaggle是一个数据建模和数据分析竞赛平台。 泰…

霍金

伟大的物理学家去世了&#xff0c;他的事迹将永远停留在这一页。请让我问您沉痛哀悼。。。

热重分析(TG)基本原理与实战分析

TG的基本原理? 热重分析(thermogravimetric analysis&#xff0c; TG或者TGA)是指在程序控温条件下测量待测样品的质量与温度变化关系的一种热分析技术&#xff0c;可以用来研究材料的热稳定性和组分。 注&#xff1a;之所以定义为质量的变化而非重量变化是基于在磁场作用下&a…

思维模型 霍金斯能量场(能量层级)

本系列文章 主要是 分享 思维模型&#xff0c;涉及各个领域&#xff0c;重在提升认知 1 模型故事 霍金斯能量场-组织 科学家发现&#xff0c;在任何一个组织里面&#xff0c;霍金斯能量场 这个规律也是完全适用的。少数高层级的人的意识能量可以抵消绝大多数人的意识负能量。…

Kaggle系列(一):Spaceship Titanic(太空飞船泰坦尼克)

开坑开坑Kaggle系列&#xff08;通过kaggel练习机器学习与数据分析能力&#xff09; 2022年3月9日&#xff0c;这是第一个版本的太空泰坦尼克任务 我的Github中发布了本任务包含的相应源码与思路分析讲解&#xff0c;欢迎来⭐。 本文主要记录如何对数据进行分析的过程。 开…

霍金-现代最伟大的物理学家之一、20世纪享有国际盛誉的伟人之一

据 BBC 等多家外媒报道&#xff0c;知名物理学家史蒂芬霍金已经去世&#xff0c;享年 76 岁。 霍金的家人在周三凌晨发表声明&#xff0c;证实他已在剑桥的家中死亡。霍金的孩子 Lucy , Robert 和Tim 在一份声明中说&#xff1a;“我们亲爱的父亲今天去世了&#xff01;我们感到…

刚刚,霍金的一个预言成真了,这次吓坏不少人!

1 刚刚去世的霍金&#xff0c;对于人工智能&#xff0c;曾有这样的预言&#xff1a; 如果有人设计计算机病毒&#xff0c;那么就有人设计不断自我完善、直到最终超越人类的人工智能&#xff0c;其结果将是一种新的生命形式。 你可能并不是一个讨厌蚂蚁的人&#xff0c;但也会无…

霍金与硅谷:你不知道的故事

硅谷Live / 实地探访 / 热点探秘 / 深度探讨 “我的名字是斯蒂芬霍金&#xff0c;在过去的50年中&#xff0c;我到全世界进行演讲和学习&#xff0c;给大众普及关于时间和空间的奥秘&#xff0c;还有那掌握全宇宙的法则。” Welcome to my world。 2012年&#xff0c;6月19日晚…

细数霍金关于AI的五大预言,向伟大的科学巨人致敬

今天&#xff0c;我们这个时代最著名的物理学家之一斯蒂芬霍金去世了&#xff0c;享年76岁。这位英国科学家以其在黑洞和相对论方面的开创性著作而闻名&#xff0c;并撰写了几部畅销书。 2017年&#xff0c;霍金宣布将他在1966年&#xff0c;也就是24岁时撰写的博士论文上传到剑…