Überprüfung auf kurzes oder langes Drücken mit Entprellung

Ich bin ein absoluter Anfänger mit Arduino, habe aber ziemlich viel gesucht und kann dieses Problem anscheinend nicht beheben.

Ich versuche, eine Prozedur zu erstellen, die in der Hauptsache wiederholt aufgerufen wird und loop()abhängig vom aktuellen Zustand einer Schaltfläche sowie der Dauer, für die die Schaltfläche gedrückt wurde oder gedrückt wurde, eine Variable festlegt. Dieser Code ist wahrscheinlich chaotischer als nötig, aber er scheint die Variable einfach bei zu belassen 0. Was vermisse ich?

Es gibt Code in loop()sich selbst, der die rotaryButtonToActionVariable zurücksetzt, noPresssobald sie bearbeitet wurde.

#define noPress 0
#define shortPressReleased 1
#define longPressReleased 2
#define shortPressHolding 3
#define longPressHolding 4

int rotaryButtonState;
int rotaryButtonReading;
int lastRotaryButtonReading = HIGH;
int timeOfLastRotaryButtonReadingChange = 0;
int debounceDelay = 50;
int longPressDelay = 300;
int rotaryButtonToAction = 0;

void checkRotaryButton() {
  if (rotaryButtonToAction == noPress) { // if there is nothing to action, check the state of the button
    rotaryButtonReading = digitalRead(ROTARY_BUTTON); // store pin's current state
    if (rotaryButtonReading != lastRotaryButtonReading) { // if pin state has changed from the last reading, set timeOfLastRotaryButtonReadingChange to the time of the change
      timeOfLastRotaryButtonReadingChange = millis();
    }
    if (millis() - timeOfLastRotaryButtonReadingChange > debounceDelay) { // if more time has passed than the debounce delay, change the action state of the button
      if (rotaryButtonReading = LOW) { // if the button is still pressed, set the action to indicate it has been pressed and is still pressed
        rotaryButtonToAction = shortPressHolding;
      }
    else { // if the button was pressed for longer than the debounce delay and was released, set the action
      rotaryButtonToAction = shortPressReleased;
      }
    }
  } 

  if (millis() - timeOfLastRotaryButtonReadingChange > longPressDelay) { // if more time has passed than the long press delay, change the action state of the button
    if (rotaryButtonReading == LOW) { // if the button is still pressed, set the action to indicate it has been pressed and is still pressed
      rotaryButtonToAction = longPressHolding;
    }
    else { // if the button was pressed for longer than the long press delay and was released, set the action
      rotaryButtonToAction = longPressReleased;
    }
  }

} // end checkRotaryButton

Antworten (2)

Ich habe Arduino nie verwendet, aber müssen Sie in einer Vergleichsfunktion nicht doppelte Gleichheitszeichen verwenden?

Also if (rotaryButtonToAction = noPress)sollte es stattdessen sein if (rotaryButtonToAction == noPress)?

Funktioniert jetzt fast. Werde die funktionierende Lösung posten, sobald ich sie habe.
Ich bin kein großer Mikrocoder, aber das könnte einfacher sein, indem ich Watch-Dog-Timer (WDT) und Interrupts verwende. Es lohnt sich auf jeden Fall, es zu lernen, wenn Sie es nicht für dieses Projekt verwenden. Außerdem ist Beispielcode eine gute Möglichkeit zum Lernen. Viel Glück!
Ich werde mich auf jeden Fall mit Watchdog-Timern befassen. Ich bin noch nicht auf etwas gestoßen (ich habe meinen ersten Arduino vor zwei Wochen abgeholt). Unglücklicherweise habe ich für dieses Projekt bereits einen Drehgeber, der die beiden Interrupt-fähigen Pins des Arduino UNO aufnimmt, sodass ich den Taster nicht auf einen Interrupt setzen kann.
Es ist besser, in solchen Fällen zuerst die Konstante zu verwenden - der Compiler fängt einen Fehler ab, wenn Sie versehentlich einen Fehler machen (das passiert bei uns allen), dh verwenden Sie if(0 == Variable) anstelle von if(Variable == 0), weil Wenn Sie if(0 = variable) schreiben, fängt der Compiler den Fehler ab, während if(variable = 0) ein ganz normaler C-Ausdruck ist

Nun, nach langem Herumspielen habe ich einen völlig anderen Ansatz gewählt, der genau das zu tun scheint, was ich brauche. Ich glaube, dies ist ein Beispiel für eine "Zustandsmaschine", obwohl ich neu in all dem bin ...

void checkRotaryButton() {
  rotaryButtonReading = digitalRead(ROTARY_BUTTON); // store pin's current state
  if (rotaryButtonReading != lastRotaryButtonReading) { // if pin state has changed from the last reading
    timeOfLastRotaryButtonChange = millis(); // if pin state different, store the time of the state change
  }
  timeSinceLastRotaryButtonChange = millis() - timeOfLastRotaryButtonChange;

  if (rotaryButtonReading == LOW && timeSinceLastRotaryButtonChange < debounceDelay) {
    // has only been low for less than the debounce time - do nothing
  }
  if (rotaryButtonReading == LOW && timeSinceLastRotaryButtonChange > longPressDelay && rotaryButtonToAction != longPressed) {
      rotaryButtonToAction = longPressed;
      Serial.println("button pressed long");  
  }
  if (rotaryButtonReading == LOW && timeSinceLastRotaryButtonChange > debounceDelay && timeSinceLastRotaryButtonChange < longPressDelay && rotaryButtonToAction != holdingPress) {
      rotaryButtonToAction = holdingPress;
      Serial.println("holding button pressed");  
  }
  if (rotaryButtonReading == HIGH && timeSinceLastRotaryButtonChange > debounceDelay && rotaryButtonToAction == holdingPress) {
      rotaryButtonToAction = shortPressed;
      Serial.println("released short press");    
  }


  lastRotaryButtonReading = rotaryButtonReading; // store this reading for comparison the next time the procedure loops
} // end checkRotaryButton