arduino中断伺服电机

时间:2016-03-07 09:57:45

标签: arduino

目前正在开展项目,使用arduino UNO和伺服电机打开带门禁密码的门。正常操作需要使用工作正常的键盘输入访问代码。另一个选项需要按下一个按钮,该按钮会导致中断旋转伺服电机。我的问题是我的中断只能工作一次而且再也不能工作了。另外,如何使用for-loop将伺服电机旋转到中断功能中并延迟。我知道这是不可能的,但我正在调用另一个具有delayMicroseconds的函数,但所有这些都无效。以下是我的实施请帮助

#include <Keypad.h>
#include <LiquidCrystal.h>
#include <Servo.h>

Servo servo;


const int openButtonPin = 2;

void setup() {
  // put your setup code here, to run once:

  servo.attach(5);

  pinMode(openButtonPin, INPUT); //Pin 2 is input
  attachInterrupt(0, enforceOpenAccess, HIGH); // PIN 2

}


void(* resetFunc)(void) = 0;

void loop()
{
  //My other keypad implementations go here
}

void myDelay(int x)  // function to cause delay in the interrupt
{
  for(int i = 0; i<x; i++)
  {
    delayMicroseconds(1000); 
  }
}


void enforceOpenAccess() // ISR
{
   for(int k =0; k<=180; k+=2)
   {  
     servo.write(k); //rotate the servo
     myDelay(30);  //delay the rotation of the servo
   }
}

上面的代码是在arduino UNO上运行的,模拟了proteus,中断按钮是一个按钮。请问是否有其他方法可以实现,但具有与上述相同的行为帮助。非常感谢

2 个答案:

答案 0 :(得分:0)

您发布的代码片段中存在一些问题。为了完整起见,你应该发布循环函数,因为我们无法猜出你在里面写的是什么。

只有一条评论:你是否提出了一个问题?否则使用INPUT_PULLUP代替INPUT作为按钮pinmode。

主要原因是您将中断连接到HIGH模式,这将在引脚上升时触发中断,而不是在上升沿触发。请使用宏digitalPinToInterrupt映射到正确的引脚:

attachInterrupt(digitalPinToInterrupt(openButtonPin), enforceOpenAccess, RISING);

然后..让我们改进代码。只有当您必须立即响应(=少于几毫秒)输入时,才真正应该在严格必要时使用中断。在这里你没有必要,所以检查循环中的按钮会更好(更多关于关闭电机的信息)

uint8_t lastState;

void setup()
{
    ...
    lastState = LOW;
}

void loop()
{
    uint8_t currentState = digitalRead(openButtonPin);
    if ((currentState != lastState) && (currentState == HIGH))
    {
        // Start turning the motor
    }
    lastState = currentState;
    ...
}

这样您也可以正确去抖按钮:

#include <Bounce2.h>
Bounce debouncer = Bounce(); 

void setup()
{
    ...
    pinMode(openButtonPin, INPUT); //Pin 2 is input
    debouncer.attach(openButtonPin);
    debouncer.interval(5); // interval in ms
}

void loop()
{
    debouncer.update();
    if (debouncer.rose())
    {
        // Start turning the motor
    }
    ...
}

如果,在另一方面,你真的想要使用中断(因为等待几毫秒对你来说太多了),你应该这样做:

#include <Bounce2.h>
Bounce debouncer = Bounce(); 

void setup()
{
    ...
    pinMode(openButtonPin, INPUT);
    attachInterrupt(digitalPinToInterrupt(openButtonPin), enforceOpenAccess, RISING);
}

void loop()
{
    ...
}

void enforceOpenAccess() // ISR
{
    // Start turning the motor
}

看起来像你的代码?不,因为现在我们会谈论转动电机

你不应该使用延迟来做出步骤,否则你将等待30ms * 180步= 5.4s才能做其他任何事情。

但是,您可以制作一种简化状态机。你希望你的伺服以1为步长从0移动到180.所以让我们用任何大于180的值编码“不移动”状态,因此我们可以在循环中做这样的事情:

unsigned long lastServoTime;
uint8_t servoPosition = 255;
const int timeBetweenSteps_in_ms = 30;

void loop()
{
    ...
    if (servoPosition <= 180)
    { // servo should move
        if ((millis() - lastServoTime) >= timeBetweenSteps_in_ms)
        {
            lastServoTime += timeBetweenSteps_in_ms;
            servoPosition++;
            if (servoPosition <= 180)
                servo.write(servoPosition);
        }
    }
}

然后,使用前面的任何示例,而不是// Start turning the motor

lastServoTime = millis();
servoPosition = 0;
servo.write(servoPosition);

这样即使按下按钮也不会阻止主循环

答案 1 :(得分:0)

这就是我的循环()

NSPredicate