我想爲Arduino項目中的一個按鈕實現三種不同的功能。點擊,雙擊並按住。 我必須使用中斷,並儘可能讓系統進入睡眠狀態,因爲最終產品必須在硬幣電池上運行幾個月。Arduino單擊,雙擊並按住按鈕
#include <Ports.h>
#include <RF12.h>
#include <avr/sleep.h>
#include <PinChangeInt.h>
#include <VirtualWire.h>
ISR(WDT_vect) { Sleepy::watchdogEvent(); }
char *controller;
const int buttonPin = 3;
bool stateSingle = false;
bool stateDouble = false;
bool stateLong = false;
void setup() {
pinMode(13, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(5, OUTPUT);
// vw_set_ptt_inverted(true);
// vw_set_tx_pin(12);
// vw_setup(4000);
//
Serial.begin(9600);
PCintPort::attachInterrupt(buttonPin, wakeUp, HIGH);
}
void wakeUp() {
}
void loop() {
cli();
int i = 0;
while (digitalRead(buttonPin) == HIGH) { // Wait until button is LOW, or has been high for more than 600ms
Sleepy::loseSomeTime(50);
if (i > 12)
break;
i++;
}
if (digitalRead(buttonPin) == HIGH)
longTapAction();
else {
i = 0;
while (digitalRead(buttonPin) == LOW) { // Wait for possible double press
Sleepy::loseSomeTime(50);
if (i > 8)
break;
i++;
}
if (digitalRead(buttonPin) == HIGH) {
doubleTapAction();
while (digitalRead(buttonPin) == HIGH)
Sleepy::loseSomeTime(50);
} else
singleTapAction();
}
}
void singleTapAction() {
stateSingle = !stateSingle;
digitalWrite(5, stateSingle ? HIGH : LOW);
sei();
Sleepy::powerDown();
}
void doubleTapAction() {
stateDouble = !stateDouble;
digitalWrite(6, stateDouble ? HIGH : LOW);
sei();
Sleepy::powerDown();
}
void longTapAction() {
stateLong = !stateLong;
digitalWrite(7, stateLong ? HIGH : LOW);
sei();
Sleepy::powerDown();
}
問題是,這並不總是正確的工作。 因爲我使用中斷,millis()
裏面void loop()
是不可靠的,出於某種原因。
對於任何雙擊和任何保持操作,單擊功能也會被調用。我懷疑這是由於多箇中斷觸發,但我無法測試這個。另外,有時候,雙擊似乎只需要一次點擊。我的思想錯了嗎,我忘記了什麼嗎?
這是有道理的,特別是對於額外的單擊功能調用,當你這樣說的時候。當設備進入睡眠狀態時,這個例子會不會更復雜一些,因爲睡眠時millis()不會增加?什麼是最好的方法仍然包括反彈? –
添加類似'static unsigned long last_interrupt_time = 0; unsigned long interrupt_time = millis(); if(interrupt_time - last_interrupt_time> 200)',行爲仍然相同。 –