Introduction: Arduino Programmable Button Panel As Keyboard
This is a pretty simple and fun project with Arduino which is an ideal option for your first interaction with Arduino. You will create a panel with different buttons, each one will do an action in your computer (Mac or Pc) by emulating keyboard shortcuts or commands. In my case, I use it with coding software to have an easy and fun shortcut to copy, paste, duplicate line, save, capture screen and open a couple of apps.
You will need:
- 1 Arduino Leonardo (or any Arduino with usb interface)
- 1 Resistor (this one is optional, any between 110 to 330 ohm will do)
- 1 or more push buttons
- 1 Box
- A couple of cables
- Software: Arduino IDE
This tutorial will, not only guide you through the project, but it will also introduce you to Arduino in general, starting with a very simple push button as keyboard input and will teach you how to add buttons and features in the next steps.
It will be easier if you already have experience with coding, but I encourage you to learn by trial and error if this is your first approach.
Step 1: Let's Start
If this is your first Arduino project, you should know that the basic structure of an Arduino script consists of two parts: the setup and the loop. In the setup, you will define the variables and modes that will be needed in the project; the loop is the set of instructions that Arduino will be running over and over to check the status of its different inputs and outputs.
The first thing to consider: as you will be emulating keyboard inputs, you should be careful not to leave a free keyboard action in the loop repeating and repeating itself, because you will lose control of the computer. In the first step you are going to create a simple action to “copy” when you press a push button.
The code
The software that you'll need to upload the script to the board is called Arduino IDE, you can download it here.
You will include the keyboard library to emulate a keyboard. Then you will define the pin in which you want to connect the push button.
The other two variables will be needed to save the current state (if it is pressed or not) of the button on every cycle and the previous state to check if the state is different in the current cycle:
#include "Keyboard.h"
const int buttonPin = 2; int buttonState = 0; int prevButtonState = HIGH;
void setup() { pinMode(buttonPin, INPUT_PULLUP); digitalWrite(buttonPin, HIGH); Keyboard.begin(); }
void loop() { buttonState = digitalRead(buttonPin); if ((buttonState != prevButtonState) && (buttonState == HIGH)) { Keyboard.press(KEY_LEFT_GUI); // Command key in Mac, use KEY_LEFT_CTRL for Pc Keyboard.press('v'); delay(100); Keyboard.releaseAll(); // This is important after every Keyboard.press it will continue to be pressed } prevButtonState = buttonState; }
In this example, I'm using pin 2 in the mode INPUT_PULLUP, which means that it is an input and will be using the onboard resistor of Arduino. You need to compare the current state with the previous to force Arduino to do the output only once per press and not repeating and repeating the output in every cycle.
You can find another tutorial to create a push button in the arduino website.
The Keyboard library has different codes for every key in the keyboard. You can find the full list here.
You can run apps by command using the following:
In windows: You can open the Run dialog box using the Windows key + R, then set a delay to wait a couple of milliseconds and use Keyboard.print to run a command and Keyboard.press(KEY_RETURN) to run it.
In Mac: You can use the key combo Command + space bar to open Spotlight, then set a small delay and write the name of the app and use Keyboard.press (KEY_RETURN) to run it.
Always remember to consider delays between instructions and Keyboard.releaseAll() after emulating a key combination. As an alternative, you can assign keyboard combinations to shortcuts (Windows) and then using Arduino to emulate the combinations or you can create a macro that reacts to a key combination using software.
You can connect the Arduino board to the computer in any step. The first time, probably, will install some drivers.
The Arduino software is very simple to use. First select your Arduino board model from the Tools > Board menu, otherwise it will not be able to incorporate the keyboard library. When you think that your code is ready, test it with the Verify button, fix whatever problem the code is having, then verify it again and press the Upload button. In some versions you will have to press the reset button on the Arduino board during the upload process. When the upload process is complete, the push buttons will be working immediately. In Mac, it will detect the Arduino as a new keyboard and it will open a window to help you configuring it, just ignore it.
If the project is big, I encourage you to use Atom for the coding, with the language-arduino language support.
Now let’s set up the hardware.
Step 2: The Wiring
The push buttons, usually, have two or three connectors. If yours has two, we must connect one to gnd and the other one will be connected to the pin, whichever you like. In the example code we are using pin 2. If the push button has a third connector, ignore it. It's used to send a different signal when the button is not pressed. We can emulate this kind of action using the script.
You will need to use a resistor because the button can catch interference from the static electricity caused by the components and your own hands, which will result in false press detection. Arduino has a built-in pull-up resistor, you can turn this feature on by setting the button pinMode as INPUT_PULLUP. If you want to use an external resistor, you must connect it between the button and the gnd in the card, and then set the pinMode simply as INPUT.
You can learn more about pull up resistors and buttons in this video.
Step 3: Adding a Debouncer
Some push buttons are not very accurate and can give false press signals. You will notice this bug when you press a button and the output actions are triggered twice. This phenomenon is called bouncing, and the method to avoid it is called debouncing.
We are going to set up a variable to record the time in milliseconds and then compare every press signal change, to know if has been more than 50 milliseconds between them. If it´s been less than that, then is, for sure, a false push signal, and the script must ignore it.
#include "Keyboard.h"
const int buttonPin = 2;int buttonState = 0;int prevButtonState = HIGH; long lastDebounceTime = 0;long debounceDelay = 50;
void setup() {
pinMode(buttonPin, INPUT_PULLUP);
digitalWrite(buttonPin, HIGH);
Keyboard.begin();
}void loop() {
buttonState = digitalRead(buttonPin);
if ((buttonState != prevButtonState) && (buttonState == HIGH)) {
// Here starts the output action
Keyboard.press(KEY_LEFT_GUI); // Command key in Mac, use KEY_LEFT_CTRL for Pc
Keyboard.press('v');
delay(100);
Keyboard.releaseAll(); // This is important after every Keyboard.press it will continue to be pressed}
prevButtonState = buttonState;
}
Step 4: Scale to Multiple Buttons
The wiring is, pretty much, the same as with a single button. The signal cable will be connected straight to the pin and all the gnd will be connected by a single resistor.
For the code, you will have to define all our variables as arrays and create a "for" loops to check the status of every pin:
#include "Keyboard.h"
const int buttonPin[] = {2, 3, 4, 5}; int pinCount = 4; int buttonState[] = {0, 0, 0, 0}; int prevButtonState[] = {HIGH, HIGH, HIGH, HIGH}; long lastDebounceTime[] = {0, 0, 0, 0}; long debounceDelay = 50; void setup() { for (int thisPin = pinCount - 1; thisPin >= 0; thisPin--) { pinMode(buttonPin[thisPin], INPUT); digitalWrite(buttonPin[thisPin], HIGH); } Keyboard.begin(); } // Output actions. Probably the only part that you need to change int outputAction(int currentButton) { if (currentButton == 1) { Keyboard.press(ctrlKey); Keyboard.press('c'); delay(100); Keyboard.releaseAll(); } if (currentButton + 1 == 2) { Keyboard.press(ctrlKey); Keyboard.press('v'); delay(100); Keyboard.releaseAll(); } } void loop() { for (int thisPin = pinCount - 1; thisPin >= 0; thisPin--) { buttonState[thisPin] = digitalRead(buttonPin[thisPin]); if ((buttonState[thisPin] != prevButtonState[thisPin]) && (buttonState[thisPin] == HIGH)) { if ((millis() - lastDebounceTime[thisPin]) > debounceDelay) { outputAction(thisPin); lastDebounceTime[thisPin] = millis(); } } prevButtonState[thisPin] = buttonState[thisPin]; } }
For the wiring connection to remain firm even when you need to open the box, consider tin soldering the wires to the buttons. You can find easy tutorials about this on YouTube.
Step 5: Choose the Hardware and Other Tips
The box: this is probably the most difficult part of the project. Finding the perfect box and making the holes. Unfortunately, I can't guide you through the construction of the hardware because it is not my area of expertise. I’m just going to give you some tips:
- Test it with any cardboard box first (any cereal box will do), to find out what's the best size and configuration. In my first attempt I put the cable hole on the wrong side of the box and it was too little to fit the bigger buttons.
- Don't choose thick cardboard boxes or hard wood, since you’ll find it difficult to make the holes. Take into account that some drill sizes are hard to find and even with the right one, you can tear them apart.
- Use a piece of thin plastic, leather or paper to cover the imperfections of the drilling. You can use a snap-off blade to create the holes in it..
- If you really want an excellent finish, better buy a laser cut box with the right size.
The buttons: some are too hard, some are too soft, some are inaccurate, test a couple before buying the bunch. I am using the classic arcade buttons but there are some with Led indicators. This project is more fun than useful, so keep in mind using the buttons that seem cooler to you.
Step 6: My Current Setup
I’m using a box with 8 arcade-like buttons set in two lines. I created different functions to detect three different types of pressing. I will show you how to do this in another tutorial.
Button [1] Short press: “copy” Long press: “copy” + “search” Lingering press: “copy” + project search in Atom (command + shift + f)
Button [2] Short press: “paste” Long press and lingering press: “paste” + enter
Button [3] Short press: enter Long press and lingering press: duplicate line (the enter is canceled first)
Button [4] Short press: save Long press: save as… Lingering press: save for web in Photoshop
Button [5] Short press: screen capture (command + shift + ctrl + 3 in Mac) Long press and lingering press: screen capture + open Photoshop (Mac)
Button [6] Short press: New doc or tab Long press: New doc + enter (useful in Photoshop) Lingering press: close current tab
Button [7] Any press: go to end of next line in text processor
Button [8] Any press: random YouTube videos
You can follow the progress of the project and my setup in github.
I hope you'll have fun with this project.
You can follow me on Twitter: @pato_pitaluga

Participated in the
Hack Your Day Contest

Participated in the
Make a Box Contest
22 Comments
Question 3 years ago
Does this project work on linux too?
Answer 1 year ago
anything works on linux too
2 years ago
Hello, is it possible to use these buttons with this (https://www.ebay.com/itm/191674383707?chn=ps&norover=1&mkevt=1&mkrid=711-117182-37290-0&mkcid=2&itemid=191674383707&targetid=1068323860070&device=c&mktype=pla&googleloc=9031485&poi=&campaignid=11758054769&mkgroupid=114343353979&rlsatarget=pla-1068323860070&abcId=9300462&merchantid=101498467&gclid=Cj0KCQjw4ImEBhDFARIsAGOTMj_POAN6tYT-D_0CAJj3w7SsQv45SERDq2aLWwq4K1MiAUdjvWCPvYAaAnEJEALw_wcB) and is it possible to use 14 on one leonardo?
Reply 2 years ago
Yes. That kind of buttons will work fine. The Arduino Leonard has 12 digital pins, so up to 12 buttons will work with the same setup. I've seen larger configurations, probably you can use the analog pins too but I'm not an expert.
Tip 2 years ago
Note: Keyboard.h only works on Arduino devices that use the ATmega32u4 processor, like the Leonardo or Micro/Pro Micro.
Maybe I'm wrong but I think the line of code in "Step 4: Scale to Multiple Buttons" should be changed from:
if (currentButton == 1) {
to:
if (currentButton + 1 == 1) {
Otherwise this project worked great for me, thanks for sharing : )
Question 4 years ago on Step 6
to pato_pitaluga.
maybe you have something wrong . you conneted a registor to the GND. this is pull down not pull-up.
Reply 4 years ago
Might be. It's working just fine, though. Thanks.
4 years ago
HI all
i follow your project with 3 button but when i press button 1 does nothing. press button 2 open 2 program at the same time. Press button 3 does nothing too.why ? please check the code. Thank you very much. here is the code
Question 4 years ago on Step 6
Hi all.
I make a button project with 5 buttons do 5 action open 5 different program in PC use combine shortcut key (for ex: ctrl+alt+a , ctrl+alt+b,...). how can i do it ? my idea is when button 1 pressed , program 1 run for 60s then auto stop. and when button 2 pressed the second program run for 60s then stop. and follow on for the rest button. and when one program was running we can not press the other button until the running program stop. Thank you very much.
Question 4 years ago on Step 6
For the place I work, I need to make a keyboard with 3 switches (F1, F7, and F9), and it's going to be used on multiple computers... I've never used arduino before, and I was wondering if I needed to do anything when it's plugged in to "initiate" the keyboard, or does it just work as a keyboard as soon as it's plugged in?
Answer 4 years ago
If you use an Arduino Leonardo and the Keyboard library it will behave as the most common kind of keyboard when you plug it. So you won't need to run any software. Probably the system will install drivers if it needs to, but if you're already using a keyboard in that computer the drivers will be already installed.
If you want to emulate it before building the device just buy a cheap keyboard and plug it as a second keyboard and press the F keys.
5 years ago
Definitely you can do it with https://autohotkey.com/ I've made a custom numeric pad too: https://github.com/patopitaluga/catpad
Reply 5 years ago
The thing is, I don't trust Auto Hot Key, I was just wondering what I would write rather than "Keyboard.press(KEY_LEFT_GUI)", thanks for your help anyway! :)
5 years ago
Hello,
I am using Arduino Uno, I run the code but I receive "error: 'Keyboard' not found.
Does your sketch include the line '#include <Keyboard.h>'?" any advice?
Reply 5 years ago
It requires an Arduino Leonardo to work as a usb device. Arduino Uno will not work, sorry.
Reply 5 years ago
does it work on Arduino mega
Reply 5 years ago
Probably not. Arduino Leonardo is specifically made to identify itself as a usb device when you plug it on a computer.
Question 5 years ago
Thanks for the guide, this is really helping me. I can get all of your examples to work, except the multiple button one. I made two modifications, which i can't see making a difference.
Keyboard.press(ctrlKey) changed to Keyboard.press(KEY_LEFT_CTRL)
pinMode(buttonPin[thisPin], INPUT); changed to pinMode(buttonPin[thisPin], INPUT_PULLUP);
Everything compiles and sends just fine, just when i connect GND to one of the pins i get no output (I am not using an external resistor)
Any help greatly appreciated, this is driving me crazy!
Question 5 years ago
man, i pretend to make one thing like that, but with more buttons (like 200) any tips??
Answer 5 years ago
You can use an Arduino Mega that has 54 pins. Or you can try using removing the keys from a keyboard and soldering the wires and then use some software for remaping the keys, like AutoHotkey