So in my project I need to have 3 buttons trigger an interrupt, yet the ATmega328p only has 2 interrupt pins. So I had the idea of connecting each of the 3 push buttons connect to their own digital pin, then share a interrupt pin. When the interrupt pin is triggered, the ISR will see which of the 3 digital pins was triggered, and subsequently run the appropriate code (using a basic if statement in the ISR). Will this approach work reliably?
My main loop then checks if any of the *enabled_var variables are 0 or not 0. (Should I use alarm_enabled var = ~alarm_enabled_var, or leave it how it is? (are they practically the same?))
Ajmar:
So in my project I need to have 3 buttons trigger an interrupt, yet the ATmega328p only has 2 interrupt pins. So I had the idea of connecting each of the 3 push buttons connect to their own digital pin, then share a interrupt pin. When the interrupt pin is triggered, the ISR will see which of the 3 digital pins was triggered, and subsequently run the appropriate code (using a basic if statement in the ISR). Will this approach work reliably?
It should, but I'd use Direct Port Manipulation instead of digitialread(). Much faster -- very important in an ISR.
My main loop then checks if any of the *enabled_var variables are 0 or not 0. (Should I use alarm_enabled var = ~alarm_enabled_var, or leave it how it is? (are they practically the same?))
Hard to say. Since you didn't post a complete code, we don't know how alarm_enabled_var is defined.
EDIT:
Post a schematic as previously requested so we can understand how pressing any one button of three will activate the single interrupt-capable input pin.
Any criticisms welcome (it's my first C/C++ program), though it's not finished yet (have yet to add the main time handling code). Also cheers for the DPM link gfvalvo, though how beneficial is it likely to be? Surely digitalRead() etc. can't add that much overhead, with compiler optimizations, right?
Edit: (Obviously it's supposed to be code for an alarm clock), the 3 switches are to enable / disable potentiometers which can be used to set the time / alarm time, and to enable/disable the alarm. (Haven't commented the code yet).
Ajmar:
Also cheers for the DPM link gfvalvo, though how beneficial is it likely to be? Surely digitalRead() etc. can't add that much overhead, with compiler optimizations, right?
I'm not one to waste my own time. Therefor, I wouldn't have taken the time to look up the link and tell you about it if I didn't think it was worthwhile:
#include "Arduino.h"
void setup() {
uint32_t startTime, stopTime;
const uint32_t numIterations = 1000000;
volatile uint8_t inputPinValue;
Serial.begin(115200);
delay(1000);
Serial.println("Starting");
Serial.println();
pinMode(3, INPUT_PULLUP);
startTime = micros();
for (uint32_t i = 0; i < numIterations; i++) {
inputPinValue = digitalRead(3);
}
stopTime = micros();
Serial.print("Using Digital Read: ");
Serial.print((stopTime - startTime) / (float) numIterations, 3);
Serial.println(" us per Reading");
Serial.println();
startTime = micros();
for (uint32_t i = 0; i < numIterations; i++) {
inputPinValue = (PORTD & (1 << PD3)) >> PD3;
}
stopTime = micros();
Serial.print("Using Direct Port Manipulation: ");
Serial.print((stopTime - startTime) / (float) numIterations, 3);
Serial.println(" us per Reading");
}
void loop() {
}
Starting
Using Digital Read: 3.773 us per Reading
Using Direct Port Manipulation: 0.755 us per Reading
This suggests that using direct port access is almost 5 times faster.
It would be even faster without the final (usually unnecessary) shift into bit position 0. But, that provides an exact equivalent to the result from digitalRead(0).
According to schematic, it is not definite when the button "stops" been pressed . So, "handling" ISR first time, the interrupt vector is re-activated .
The result may be many times running ISR with one button press.
I’ve done something similar with 3 buttons on 2 pins with interrupt.
CPU sleeps until a pin is fired, then diodes across the buttons give binary 1,2,4 for which one’s pressed.
Do stuff then go back to sleep