关于舵机的控制

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;
}



创作许可协议

本项目采用 None(不开放任何权利,保留所有权利) 进行许可。

评论(3)
qq865650214158
qq865650214158
去掉舵机的程序正常是因为你这里舵机正常运行时时间太长了,检测按键的频率因此而降的很低。给你理一下思路,这个程序的主要问题就是按键判断和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中断有现成的函数,挺好用的,你可以看看。
huangjun0104
huangjun0104
作者
回复qq865650214158
非常感谢!这下明白了:lol
丄帝De咗臂
丄帝De咗臂
不懂:(
qq865650214158
qq865650214158
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,并且在很短的时间内刚好满足了上面的判断条件,这时舵机状态就改变了。
上面是第二个问题的原因。仅供参考!
huangjun0104
huangjun0104
作者
回复qq865650214158
可以试一下下面的这段代码,如果把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;
}
huangjun0104
huangjun0104
作者
回复qq865650214158
同样是上面的代码,如果我把舵机的控制程序去掉,只留下控制LED灯的程序,则不会有任何问题,当然,烧录程序运行后,led灯的状态依然会取反一次,这个问题应该就是你说的那个原因。
共3条回复,已加载2条,点击查看更多共3条回复,已加载全部
- 没有更多了 -