The ButtonShield, a 34 button mini-keyboard shield

I finally got around to uploading pictures and debugging all the code… so I figured I’d post some pictures of the ButtonShield I built here too, in my attempts to make my Arduino do things it definitely wasn’t meant to do originally… which I think is the whole point of Arduino in the first place. I spent a bunch of time building and debugging the shield, and my fingers are still sore from manually “picking and placing” all the buttons with eyebrow tweezers…

This is a little shield that has a 4x8 pad of buttons, and a space bar and a shift key in the lower left that has two white LEDs that are either on or off to indicate whether the shield is in Mode A or Mode B. Depending on the mode, it uses a different set of pins to communicate with the Arduino, so it can “get out of the way” of other shields (and so it doesn’t clobber them).

Here’s a zoomed in photo of the shift key’s LEDs:

And this is what it looks like when it’s in shift mode:

Chris and I made a bunch of them by hand, and tried to learn how to use a “homemade” solder reflow (toaster) oven to assemble them:

The shield also has a backlight on the underside, which is controlled with an SPDT switch (the other switch is to set the shield in either Mode A or Mode B):

Omar, Chris, and I built an Arduino library file to abstract all the backend code, so the function to read a button is pretty clean (there’s a buffer too, in case buttons are pressed faster than the Arduino can poll them):

#include < ButtonShield.h >

ButtonShield buttonsA = ButtonShield(0); /* Created a new ButtonShield on Mode A */
ButtonShield buttonsB = ButtonShield(1); /* Created a new ButtonShield on Mode A */

void setup() {

void loop() {
Serial.print("ModeA: ");
Serial.print(" ModeB: ");

There are a couple of videos up on YouTube too of the shield in use (since I can’t remember how to embed youtube videos on the forum)…

sexy ;D

shield shield shield shield shield

I wonder if I could have used the word shield again in the title... I should probably re-read things a little closer before hitting post... oh well...

@jezuz - thanks :-)

Hi inthebitz,

This is real nice stuff. Acknowledge the sheer effort that's required to do the polling and multiplexing and the home toaster. There surely is a lot of stuff going here in the Arduino community. Arduino has clearly become the new Altair.

As for the shield itself, do you envision any potential applications from its use? like a microcomputer with display and keyboard. Its hard to see how this could be used for microcomputer applications when you have a PC that has become the center of things like visualization, input, output. Nevertheless, it takes the community a leap forward. Nice work. keep it up.

Tell me about your button library. I've been thinking about keyboard drivers (for computer keyboards, in my case), and wondering whether it makes more sense to have individual button status, group button status, events, "changed" status, or something else (or some combination.)

boolean x = button_status(A_BUTTON); // single button long buttons = button_status(MASK); // up to 32 buttons byte nextButton = button_read(); // next button press detected

I guess part of the problem is not being quite sure what I'd be using the buttons FOR; it probably changes depending on application (ascii keyboard device being significantly different than music device, for example.)


If you describe the Buttons as a big array, then you can easily scan through the entire list. Here is snippet of the ButtonShield ‘core’ code.


/* The user pin lookup table.
   This table provides a mapping to the ButtonShield hardware pins. */
PIN_DESC_T const pinTable[] = {

    /* 0 */  { &PORTA, 0, &PINA, &DDRA }, //not a button

    /* 1 */  { &PORTA, 5, &PINA, &DDRA }, //the top left button
    /* 2 */  { &PORTA, 6, &PINA, &DDRA },
    /* 3 */  { &PORTE, 3, &PINE, &DDRE },
    /* 4 */  { &PORTE, 4, &PINE, &DDRE },
    /* 5 */  { &PORTD, 3, &PIND, &DDRD },
    /* 6 */  { &PORTB, 5, &PINB, &DDRB },
    /* 7 */  { &PORTD, 7, &PIND, &DDRD },
    /* 8 */  { &PORTD, 0, &PIND, &DDRD },

    /* 9 */  { &PORTA, 4, &PINA, &DDRA },
    /* 10 */ { &PORTC, 7, &PINC, &DDRC },
    /* 11 */ { &PORTE, 2, &PINE, &DDRE },
    /* 12 */ { &PORTE, 7, &PINE, &DDRE },
    /* 13 */ { &PORTD, 6, &PIND, &DDRD },

Now with your table, you can easily index through a huge list of Buttons and set them all to inputs in a few lines of code, for example like this:

    for(pin=1;pin<36;pin++) // loop that sets pins 1 to 36 as inputs
        pinMode(pin, INPUT);  //sets the pin as an input pin on the buttonshield
        digitalWrite(pin, HIGH); //sets the input to be high by default (enable internal pull up resistor)

To poll the Button inputs again, scan through the entire PinTable in a for() loop, ditching out when you’ve found a pressed button.

That’s your foundPin

Using the foundPin id, the ButtonShield directly writes to 6 Arduino input pins, or ‘bits’ if you’d like to think about it that way. Like this:

    /* Write the button value onto the Arduino pins */
                digitalWrite((i+kArduinoPinsOffset), foundPin&1);
                foundPin =  foundPin>>1; 

That’s it!

What is the chip on the back that does all the work anyway? Is it another ATMEGA?

you could say it's kind of a workhorse, doing all the debouncing for the 38 inputs into the chip.

The atmega645 core is just like the one in the Illuminato board.

@vxir - Yeah, the problem with working with buttons in projects is that I can easily get 1 to work with debouncing. But then when I want to do 4 or 5 buttons, the computational load to debounce the buttons starts eating up all the clock cycles in the main loop. Heaven forbid I wanted to do a software-based serial at the same time, or maybe even a couple of pwn controls (even thought pwm is hardware, dynamically changing values in response to some input can be intensive). So doing all the polling and calculation for 34 buttons is pretty much all most microcontrollers can handle… hence the need for a dedicated processor on the backside.

There are other ways to do it, like row-column polling (kind of like doing the inverse of charlieplexing), but then you can’t capture multiple presses, there are errors on same row-same column back to back quick button presses, etc.

It was a fun project, actually, … I even went back to some old keyboards I had, opened them up, and reverse diagrammed how they worked to figure out how other people solve the same kinds of “many button” problems (kinda like the “many body” problem - ha).

I’m working on a little microlaptop project using the buttonshield right now… but I think it’ll take 2 more weekends before it’s ready…

@inthebitz -- Thanks for the reply! So since its an AVR 645 it sounds like if I had a really simple application (or maybe just some more advanced button-combination logic) I might be able to run it on the button shield directly...

Also are the buttons surface mounted? If so, could you briefly describe how you managed to surface mount onto both sides in the toaster oven. Most sites on the web that I've read tell you NOT to DIY double sided surface mounting.

@vxir - well, ya do one side, then you do the other :) seriously, though, sometimes it works sometimes it doesn't. in general, i did the buttons on one side with the reflow oven, and the back side with the complicated chips chris and i tended to do manually. i think you can get special types of solder paste that let you reflow both the back and the front at the same time. by the way, great posts on the open company!

thats an awesome little shield :)

can u say cigar box serial terminal/computer? :P (as long as u can add a small screen in someplace XD)

two quick questions:

when will these be on sale?


I'm relatively new to electronics (only 3 months, ish), and ive noticed that a lot of people use at atmega on their shields to interface with the atmega in the arduino...

first of all - is that so that you can pre program the atmega on the shield to respond is a specific way when it receives input from the real arduino atmega through specific pins? or is there some sort of other reason for the extra chip?

and finally - when you do place smd versions of the atmega onto boards like that, how do you program them beforehand? I mean, you cant really pop it into the usual arduino 2009 or anything, so how does the code get onto the chip?

EDIT// - also, what are the dimensions of the buttonshield?

@jezuz - well actually, i have a couple that i've been making here at my desk for the last week, every day i get home from work. if you want one, send me an email at inthebitz at gmail, and i'll build one for you :)

btw the reason to use an atmega on the shield itself too is to abstract a lot of the complex continuous-polling routines and code, so that the code that actually runs on just the arduino itself can stay small, clean, and fast. if you were to put all the code for the buttonshield, plus a touchshield, plus a midishield and a wifi shield all in one place, it's overwhelm the poor little arduino chip ... ha

A mini keyboard also known as an ergonomic keyboard, has many benefits. There are many definitions of ergonomics, keep in mind that they vary based on the working conditions. The most basic definition is the science of people-machine relationships. Make sure that you become aware with each and every aspect of ergonomics so that you can avoid problems that come from working with the wrong posture.


Ummm, that last post seems kinda SPAM to me.


@phil - yeah, exactly… it’s a good way to find out where the spammers’ hot keywords are too, i suppose. “mini keyboard” probably got him all excited. i guess that means i probably shouldn’t tell anyone about my viagrarduino project :slight_smile:

in all seriousness, though, if i can find some more time away from work this week, i’m building a little mini computer with the buttonshield right now, and i’m hoping it’ll be done by the weekend…

I always love a mini keyboard because it can help you escape the pain and other effects of carpal tunnel syndrome.

Somebody really loves his mini keyboard for sending SPAM.