7734| 7
|
[求助] 关于舵机的控制 |
自己写了一段程序,通过按钮控制舵机的转动与停止,并且带有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; } |
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 多谢指点,期待继续交流! |
Jason_G 发表于 2015-12-14 10:23 同样是上面的代码,如果我把舵机的控制程序去掉,只留下控制LED灯的程序,则不会有任何问题,当然,烧录程序运行后,led灯的状态依然会取反一次,这个问题应该就是你说的那个原因。 |
Jason_G 发表于 2015-12-14 10:23 可以试一下下面的这段代码,如果把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) { boolean current=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中断有现成的函数,挺好用的,你可以看看。 |
© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed