Learning CNC and Making a MediaBox


Earlier this year I talked about my “Bit-Box” – a custom keyboard, program launcher, Stream Deck clone, device. https://www.bit-101.com/blog/2020/07/bit-box/

The box was handmade, but I had purchased a 3d printed plate to hold the switches. A little later I had the idea of making my own plate with wood. Initial tests, chiseling out a square hole for a single switch worked pretty well, but as soon as I tried to cut out several adjacent holes, the wood between the holes kept chipping out.

I started thinking about using a CNC to do this, and eventually picked up a Sainsmart 3018 Prover.

It took a couple of hours to assemble. Pretty easy actually. And it only came with some relatively useless v-shaped engraving bits, so I ordered a set of flat endmills in different sizes. Since then I’ve picked up a bunch of different bits.

In terms of software, I’ve tried a few different options.

One is Inventables Easel. This is a web app made for the Inventables X-Carve cnc machine. But it can export gcode that can be used with the 3018. Easel has some decent features for free, but you have to pay for full functionality.

The other one I’ve used is Carbide Create. This is made for Carbide3D’s Shapeoko machines. It’s desktop software and is totally free. It also exports gcode. I like Carbide Create a lot better.

The basic flow is to create a set of simple 2d vector shapes – rectangles, circles, paths – then apply tool paths to each shape. For example, you’d specify that you want to use this rectangle as an outline shape that is cut 1/4″ deep. Or you want to use this circle as a pocket, 1/8″ deep. A pocket cut cuts the entire inner area of a shape to a certain depth. You can also do boolean operations to combine or subtract different shapes. It’s super basic, but really does most of what you’d need.

If you want to really go crazy, you can get into 3d modeling with something like FreeCAD or Fusion360, and then create tool paths from those models. A much bigger learning curve and probably overkill until you get into some really complex stuff.

I use Candle to send the gcode to the machine itself.


My goal was to create a “MediaBox”. This is just what I call a custom mini keyboard with media keys – play/pause, next, previous tracks, volume up/down/mute. Six keys in all. Here’s an overview of all my attempts from one of the original hand-cut versions, some test cuts, a couple of failed attempts, through the final working build:

The initial holes for the keys worked perfectly. A 0.555 inch square hole is all you need. Spacing is something like 0.205 inches between keys.

The main design issue beyond that was where to fit the Arduino board and how to route the usb cable. I was initially using 1/2″ black walnut. On the top were the holes for the keys. I then flipped it over and created a recess on the bottom. But the half inch depth was really too shallow. And my original design was just too small once I attached the cable.

So I switched over to 3/4″ walnut and made the whole thing just a bit larger.

Wired it up much the same as I did for the BitBox. Did some finish sanding and applied some tung oil, glued on a leather bottom.

The software presented a bit of a problem. The Arduino keyboard library does not provide a way to send media key codes. Luckily there is another 3rd party library, HID-Project.

You can add this library to your project by going to sketch / manage libaries and searching for “hid project”.

Here’s the code I came up with:

#include <hid-settings.h>
#include <hid-project.h>

// Define Arduino pin numbers for buttons and LEDs
#define VOL_DOWN 2
#define VOL_MUTE 4
#define VOL_UP 3
#define PLAY_PREV 5
#define PLAY_PAUSE 6
#define PLAY_NEXT 7

const long debounceTime = 30;
unsigned long lastPressed = 0;
boolean A, a, B, b, C, c, D, d, E, e, F, f;

void setup() {

  a = b = c = d = e = f = false;

void loop() {
  if (millis() - lastPressed  <= debounceTime) {

  lastPressed = millis();

  A = digitalRead(VOL_DOWN) == LOW;
  B = digitalRead(VOL_MUTE) == LOW;
  C = digitalRead(VOL_UP) == LOW;
  D = digitalRead(PLAY_PREV) == LOW;
  E = digitalRead(PLAY_PAUSE) == LOW;
  F = digitalRead(PLAY_NEXT) == LOW;
  if (A && !a) {
  if (B && !b) {
  if (C && !c) {
  if (D && !d) {
    Consumer.write(MEDIA_PREV); // alternately MEDIA_REWIND
  if (E && !e) {
  if (F && !f) {
    Consumer.write(MEDIA_NEXT); // alternately MEDIA_FAST_FORWARD
  a = A;
  b = B;
  c = C;
  d = D;
  e = E;
  f = F;

This was adapted from a few other sample projects I found, as well as the code I had for the BitBox. It works great.

Want one?

I made this for myself, but I’d love to make some more. The materials aren’t cheap though. Well over $30 for the wood, leather, Arduino, keys and key caps. Then the time for cutting, finishing, soldering. I’ve got to work out pricing and different options, and the best way to sell them, but contact me if you’re interested.

I’d also be open to selling just the wooden box, either finished or straight off the mill and you can buy the other parts and put it together yourself. It’s a fun project.

Or… if you have a cnc already, I’m going to post the Carbide Create file I used, with instructions, for free. Check back soon for that.