当前位置: 首页 > news >正文

《平衡小车控制系统》电子设计大赛校赛感悟

我们学校举行了一次电子设计大赛选拔赛,虽然我们在测试的时候全部都可以完成,最后考核的时候因为方案选择问题以及各种设计逻辑等原因没能成功晋级,但我能从这次备赛中学到很多东西,遂分享一下,与广大网友交流经验。(只讲思路,代码太烂了就不提供了)

题目如下:

考察点:

基础部分:1.小车循迹 2.停车+蜂鸣器 3.控速停车

发挥部分:1.视觉云台,激光打靶 2.上下坡 3.字模识别+信息传输 4.考察小车上坡部分是否能够灵活,不写死。(虽然差不多也算是写死了)

根据题目要求,其实主要就分两部分:平衡小车循迹上坡+激光云台追靶子。

平衡小车部分:硬件清单:STM32F103C8T6 MPU6050 蜂鸣器模块 OLED显示屏 LM2596降压模块 正点原子ESP8266WiFi模块 TB6612MG 按键 波动开关 

激光云台:STM32F103C8T6 串口TTL模块 OLED显示屏 左右舵机线 还有些零件

基础部分:

小车循迹部分:模块采用的是八路灰度传感器,代码层面只需要移植商家给的资料,然后通过现场调试,通过自适应调试能够很好地适应赛道情况。处理逻辑也不难,就是当检测到左边出现黑线就给小车双轮赋值一个差速使它往右拐,检测到右边出现黑线就往左拐。然后用循迹函数封装起来。(在赛场上我还看到了拿OpenMV做循迹的,当时我们还没有这个财力,后续可能会考虑一下优化方案,这也是我们吃亏的地方TvT)

如下图所示:

小车平地停车部分:我们根据赛道规则,这里有挺多方案,可以选择通过检测黑线个数,达到第四个就让小车停下来,也可以通过时间计时,大概时间点停下来,也可以通过里程计,计算到差不多的时候停下来,我们采用的是比较保险的里程计+黑线检测方法。让小车停下来。(至于声光提醒只需要给个标志位然后在主函数执行即可)

时间要求:正常速度应该在20-30s内即可完成,速度要求可以忽略。

发挥部分:

发挥部分还是比较复杂的考虑的因素很多,我们整体方案采用的是工控机+OpenCV等方式进行执行视觉的全部功能(这里有个弊端,也是后面没晋级的原因)这里分几个点讲述一下大体思路,代码写的比较丑就不分享了。

视觉部分:

主要是OpenCV的处理算法,由于寒假期间配置过了环境以及YOLOv5,YOLOv8等环境,对OpenCV有了比较深刻的了解,所以我后面就主要负责这一部分。

识别靶子思路

                                                          

可以看到靶子是张这个样子的,我首先考虑的是,通过OpenCV识别圆形的算法实现靶子检测,但是当时没有考虑到一个点,如果单单是检测圆形的话,这要求比较严格,仅仅只有在小车运动的时候靶子始终正对着摄像头才有可能是一个标准的圆。所以只能另寻其路。

我们通过观察靶子实时运动情况,发现一个方案,就是通过椭圆拟合算法,恰好OpenCV里面也有类似的算法。然后通过灰度,高斯模糊,二值,边沿检测,轮廓提取等视觉处理方法,最后还要进行椭圆拟合(长短轴限定,面积限定等方法提高精确度)拟合成功后最重要的是得到靶子中心的坐标(这个是相对于摄像头图像640x480大小左上角来说的坐标),然后通过串口把中心坐标传输给单片机,再通过PID算法控制激光云台进行云台追踪。最后的效果如下:


                                (做了半个月的效果还算可以至少跑基础部分还不会跟丢)

识别字模思路:

                                              

                                                                         (字模库)                          

因为我们用的是工控机所以我们也不能像K210,那样可以进行训练,因为工控机性能没达到那个Level,所以在这里我们用OpenCV自带的模版匹配功能。方案也挺简单。首先按顺序保存待匹配的模版到文件夹里面,因为这里的顺序就是对应的数字1-8的顺序不然没经过训练,他不知道图像对应的是什么顺序。然后再通过对读入的图像进行简单处理,灰度,二值,提取轮廓等,然后获取边框信息再裁剪成符合字模库大小进行一一对比。并且输出对比得分最高的即可实现。所需功能。

传输方式:

因为工控机和平衡小车是不能连一条线的,所以采取的方案是小车搭配ESP8266与主机进行SOCKET通信(TCP)把得到的数字进行取余2判断是奇还是偶。然后让小车指定冲坡。

云台部分:

坐标的作用:

首先我们要明白靶子的中心坐标是指什么?

解释:因为每个摄像头能捕获的视频帧图像大小是固定的,它只能看到这么大的范围。而我们把这么大的范围抽象成像素点,有(640,480)大小的图像,这里的坐标是指距离左上角(0,0)的相对位置。在这里我们可以从图中看出红点坐标是(188,156)。

那么我们得到坐标的目的是什么?

解释:因为我们需要用云台去通过摄像头实时去追靶子,这样我们就需要通过摄像头实时得到靶子的位置。在这里我们为了方便,我们把摄像头中点定为激光中点。

为什么可以把摄像头中点定为激光中点?

因为我们的云台长这个样子:

我们只需要保持在竖直方向上激光和摄像头中点是在同一水平线上的。然后通过双头夹子往摄像头方向偏一定的角度,因为两直线只要不平行就一定会相交(前提是竖直方向是一样高度)。当然,也可以横轴在同一水平,竖轴形成夹角  。                              

                                           

这样我们就可以认为摄像头中点就是激光打到的中点了。

激光云台部分:

得到坐标后,我们还需要控制云台通过转动横轴竖轴(这里我们称X,Y轴)来实现实时追踪运动的靶子。这里发现,我们可以实时得到靶子中心点和摄像头中心点的坐标差,有了这个,我们就可以仿照平衡小车,速度环,直立环,转向环等等使用PID算法实现实时追踪。大概就张这个样子。

有了这个函数,我们只需要调KP,KI,KD即可(都试试看看哪个效果比较好就用哪个)

调试方法:

由于我们用的是数字舵机   X轴365.5°(转弯一圈要复位) Y轴180°

所以因为脉冲范围是500-2500,所以对于我们来说,主要调的是KI,要求累加到2000左右。如果用的是步进电机的话,可能不需要KI,可能KP就差不多了(我同学说的)

调好之后,再进行一些算法处理比如过滤偏移量过大的点,动态调节PID(适应冲坡速度剧增)等等方法,可以增强稳定性。

平衡小车部分:

                                               

冲坡部分:

这一部分,主要是要做好循迹和选择合适的时候加大速度冲上坡,当然如果循迹模块用得不好,每次上坡都是不稳定因素,他只取决于在最后一刻冲坡的角度,如果偏的太多可能会冲歪,后续就会脱离轨道循不回去。我们就采取比较笨的方法,就是检测到黑线就嘎嘎加速,一直走直到冲完坡的时候才减速。这样是十分不稳定的,但是没有什么办法,因为判断坡放在哪,八路循迹是做不到的,如果用里程计也是有点误差的。除非我们用OpenMV实时监测路况。(如果网友有好的办法,请指教)

停坡部分:

这次比赛的精髓,对于我们来说就是不可控因素,因为我们停坡其实相对写死,我们采用的方案是上坡后通过检测黑线来让停止,当然由于坡上平地只有8cm,这很可能会来不及停就冲下去了,所以我们就使用一个刚好能冲上坡的速度,让它冲上去速度就减小到一个很小的速度,再给他赋值一个相对平衡的目标值即可实现停坡。因为只要两秒,可以用反复赋值硬控两秒。我们在比赛前两天,发现我们这种办法其实不稳定,换一个场地就会受到影响,所以我们只能在实地调整。)不知道网友是否有更好地方法交流交流)

下坡部分:

主要做的是减速+偏转一定角度,使其下坡能够及时循迹,防止脱离轨道,循不回去。这里也没做什么方案,就纯属硬调。

反思与总结:这次没能成功晋级校赛原因其实有很多,但大部分都是自己的原因,因为我们选择的是工控机OpenCV做视觉处理 STM32F103C8T6作为主控。没考虑周到。

1.工控机没有写自启动程序,而采用电脑远程终端控制并且写了两个代码需要切换代码,这样做会被误认为在数字识别部分动手脚,违反规矩。

2.STM32F103C8T6作为主控,缺点是引脚太少了!!!我们本来想加上按键来执行每个部分,但是无奈的是管脚都拉满了,根本不够用,其实也是因为自己没学好其他单片机的原因造成的,这是后续需要加强的。

3.代码逻辑,不应该把全部部分融合到一起,依次执行,仅仅通过计时器来控制每一部分执行时间。导致我们在附加部分,老师没放好坡我的小车就已经开始走了,最后直接喜提0分(满分30)应该要通过关机开机然后按按键的方法,不要再写一堆了。

总结下来还是因为自己水平没达到像其他实验室同学,师兄的Level。后续需要加强学习,不断提高自己的能力!

相关文章:

  • A44 STM32_HAL库函数 之SD通用驱动 --B -- 所有函数的介绍及使用
  • 有哪些技术可代替docker?
  • Java--数组的使用
  • 数据结构习题
  • CSS【实战】抽屉动画
  • HTB Editorial
  • 对LitJson开源插件的自定义尝试
  • shell脚本编程(概念、编程和语句)
  • MoCo v3(ICCV 2021)
  • 2024年阿里巴巴全球数学竞赛首次向人工智能(AI)开放
  • 软件设计不是CRUD(22):在流式数据处理系统中进行业务抽象落地——设计思考
  • Shell中执行.sh文件的常见方式
  • 微服务中的相关概念
  • Qt QListView自定义树状导航控件
  • 【学习】程序员资源网址
  • 10个确保微服务与容器安全的最佳实践
  • 2017 前端面试准备 - 收藏集 - 掘金
  • HashMap剖析之内部结构
  • JavaScript实现分页效果
  • vue自定义指令实现v-tap插件
  • 道格拉斯-普克 抽稀算法 附javascript实现
  • 反思总结然后整装待发
  • 服务器之间,相同帐号,实现免密钥登录
  • 关于Flux,Vuex,Redux的思考
  • 记一次删除Git记录中的大文件的过程
  • 力扣(LeetCode)21
  • 面试题:给你个id,去拿到name,多叉树遍历
  • 前端工程化(Gulp、Webpack)-webpack
  • 如何合理的规划jvm性能调优
  • 如何使用Mybatis第三方插件--PageHelper实现分页操作
  • 如何在GitHub上创建个人博客
  • 用 Swift 编写面向协议的视图
  • 用Canvas画一棵二叉树
  • 在Mac OS X上安装 Ruby运行环境
  • 06-01 点餐小程序前台界面搭建
  • media数据库操作,可以进行增删改查,实现回收站,隐私照片功能 SharedPreferences存储地址:
  • CMake 入门1/5:基于阿里云 ECS搭建体验环境
  • ​人工智能书单(数学基础篇)
  • # Spring Cloud Alibaba Nacos_配置中心与服务发现(四)
  • #经典论文 异质山坡的物理模型 2 有效导水率
  • %3cli%3e连接html页面,html+canvas实现屏幕截取
  • (22)C#传智:复习,多态虚方法抽象类接口,静态类,String与StringBuilder,集合泛型List与Dictionary,文件类,结构与类的区别
  • (4) openssl rsa/pkey(查看私钥、从私钥中提取公钥、查看公钥)
  • (安全基本功)磁盘MBR,分区表,活动分区,引导扇区。。。详解与区别
  • (附源码)ssm经济信息门户网站 毕业设计 141634
  • (论文阅读32/100)Flowing convnets for human pose estimation in videos
  • (每日一问)计算机网络:浏览器输入一个地址到跳出网页这个过程中发生了哪些事情?(废话少说版)
  • (一)基于IDEA的JAVA基础1
  • (轉貼)《OOD启思录》:61条面向对象设计的经验原则 (OO)
  • .NET / MSBuild 扩展编译时什么时候用 BeforeTargets / AfterTargets 什么时候用 DependsOnTargets?
  • .net core IResultFilter 的 OnResultExecuted和OnResultExecuting的区别
  • .NET HttpWebRequest、WebClient、HttpClient
  • .net mvc 获取url中controller和action
  • .NET(C#、VB)APP开发——Smobiler平台控件介绍:Bluetooth组件
  • .Net6 Api Swagger配置