掌上单片机实验室 – 低分辨率编码器测速方式完善(24)

一、背景

        本以为“掌上单片机实验室”这一主题已告一段落,可最近在测试一批新做的“轮式驱动单元”时,发现原来的测速算法存在问题。

        起因是:由于轮式驱动单元的连线较长,PCB体积也小,导致脉冲信号有干扰,加之脉冲周期正好和定时器溢出的周期相近,使得很多产品在测试过程中,PID调速不成功。先是怀疑硬件焊接存在问题,可连接示波器监测脉冲信号后发现,输出的脉冲是正确的,推测应该是软件上还有不完善之处。加之我一直对目前的测速算法有点不满意,觉得太过复杂,连自己隔段时间再看程序,都有点晕,所以决心彻底完善一下。

        这个算法断断续续搞了10多年了,一开始因为只是做示例程序,没有太花心思,只是将曾在工作中用过的思路搬了过来,以解决所做的小车编码器分辨率较低的问题,实现用低分辨率码盘实现测速、调速。测试虽不完美,但能实现,也就没有再深究。后来因为各种原因,小车的事情也是断断续续,测速的问题也就被搁置了。

        这次重拾小车,感觉应该彻底解决一下,不留遗憾;调速PID自整定问题解决了,测速就成了小车能否可靠调速的唯一障碍。所以再次审视自己原来的构思,是否设计上就存在不合理之处。

二、问题发现及完善方案

        目前的测速方式是:利用前一脉冲的周期,计算当前测速周期结束时不完整脉冲的当量,从而提高测量精度。

        因为目前小车硬件所提供的码盘,分辨率较低,脉冲频率一般在10 ~ 200Hz之间,如果将测速周期定为100ms,用计数法,每次只有不到20个脉冲,一般在10个一下,量化误差太大。

        所以才想出所谓基于前一脉冲周期倍频的方式。但实施下来发现,为了避免各种意外导致计算出错,尤其是采集脉冲通常使用中断,计算则在中断外完成,为了消除由此可能产生的异常,在程序上逐步增加了不少代码,导致可读性极差,且并未真正消除。

        这次在轮式驱动单元的成品测试中,对照示波器采集的脉冲信号,就发现了由于上述原因导致的粗大误差。

        重新思考原来的测速构思,发现自己有点“自寻烦恼“,折腾了半天,把代码搞得那么复杂,其最后的实质就是用测周期方式代替计数法测速(也就是频率)!所有的问题以及增加的防护代码都源于最后那个不完整的脉冲是否计入本次测速的计算。可实质是:即便实现了,也是基于前一脉冲周期的推测,而非实际情况,没有价值。

        所以,决定只使用周期计算,放弃最后一个不完整脉冲。但为了避免单个脉冲的波动(由于结构上的问题,存在这种可能),导致速度变化不真实,取前N个脉冲的平均周期作为计算依据。如针对我所做的轮式驱动单元以及FIRA小车,轮子转一圈的脉冲分别为100、60,假设用10个脉冲的平均周期计算,实质上只对应了轮子1/10(1/6)圈,也就是说可以一圈中调整10(6)次速度,完全可以满足需求。

        替换为这个算法后,程序大大简化了,逻辑很清楚。

        原来程序设计的脉冲周期采集方式我觉得还不错,保留不变,具体方式是:

        建立一个连续的 us 计时器,每采集一个脉冲,对应记录一个时标,设置一个16个单元的环形缓存,可记录前16个脉冲对应的时标。计算时,用当前脉冲时标减前N个脉冲的时标,即可得到N个脉冲的平均周期。

        之前为了尽量使用 Arduino 原生函数,us定时器直接使用了 micro() 函数;由于采集是在中断程序中完成,似乎存在问题,没有去仔细研究这个函数是如何实现的,暂时放弃,改为使用硬件定时器。

        为了可靠采集脉冲周期,尝试使用了 HAL 函数,可行。使用时发现,STM32duino也在不断完善,以前在2.2.1版本中也用过,这次升级为 2.7.1,发现原来的方式不行了,阅读硬件定时器头文件发现,增加了获取硬件定时器句柄的函数:

        以便方便使用HAL库,从而使用定时器的一些高级功能。

        唯一增加的防护性代码是:

        因为作为时标的计时器设计为32位,高16位是硬件定时器溢出中断程序中软件计时实现的;而记录脉冲时标也是在中断中操作,如果出现读取计时值时正好计时器产生溢出中断,而此时由于正处于脉冲中断服务中无法响应,则会出现计时器高位少计,导致脉冲时标出错,防护方式如下:

        此外,新增加了脉冲干扰处理,因为正常脉冲宽度至少1ms(按目前设计,转速最快也不到1kHz),小于此宽度应该是干扰信号所致。正好使用了硬件定时器,启用通道比较功能,脉冲中断只是启动定时器延时(暂定延时500us),延时触发中断后,采集脉冲引脚,如脉冲信号仍然有效,则确定为有效脉冲,执行相应处理:

        这样修改后的测速计算如下:

        和原来的测速计算比较(可以看前面上传的程序),新的只有20行代码,原来的有约70行代码。关键是,修改后的测速效果更好、更可靠了;原来在绘制速度曲线时,总会出现一些异常值,这次完善后从未出现。实际效果如下:

1、自整定波形:

2、调速波形:

        十分满意,圆梦小车应该说画上了一个完美的句号,因为作为小车底盘部分,测速、调试是核心功能。

三、结语

        圆梦小车从2005年开始做,测速、调速一直是困扰着小车,因为宗旨是作为学习素材,初衷就是要基于低端的电机、简易的编码器实现小车的测速和调速。通过开模,在轮毂上实现了60、100线的简单编码器,控制小车行走距离尚可,精度大约在2~3mm左右,作为测速就十分勉强了,只有通过算法弥补。这些年一直没有沉下心来去完善,这次总算是了了一桩心事。

        最近GPT比较热,能够自动生成代码,我在上述优化算法过程中,也尝试了 AI,它给出的代码猛一看,煞有介事,仔细一琢磨,似是而非。尤其是单片机应用这种和硬件直接相关,且很多时候是为了弥补硬件局限性、不一致性所构思的代码,似乎 AI 目前还无法应对。或者说这类代码网上分享的太少,类似于前面写的内容在网上占比很低,没有提供给AI足够的学习素材。看来在ChatGPT引来的职业哀鸣中,似乎嵌入式硬件工程师还能多存在一会儿。

————————————

完善后的单片机程序:

链接:https://pan.baidu.com/s/1L_iUJLdNrUkOCDE3acZGXw

提取码:132v

配套完善后的PC端程序:

链接:https://pan.baidu.com/s/1NBOYZzWUpszxQmsnMMfbww

提取码:ospn

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

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

相关文章

基于springboot猪场管理系统-计算机毕业设计源码11779

摘要 信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以攻克的课题。针对猪场管理系统等问题,对猪场管理系…

Linux的启动与进程管理[上]

一、启动管理 1、启动过程 //不需要自己操作,仅需等待登录,不多赘述 2、Linux运行级别 查询: 使用runlevel指令 会提醒上次所处的运行级别和当前系统正在运行的运行级别 系统开机时就进入级别x(x可为数字0~6) 因此…

MySQL篇—性能压测工具mysqlslap介绍

☘️博主介绍☘️: ✨又是一天没白过,我是奈斯,DBA一名✨ ✌✌️擅长Oracle、MySQL、SQLserver、Linux,也在积极的扩展IT方向的其他知识面✌✌️ ❣️❣️❣️大佬们都喜欢静静的看文章,并且也会默默的点赞收藏加关注❣…

给程序加个进度条吧!1行Python代码,快速搞定~

你在写代码的过程中,有没有遇到过以下问题? 已经写好的程序,想看看程序执行的进度? 在写代码批量处理文件的时候,如何显示现在处理到第几个文件了? 👆如上图所示的进度条是一个最好的解决方法…

Docker中创建并配置MySQL、nginx、redis等容器

Docker中安装并配置MySQL、nginx、redis等 文章目录 Docker中安装并配置MySQL、nginx、redis等一、创建nginx容器①:拉取镜像②:运行nginx镜像③:从nginx容器中映射nginx配置文件到本地④:重启nginx并重新配置nginx的挂载 二、创建…

大语言模型系列-BERT

文章目录 前言一、BERT的网络结构和流程1.网络结构2.输入3.输出4.预训练Masked Language ModelNext Sentence Predictionloss 二、BERT创新点总结 前言 前文提到的GPT-1开创性的将Transformer Decoder架构引入NLP任务,并明确了预训练(学习 text 表征&am…

vim 编辑器如何同时注释多行以及将多行进行空格

一、场景 YAML文件对空格的要求非常严格,因此在修改YAML时,我们可能需要批量添加空格。 二、操作步骤 请注意:您的所有操作都将以第一行为基准。也就是说,第一行有多少个空格,下面的行就会模仿添加相同数量的空格。…

Spring WebSocket实现实时通信的详细教程

简介 WebSocket 是基于TCP/IP协议,独立于HTTP协议的通信协议。WebSocket 连接允许客户端和服务器之间的全双工通信,以便任何一方都可以通过已建立的连接将数据推送到另一方。 我们常用的HTTP是客户端通过「请求-响应」的方式与服务器建立通信的&#x…

Ubuntu 22.04.1 LTS VirtualBox7.0 解决虚拟机窗口失去焦点一段时间后,虚拟机显示不刷新问题

故障描述: virtualbox安装在ubuntu系统上,虚拟机内安装了windows操作系统。使用中发现,当linux系统窗口被激活,如firefox浏览器,虚拟机的显示一段时间后会暂停刷新,鼠标划入虚拟机窗口后,才会立…

mysql数据迁移报错Specified key was too long; max key length is 767 bytes

目录 场景: 说明: 疑问: 解决: 验证: 场景: 线上项目支持的过程中遇到mysql库表结构和数据由A库迁移到B库上提示Specified key was too long; max key length is 767 bytes报错,第一次遇到特此…

Rust之旅 - Rust概念、Windows安装、环境配置

🌹作者主页:青花锁 🌹简介:Java领域优质创作者🏆、Java微服务架构公号作者😄 🌹简历模板、学习资料、面试题库、技术互助 🌹文末获取联系方式 📝 系列专栏目录 [Java项目…

生成式对抗网络GAN

Generative Adversarial Nets由伊恩古德费洛(Ian J.Goodfellow)等人于2014年发表在Conference on Neural Information Processing Systems (NeurIPS)上。NeurIPS是机器学习和计算神经科学领域的顶级国际学术会议之一。 1. GAN在哪些领域大放异彩 图像生…