关于舵机的控制
自己写了一段程序,通过按钮控制舵机的转动与停止,并且带有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)
{
booleancurrent=digitalRead(swaybutton);
if(current!=last)
{
delay(5);
current=digitalRead(swaybutton);
}
return current;
}
currentbutton=debounce(lastbutton);
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,并且在很短的时间内刚好满足了上面的判断条件,这时舵机状态就改变了。
上面是第二个问题的原因。仅供参考! 不懂:( Jason_G 发表于 2015-12-14 10:23
currentbutton=debounce(lastbutton);
if(currentbutton==HIGH&&lastbutton==LOW)
{
多谢指点,期待继续交流! Jason_G 发表于 2015-12-14 10:23
currentbutton=debounce(lastbutton);
if(currentbutton==HIGH&&lastbutton==LOW)
{
同样是上面的代码,如果我把舵机的控制程序去掉,只留下控制LED灯的程序,则不会有任何问题,当然,烧录程序运行后,led灯的状态依然会取反一次,这个问题应该就是你说的那个原因。 Jason_G 发表于 2015-12-14 10:23
currentbutton=debounce(lastbutton);
if(currentbutton==HIGH&&lastbutton==LOW)
{
可以试一下下面的这段代码,如果把lastbutton=currentbutton去掉的话程序反而不好使了。
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)
{
booleancurrent=digitalRead(pin);
if(last!=current)
{
delay(5);
current=digitalRead(pin);
}
return current;
}
本帖最后由 Jason_G 于 2015-12-15 00:16 编辑
去掉舵机的程序正常是因为你这里舵机正常运行时时间太长了,检测按键的频率因此而降的很低。给你理一下思路,这个程序的主要问题就是按键判断和sway标志的翻转。不用很复杂,你这样想,只要在判断按键按下的函数debounce中,当检测到按键第一次按下时,将sway = TRUE; 当检测到按键再次按下的时候, sway = false。后面在主程序中判断sway,然后做相应动作就行了。这里给你写一些伪代码,你可以类似修改下,就不帮你写完整的程序了,程序还是自己动手写比较好,出错很正常,这个程序不要写的复杂,容易出错。你可以参考下面的代码写一写:
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中断有现成的函数,挺好用的,你可以看看。
Jason_G 发表于 2015-12-15 00:14
去掉舵机的程序正常是因为你这里舵机正常运行时时间太长了,检测按键的频率因此而降的很低。给你理一下思路 ...
非常感谢!这下明白了:lol
页:
[1]