ISR / Millis or alternative

Status
Not open for further replies.

mtiger

Well-known member
Hi Guys,

I'm trying to figure out which method might be the best, or the most effective, and how I might go about this.

I'm going to build a little test circuit involving a button and an encoder. My goal is to be able to hold down the button (indefinitely) whilst increasing or decreasing the encoder's value. Upon release of the button, the value of the encoder would then be stored to the variable of the button.

I'm wondering how I would achieve something like this? Would an ISR be suitable, or perhaps the millis function or a while loop.

Any guidance would be great here :)

Thanks
M
 
Does anything else need to happen while the button is pushed to change the value? Updating a display or any other processing
 
At this stage, it would just be assigning the midi note value for the button held with the encoder. I'm just trying to conceptulise the best practice for such a function.
 
I suppose the td_libs_Bounce.html is the standard answer. If you keep looping without delays you can catch changes and when held down pick a time interval to change the value by some amount. When released stop doing that. You can update the midi note in loop or just after the button is released. Use an elapsedMillis variable to set to zero when pressed and when 100 or 1000 as desired change the value and set that back to zero and repeat until released. Repeat for multiple buttons if there is an up and down.
 
Ok, thanks for that.

Currently I would be using the button in a midi step sequencer configuration. So I press the step button to toggle it on, and then if I press it again, it toggles the step off.

How would I allow the ability to hold and edit the steps value with the encoder? As if when I press and hold, it would toggle the step off instead of allowing me to press and hold to edit.
 
just a thought, have you tried teensythreads?

drop your encoder in one thread, leave all your other stuff in loop(), and set your timeslices to 1ms
 
Similar approach of what defragster said, but step value is only set upon release. See comments for what happens where:
Code:
#include <Bounce.h>

const int buttonPin = 1;
Bounce button = Bounce(buttonPin, 10);
bool down;
elapsedMillis startMillis;

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);
}

void loop() {
  if (button.update()) {
    if (button.fallingEdge()) {
      startMillis = 0;
      //handle your step_on logic here
      down = true;
    } else if (button.risingEdge()) {
       if (startMillis < 1000) {
        //handle your step_off logic here
      } else {
        //handle your set_midi_value here
      }
      down = false;
    }
  } else if(down) {
    //handle your encoder logic here
  }
}
 
Thanks, I'm trying not to use pre-existing libraries to help me better understanding the logic behind it all.
 
Cool, post what you try.

The bounce page indicates the trouble reading a button opening or closing... I.e. Chatter or bounce of multiple transitions in the short term. Detecting a short or long press will need attention
 
Ok, this is what I have so far (which unfortunately doesn't work as first thought)

Code:
int buttonPin = 14;
boolean holdState = false;

int stepState = 0;

uint64_t currentMillis = 0;
uint8_t buttonState = 0;
uint8_t buttonLastState = 0;

void setup() {
  Serial.begin(9600);

  pinMode(buttonPin, INPUT);

}

void loop() {
  int reading = digitalRead(buttonPin);

  if (reading != buttonLastState)
    currentMillis = millis();
  if ((millis() - currentMillis) > 25) { //SHORT PRESS
    if (reading != buttonState) {
      buttonState = reading;
      if (stepState == 0) {
        if (buttonState == HIGH) {      //RISING EDGE
          stepState = 1;
          Serial.println(stepState);

        }
      } else if (stepState == 1) {
        if (buttonState == LOW) {        //FALLING EDGE
          stepState = 0;
          Serial.println(stepState);
        }
      } else if (buttonState == HIGH) {
        if ((millis() - currentMillis) > 500) {
          if (holdState == false) {
            holdState = true;
            currentMillis = millis();
            Serial.println("B");
          }
        }
      }
    }
  }
  buttonLastState = reading;
}

The logic:
stepState - toggle the step on or off.

On the rising edge (HIGH) I want to turn on the step (1), and then the button is released. On the falling edge (LOW) I then want to turn off the step (0). Assuming turning off the step on the falling edge would allow me to go into a timed state if stepState = 1.

Pressing and holding the button in stepState (1) , which would allow me to then use the encoder to select the value. Upon released, the stepState still remains active, until I press it again and it turns off on the falling edge.

Hope that makes more sense of what I'm trying achieve.
 
Last edited:
Your first posts seem clear in what you wanted - I think I could write it. Notes above say that is tricky with the way closing switches typically cycle the pin state on and off multiple times on for each intended change in state for some short time.

Post #4 links to Bounce - it shows a test program before showing bounce use. Working with that will show the behavior to work with and around that will be aggravating the code in post #11.

Even with Bounce it will take some clear stepping through states based on time and chosen action. Without Bounce handling the initial layer of pin noise that needs to be addressed first.
 
Thanks, I'm trying not to use pre-existing libraries to help me better understanding the logic behind it all.

Ok I'll work further on it, thanks for your help though :)

Well - you said you wanted to 'not use pre-existing ...' :)

Start with a simple example - with nothing but one button being tested - make that work - then if help is needed your code can be used on any teensy with a button. Once you have that part worked out - single detection recorded for any press or release - add the logic to wait for ongoing repeat adjustment time while held.

If you hook an interrupt it will be called multiple times on most presses - or releases. And a tight while watching it will see HIGH and LOW return multiple times on most changes. The Bounce library has the coding to detect that for a selected interval where it is expected.
 
Defragster, an update.... been working on it using multiple states and booleans and getting close. Will post the code soon once I have it working the way I intend.
 
Status
Not open for further replies.
Back
Top