中断是否适用于我的机器人?

时间:2014-03-31 07:33:32

标签: arduino interrupt robotics motordriver

所以我有这个旧的电动轮椅,我试图转换成机器人。我用sabertooth 2x12替换了原来的电机驱动器,我正在使用Arduino micro来跟它说话。电机轴一路向前推,因此我将磁铁和霍尔效应传感器安装在背面,作为旋转编码器。我目前的目标是能够告诉机器人向前移动一定量的脚然后停止。我写了一些代码来线性地执行此操作但是这不能很好地工作。然后我了解了中断,这听起来就像我需要的那样。所以我尝试了一下,在几个不同的层面上出了问题。

第一级:我似乎从来没有能够正确地驱动电机,似乎任何时候我把命令放在一个循环内部或者如果声明他们决定做他们想要的事情并偶尔和不可预测地移动

第二级:我觉得中断正在打断他们自己和我设置的停止车轮向前移动的事情,因为我可以告诉它向前移动14个旋转编码器点击并且一个车轮将继续移动超过1000次点击而另一个停止

第三级:几次我想我把我的中断错了,因为当我上传代码窗口时会停止识别Arduino并且我的驱动程序会破坏,直到我按下重置按钮后上传了闪烁草图,这也重新加载并修复了我的驱动程序。然后,如果我删除了其中一个中断,它将正常上传。

第四级:当电机打开时,我的霍尔效应传感器似乎无法正常工作。他们倾向于在几秒钟内从1次点击到200次点击。这反过来又淹没了我的串口并崩溃了Arduino ide。

因此,您可以看到系统中存在一些缺陷,无论是硬件还是软件,我都不知道。我是以正确的方式接近这个还是有一些我不知道的Arduino秘密会让我的生活变得更轻松?如果我接近这个权利,你可以看看下面的代码,看看我做错了什么。

 #include <Servo.h>//the motor driver uses this library

Servo LEFT, RIGHT;//left wheel right wheel

int RclickNum=0;//used for the rotory encoder
int LclickNum=0;//these are the number of "clicks" each wheel has moved

int D =115;//Drive
int R =70;//Reverse
int B =90;//Break

int Linterrupt = 1;//these are the interrupt numbers. 0 = pin 3 and 1 = pin 2
int Rinterrupt = 0;

int clickConvert = 7;// how many rotery encoder clicks equal a foot

void setup()
{
  Serial.begin(9600); //starting serial communication 
  LEFT.attach( 9, 1000, 2000);//attaching the motor controller that is acting like a servo
  RIGHT.attach(10, 1000, 2000);
  attachInterrupt(Linterrupt, LclickCounter, FALLING);//attaching the rotory encoders as interrupts that will 
  attachInterrupt(Rinterrupt, RclickCounter, FALLING);//trip when the encoder pins go from high to low


}
void loop()
{//This is for controling the robot using the standard wasd format
  int input= Serial.read();
  if(input == 'a')
    left(2);
  if(input == 'd')
    right(2);
  if(input == 'w')
    forward(2);
  if(input == 's')
    backward(2);
  if(input == 'e')
    STOP();
}

void forward(int feet)//this is called when w is sent threw the serial port and is where i am testing all of my code. 
{
  interrupts(); //turn on the interrupts
  while(RclickNum < feet * clickConvert || LclickNum < feet * clickConvert)// while either the left or right wheel hasnt made it to the desired distance
  {
    if(RclickNum < feet * clickConvert)//check if the right wheel has gone the distance
      RIGHT.write(D); //make the right wheel move
    else
      RIGHT.write(B);//stop the right wheel

    if(LclickNum < feet * clickConvert)
      LEFT.write(D);
    else
      LEFT.write(B);
  }
  noInterrupts();//stop the interrupts 
  resetCount();//set the click counters back to zero
}

//once i have the forward function working i will implament it through out the other functions
//----------------------------------------------------------------------

void backward(int feet)
{
  RIGHT.write(R);
  LEFT.write(R);
}

void left(int feet)
{
  RIGHT.write(D);
  LEFT.write(R);
}

void right(int feet)
{
  RIGHT.write(R);
  LEFT.write(D);
}

void STOP()
{
  resetCount();
  RIGHT.write(B);
  LEFT.write(B);
}

void LclickCounter()//this is called by the left encoder interrupt
{
  LclickNum++; 
  Serial.print("L");
  Serial.println(LclickNum); 
}

void RclickCounter()//this is called by the right encoder interrupt
{
  RclickNum++;
  M Serial.print("R");
  Serial.println(RclickNum);
}


void resetCount()
{
  RclickNum=0;
  LclickNum=0;
}

1 个答案:

答案 0 :(得分:1)

  1. 不要使用interrupt()nointerrupt()(或cli()sei()),因为它们会停止计时器和串行中断,从而打破了很多的东西。只需将计数变量设置为0或使用detachInterrupt和attachInterrupt。

  2. 在中断和正常执行流程中使用的变量应该声明为volatile,或者它们的值是未经同步的。所以将它们声明为volatile int RclickNum=0;

  3. 中断应该快速执行,因为默认情况下,其他中断在中断时不会执行。

  4. 永远不要使用Serial内部中断;如果串行缓冲区已满,它将调用Serial.flush(),它将等待写入字节的串行中断,但因为你在内部中断的alreadi将永远不会发生...死锁也称你的代码永远挂起!

  5. 因为你的&#34;移动&#34;函数使用相当长的时间来执行,如果多个命令到达串口,thay将保持isnode缓冲区直到readed。因此,如果在终端中你写了#34; asd&#34;然后&#34; e&#34;,你会看到机器人向左,向后,向右,停止(是的,实际上停止功能没有用,因为它什么也没做,因为你的&#34;移动&#34;功能是& #34;阻塞&#34;,这意味着他们不会返回直到他们结束,所以loop()代码(和&#34; e&#34;的读取)将不会执行,直到serial的缓冲区有已经处理完毕。