attachInterrupt CHANGE - how to check if the change was a HIGH or LOW

Status
Not open for further replies.

stephanschulz

Well-known member
I am using attachInterrupt on a teensy 3.2.
Inside my interrupt function I need to know if the CHANGE was due to a pin going HIGH or LOW. Because inside the function then measure the time difference for the HIGH state and LOW state.

Is it ok to do a digitalRead to get the pin state or will that not be accurate as the CHANGE already occurred?
Would it be better to use two attachInterrupt(), one for FALLING and one for RISING?

Thanks for any advice.

Code:
void setup(){
attachInterrupt(digitalPinToInterrupt(HAND_INPUT), handInput_interrupt, CHANGE);
}

void handInput_interrupt() {
  pulse = digitalRead(HAND_INPUT);
}
 
digitalReadFast with a constant for the pin # will be good and fast to use :: pulse = digitalReadFast(HAND_INPUT);

Depending on the initiator it might be bouncing? But if you track the prior state you can also toggle that yourself if every change is trapped. AFAIK there is only a single interrupt vector for each pin - so doing one of each won't work. If the pin input doesn't make a single clean transition - there will be multiple interrupts possible.
 
The name hand input suggests the use of a button press. If so, the action of pressing will cause signal bounce. If the purpose is to measure the time a user held the button, then the event will trigger FALLING and RISING a few times at the start and then a few times at the end of the press.

The first fall will indicate the start of the press, but button press completion is a little trickier, since we don't know whether bouncing will still occur (implying contact). If we define the press release as the last time contact were made, then we can start a timer interrupt within the CHANGE interrupt to callback a short time after the last RISING event.

FALLING events will kill the timer, and RISING event will start the timer afresh. A short time after the last RISING event we would receive the timeout callback signifying the end of the press.

We could calculate the press timing by storing the timestamp of the first press FALLING event and update the timestamp of the the latest FALLING event. In the callback function we find the difference of the two.

Before the press, the press timestamp is set to zero, when the value is non zero, we don't set this value again, since we are still within the press event period. We set the press timestamp to zero once we are in the callback function.

To know which phase we are seeing (RISING / FALLING) for simple (clean digital) systems you might get away with toggling a boolean, since presumably we always receive both events in sequence. But, for noisy (or super fast) input, I couldn't say whether you could rely on always receiving a rise after a fall after a rise etc.

As defragster stated you can't attach two interrupts to the same pin. But, you can connect two input pins together, attach the RISING interrupt to one pin and the FALLING interrupt to the other pin.

defragster: What can you tell us about the reliability of events? Is it possible to receive two RISING events in a row without a corresponding FALLING event in between?

Maybe this will be another experiment to play with tomorrow...
 
Speculation and solving a potential problem can be fun - hopefully @stephanshulz can provide details - like if the input can bounce … what is the expected duration of the event?
 
Status
Not open for further replies.
Back
Top