Sim Racing Button Box

42,052

43

23

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!

Be the First to Share

    Recommendations

    • Puzzles Speed Challenge

      Puzzles Speed Challenge
    • "Can't Touch This" Family Contest

      "Can't Touch This" Family Contest
    • CNC Contest 2020

      CNC Contest 2020

    23 Discussions

    0
    dispens1918
    dispens1918

    Question 14 days ago

    What should i do?

    ard button.jpg
    0
    StepOnItNow
    StepOnItNow

    Reply 3 months ago

    Hiya, this still doesn't work for me. What libraries did you have to include? I have selected to include:
    Joystick
    Keypad

    and now I get an error:

    C:\Users\Admin\Documents\Arduino\libraries\Joystick-1.0.0\src\Joystick.cpp:6:1: error: 'Joystick' does not name a type; did you mean 'Joystick_'?

    0
    Mungrel
    Mungrel

    Question 1 year ago on Step 7

    Good write up & diagrams, however
    I have added the keypad library and joystick library as directed, but upon verifying I get
    'rotary_init" was not declared in this scope. I've found a number of "not declared in this scope" examples and understand the concept of it, but not entirely sure on how to fix it in this code. Any chance of help please?


    rotary_init.JPG
    0
    bekathwia
    bekathwia

    Answer 1 year ago

    It appears as though the rotary_init(); and CheckAllButtons(); functions somehow were truncated upon pasting into the Instructable, hopefully the author can upload the full .ino file as a step attachment.

    0
    StepOnItNow
    StepOnItNow

    Reply 3 months ago

    How do we fix this? Just copy what you wrote:
    rotary_init();
    CheckAllButtons();

    Thanks in advanced

    0
    brpcosta86
    brpcosta86

    3 months ago

    Hi.
    Thank you for this project.
    I have done it and it's working, but what i need is a way to "convert" this into a "Keyboard" so it can be detected on PS4.
    Is there any way we can give each function like an "A", "B", "C", and so on? so in the games on PS4 i can assign buttons?

    1
    troy.m.holman
    troy.m.holman

    3 months ago

    No credit to am_studio? Seems to be an exact copy of their YouTube video

    0
    OnnoN
    OnnoN

    3 months ago

    the first toggle switch on the left top is that part of the pink line or gray?

    InkedFU2VJJZJKWUQKX9_LI1.jpg
    0
    HumbertoG14
    HumbertoG14

    4 months ago

    Hello ! instead of encoders, could I use potentiometers instead? do we need to change the code?

    0
    josephcote27
    josephcote27

    Question 4 months ago on Step 8

    Hey there! Thank you for posting this! I'm curious, though, how did you mount it to the Playseat Challenge? What's the details on that bracket?

    0
    arvidn04
    arvidn04

    Question 6 months ago

    Is it possible to use this code with only 4 switches?

    0
    Eviljonbob
    Eviljonbob

    Answer 6 months ago

    Should work. You just need to ensure that you know which row and column the switches are connected in the matrix. You don't have to connect all switches. I am only using four switches as well. I have them connected to pin 14, 15, 16, 10 and 9 (last row of buttons in the diagram). Problem is that I can't get the incomplete code to work. Hoping that the author will fix the instructable.

    0
    arvidn04
    arvidn04

    Reply 6 months ago

    Btw and also... I have 4 switches but i want them to work like buttons. Like one signal is sent when i push down the switch and one signal sent when i push up back. How do you have yours? You know if it’s possible to do like that?

    0
    Eviljonbob
    Eviljonbob

    Question 6 months ago

    Any chance you can upload the complete code?

    0
    dzidzior
    dzidzior

    Question 7 months ago on Introduction

    is it possible to use your script to connect 2-pin toggle switch? thank you!

    0
    Eienn
    Eienn

    Question 8 months ago

    Hi. I need help." 'rotary_init' was not declared in this scope " How can i fix it ?

    0
    BiancaI6
    BiancaI6

    1 year ago on Step 8

    Hi, i need a help. What i need to write after de #include in first and second line?
    I'm still learning, sorry.

    error.jpg
    0
    Mungrel
    Mungrel

    Reply 1 year ago

    G'day, not sure if you got this fixed or not, but to fix that problem, first ensure you have the joystick library zip folder from github mentioned in step 7, and have the keypad library added. When you have both of these, go to Sketch -> Include Library and select Joystick and Keypad. That'll generate the following:

    #include <Key.h>
    #include <Keypad.h>

    #include <Joystick.h>

    1
    Racersims
    Racersims

    Question 1 year ago on Step 8

    Hello loved the instructable went well but I am trying to upload the sketch and get an error
    'Joystick_' does not name a type
    and highlights the following part any help?

    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() {