Introduction: Sim Racing Button Box

Welcome sim racing addicts!

Are you running out of keybinds to map all your car controls to? You're probably in need of a button box! In this Instructable we'll be creating one from scratch. The button box will have 32(!) available button states. No additional software is required to use this button box. You'll learn how to setup a button matrix and write (or copy) code to upload to your Arduino.

It's important to know that the button box does not support a lot of simultaneously pressed buttons.

Let's get started!

Step 1: Preperation

You'll need some tools, buttons and more items to create the button box. Feel free to create the button box to your desire.

Electronics:

  • Buttons
  • Toggles
  • Rotary encoders
  • Arduino Pro Micro
  • Mini USB to USB cable
  • Wires

Tools:

  • Drill
  • Solder
  • Caliper
  • Screwdrivers
  • Cutter
  • Wrench

Software:

  • Arduino IDE
  • Photoshop/Paint (optional; can be drawn by hand)

Other:

  • Enclosure (a box; can be bought or custom 3D printed)
  • Carbon vinyl wrap (optional)
  • Rotary encoder knobs
  • Switch covers (optional)
  • Label printer (optional)
  • Rubber grommet

Once you have all (or enough to get started) items we can start designing the layout of the button box.

Step 2: Design the Box Layout

Tools required for this step:

  • Photoshop/Paint (optional; can be drawn by hand)

The design of a button box can be different for everyone. However, for this Instructable we'll use a layout that consists of:

  • 4x three way toggle switches
  • 2x one way toggle switches
  • 10x simple push buttons
  • 4x rotary encoder with simple button

Three way toggle switches:

There are many types of toggle switches. Some are momentary and some stay in place until switched back. It's up to you which type to use, but I advise using momentary switches as this button box is not capable of having many mutiple buttons active at the same time. Since the toggle switches are three way (on/off/on), we have eight (4x2) buttons available.

One way toggle switches:

These can be considered as simple buttons (off/on). These can also be momentary or toggle. Again, up to personal preference which to choose. These give us two (2) available buttons.

Simple push buttons:

Buttons like these can be used by simply pushing them (off/on). These will give us ten (10) buttons.

Rotary encoders with simple push button:

Most (if not all) rotary encoders can be turned to both directions infinitely. Everytime you rotate them to a direction it's used as a button press. These rotary encoders can also be pressed giving them another button. The rotary encoders give twelve (12 = 4x3; rotate left/rotate right/push) buttons.

32 buttons:

Having them all together gives us 32 (8+2+10+12) button presses!

Satisfied with the layout? Time to start building!

Step 3: Measure and Drill

Tools required for this step:

  • Caliper
  • Drill
  • Electronics (buttons, switches, etc.)

Measure all the buttons that you want to add to your button box. If you're having trouble finding the dimensions of your electronics, use a (digital) caliper to get the diameter of them.

Mark the centerpoints of the electronics on the face of your enclosure and drill holes with the correct sizes. Looking to make the enclosure a bit more aesthetically pleasing? Wait with fitting the buttons!

Once you're done drilling the holes we can make it start to look like a real button box!

Step 4: Fit the Buttons, Rotaries and Toggles

Tools required for this step:

  • Electronics (buttons, switches, etc.)
  • Wrench
  • Carbon vinyl wrap (optional)
  • Cutter (optional)

All of your electronics should come with a nut to screw it in place. If not; measure them and purchase the correct size nut.

Should you want to improve (personal opinion) the look of your button box you can use a carbon fibre vinyl wrap. Cut it to the size (and a bit larger) of your enclosure's face in which you drilled the holes. Apply the vinyl and wrap it around the corners to the back. This will make sure the wrap stays in place when the enclose is closed. Excessive vinyl that now block the holes can be removed using a cutter.

Having put on the wrap (or not) you can fit in the electronics to create the front of your button box. You should now have something that really looks like one already! Sadly, it doesn't work yet...

Step 5: Design the Wiring Layout

Tools required for this step:

  • Photoshop/Paint (optional; can be drawn by hand)

Creating a matrix:

Using a matrix will save us time and a lot of unnecessary wiring and soldering. I won't go into much detail myself, but will suggest that you take a look at this article if you're unfamilair with the concept of a matrix.

Design your own matrix or use the layout from this Instructable. In the matrix we will use five groups. The groups are connected to the following pinouts on the Arduino:

  • 15: four rotary encoders
  • A0: five push buttons
  • A1: two three way toggles and one push button
  • A2: two three way toggles and one push button
  • A3: five push buttons

Step 6: Soldering

Tools required for this step:

  • Soldering iron
  • Solder
  • Electronics (mounted on your enclosure)
  • Arduino Pro Micro
  • Wires

Optional:

Upload the code from the next step first if you're worried about soldering. This will allow you to check your connections!

We want to apply the matrix designed in the previous step to the actual button box. Take some time for this, especially if this is your first time soldering.

Some tips:

  • Do one group at the time
  • Connect the Arduino to your computer to test occasionally
  • Do not heat up plastic buttons too much as they can melt and break connections
  • Do not use too much solder, less is better
  • Use different color wires for each group/ground

Step 7: Writing the Code

Tools required for this step:

  • Arduino IDE
  • Joystick library
  • Keypad.h (Arduino IDE > Sketch > Include Library > Manage Libraries... > Search for Keypad and install the one that is created by Mark Stanley and Alexander Brevig)

#include
#include

#define ENABLE_PULLUPS #define NUMROTARIES 4 #define NUMBUTTONS 24 #define NUMROWS 5 #define NUMCOLS 5

byte buttons[NUMROWS][NUMCOLS] = { {0,1,2,3,4}, {5,6,7,8,9}, {10,11,12,13,14}, {15,16,17,18,19}, {20,21,22,23}, };

struct rotariesdef { byte pin1; byte pin2; int ccwchar; int cwchar; volatile unsigned char state; };

rotariesdef rotaries[NUMROTARIES] { {0,1,24,25,0}, {2,3,26,27,0}, {4,5,28,29,0}, {6,7,30,31,0}, };

#define DIR_CCW 0x10 #define DIR_CW 0x20 #define R_START 0x0

#ifdef HALF_STEP #define R_CCW_BEGIN 0x1 #define R_CW_BEGIN 0x2 #define R_START_M 0x3 #define R_CW_BEGIN_M 0x4 #define R_CCW_BEGIN_M 0x5 const unsigned char ttable[6][4] = { // R_START (00) {R_START_M, R_CW_BEGIN, R_CCW_BEGIN, R_START}, // R_CCW_BEGIN {R_START_M | DIR_CCW, R_START, R_CCW_BEGIN, R_START}, // R_CW_BEGIN {R_START_M | DIR_CW, R_CW_BEGIN, R_START, R_START}, // R_START_M (11) {R_START_M, R_CCW_BEGIN_M, R_CW_BEGIN_M, R_START}, // R_CW_BEGIN_M {R_START_M, R_START_M, R_CW_BEGIN_M, R_START | DIR_CW}, // R_CCW_BEGIN_M {R_START_M, R_CCW_BEGIN_M, R_START_M, R_START | DIR_CCW}, }; #else #define R_CW_FINAL 0x1 #define R_CW_BEGIN 0x2 #define R_CW_NEXT 0x3 #define R_CCW_BEGIN 0x4 #define R_CCW_FINAL 0x5 #define R_CCW_NEXT 0x6

const unsigned char ttable[7][4] = { // R_START {R_START, R_CW_BEGIN, R_CCW_BEGIN, R_START}, // R_CW_FINAL {R_CW_NEXT, R_START, R_CW_FINAL, R_START | DIR_CW}, // R_CW_BEGIN {R_CW_NEXT, R_CW_BEGIN, R_START, R_START}, // R_CW_NEXT {R_CW_NEXT, R_CW_BEGIN, R_CW_FINAL, R_START}, // R_CCW_BEGIN {R_CCW_NEXT, R_START, R_CCW_BEGIN, R_START}, // R_CCW_FINAL {R_CCW_NEXT, R_CCW_FINAL, R_START, R_START | DIR_CCW}, // R_CCW_NEXT {R_CCW_NEXT, R_CCW_FINAL, R_CCW_BEGIN, R_START}, }; #endif

byte rowPins[NUMROWS] = {21,20,19,18,15}; byte colPins[NUMCOLS] = {14,16,10,9,8};

Keypad buttbx = Keypad( makeKeymap(buttons), rowPins, colPins, NUMROWS, NUMCOLS);

Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, JOYSTICK_TYPE_JOYSTICK, 32, 0, false, false, false, false, false, false, false, false, false, false, false);

void setup() { Joystick.begin(); rotary_init();}

void loop() {

CheckAllEncoders();

CheckAllButtons();

}

void CheckAllButtons(void) { if (buttbx.getKeys()) { for (int i=0; i

void rotary_init() { for (int i=0;i

unsigned char rotary_process(int _i) { unsigned char pinstate = (digitalRead(rotaries[_i].pin2) << 1) | digitalRead(rotaries[_i].pin1); rotaries[_i].state = ttable[rotaries[_i].state & 0xf][pinstate]; return (rotaries[_i].state & 0x30); }

void CheckAllEncoders(void) {
for (int i=0; i < NUMROTARIES;i++) {

unsigned char result = rotary_process(i);
if (result == DIR_CCW) { Joystick.setButton(rotaries[i].ccwchar, 1); delay(50); Joystick.setButton(rotaries[i].ccwchar, 0); }; if (result == DIR_CW) { Joystick.setButton(rotaries[i].cwchar, 1); delay(50); Joystick.setButton(rotaries[i].cwchar, 0); }; } }

  1. Connect your Arduino Pro Micro to your computer by plugging in the USB cable
  2. To upload the code select the Arduino type by going to Tools > Board:... > Arduino/Genuino Micro.
  3. To select the correct USB port go to Tools > Port: > COMx (Arduino/Genuino Micro)
  4. Verify the sketch by clicking on the ✓ in the top left corner (under File)
  5. Press the → next to it to upload it to the Arduino

Step 8: Add to Your Rig

Congratulations! You've come so far. Now it's time to race!