7545浏览
查看: 7545|回复: 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;
}



Jason_G  高级技师

发表于 2015-12-14 10:23:22

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,并且在很短的时间内刚好满足了上面的判断条件,这时舵机状态就改变了。

上面是第二个问题的原因。仅供参考!
回复

使用道具 举报

丄帝De咗臂  高级技匠

发表于 2015-12-14 20:02:27

不懂:(
回复

使用道具 举报

huangjun0104  见习技师
 楼主|

发表于 2015-12-14 20:27:40

Jason_G 发表于 2015-12-14 10:23
currentbutton=debounce(lastbutton);
  if(currentbutton==HIGH&&lastbutton==LOW)
  {

多谢指点,期待继续交流!
回复

使用道具 举报

huangjun0104  见习技师
 楼主|

发表于 2015-12-14 20:32:54

Jason_G 发表于 2015-12-14 10:23
currentbutton=debounce(lastbutton);
  if(currentbutton==HIGH&&lastbutton==LOW)
  {

同样是上面的代码,如果我把舵机的控制程序去掉,只留下控制LED灯的程序,则不会有任何问题,当然,烧录程序运行后,led灯的状态依然会取反一次,这个问题应该就是你说的那个原因。
回复

使用道具 举报

huangjun0104  见习技师
 楼主|

发表于 2015-12-14 20:42:25

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&&currentbutton==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:14:57

本帖最后由 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中断有现成的函数,挺好用的,你可以看看。
回复

使用道具 举报

huangjun0104  见习技师
 楼主|

发表于 2015-12-15 12:24:53

Jason_G 发表于 2015-12-15 00:14
去掉舵机的程序正常是因为你这里舵机正常运行时时间太长了,检测按键的频率因此而降的很低。给你理一下思路 ...

非常感谢!这下明白了:lol
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
关于楼主

楼主的其它帖子

上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail