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); }; } }
- Connect your Arduino Pro Micro to your computer by plugging in the USB cable
- To upload the code select the Arduino type by going to Tools > Board:... > Arduino/Genuino Micro.
- To select the correct USB port go to Tools > Port: > COMx (Arduino/Genuino Micro)
- Verify the sketch by clicking on the ✓ in the top left corner (under File)
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!
40 Comments
3 years 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?
Reply 10 months ago
Check this: https://gimx.fr/wiki/index.php?title=Main_Page, on ps3 worked perfect with diy steering wheel (emulation g27) and gran turismo 5 and 6 :D
Question 1 year ago
What pin are you using for 15, there is no 15 on a Arduino micro? Niether is there a 14 pin....
Question 1 year ago on Step 8
I have some questions about this
1)how many switches can be simultaneously pressed?cause I have many toggle switches(15) on my layout
2)what if I want to use more than 32 buttons?can I do a bigger matrix combinations?what connections of pro micro should I use then?
3)do I need an external power supply to power my LEDs or I can take from pro micros 5v?
2 years ago
I see some still have the Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, And still getting the error when trying to upload or verify 'Joystick_' does not name a type. Sure wish someone would fix it or reply with the fix for this problem. I have serched the net and there is no answers for this problem Please lets have some help on this.
Reply 1 year ago
It may be a problem with downloading the wrong libraries. I didn't get any problems with the code, here's what I did:
Instead of using the code on the instructable, I used the code in the Github link Eviljonbob posted below in the comments. Copy and paste the code in the link.
download the Joystick Library here - https://github.com/MHeironimus/ArduinoJoystickLibr...
click the Green button that says Download Code (it is to the right of "Go to file")
make sure to download it as a Zip and put it on your desktop
In the Arduino IDE go to sketch>Include Library> add .ZIP Library and then click on desktop. Click on the Zip you just downloaded.
For the Keypad Library, go to https://playground.arduino.cc/Code/Keypad/
under download, install and import, there should be a link to download the zip called keypad.zip . It should download in your browser, then drag it onto your desktop. In the Arduino IDE go to sketch>Include Library> add .ZIP Library and then click on desktop. Click on the Zip you just downloaded.
Reply 1 year ago
I have the same problem and I downloaded the correct libraries... :/
Reply 1 year ago
Hi! Go to Documents Folder and you have been two "joysticks" libraries! Delete the other one, not this one!
Question 1 year ago
Hi! This works with Arduino Nano?
Answer 1 year ago
yep it should! pretty sure it specially works with nano because the board is seen as a human interface device (like a game controller, keyboard or mouse etc.) to your pc
1 year ago
Thanks for the guide.
If you have trouble with programming the arduino, use the link eviljonbob posted, this worked for me right away without hassle.
1 year ago
Great Button Box! I was wondering if anyone needed to put any Diodes in to prevent Ghosting? If so, where would I put them in the wiring?
3 years ago
No credit to am_studio? Seems to be an exact copy of their YouTube video
Reply 2 years ago
He (am_studio) didn't write this code, it's a code that has been available in the Arduino libraries for quite some time. Well before his video and well before he forked it on GitHub. It is however a direct copy of his box, although considering if he (am_studio) is taking credit for the script then he likely stole the box format as well. As for the wiring diagram, it's a basic set up that's been around since, well, keyboards.
3 years ago
Hello ! instead of encoders, could I use potentiometers instead? do we need to change the code?
Reply 2 years ago
Yes, I used potentiometers.
3 years ago
the first toggle switch on the left top is that part of the pink line or gray?
Reply 2 years ago
That should be a pink line. I fiinally got mine built and it works great!
Question 2 years ago
Can I only use 2 encoders ?
Question 2 years ago
I have a problem with programming the board. Error in the attachment what do i have to do?