I’ve been doing a little streaming on Twitch (hiya!), and a lot of streamers I follow have something called an Elgato Stream Deck. The Stream Deck is a small device with 15 buttons, each of which has its own customizable RGB icon. By configuring the bundled software, users can set button icons and macros to control your casting software, send messages in the stream chat, launch programs, and much much more.

Unfortunately the Stream Deck is out of my price range, at a whopping $149.99 retail.  Fortunately I think I can make something that replicates the basic functionality for a fraction of that price: what I’m calling a “Stream Cheap”.

Although I’m focusing on using this as a replacement for a Stream Deck, at heart this is really a custom macro keyboard. It could be used as a hotkey board for any program. I’m just using it for OBS and Twitch.


The Stream Deck itself is a fantastic piece of tech. Adafruit did an interesting breakdown on stream, but it’s essentially a mini computer using an Atmel ARM926EJ-S driving a 480×272 resolution LCD. The buttons on top allow the LCD to shine through for the backlight icons, and push down on a touch matrix to trigger button presses.

There was a lot of engineering that went into making the Stream Deck, and I’m going to have to simplify. The #1 rule for this is cheap. I wanted to make something that people could reasonably build at home, at a much lower cost than an off-the-shelf Stream Deck. The fancy ARM processor is going to be replaced with a dirt-cheap AVR, the touch-matrix keys are going to be replaced by basic mechanical switches, and the customizable RGB icons are going to be swapped out for relegendable keycaps.

That’s just the hardware. When I say “basic” functionality, I do mean basic. Much of the power of the Stream Deck is in the bundled software, and I’m not going to spend the time to develop a complete software package to replicate everything. Fortunately though, I can replace the fancy USB communication with hotkeys from an off-the-shelf keyboard library and an Arduino. This is perfect, since most of what I need this device to control is OBS, which already has a great built-in hotkey manager.

Making the Stream Cheap

The obvious tool of choice for building this was a 3D printer: fast, cheap, and with minimal design constraints. This meant that I had a lot of freedom for designing the case so long as I avoided overhangs.

I chose a two-row design, each with four buttons for a total of eight hotkeys. Eight switches seems like just enough to accomplish what I need it to without getting exorbitant. It also keeps the footprint small on my desk.

The final design is in two parts with a base and a faceplate. The base is a rounded rectangle that curves up to angle the buttons at 20° for easier viewing. It also accommodates the microcontroller with enough room for the backs of the switches and the requisite wiring.

The faceplate is a flat piece of 0.050″ plastic. Although I ended up 3D printing this for convenience, it could just as easily be laser-cut for a nicer finish.

Switchboard Assembly

After printing both parts of the case out of black ABS, it was time to assemble. I’m using Cherry MX Black switches, which are standard fare for mechanical keyboards and have plenty of keycap options. I picked up 8 from DigiKey for $6.32. These are a press-fit into the faceplate, and are retained with tabs.

With the switches in place I got to soldering. Although keyboards usually use a matrix to keep the number of wires down, I decided that with the limited number of switches I could get away with dedicating wires to each button. This also keeps the complexity down as I don’t have to worry about purchasing and installing diodes for each switch. Each switch got a separate signal wire, with the commons all being connected to a ground line. With eight switches, this makes 9 total wires. (I used 22 AWG wire for this. I could have used a smaller gauge to make packaging easier, but I didn’t have any on hand.)

These wires all run to a female DuPont connector, which connects to a right-angle header on the Arduino Pro Micro acting as the brains of the operation. Using a header here allows me to pull out the switchboard or swap out the microcontroller as-needed. I’m using the DuPont connectors because they’re on-hand and easy to find, although it would have been wiser to use a polarized, positive-locking connector.

Micro and Packaging

The microcontroller I’m using for this is a 5V Arduino Pro Micro, which is based around the Atmel 32U4 chip. The 32U4 supports native USB, which allows the Arduino to imitate an HID keyboard. It’s also small and very inexpensive.

The footprint for the Arduino in the case has cutouts for the underside pins, and a cutout in the back for the USB port. Otherwise the walls around its perimeter should prevent it from sliding around, and support it during USB connects / disconnects.

After testing the switch and Arduino setup, it was time to stuff everything into the case. The two holes on the side of the case were tapped with an M3 tap, and then the Arduino was taped into its mounting position. The switchboard was connected and then the faceplate was attached using two M3 screws.

Keycap Icons

The last step to finish off the hardware was adding keycaps with custom images. I could just as well use regular run-of-the-mill keycaps with stock lettering or images, but where is the fun in that?

In anticipation of building this way-back-when, I purchased 20 re-legendable keycaps from MassDrop last year at about $1.40 each. These are the Rolls-Royce of re-legendable keycaps (har), but I really liked the styling. Although these are hard to find and pricey, you can find cheaper relegendable keycaps at places like B&H.

The inside of each keycap is approximately 0.55 x 0.55″. I created an Illustrator template and set to work. This is what I came up with:

They’re a little campy, but they’re colorful and they’ll do the job. I printed these out on glossy photo paper using my home inkjet printer and cut them to size.

Stream Cheap Software

The last step is to make the software for the board. This is going to be relatively simple, as I can rely heavily on a pre-existing Keyboard library.

Secret Keys

When I set everything up to start streaming, I set a few hotkeys to do things like mute my microphone or switch scenes. Unfortunately it can be difficult to find an unused key to use as a hotkey, even on a full-sized keyboard. Often times I would accidentally tap a hotkey (e.g. numpad ‘-‘) while typing something, and have to be told by a viewer that my microphone was muted.

To avoid this problem for the Stream Cheap, I’m going to rely on some “secret” keyboard keys. Included in the HID keyboard spec are twelve additional keys: F13 through F24. These function keys are available to be ‘pressed’ by the USB spec, but aren’t physically on the keyboard. Even though the user cannot accidentally press them, in all other ways they act exactly like every other key.

These keys are picked up by hotkey-enabled programs, but otherwise won’t affect the computer’s functionality. This makes them perfect for a macro board.

Arduino Code

As of this writing, the official Arduino keyboard library does support keys F13 – F24, but this update was done recently and it has not been included in the most recent IDE release. I downloaded the updated library from GitHub and included it in the sketch folder to get access to these keys.

As of May 9th, 2018 version 1.0.2 of the Arduino Keyboard library was released and adds support for keys F13 – F24! You can update your library version in the libraries manager of the Arduino IDE.

The rest of the sketch is very simple: it polls each switch to check if the button has been pressed, and if so sends the respective key stoke to the PC. I’m also using a small helper class to poll each pin and handle press/release functions and debouncing.

As with all smartly-written programs that spam keyboard inputs, there is a failsafe if there is a hardware issue or an error was made during programming. On startup a safety catch will check if pin #1 (arbitrary) has been grounded, which will halt any further action.

With this uploaded, I went into OBS and tried setting a few hotkeys. IT WORKS!

Hotkey Assignments

This will probably change in the future, but here’s how I have the hotkeys set up.  The key numbering goes from left to right, top to bottom:

  1. OBS Scene: Main
  2. OBS Scene: Be Right Back
  3. OBS Scene: Technical Difficulties
  4. (Custom button for stream integrations)
  5. OBS Source: Mute microphone
  6. OBS Source: Hide camera
  7. Twitch Chat: Spam “<3”
  8. Twitch Chat: Spam “💡” (Unicode 1F4A1)

The Twitch chat macros uses an OBS script I wrote, which stops and starts with OBS and hooks into its hotkey menu as well. The custom button (code symbol) is the odd man out – this is going to be a custom button that changes based on whatever interactive stream thing I use that day.


And it’s built! Total cost was around $20, although only because I splurged on the expensive keycaps and the nice switches. You could definitely build this for less.

As I stressed in the introduction, this device is not just limited to streaming! Because it works as a generic keyboard device, it can be used as a macro box for all sorts of programs! I could set simple shortcuts in any program, or use something like AutoHotkey for more complex commands without having to reupload the firmware.

All around this project was a huge success: the “StreamCheap” works exactly as I designed, taking the role of a Stream Deck at nearly a tenth of the cost!

If you’d like to build your own, I’ve uploaded the 3D files to Thingiverse. Have fun!

Parts List

Per tradition, I linked parts throughout the post as they’re used. But it’s handy to have a single point of reference, so here’s a complete list. Be aware that some of these are Amazon Affiliate links that help fund the content on this site. Thank you for your support!

You’ll also need a USB cable, solder, and a little bit of double-sided tape. I used an M3 tap for the bolt holes but you could probably get away with using a heated bolt.

To build this project more cheaply, you might consider ordering the Arduino from AliExpress, and purchasing less expensive keycaps.

I’d recommend keeping the Cherry switches, even though they’re somewhat pricey. A quality switch can make or break a project and these switches are very well-built. All of the switches in the MX line should have the same footprint, so feel free to switch out the MX Blacks for a different color if you want a lighter feel or a tactile response. WASD Keyboards has a good overview of the switch types here.


  1. Any chance you could modify the design to fit two rows of five instead of four? Going to be building this soon but like like some extra keys. Thanks in advance 🙂

    Adam Balfe
    1. Sorry, I didn’t really design the CAD file to scale based on the number of buttons and I’m already knee-deep in some other projects. The model would be a good candidate for a SCAD conversion though, if I ever find the time!

    2. Not OP but you can use some tools created by the mechanical keyboard community for that:

      * Create the base layout of your macropad using keyboard-layout-editor.com
      * Get the raw data from the first site and paste it on builder.swillkb.com, this site will generate the appropriate CAD files for laser cutting the switch plate and what is called a sandwich-style case (layers that are screwed together to make the case)
      * (Optional) Post your macropad at reddit.com/r/mechanicalkeyboards! 😀

  2. When I try to upload the sketch, it says “‘KEY_F13’ was not declared in this scope”. Did I use the wrong library? I’m pretty sure I installed the github library.

    1. You can’t install the library in the IDE because it will conflict with the built-in one. You have to put the source files into the same folder as the sketch, and use quotation marks in your include statement in place of brackets so the compiler looks for the local file.

      1. Should I create a folder with the StreamCheap.ino, then copy the Keyboard library zip into the same folder, or do I put the Keyboard.cpp and Keyboard.h files in? I’m not quite sure how to do it 😛

          1. I don’t have a wiring diagram, but the wiring is very straight-forward. Each key switch has two pins: attach one pin to ground, and one pin to a numbered pin on the microcontroller.

  3. This is probably a really silly question. Trying to upload the sketch to the Arduino – got the sketch file in the same folder as the keyboard library, double checked all of the {}s to make sure there aren’t any extra ones by reformatting and counting and it all -looks- pretty good. However, in trying to compile I get the following compiling errors:

    error: expected primary-expression before ‘void’
    void setup()

    error: expected ‘}’ before ‘void’
    error: expected ‘,’ or ‘;’ before ‘void’
    error: expected unqualified-id before numeric constant

    void setup()
    error: expected declaration before ‘}’ token

    exit status 1
    expected primary-expression before ‘void’

    I haven’t had an opportunity to code in anything that looks like C in a very, very long time but near as I can figure the code looks solid. The only other thing that I can think of is that there’s something missing that I can’t identify through inexperience. Any recommendations?

    -= george =-

    George E. Nowik
    1. Sorry George, I’m not sure what to tell you. I just tried building the sketch new from the online files and it compiled without issue.

      If I were you I’d re-download the sketch and try again. Those errors would seem to indicate some sort of syntax error just before the ‘setup’ function, but I don’t see anything obvious in the code.

      1. Hey there Dave,

        I took your suggestion and just started from scratch; new folders, new paste of the code, everything. Worked like a charm. I have no clue what was up with the oddities from before.

        Thanks for the suggestion!

        -= george =-

        George E. Nowik
    1. Can’t speak about that specific device, but you could definitely retrofit a standard numpad with an Arduino (or similar microcontroller). Although you’d need to rework the code to support a matrix layout.

    1. Sure, you’d just have to change the key mappings in the code. Though it’s untenable for large numbers of keys because for simplicity it doesn’t use a matrix layout.

  4. Is there any chance you would know a way to turn this into a media controller (I.E Pause/Play, next track)? I’m brand new to Arduino stuff and I have no idea how to do about this.

    1. Not a quick and easy way, no. The built-in keyboard library doesn’t work with media keys last I checked, so you’d have to port the code to use something like Nico Hood’s HID library.

    2. You can use autohotkey to perform this task. Below is the code I currently use for ctrl+win+key for media buttons on my 60% kb. You’ll have to modify what is put before the “::” to the F13-F24 keys you set for this macro keyboard. I’m buying the parts now for this to make it, I’ll let you know how it goes.

      ^#,::sendinput {Media_Prev}
      ^#/::sendinput {Media_Next}
      ^#.::sendinput {Media_Play_Pause}
      ^#h::sendinput {Volume_Up}
      ^#n::sendinput {Volume_Down}
      ^#m::sendinput {Volume_Mute}

      Put the script in your startup folder so it runs when your computer boots.
      * ctrl+c to copy script > Win+R > shell:startup > right-click > paste shortcut

      Andy P
  5. Hi, I’m trying to find, find someone to build, or learn how to build a 3-wide by 5-high, maybe even 6- or 7-high board that duplicates (more or less) the traditional ‘nav’ section of a full-size keyboard. I.E., I’m simply trying to find a traditional inverted-T Arrow/Cursor cluster, and it would be nice to have the traditional 3w x 2h nav cluster (fn/del/home/end/up/down), as well as F13-F15, and a row of extra macros above that wouldn’t hurt; maybe even a an extra row of macros between the arrows and standard nav keys. It does not have to have the traditional large gap between arrows and the first nav/macro row, but it does need to maintain the traditional blank spaces on either side of the inverted-T; and it would be nice if there was *some* gaps between navs and F-keys; F and upper macros; etc.

    I’m totally new to this, and I was only able to breeze your article. If there’s enough information in it to make this happen, just say so, and I’ll dive in more carefully. Otherwise, if there’s another spot I can go where someone might’ve already built this, or someone is willing to take it in for a reasonable profit, I’d appreciate a pointer. I’ve tried somewhat on Reddit, but I’m not getting any easy answers. Nowhere near as clear as this will-written tutorial, anyway.

  6. Hi

    Could this be built and programmed to control my logitech webcam software. Mainly Im after two buttons. One that focuses the camera in and another to focus out. Is this possible? Ill take advantage of the other buttons of course, as a streamer on OBS, but these two are my main needs.

    Penelope Blake
    1. It depends whether the software supports hotkeys or not. If you can already control those functions with the keys on your keyboard, then yes. Otherwise you’d need some sort of “go-between” software that takes hotkey input and adjusts the camera settings.

  7. Great project!
    Can it be done with Arduino Nano instead of the Micro?
    I compared the specs of both on the Arduino home page and they are the same, but the Nano is much cheaper.
    And if I want to make a bigger interface, the size wouldn’t be an issue.

  8. I had seen Maker’s Muse do a diy deck inspired by yours but he was using nine buttons instead of eight. I ended up modifying his design but I was curious if there is a way to edit the code so that I can some how daisy chain eight and nine together but still get different f-keys or is there an extra empty slot on the bored I could use. I am very new to Arduino but figured it was a good place to start learning. Thank you.

    1. Hi Austin! With the way mine is set up, all you need to do to wire a ninth button is find a free I/O pin on the board and connect it like the others, then add the additional button/pin to the array in the code. The Pro Micro has an extra 10 pins that are unused in the project, so you can have up to 18 buttons without having to switch to a matrix array.

  9. I was looking to build something exactly like this! Are the extra posts on the PCB mountable switches that you linked required? Or will 3-pin plate-mount switches suffice?

    1. Make sure you have the correct board selected in the menu. It will throw that error if you’re trying to build for a board that doesn’t support the library (like the Uno).

  10. Hello

    having an issue with the supplied code

    error: ‘Keyboard’ not found. Does your sketch include the line ‘#include ‘?

    Library is added to the ID and it wont pick it up and i have no idea why

    1. It will (very unhelpfully) throw that error if you are trying to use the Keyboard library with a board that doesn’t support native USB (Uno, Nano, Mega, etc.). Double-check that you have the correct board selected in the “Boards” menu (Tools -> Boards).

  11. I have been thinking about how I will build a keyboard input for OBS while I wait for my Arduino to arrive. (I am in China so it takes a while) I was going to go the key pad route as you have done, but I don’t stream, rather, I give online presentations and so I am usually standing. I was thinking the keypad would still be a little awkward. So I was looking through my Arduino parts and found that I had an IR receiver and a small IR remote. So I will implement it using a remote. The remote has arrow keys as well as 0-9 keys and A-F keys. So pressing one of these keys will send an appropriate Keyboard code to OBS. I learned some things reading through your article so thank you. Most interesting was the secret keys F13 to F24. Those will be the “appropriate “keystrokes” that will not be confused with other programs. Good info!

    Carl Johnson
    1. It’s definitely possible but it wouldn’t be an off-the-shelf solution. You could use either a Bluetooth module, master/slave microcontrollers with RF modules, or even a WiFi solution and a program on the PC that reads and processes the commands. Regardless of what method you choose, you’d have to rewrite the code from scratch. You’ll also need a lipo battery and a charging circuit.

      I don’t have any specific parts to recommend, sorry!


Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.