Comprobación de pulsaciones cortas y largas con rebote

3

Soy un principiante completo con Arduino, pero he hecho un poco de búsqueda y parece que no puedo solucionar este problema.

Estoy intentando crear un procedimiento al que se llama repetidamente en el loop() principal que establecerá una variable según el estado actual de un botón, así como la duración que se presionó o presionó el botón. Este código probablemente sea más desordenado de lo que debe ser, pero parece que deja la variable en 0 . ¿Qué me estoy perdiendo?

Hay un código en el mismo loop() que establece la variable rotaryButtonToAction nuevamente en noPress una vez que se ha actuado.

#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
    
pregunta Jens Hembach

2 respuestas

2

Nunca usé Arduino, pero ¿no necesita usar signos de doble doble en una función de comparación?

Entonces, if (rotaryButtonToAction = noPress) debería ser if (rotaryButtonToAction == noPress) en su lugar?

    
respondido por el Analog Arsonist
1

Bueno, después de jugar mucho, he adoptado un enfoque completamente diferente que parece hacer justo lo que necesito. Creo que este es un ejemplo de una "máquina de estado", aunque soy nuevo en todo esto ...

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
    
respondido por el Jens Hembach

Lea otras preguntas en las etiquetas