3
\$\begingroup\$

I'm a complete beginner with Arduino but have done quite a bit of searching and can't seem to fix this problem.

I'm trying to create a procedure that is repeatedly called in the main loop() that will set a variable depending on the current state of a button, as well as the duration the button has been or was pushed for. This code is probably messier than it needs to be, but it just seems to leave the variable at 0. What am I missing?

There is code in the loop() itself that sets the rotaryButtonToAction variable back to noPress once it has been acted upon.

#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
\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

Never used Arduino, but don't you need to use double equal signs in a compare function?

So, if (rotaryButtonToAction = noPress) should be if (rotaryButtonToAction == noPress) instead?

\$\endgroup\$
4
  • \$\begingroup\$ Almost working now. Will post the working solution as soon as I have it. \$\endgroup\$ Commented Oct 7, 2012 at 19:25
  • \$\begingroup\$ I'm not a big micro-coder but this might be simpler by using watch dog timers (WDT) and interrupts. It's definitely worth learning if you don't use it on this project. Also, sample code is a good way to learn. Good luck! \$\endgroup\$ Commented Oct 7, 2012 at 19:32
  • \$\begingroup\$ I'll definitely look into watch dog timers. Not something I've come across yet (I picked up my first Arduino two weeks ago). Unfortunately for this project, I already have a rotary encoder taking up the Arduino UNO's two interrupt-capable pins, so I can't put the pushbutton on an interrupt. \$\endgroup\$ Commented Oct 7, 2012 at 19:36
  • \$\begingroup\$ it's better to use the constant first in such cases - the compiler will catch an error if you just make mistake accidenally (that happens for all of us) ie use if(0 == variable) instead of if(variable == 0) because if you write if(0 = variable), the compiler will catch the error, while if(variable = 0) is perfectly normal C expression \$\endgroup\$
    – miceuz
    Commented Oct 7, 2012 at 20:37
1
\$\begingroup\$

Well, after much playing around I've taken a completely different approach that seems to do just what I need. I believe this is an example of a "state machine", though I'm new to all of this...

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
\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.