关于舵机的控制
2015-12-131.4万
AI 快速预览详细
本文介绍了一个通过按钮控制舵机摆动与停止的程序,并详细分析了两个常见问题:布林变量sway自动变为true和多次按键才能停止。文章提供了具体的解决方法,包括优化按钮检测逻辑和增加延时,以确保按钮状态稳定,避免误触发。适合初学者学习Arduino编程和STEM教育场景。
|
自己写了一段程序,通过按钮控制舵机的转动与停止,并且带有led灯作为指示,按下一次并松开舵机开始摆动,且led灯亮,再按一次松开舵机停止,led灯灭。但是遇到了问题,控制是以布林变量sway作为判断依据,当sway为真,舵机摆动,反之,舵机停止,且在setup中已经设置了sway为false,在实际运行中,写入程序后,在没有任何操作的情况下,sway自己就变成了true,这是第一个问题;第二个问题:当sway变为true之后,舵机开始摆动,但想要再次按下按钮停止,却很不好控制,要按若干次才能停止,而在静止状态下要启动舵机则很容易,不知道这是为什么,下面是代码。 #include<Servo.h> Servo myservo; int swaybutton=11,led=7; int pos; boolean sway; boolean currentbutton=LOW; boolean lastbutton=LOW; void setup() { sway=false; myservo.attach(4); pinMode(swaybutton,INPUT); pinMode(led,OUTPUT); } void loop() { currentbutton=debounce(lastbutton); if(currentbutton==HIGH&&lastbutton==LOW) { sway=!sway; } lastbutton=currentbutton; digitalWrite(led,sway); if(sway==true) { for(pos=0;pos<=150;pos++) { myservo.write(pos); delay(5); } for(pos=150;pos>=0;pos--) { myservo.write(pos); delay(5); } } else { pos=0; myservo.write(pos); } } boolean debounce(boolean last) { boolean current=digitalRead(swaybutton); if(current!=last) { delay(5); current=digitalRead(swaybutton); } return current; } |




sway = false; // 定义变量的时候初始化
int current; //临时存储变量
debounce(int keyenable, int pin) //keyenable:如果按键按下的时候引脚读到低电平,此时keyenable就是0,
{
current=digitalRead(pin);
if(current == keyenable) //检测到按键按下
{
delay(10); //按键去抖动
if(current == keyenable) //去抖动后还能检测到按键按下,表示按键真的按下了
{
while(!current); //等待按键释放
sway = !sway; //当按键释放后,将sway取反
}
}
}
上面就是一个按键的去抖程序,正常运行时判断按键按下的效果还是会不错的,到这里你的舵机控制标志位就解决了对吧
然后在主程序loop()的一开始调用debounce(0,11);
后面就只要判断sway就行了:
loop()
{debounce(0,11);
if(sway)
{
//舵机动作程序
//点亮小灯
}
else
{
//舵机停止
//灭小灯
}
}
看上去问题好像解决了,但是这里面有个BUG,包括你上面写的程序,即使你用类似上面的程序来实现,点亮LED是没有问题的,但是,因为你的舵机控制程序整个运行下来的时间都超过1.4S了,这样一来,检测按键的程序差不多是1.5s检测一次,这么长的时间对检测按键来说是一个严重的BUG,很难检测到,稍微时间按长一点点是可以的,有没有好的解决办法呢???用中断来判断按键是否按下是一个很好的想法,Arduino中断有现成的函数,挺好用的,你可以看看。
if(currentbutton==HIGH&&lastbutton==LOW)
{
sway=!sway;
}
lastbutton=currentbutton;
目测你上面的这段程序是为了判断按键是否按下,然后改变舵机控制标志sway,并且记录当前按键状态用做后面第二次按键按下的判断。
在 debounce(boolean last)函数中,如果把电路接好,按键也连接上的时候,current=digitalRead(swaybutton)正常读到的是高电平
那么
if(current!=last)
{
delay(5);
current=digitalRead(swaybutton);
}
上面这段程序就会直接被执行,程序返回HIGH。
此时loop()函数中,下面的程序将会满足条件:
if(currentbutton==HIGH&&lastbutton==LOW)
{
sway=!sway;
}
到这里,sway会被置为TRUE;你的第一个问题为什么程序烧进去sway就会变TRUE就是应为上面的原因。
后面的这段程序:
lastbutton=currentbutton;
你可能是为了记录上一次按键状态,但是这条语句的意义不大,应为你的lastbutton初始化的时候是LOW,在程序烧进去的时候是LOW,当程序开始执行的时候就编程HIGH了,这个时候要想再次改变sway,需要执行下面的程序:
if(currentbutton==HIGH&&lastbutton==LOW)
{
sway=!sway;
}
因为程序正常执行后lastbutton = HIGH, 在判断条件中又需要lastbutton = LOW满足条件,这是比较难实现的,当你多次按下按键的时候,恰巧在按键按下期间出现短暂的lastbutton = LOW,并且在很短的时间内刚好满足了上面的判断条件,这时舵机状态就改变了。
上面是第二个问题的原因。仅供参考!
int ledpin=7;
boolean lastbutton=LOW;
boolean currentbutton=LOW;
boolean ledOn=false;
void setup()
{
pinMode(11,INPUT);
pinMode(ledpin,OUTPUT);
}
void loop()
{
currentbutton=debounce(lastbutton,11);
if(lastbutton==LOW&¤tbutton==HIGH)
{
ledOn=!ledOn;
}
lastbutton=currentbutton;
digitalWrite(ledpin,ledOn);
}
boolean debounce(boolean last,int pin)
{
boolean current=digitalRead(pin);
if(last!=current)
{
delay(5);
current=digitalRead(pin);
}
return current;
}