Electronics > Beginners
How to initialise INPUT_PULLUP before Interrupt runs in Arduino?
skillz21:
--- Quote from: mjkuwp on March 23, 2019, 12:26:34 am ---interrupts can be pretty sensitive and sometimes they cause too much trouble when they are used for a feature that doesn't really call for them. That said - I wrote something you could try. There is a bit of a delay added before the interrupts are enabled.
if I were doing this I would likely do this by polling, not an interrupt and there would be a state machine to help with de-bouncing.
--- Code: ---volatile int buttonPin = 21;
volatile bool gotPressed= false;
void setup() {
pinMode(buttonPin, INPUT_PULLUP);
digitalWrite(buttonPin, HIGH );
noInterrupts();
attachInterrupt(digitalPinToInterrupt(buttonPin), Button, FALLING);
delay(1);
interrupts();
}
void loop() {
if(gotPressed)
{
//Does stuff
gotPressed = false;
}
}
void Button() {
gotPressed = true;
}
--- End code ---
--- End quote ---
I tried it, but it didn't do anything. How would you do it by polling? I the code is running a delay for example, and I pressed the button, it wouldn't register the click right?
mjkuwp:
"didn't do anything"
well, to be fair the code doesn't do anything : ) it is empty code.
you are correct in that a button press that occurs in hardware while the code is in delay will not get noticed in a polling situation. A couple of ways to address that.
1. don't use delay
2. write a state machine that looks for the button to be pressed, starts a timer and checks that it is still pressed X number of milliseconds later while never having been un-pressed during that time.
or, better yet look at this:
https://www.arduino.cc/en/tutorial/debounce
Ian.M:
The weak internal pullup needs time to charge the stray capacitance of the pin & button wiring to reach a valid logic '1' level. Therefore a delay between pinMode(buttonPin, INPUT_PULLUP); and attachInterrupt(digitalPinToInterrupt(buttonPin), Button, FALLING); is essential if you want to avoid a spurious interrupt.
1 ms is excessive - somewhere between 10 and 100 us should be sufficient. If you've got a scope, write a test program that outputs '0' on the pin then switches to INPUT_PULLUP mode, in a loop with a 1ms delay. With the switch wiring connected, probe the pin and measure the risetime (to 90%) and triple that time to get a reasonable delay to use in your actual code.
Also, its a good idea to clear any pending pin change interrupts after you've set up the interrupt on the pin, before enabling interrupts. Reading the pins followed by PCIFR=7; should do that (assuming an ATmega328P based Arduino, see datasheet section 17.2.5. Pin Change Interrupt Flag Register).
There's a tutorial on AVR pin change interrupts at http://microchipdeveloper.com/8avr:pin-change-interrupts
The Arduino libraries hide some of the complexity but the hardware and registers are the same.
N.B. Pin interrupts are a *HORRIBLE* way of handling user buttons, and you risk an interrupt storm if the buttons don't have 100% effective hardware debouncing. Jack Ganssle's article on debouncing is worth a read : http://www.ganssle.com/debouncing.htm
skillz21:
--- Quote from: Ian.M on March 23, 2019, 03:27:22 am ---The weak internal pullup needs time to charge the stray capacitance of the pin & button wiring to reach a valid logic '1' level. Therefore a delay between pinMode(buttonPin, INPUT_PULLUP); and attachInterrupt(digitalPinToInterrupt(buttonPin), Button, FALLING); is essential if you want to avoid a spurious interrupt.
1 ms is excessive - somewhere between 10 and 100 us should be sufficient. If you've got a scope, write a test program that outputs '0' on the pin then switches to INPUT_PULLUP mode, in a loop with a 1ms delay. With the switch wiring connected, probe the pin and measure the risetime (to 90%) and triple that time to get a reasonable delay to use in your actual code.
Also, its a good idea to clear any pending pin change interrupts after you've set up the interrupt on the pin, before enabling interrupts. Reading the pins followed by PCIFR=7; should do that (assuming an ATmega328P based Arduino, see datasheet section 17.2.5. Pin Change Interrupt Flag Register).
There's a tutorial on AVR pin change interrupts at http://microchipdeveloper.com/8avr:pin-change-interrupts
The Arduino libraries hide some of the complexity but the hardware and registers are the same.
N.B. Interrupts are a *HORRIBLE* way of handling user buttons, and you risk an interrupt storm if the buttons don't have 100% effective hardware debouncing. Jack Ganssle's article on debouncing is worth a read : http://www.ganssle.com/debouncing.htm
--- End quote ---
Instead of using an interrupt, is there any other way for the Arduino to recognise a button press and change a variable? It wouldn't actually do this if there is another piece of code running, right?
Ian.M:
Instead of making the button trigger an interrupt, poll the button from a timer ISR (which avoids any risk of an interrupt storm), and implement one of the software debouncing algorithms from part 2 of J. Ganssle's article.
N.B. The Timer 0 overflow interrupt is used for various Arduino sytem functions involving timekeeing, and (unless thing have changed since I last looked at the Arduino libraries), its very difficult to patch in your own code in that ISR. If you want to run your button code on a Timer 1 interrupt (approx. every milisecond), you'll need to use the timer's Compare A interrupt. Set OCR0A to 0 and enable OCIE0A to interrupt immediately after the system overflow routine.
Navigation
[0] Message Index
[#] Next page
[*] Previous page
Go to full version