4

I've researched how to attach multiple buttons to a single analog input using a resistor network. Instructables has a good lesson on this: http://www.instructables.com/id/How-to-access-5-buttons-through-1-Arduino-input/?ALLSTEPS

My requirement is that I need to attach an interrupt to buttons (ie the analog input) before reading the analog value, so that all the buttons can act as a trigger.

This works for voltages in the higher range, but not in the lower range (the trigger input waits for a RISING edge).

Can any one suggest a circuit that steps a >0V+ to +5V input to a +5V output so that any button push would trigger the input?

Otherwise, does anyone have other suggestions on how to use triggers for each button?

3 Answers 3

6

Use the analog comparator in the ATmega328P to trigger an interrupt once the input voltage rises enough to indicate a button press.

Connect the analog network to both the analog input and D6.

If your lowest analog voltage is not greater than 1.2V then apply a voltage greater than 0V but more than 40mV less than your lowest analog voltage to D7. If you have not connected the voltage then configure the comparator to use the internal bandgap reference (ACSR |= _BV(ACBG)).

Enable the comparator interrupt and capture on a rising edge (ACSR |= _BV(ACIE) | _BV(ACIS1) | _BV(ACIS0)).

Disable the digital input on D6 (AIN0), and on D7 (AIN1) if connected to a voltage reference (DIDR1 |= _BV(AIN0D), DIDR1 |= _BV(AIN1D)).

Write an ISR that does what you want on comparator trigger (ISR(ANALOG_COMP_vect) { ... }).

Now go back and read all that three more times until you understand it. As always, see the ATmega328P datasheet for details.

6
  • 2
    Cool. I learned something new today. (Voted). I did not know that ATMega chips include an analog comparator, much less that you can trigger an interrupt based on comparator results. I would have built something using an op-amp, but I like the software-only solution. It looks like the ATMega2560 has the same feature. Cool! (I guess I said that...)
    – Duncan C
    Commented Sep 9, 2014 at 0:09
  • Do you have any links to sample sketches using the analog comparator, particularly using it as an interrupt? The registers and configuration on the AVR family are a little quirky and I find a working example very helpful in understanding how to use them. (I'm an old assembler jockey, so I'm pretty good at this stuff.)
    – Duncan C
    Commented Sep 9, 2014 at 0:13
  • Nope. But there is AVR128. Commented Sep 9, 2014 at 0:52
  • That'll do nicely. I didn't know that the ACI flag was set when an interrupt condition was met, even if interrupts are disabled. That's very cool, and useful for writing a tight polling loop rather than an ISR.
    – Duncan C
    Commented Sep 9, 2014 at 2:01
  • I re-read this 10 times and I still don't understand it...
    – hagope
    Commented Sep 9, 2014 at 23:43
2

Considering the fact that from a functional point of view, you just want to have more digital inputs, I would propose to use a Parallel-In Serial-Out Expander, (e.g. CD4021B or 74HC165).

This IC (i.e. 74HC165) has 8 digital inputs, that can be 'shifted' and send to your Arduino using just 2 wires. Arduino has a built-in function for this (i.e. shiftIn) to read the input and to convert it to a byte.

If 8 inputs is not enough, then you can chain multiple IC to create 16, 24 ... digital inputs.

There is an official tutorial for the CD4021B.

I don't know if this is a requirement, but if you want to register multiple key-presses at the same time, then this is a really good strategy.

0

I really do not know your level of experience, so please, ignore this if not applicable; Most cases of a push button will not need an interrupt. It is a human pushing the button and so precise timing is no where close to needing an interrupt. You would only need an interrupt if you wanted to actually interrupt some looping code. And since timing (of a human by definition) is not that great, simply checking for a button press in your looping code will always be good enough. That being said, the common resistor networks you have read about will work adequately.

psuedo code;
void loop()
{
  int btn = analogRead(pin);
  if (btn > pin1Level) 
  {
    if (btn > pin5level) DoPin5();  
    else if (btn > pin3level) DoPin3();
    else DoPin1();
  }
  doOtherStuff();
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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