Skip to content
quick program for mapping the ADC values for buttons
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.


Quick program for mapping the ADC values for buttons in my Mage project.

Because I'm working with a microcontroller with only 5 usable I/O pins, I had to be creative with how to have multiple buttons.

The current version of Mage has 7 buttons: UP, DOWN, LEFT, RIGHT, A, B & C.

By wiring them as follows, I can use a single pin to capture input from each button, but also, combinations of buttons:


There are a few issues with doing it this way - in particular, the slight difference in resistor values (I had a bunch of +/- 5% I believe), each unit I make ends up with different ADC values! I also noticed that in some cases, A+B together ends up giving the same value as RIGHT.

Taking some more time to map out different resistor values and using ones with better tolerances would help, however, by the time it goes from a breadboard to a PCB, the whole thing ends up changing. Ultimately, I am planning to use a microcontroller with more pins which would allow 1 pin per button, but I'm happy with this solution for now.

Using the ADC actually turns out to be pretty easy:

ADMUX = 0x00 | 2;                               // Activate ADC2 (Pin 4)

ADCSRA = 0xC7;                                  // Begin conversion
while(ADCSRA & (1<<ADSC));                      // Wait for conversion to finish
unsigned char low = ADCL;                       // Collect bottom 8 bits of value
unsigned char high = ADCH;                      // Collect remaining 2 bits
unsigned int btn_value = (high << 8) | low;     // Shift high byte up, or with low byte

Typical ADC values look like this:

#define _UP     695     47k ohm
#define _DOWN   852     20k ohm
#define _LEFT   930     10k ohm
#define _RIGHT  608     68k ohm
#define _A      512     100k ohm
#define _B      320     220k ohm
#define _C      252     300k ohm

//TODO: Include button combination values once established!

An earlier version also had an 8th button (actually a switch) that I put a 270 ohm resistor on, this gave an ADC value of ~ 1012 (1024 being the max with an ATTiny85 10-bit ADC). This ended up being mostly useless if you wanted to allow for multiple buttons to be held down together.

I haven't had much need for multiple buttons, although I briefly used it as a software reset for buttons A & C. ADC value for those two together was

#define _AC     584

These resistor values give a reasonable separation. Another earlier version of the hardware had a 51k ohm resistor on RIGHT which made it quite difficult to distinguish between UP and RIGHT under some conditions. Much lower than 10k ohm makes the value too large for button combinations to be distinguishable.

I've also noticed that the ADC values drift a bit if my fingers are touching the solder joints on the back of the unit, enough to cause the buttons to not be detected. I'm not sure the exact cause of this - in the most recent board iteration, I've sprayed the front and back with conformal coating to try to eliminate conductive effects, but it's possible the values could still be influenced by induction. I think only a case covering the board would help this but I will continue to experiment. Using a chip with more pins would eliminate this issue entirely.

I could of course extend this program to store the ADC values in EEPROM for each unit/chip combination, however, that seems like a lot of work for this stage of the project! Definitely something I can come back to if I end up making more than a handful of Mages.

You can’t perform that action at this time.