Arduino碰撞开关(按钮传感器)消抖秘籍第一招
消抖?你看到这个标题是不是有点懵?为什么要消抖?我们先看一个实例,你就会感觉抖动的威力了。先把测试神器拿出来,在一个Aruduino UNO主板(为了方便,用上了扩展板)的3号数字管脚上外接了一个按钮传感器(碰撞开关),如图1所示:
图1:Arduino UNO+扩展板+碰撞开关
接着打开Scratch的改造版软件(AS-Block或者类似的都可以,只要能连接Arduino主板并能使用常见的传感器都可以),编写一个简单的程序先试试,如图2所示:
图2:Scratch程序
程序很简单,设置一个“次数”变量,初始化赋值为0,接下来重复执行,先判断按钮是否按下(注意我使用的按钮传感器在没有按下的时候返回值是true,按下的时候返回值是false,所以我要使用逻辑里的“不成立”模块让按钮按下时条件成立,有点绕吧,慢慢来,不着急),如果按下,就把“次数”这个变量增加1,否则不变,最后把“次数”这个变量让小猫说出来,理想状态应该是按一下,就增加1,也就是如果按10下,小猫就应该从1说到10,可实际情况如何呢?请你看下面的视频。
视频1:消抖前的效果
你会发现,我每按一下按钮开关,小猫所说的数字并不是每次增加1,是2-4不等,我已经使出了洪荒之力,让自已按下去然后松开的速度足够快了,可为什么还是感觉按下一次就相当于一次那是怎么回事呢?
原来呀,我们人从按下按钮到松开的反应速度最快也需要0.2秒的样子,如果再算上开关可能会存在的氧化、杂物(灰尘)等,那时间还会延长,而我们Arduino UNO主板的反应速度是ms(毫秒)级(1秒=1000毫秒),按最快的反应速度0.2秒(200毫秒)来算,你想想,在你这个反应时间,Arduino UNO主板已经往返跑了多少圈了?从上面视频的实验来看,按我最快的手速,Arduino UNO已经执行那个程序2次了,慢一点的话就是4次了。
那怎么解决这个问题呢?网络上各路大神提供了N种方法,我逐一进行了试验,本着服务初学者的原则,我这先提供最简单的办法,那就是延时,没错,让程序先短路一下(中断),或者说让Arduino UNO暂停一下快速奔跑的脚步,等一下我这慢腾腾的手速,我们先看看消抖后的效果,再看程序。
视频2:使用延时消抖后的效果
图3:Scratch程序对比图
赶紧试试吧,你会发现按钮传感器(碰撞开关)又变成听话的小朋友了,不会再淘气了。当然,这种办法的优点就是简单,但是延时函数阻塞了程序的运行,不太完美,而且延时的时间长短还要根据用户的使用习惯以及这个开关的物理特性去调试。
总而言之,这个小技巧适应于大部分对于使用要求不高的场合,能大概率避免因抖动带来的误差就可以了。
PS:如果你使用的Arduino IDE编程,那就在输出命令的后面加一个Delay(200)命令即可(括号里的数字是时间,单位为毫秒),如图4第14行代码处所示:
图4:Arduino UNO 程序示例
这个程序的作用和上文当中的Scratch程序类似,是在串口监视器当中显示变量“state”的值,你也可以试一下,去掉第14行代码的效果,我把完整代码贴出来,请你自已去尝试吧,尝试结果如何请在评论区留言告诉我哦。
#define BUTTON 3//定义按钮在3号引脚
int val = 1;//变量val 存储按钮的状态
int old_val =1;//暂存val变量的上一个时间状态
int state = 0;//打印到串口的数据,按钮每被按下一次,state自增1
void setup(){
pinMode(BUTTON, INPUT);
Serial.begin(9600);//用于串口输出
}
void loop(){
val = digitalRead(BUTTON);
if((val==HIGH)&&(old_val==LOW))
{
printState();
delay(200);//我就是消抖的关键啦 :)
}
old_val=val;//val现在是旧的了,让我们暂存一下
}
void printState()
{
state++;
Serial.println(state);
}
好了,今天的分享就到此结束,更为完美的消抖方法下次再和大家分享,我是初始化工作室大陈,我专注于Arduino、乐高的学习与创意,如果需要更多相关课程,请点击“关注”按钮关注我,谢谢。
--end--
声明:本文章由网友投稿作为教育分享用途,如有侵权原作者可通过邮件及时和我们联系删除:freemanzk@qq.com