Custom Macro Mechanical Keypad




Posted in TechnologyArduino

Introduction: Custom Macro Mechanical Keypad

About: I make stuff. I personally like 3d printing, and Arduino. Keyboards are a great mix of both

In this Instructable I will be taking you through the basics of creating your own 6 keyed macropad, controlled by an Arduino. I will be taking you through what you need, how to assemble it, how to program it, and how to improve it or make it your own.

After much research, I couldn't really find a great guide on how to make a macro keypad, or a hand wired keyboard in general. So I decided to do it myself, in the simplest way possible, without diodes, resistors, or anything else. I also wanted to have a unique modular keyboard, where I could grab any parts that I needed, this is the first of many other parts. This module's inspiration was from arrow keys on a keyboard, being able to fit it in your pocket, and taking it anywhere if you needed a few extra buttons on the go.

Due to how this keypad was made, I highly recommend that you read all of the Instructable before you make any purchasing decisions.

I also tried to make the Instructable in a logical order, but I don't build logically, so it might be better to skip around in the order of the steps depending on how you build.

Step 1: Getting the Parts

The longest step is right here, buying the parts and waiting for them to ship. Amazon links will be Canadian Amazon. The parts that you are going to need are:

  1. Mechanical Key switches
    • I choose the Gateron switches with clear tops from here (Clear tops make the next step easier, most common types of switches are covered there too)
    • Other places to buy can be found here under your favorite switch section
      • I also highly recommend doing some research here on what switch you would like here under the 'Feels' section
  2. Mechanical Keycaps
    • Make sure that they are compatible with your switch that you choose!
      • Also make sure that they are back light compatible so you can change the colour
    • Vendors can be found here under the 'Novelty Keys (standard manufacturing)' section, unless you want a full Keycap set
  3. Addressable RGB LED strips (Optional, but highly recommended)
    • I bought something similar to these from Amazon
      • Make sure that the LEDs are WS2812B LEDs, they can accept a lower voltage.
      • You could also buy 3mm regular LEDs of your favorite colour to use, but you'd need resistors
  4. An HID compatible micro controller (I used a Pro Micro)
    • I bought these from Amazon for the best deal
      • You can buy other micro controllers, but make sure that they are both Arduino and HID (human input device) compatible
  5. A 128x32 I2C OLED display
    • I bought this from Amazon
  6. Access to a 3D printer
    • Try with local libraries or schools around you and see if they have a 3D printer
    • I've personally never used an online service, but you could use those too (something like this)
  7. Thin Wire
  8. General Tools Needed
    • Soldering Iron and Solder
    • Side Cutter Pliers
    • Small Files (Somewhat optional)
    • Hot Glue Gun and Glue
    • Screwdriver and screws of your choice

Step 2: Keyswitch Modifications

Start to disassemble the switches that you bought. We are doing this to allow the light to shine through better to reach our keycaps. If you have chosen keycaps that don't support RGB, skip this step.

Take 2 small wedges (I used 2 flathead screwdriver bits) and push under the tabs on the side of the switch. Then put something in between the top and bottom so it doesn't close. Proceed to push the tabs of the other side, so no tabs should still be holding the top on. After that, finish up and pop off the top of the switch. There usually is four parts, the top and bottom of the casing, the spring, and the stem (sliding part of the switch that holds the keycap).

Start to cut small little pieces out of the bottom of the case to allow more light to pass. Cut the tab that holds the switch on the plate first. Then cut a bit of the original LED pass through, (the part with the 4 holes, those are for the legs of the LEDs). Slowly cut down on that tab inside to get down to the bottom. Then proceed to cut up to the cylindrical center of the switch that holds the spring. We don't need to go further than that. After that, widen the hole a bit, by slowly cutting off both sides with the pre-molded supports. Another optional step is to file it down, to make it nicer, and less jagged. Make sure that there are little to none plastic bits inside of the casing from this, as you don't want the switch to get stuck. Make sure to do these cuts slow and small, as I've broken a few cases from the width of the side cutters forcing the case apart.

If the top half of your switch isn't clear as well, try to modify it to allow the light to shine through. Try little by little without breaking the switch, because you don't want the stem to fall out. A possible solution may be to cut out the piece of plastic that would hold a normal LED, and leave the plastic that keeps the stem enclosed, and only file it down.

Step 3: 3d Printing

You will need to download one of the zip files below, and 3d print them. There will be different versions depending on what you want. There will be a folder with all of the normal stl files in it (KeybArrowSTLFiles), and one with the Autodesk inventor files (KeybArrowSourceFiles), so that you could modify the files and change them to your own needs. The files are slightly different from what I printed, this was because there were some design flaws, and I felt I could improve them. Example would be the sides of the case, mine were a bit too high so the keycaps wouldn't push all the way down, the new files should fix that.

The design of them was pretty complicated, with over 30+ steps. All I will say is that if you want to design a case for a different size, you should make sure that you have experience with somewhat complicated 3d designs. It's not really for people who are new to 3d design.

Note that both of the casing files are at a 3 degree angle, and you should angle them flat on the bed.

Step 4: Assembling What You Have So Far

Now that we have all of our parts, and we have the 3d printed parts, it's time to assemble it a bit!

Place all 6 of the switches into the plate, and glue them in place. We need to glue them because we cut off the tabs that hold it in place. I suggest waiting to put in the OLED because you don't want it slanted.

Next, cut 6 LEDs off and place them on the LED plate. The squares on the plate are to help you align the LEDs. The square LEDs will fit into them, so you could 3d print another to help alignment, or just line it from the back. Make sure that the arrows point to the other LEDs, as DO would be soldered to DI. Use those squares to glue on the LEDs with hot glue, and hold them in place and wait for the glue to hold.

I used a prototype plate for the switches to hold the LEDs (in the images) because I don't like to waste filament, and decided to reuse. The new file won't affect anything, just make it simpler to align.

Step 5: Setting Up the OLED

I recommend using this Instructable for a thorough walk through. They did a really well job of explaining it.

You will need to download and import this library and this library for the code to work.

First wire it up. Wire VCC to VCC, and GND to GND. Then wire the SDA and SCL pins. The SDA and SCL pins may vary from each Arduino, but on the pro micro, SDA is wired up to pin 2, and SCL is wired up to pin 3. Look up a pinout of your micro controller if you are unsure of what pins SDA and SCL are wired to.

Next is to get it displaying and making images. There will be files below of how to get it working. The first step is to use the ScreenScan code (originally provided by Arduino here). Upload the code onto the Pro Micro and open the Serial reader (under the tools tab at the top). It will read you back and address of the OLED. If your address is 0x3C, then you don't need to change anything. If it isn't, then you need to go and change the address in the ssd1306_128x32_i2c code and the final code (named ArrowKeypad) so that it works properly.

Now test out the example code that was included with the Adafruit ssd1306 library that for the 128x32 i2c code (named ssd1306_128x32_i2c)

After that, keep the Arduino on, and try to line up the OLED on the switch plate, then turn it off and try to glue it in place. You will most likely not get this first try, but keep adjusting to try to get it aligned, so that it isn't angled when it is completed. I suggest gluing one side a bit, and checking before you glue the other side to make sure that it isn't slanted.

Download the code now, and use the other files of code in Step 8 later in this Instructable.

Step 6: Soldering

A Fritzing file will be available below. This will allow you to interact with the circuitry and if you left click and hold, you can see what wires are all connected (highlighted in yellow dots) files that need to be imported to Fritzing before you open the file will be down below (for the Pro Micro and LEDs).

Make sure the pins labled "MOSI, MISO or SCLK" are UNUSED or it will cause glitches with the OLED.

After cutting the 6 LEDs into single strips, and gluing them onto the plate. Place the soldering iron on the copper pads, and add solder to each of the pads. Cut small pieces of wire and strip half of it, twist it, then take the other half off and twist the wire. The wire will need to be held with pliers or some soldering helping hands, while you get it held in place by the solder. Add more solder to hold it there nicely. Solder all of the LEDs in the row together. Cut a wire, and solder it to the end of the LED on the first row, with the label 'DO' or 'D-', and connect it to the first LED on the second row with the label 'DI' or 'D+'. You can do this with the 5v and GND too, but it's easier if the first LEDs 5v and GND on each row are wired together. Wire the 5v wire to VCC, Data pin to any digital pin (code has it set as 10) and GND to a GND on the Arduino.

To get the Arduino to recognize an input, the switches need to connect ground to a data pin. So, you can solder one wire to connect all 6 switches to ground. Solder one wire to each switch, and if possible, try to change the colours of wire to keep track of what switch is what wire. Feed the wires through the LED plate and wire them to a data pin on the Arduino (I used data pins 5-9 for this)

The two switches on the side have different functions, one is a reset switch for programming, while the other is a function switch, which will switch between layers of the Keypad to quickly change functions of the buttons. The top switch, is wired to reset (RST) and GND, when connected, it causes the reset. The bottom switch is wired up to pin 18, which is labeled as A0 on the Pro Micro.Give yourself some slack with the switch wires, as you still need to slide in the plates, and too little of a wire won't allow the plates to inset through the top.

Step 7: Introduction to Programming

Before you want to close the case, you want to test it and make sure it works. You could skip to step 11 to assemble it now. I just find that testing it beforehand helps to reduce the amount of times you open and close it. Even though it shouldn't affect it much, I used the Arduino IDE version 1.8.3, so if you have issues, try to use this version. The code is on Step 5, it is a zip file that you will need to extract and upload through Arduino.

There will be multiple pieces of code below. One will be the final code, two will be to test the OLED (One to test, one to find the address), and one will be to test the RGB. Use the final code to test the switches.

If you want to design your own code, I'm teaching that in the next 3 steps, but it's totally fine if you want to use my code, or take it and modify it.

Some basics of programming this

  • Under the "Tools" tab, then the "Board" tab, set it to an Arduino Leonardo (Unless you have a micro controller that is different from the Pro Micro)
  • Use the reset switch every time you upload code to the Pro Micro. I've found that once the compiling bar is full, and is still uploading, it is a good time to flick the switch on and off to program. (If you don't do this, the upload will just fail to upload.)
  • All Libraries used must be installed and imported
    • To import, go to the tools tab and click include library. (Note also, my code examples on the webpage need to have the <> around the library name, I couldn't enter them in the example code section on the next few steps)
  • The LED and OLED libraries will be initialized as objects, you can name them whatever, but for the sake of demonstration I will name them 'strip' and 'display'
    • Call functions from a object by typing the object name, putting a period, then typing the function you want to use

Next test the LEDs, upload the code, and make sure that they all work. If none work, your missing a pin going to them, check your soldering of the first LED.

Lastly, use the final code to test your switches. This should be the easiest to do. Note that now, after uploading some HID code, you will need to reset the Arduino every time that you upload code to it. Just reset it halfway through uploading it and it should work.

Step 8: Programming the Switches

Out of all of the programming, the switches are the least complicated. To get it recognized as a keyboard, all you need to use is the Arduino Keyboard library, and conditional statements. Make sure that under the Tools tab, the Board is set to an Arduino Leonardo if you are using a Pro Micro like me.

Before we start with the conditional statements, we need to setup the pins. We only need this to run once, so put this into the void setup. Start with pinMode(PinNum, INPUT_PULLUP); This tells the Arduino that the PinNum is expecting an input, and that it adds a pullup resistor (so that we don't need to wire any in the hardware)

The input pullup has 2 states, LOW and HIGH. The Arduino will read LOW on a pin when it is connected to Ground (GND) and will read HIGH when it is disconnected. To find what the pin is reading, we use digitalRead(PinNum).

Starting with the basics, we use conditional if statements to find if the key was pressed. We want this to run over and over so we want this to be put the void loop. If the key was registered as "LOW" then we want the key to be pressed, and the key to be released when the input is "HIGH". So to do this, we code if(digitalRead(PinNum)==LOW){ [Code for when the button is pressed] } and code if(digitalRead(PinNum)==HIGH){ [Code for when the button is released] }

For the code for the keyboard, import the Keyboard library. Put a keyboard.begin(); in the void setup. Then inside of our conditional statements, we use[key]); and keyboard.release([key]); or keyboard.releaseAll(); if you had multiple keys pressed. You could also use keyboard.print([String]); and keyboard.println([String]) to print strings, like a password. print and println are similar, but println just adds an ENTER, so it automatically goes to the next line.

Step 9: Programming the OLED

Starting with programming the OLED, you will need to have basic setup code. This basically tells the computer where your OLED is located, the size of it, and how it is programmed. Once you have the setup code for the OLED, assuming you're only displaying text, it should be pretty simple to program. First include the Wire and SSD1306 libraries.

Define the OLED_RESET as 4, and include the SSD1306 library in your code. Put Adafruit_SSD1306 display(OLED_RESET); in your code to begin the use of the Adafruit SSD1306 library.

Start with Serial.begin(9600); then display.begin(SSD1306_SWITCHCAPVCC, 0x3C); to initialize the i2C display with the address of 0x3C (unless it changed in step 5). Put both of these in void setup because they only need to run once.

Before you program the display, you should make sure you use display.clearDisplay. If you don't what was inputted will overlap, and depending on what was changed, won't be legible. You also want to set the origin, so use display.setCursor(0,0); to set it on a point on your display, put (0,0) to reset it back to the beginning. To set the size of the text, use display.setTextSize(1); I wouldn't go much bigger than 1, it's much larger than expected.

Even though our display is monochrome, we need to set the text colour, so we program it like display.setTextColor(WHITE);

Now that you have your library imported and your display object, you can start to program it. To add text, use display.print(); and display.println(); to print strings. Again, print doesn't add a return while println automatically returns to the next line when something is printed again.

Before you get anything to display, you need to update the OLED, and tell it to update, you use display.display(); with no parameters and it will update.

The code should look something like this now:

//Code Made by Foster Phillips
#include Adafruit_SSD1306.h
#include Wire.h
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

void setup() {
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
void loop() {
  display.println("Hello World!");
  display.println("Hello Instructables!");

This Instructable and this Github link are both very good references for troubleshooting, and learning more on programming the display respectively.

Step 10: Programming the LEDs

The LEDs are reasonably simple too. We will be using the Adafruit Neopixel library. Personally, the NeoPixel library is very similar to programming in Processing, if you've ever programmed in that.

There is first setup code, addressing what library we are using, and setting up an array that basically says how many LEDs are on the pin, what pin is for data, and how it is programmed. This is done with an example like Adafruit_NeoPixel strip = Adafruit_NeoPixel(6, 10, NEO_GRB + NEO_KHZ800); This explains that there are 6 LEDs, the pin is pin number 10, and that is uses the NEO_GRB + NEO_KZH800 type of addressable strips. Usually the last argument doesn't need to be touched, the LED strips that I used didn't need that changed.

After that you need the strip.begin(); function showing that you are ready to start using them. Nothing needs to be in the brackets.

Once you have that, you can call different functions with the strip.[function]

One that you will need to know is strip.setPixelColour. This has 4 functions in the brackets. You have the LED in the 'array' of LEDs (remember, Arrays start at 0) and the corresponding Red, Green, and Blue values from 0-255. This will allow you to mix the desired Red Green and Blue values to get a colour that you want. The code should look like: strip.setPixelColour(0,0,255,255); if you wanted a cyan colour on the first LED.

The LED also needs to be sent that data, which is what; does. It will update the pixels after you have changed something with them. Nothing needs to go into the brackets.

The code should look like:

//Code Made by Foster Phillips
#include Adafruit_NeoPixel.h
#define PIN 10
#define Num 6

Adafruit_NeoPixel strip = Adafruit_NeoPixel(Num, PIN, NEO_GRB + NEO_KHZ800);

void setup() {
void loop() {

More information can be found here.

Step 11: Assembling!

This is probably the easiest step, and the coolest.

Start by placing and sliding in the Pro Micro onto the case closure. Glue it into place with some hot glue.

The case/closure was designed so that you could side the switch plate and LED plate in. Just slide it in, and depending on how you printed it, you might need to file or cut the inside of the slides to remove some overhang plastic.

After that, get your screws and just jam it into there and make your own screw holes. I didn't have specific screws threads when I designed the files, so I just made a hole roughly the size of a screw and screwed it in myself. Heating it up with a lighter will help to form it to the screw you need, and usually strengthen the layers. Make sure not to push too much on the screws, or you can strip the head. I used Allen key screws to reduce this risk.

Then just push the key caps onto the keys. Then it's pretty much done! My version of the Arrow Key Macropad is complete!

Step 12: Your Own Improvements!

Now that you know how to make my version, you can make your own! Keyboards can arguably be about expressing yourself, so just having someone else's design isn't fun unless you modify it to fit you! There are many improvements you can do! Here are some improvements that I'd like to add or thought of!

  • Program Tetris and other simple games
  • Make it bluetooth
  • Allow it to read data from slideshows and display it one the OLED (Show the slide number and name of slide)
  • Make a full sized keyboard or larger macropad using these technique
    • You'd need to learn how to make a switch matrix for this
  • Program more colour options
  • Program macros for games, video editing, etc.
  • Use the Autodesk Inventor source files to make your own case, or modify it to be uniquely yours!
  • Add a sound board to have it double as a music player

Have fun making! Feel free to add tips or ask me to clarify!

If you want to see progress of the other parts, consider checking out my Instagram. Thanks for reading my Instructable!

Microcontroller Contest

This is an entry in the
Microcontroller Contest



  • Woodworking Contest

    Woodworking Contest
  • Make it Move Contest

    Make it Move Contest
  • Microcontroller Contest

    Microcontroller Contest

We have a be nice policy.
Please be positive and constructive.


4 Questions

Hi , I have this code for my project

but I am getting the error 'Keyboard' not found. Does your sketch include the line #include <Keyboard.h>


The list of keyboard modifiers can be found here: all you need to do is put those modifier names in the functions brackets. Something like: keyboard.print(KEY_UP_ARROW); if you want to input a letter, all you need to do is put the letter in apostrophes, and put it inside the brackets. Example:'e'); If your wondering, inputting both shift and a letter will automatically capitalize it, you don't need to write code for that. Don't forget to release the key as well, in the second if statement when the key goes back to a state of HIGH.

More functions of the keyboard library can be found here:

2 more answers


The only thing I can think of being the issue, is that you either have a board that isn't HID compatible (make sure that the chip is an atmega 32u4 chip) or that you either have the wrong board set when programming. If your micro controller isn't an atmega 32u4 chip, you will need a different micro controller. If you have an Arduino Pro Micro like I do, make sure that under Tools, the Board section is set to an Arduino Leonardo. Hope that helps!

thanks! setting it to Arduino Leonardo worked. Also is there a list of keycodes that you use.

Is there a way for the Arduino to receive and use input from a 5.8 GHz FPV signal? This keypad would be very useful for an FPV ground station.

I don't believe that would be possible. IIRC, FPV transmits video, which is way too much for the Arduino to be able to process it. Maybe an ESP32, but I don't guarantee anything. You'd probably need something more powerful like a Mini PC, like Raspberry or Orange Pi.

2 more answers

Okay, so can this keypad be done on a Raspberry Pi? I am not the best at figuring out how to hook up these things.


I'm not really that experienced with things like that. It's most likely possible, but you may need to combine this with another Instructable or project. Try doing some research if there is a shield or something that would be able to send a 5.8 GHz signal with a Arduino, then use this Instructable for the build. Maybe you could have it transmit to a computer that would transmit the signal to the drone, although I know that'd be inconvienient. Sounds like an intriguing project!


Hi, you can use a USB port to plug this into a computer and it will act as a keyboard right? Also, can you make it without the OLED screen?


Yup, It just connects with a USB port, it acts exactly as a keyboard. You can make it without the OLED as well, just skip the OLED step and remove the OLED code from the final code. You might want to modify the files too, so you don't have the empty spot, but otherwise it is possible!

1 more answer


YEE! Im going to make one as small as possible with small buttons instead of mechanical ones! :D

What is this used for?


It can really be used for anything. Most of the time, it will be used if you just need a few extra buttons, or want some macros to simplify editing videos or creating a 3d file.

2 more answers


A game control like Tetris

Thank you for updating my brain. Cheers


Hey great project! doing something simmilar myself;

You could save some pin mapping by making your buttons into a matrix like a keypad etc. Are there any downside by doing that? (3x2-matrix)

They you could also make a keypad object in your code just to make the code that little bit more dynamic and scaleable! I can provide some simple examples of what I mean.

4 replies

Actually come to think of it. It might make it harder for holding buttons down.

I'll do some more research.

Personally a keyboard matrix is really only useful for a full sized keyboard, but even then you could buy a larger microcontroller such as a Teensy 3.5. I think it'd just be fun to try, but I'm not sure how effective it is other than organization of wires.

The scalable code is a great idea though! I'm still learning c++ and the arduino ide but I'm sure I could adapt what I know about java, and make a class for objects of switches instead of all the if statements. I'll try it out!

You would be able to upgrade 3 more buttons (if you want) with only 1 more wire to the controller.

But ofcource no need if you only need those 6 buttons. :) Great project looks amazing. Have a nice day!

I really only need the 6 keys. This is a small part in a larger keyboard, where everything is modular, so I really did mean to base the macropad off of the arrow keys. I never really needed a matrix, as I already have enough pins for the switches, even for the full keyboard, so the matrix doesn't seem beneficial. Good tips though!

Very cool. I really like the LEDs, I'll definitely be making my own version once I get a 3D printer. Thanks for sharing!


Thank you P. Foster, this is a cracking project, and one that I would have made a few years ago.

However, in my previous job I came across the Cherry G84-4700 programmable number pad with 21 programmable keys. The USB version is really easy to program.

I Googled it today and found one for £48.33 GBP.

So, for those that like the concept but are unable or unwilling to undertake the challenge of the build, there is an alternative option.

Can you change the USB communication to Bluetooth?

2 replies

It definitely would be possible, but you'd probably need to increase the size of the case to fit a bluetooth shield and battery. From what I see also, you might need to remove the OLED display as it might interfere with the communication. I'd research it a bit more and see what pins the bluetooth shield would use to prevent interference, maybe research a different microcontroller as well, as different micro controllers might not have the interferance that I experienced

You don't need an entire shield to add Bluetooth functionality to an Arduino. Something like a HC05 accepts serial input, can act as a host (connect to PC automatically) and is easily configured. The only drawback of using Bluetooth would be that the module is seen as a serial port on the PC too (not a HID device), so a program running on the PC is needed to activate any keys.

A quick Google search reveals that the HC05 module can be reprogrammed as a hid device, but that is a little advanced. There also exist HID Bluetooth modules, however. See for example.

I wonder that to. I don't know how popular they would be, and I'm not sure how I would work things out like shipping times and cost, but maybe I should try it with etsy or something?

Looks like a great idea; very useful to have these around, and I'm glad you decided to show us your process- it's always quite nice to have some help doing stuff like that. :)

(constructive criticism) your 3d print looks a little rough, (that may not be something you cared about when you made this, but if you do) you may try using filler paints to smooth the printing lines, or sanding them, or a combination of both. After that process, depending on how much work you put into it, the prints usually come out looking pretty much as smooth as injection molds.

Still though, you did this first so props to you :)

2 replies

I know my prints aren't the best, but that's because I still need to fine tune it. I've improved them a lot, but I'm not super stuck up on the quality. For something like this, it does me well, but with previous prints I've put layers of primer. It all depends on what the print is for, plus for something like this, I don't really want paint on this, for the smell, and chipping, even though I know that you can get rid of those.

Ah I see, perfectly fine :) I know some people care a lot about the aesthetics as well, so I was just giving some advice. In that case, functionally, I can see it works quite well. Congratulations on the current success, and I hope the next version turns out even better. :)

Love your work, thanks for sharing :)

You can't unsee it once you know. Cherry MX style keys are marked only on the top 1/3 of the key because of the switch mechanism being in the center of the key. There is another kind of key switch called RomerG made by Logitech where the light is in the center but they're harder to get ahold of, both switches and caps.