Electronics > Beginners

How to initialise INPUT_PULLUP before Interrupt runs in Arduino?

<< < (3/4) > >>

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

There was an error while thanking
Thanking...
Go to full version
Powered by SMFPacks Advanced Attachments Uploader Mod