2016-03-07 163 views
0

目前正在開發項目,使用arduino UNO和伺服電機打開帶門禁碼的門。正常操作需要使用正在工作的小鍵盤輸入訪問代碼。另一個選項需要按下一個導致中斷旋轉伺服電機的按鈕。我的問題是我的中斷只能工作一次,永遠不會再工作。另外,我怎麼把for循環在中斷功能內部延遲地旋轉伺服電機。我知道這是不可能的,但我正在調用另一個具有delayMicroseconds的函數,但所有這些都不起作用。下面是我的實現,請幫助帶伺服電機的arduino中斷

#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運行的代碼被模擬的變形和中斷按鈕是一個按鈕。請如果有其他方式實施,但具有相同的行爲,我已經描述了上述的幫助。非常感謝

+0

爲什麼服務程序只在按下按鈕時運行一次並且從不再運行 –

+0

在中斷處理程序中花費很長時間的工作並不好。我認爲你應該讓你的中斷處理程序引發一個標誌,'loop()'應該輪詢該標誌,並在引發標誌時執行該操作。 – MikeCAT

回答

0

您發佈的代碼片段存在一些問題。爲了完整性,您應該發佈循環函數,因爲我們無法猜測您在裏面寫了什麼。

只有一個評論:你把一個pullup?否則,使用INPUT_PULLUP而不是INPUT作爲按鈕pinmode。

最主要的是你爲HIGH模式附加了中斷,這會在引腳處於up狀態而不是在上升沿時觸發中斷。並請使用宏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); 

這樣你就不會阻塞甚至當按鈕被按下主循環

+0

這就是我的循環() –

+0

什麼是你的循環? – frarugi87

+0

我剛剛發佈了它,再次檢查我的答案,現在考慮你的答案,似乎我應該這樣做的更好的方式是通過輪詢而不是中斷,是嗎? –

0

這是在我的循環()

char key = keypad.getKey(); 
    if(key) 
    { 

    if(j < 10) 
     { 

     studentNumber[j] = key; 
     //holdMaskedNumber[j] = '*'; 
     lcd.setCursor(0,2); 
     lcd.print(String(studentNumber)); 

     if(j == 9) 
     { 
      studentNumber[9] = '\0'; 
      //holdMaskedNumber[9] = 0; 
      lcd.clear(); 
      //String number = String(studentNumber); 
      //lcd.print(number); 

      //delay(1000); 
      //lcd.clear(); 
      lcd.print("Access Code"); 

     } 

     j++; 
     } 


    else 
    { 
     if(i < 5) 
    { 
     accessCode[i] = key; 
     holdMaskedCode[i] = '*'; 
     lcd.setCursor(1,2); 
     lcd.print(String(holdMaskedCode)); 
     if(i == 4) 
     { 
     holdMaskedCode[5] = '\0'; 
     accessCode[5] = '\0'; 
     //lcd.clear(); 
     //lcd.setCursor(0,0); 
     //accessCodeString = String(accessCode); 
     //lcd.print(accessCodeString); 
     //delay(1000); 
     lcd.clear(); 


    for(int i =0; i<6; i++) 
      { 
      lcd.print("Please wait."); 
      delay(500); 
      lcd.clear(); 
      lcd.print("Please wait.."); 
      delay(500); 
      lcd.clear(); 
      lcd.print("Please wait..."); 
      delay(500); 
      lcd.clear(); 

      } 
      digitalWrite(4, HIGH); 
      lcd.print("Access Granted"); 
      for(int k =0; k<=180; k+=2) 
      { 
      servo.write(k); 
      delay(30); 
      } 
      resetFunc(); 

     } 

     i++; 
    } 
    } 
    }