2

I'm working on an Uno, which has only two interrupt capable pins, but i need at least three buttons to wake it up from its power saving mode.

Is there a way to wire buttons such that, in addition to their individual pin, they will also activate a common pin (in this case, the interrupt one)?

3
  • 2
    Why not using the PinChange Interrupt instead? That can also wake the Arduino from sleep modes. And it works with nearly every pin. Though you have one interrupt for a group of max 8 pins and you need to check, which button was pressed, inside the ISR.
    – chrisl
    Dec 9 '20 at 11:55
  • Thanks! Will this also work while in CPU sleep mode from the avr/sleep.h library? Dec 9 '20 at 12:31
  • You could use diodes to "or" multiple buttons together. But in this case I'd go with the pcint solution proposed by chrisl.
    – Gerben
    Dec 9 '20 at 15:44
3

You can connect all the buttons to a single interrupt pin by ORing them via diodes (like Gerben wrote in the comments). That would look like this:

schematic

simulate this circuit – Schematic created using CircuitLab

The diodes isolate each input pin from the other, but allow the buttons to pull down the interrupt pin.

Though that is not the way, that I would suggest. Instead you could simply use the PinChange interrupt. That is a different type of interrupt, which can react to all pins of a port in a single ISR for the whole port. You can mask unused pins of the port away, so that the interrupt doesn't trigger for them. Nearly every pin is usable that way.

If you want to use the Arduino framework for this, you can just use the attachInterrupt() function, which can use the PinChange interrupt in the background.

If you want to go more down into the hardware side and configure the interrupt yourself, you should look into the corresponding sections of the datasheet. The Uno uses the Atmega328p. From 12.2.4 on you see the registers used for the PinChange interrupt (aka PCINT).

  • With the bits in PCICR you can enable the PinChange interrupt for the ports (3 distinct interrupts for the Uno).
  • The PCMSKn (n meaning number between 0 and 2) is used to mask unused pins of the port away. You should set the bits for the used pins to 1, the others to zero.

Then you need to define the actual Interrupt Service Routine (ISR) in your code:

ISR (PCINTn_vect) // handle pin change interrupt for D8 to D13 here
{    
    ...
}

Here again substitute the n for the number of the PinChange interrupt, that you are using. Inside the ISR you need to read all the input pins of the buttons, that are connected to this PinChange interrupt, and execute your code accordingly. Note: As the name states, the interrupt is triggered on every change of the pin. Inside the ISR you need to sort out, what change that was. It comes down to just reading the pin, but you should keep that fact in mind.

Also make sure to never do long things inside an ISR; it has to be as short as possible; Do long things inside the main code, which can get triggered via a flag variable from the ISR)

If you google for something like "Arduino pin change interrupt" you can find detailed tutorials for this, which can go way deeper, than I can on this Q&A site.

Will this also work while in CPU sleep mode from the avr/sleep.h library?

According to Table 9-1 in Chapter "9.1 Sleep Modes" in the datasheet, the PinChange interrupts are on the same level as the External Interrupts INTn in regard of sleep modes. So this should work just like with the INTn interrupts.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.