You can build a 20-plus button box with a couple of rotary encoders and a few toggles for around $35 in parts, and it will work in iRacing, ACC, Le Mans Ultimate and rF2 exactly as well as a $150 boutique box. The controller that makes this possible is a clone Arduino Pro Micro, which costs about $6 and shows up in Windows as a proper USB game controller with no drivers. Everything else is switches, wire, a box, and one evening of soldering.
The catch is the evening of soldering. If you have never held an iron, budget another $25 for a Pinecil or a cheap 60W pen from Amazon, and accept that your first box will look like it was assembled in the dark. Mine did. It still works six years later, sitting under a Simucube that cost forty times as much, and I press its scuffed pit-limiter button more often than anything on the wheel.
The parts list, with real prices
Prices below are what I paid or what the usual suspects (AliExpress, Amazon, eBay) were showing this month. They move around, but not by much.
| Part | Qty | Roughly |
|---|---|---|
| Pro Micro clone (ATmega32U4, Micro USB or USB-C) | 1 | $5–7 |
| 12mm momentary push buttons, mixed colours | 20 | $6–8 |
| Toggle switches, SPST or SPDT, 6mm panel mount | 4 | $5–6 |
| EC11 rotary encoders with push switch | 2–3 | $3–5 |
| 1N4148 diodes | 30 | $2 |
| ABS project box, around 150 × 100 × 50mm | 1 | $6–9 |
| Hookup wire, heat shrink, hot glue | – | $3–5 |
Call it $32 to $40 depending on how much of the consumables you already own. If you have a 3D printer, the box line drops to a dollar of filament and you get to size it to your rig, but the ABS box is fine and easier to drill than people expect.
Two things on the list deserve a warning. First, it has to be an ATmega32U4 board. A Nano or an Uno uses a separate USB-to-serial chip and cannot pretend to be a joystick without ugly firmware hacks. The Pro Micro, the Leonardo and the Micro all have native USB on the main chip, which is the entire trick. Second, buy two Pro Micros. They cost six dollars, and the clone bootloaders are flaky enough that flashing at the wrong moment can leave one apparently dead. Usually it isn’t dead (double-tap the reset pins to ground and try again within eight seconds), but a spare saves the night.
Why not just buy a Bodnar board?
The Leo Bodnar BBI-32 is the answer you’ll get in every r/simracing thread, and for good reason: it’s plug and play, handles 32 inputs, and the encoder support is baked in. It’s also around $40 to $45 shipped from the UK before you’ve bought a single switch. That is the whole budget for this article spent on one PCB. It makes sense if you want zero firmware fuss and you’re already spending $100 on the box. It does not make sense under $40.
The other shortcut people reach for is the $10 “Zero Delay” arcade USB encoder. It works, it needs no code, and I’d steer you away from it anyway, because it has no idea what a rotary encoder is. Encoders are the point of a button box. Brake bias, TC, ABS, engine map: those are all things you adjust by clicks, not by stabbing a button five times while braking into Turn 1 at Spa. Skip the arcade board.
How the wiring actually works
A Pro Micro has 18 usable pins. If you wire one switch per pin, that’s 18 inputs, which is respectable but wastes most of the board’s potential. A matrix gets you far more: 5 row pins by 6 column pins gives 30 switches on 11 pins, with 7 pins left over for encoders.
The matrix is dead simple in concept. Each switch sits at the intersection of a row wire and a column wire. The firmware pulls one row low at a time and reads all the columns; whichever column reads low has a closed switch on that row. The diode is the part beginners skip and then regret. Without a diode in series with each switch, pressing three buttons that form three corners of a rectangle makes the fourth corner “press” itself. That’s ghosting. The 1N4148 in series with each switch (band toward the column, if you’re following the common Arduino Joystick wiring) blocks the sneak path. Thirty diodes is $2. Fit them.
Toggle switches go into the same matrix as any other switch. Encoders do not. Each encoder gets two dedicated pins for its A and B channels, plus a common to ground, and its integrated push switch can go into the matrix like a normal button. Wire the encoder pins to the ones that support interrupts on the 32U4 (pins 0, 1, 2, 3, 7) if you can, because the polling approach misses fast twists.
Practical tips from doing this badly the first time:
- Solder the diodes to the switch legs before anything goes in the box. Once 20 switches are mounted, there’s no room to work.
- Use ribbon cable pulled from an old IDE drive cable for the columns. Free, flat, colour-coded.
- Hot glue every solder joint on the Pro Micro. The USB socket on clones rips off the board under any cable strain, and that is the single most common way these projects die.
Firmware: the part everyone overthinks
You have three sane options and I’ll tell you which one to use.
ArduinoJoystickLibrary by Matthew Heironimus is the one. Install the Arduino IDE, add the library through Library Manager, select “Arduino Leonardo” as the board, and write about 60 lines of code. The library creates a joystick with up to 32 buttons, and you scan the matrix in loop() and call setButton() for each intersection. There are a dozen example sketches on GitHub written specifically for sim racing button boxes; search “AMSTUDIO button box” and you’ll find the one half of YouTube copied.
FreeJoy is the second option, and it’s arguably better firmware, but it runs on the STM32 “Blue Pill” board, needs a separate ST-Link programmer or a fiddly serial flash, and the configuration tool has a learning curve. Great for a second build. Not for this one.
MMJoy2 is the old-school pick from the flight sim crowd. It still works. It’s also been mostly abandoned, and the config tool is a Russian-language Windows app that makes new users nervous. Leave it.
The one firmware detail that matters more than any other is how you handle encoders and toggles. A sim wants a momentary button press. An encoder twist should produce a short press on a virtual button, not a state change. The naive code sets the button on and off in the same loop pass, which makes the “press” a few microseconds long, and iRacing simply won’t see it. Hold the virtual button for somewhere between 30 and 60 milliseconds. I use 40ms and it registers everywhere. Go much past 80ms and fast twists start dropping clicks.
Toggles have the opposite problem. Wire a toggle straight into the matrix and it holds a virtual button down for as long as the switch is up. iRacing tolerates this for some bindings. ACC’s binding screen does not; it sees a stuck button and refuses to map anything else until you flip it back. The fix is in code: track the toggle’s previous state and emit a 40ms pulse on one virtual button when it goes up and on a different virtual button when it goes down. Now a toggle behaves like two momentary buttons, which is what every sim actually wants.
Windows will show the device as “Arduino Leonardo”. You can rename it by editing the board’s entry in boards.txt inside the Arduino install folder before you flash, and give it a distinct product ID while you’re there. This matters more than it sounds if you plan to build a second box, because two devices with identical VID and PID make iRacing’s controls page lose its mind.
The box, and where it goes
The ABS project box is ugly and it’s fine. Mark the holes with masking tape and a ruler, drill pilot holes, then step up to 12mm for the buttons and 6mm for the toggles. Encoder shafts need a 7mm hole. A step drill bit (around $8, not in the budget but you’ll use it forever) makes far cleaner holes in ABS than twist bits, which tend to grab and crack the lid.
The lid on a cheap box flexes. Toggle switches with the stiff, satisfying throw everyone wants will bow a 2mm lid enough to pop nearby buttons out of their nuts over a few weeks. Two options: buy the box with the aluminium lid variant (usually $3 more) or glue a strip of 3mm plywood or scrap aluminium behind the toggles. I did the plywood thing. Nobody can see it and it fixed the problem.
Mounting is where DIY boxes go to die. On a desk, the box slides the first time you slap a button under braking, so stick four rubber feet on it or a strip of that non-slip drawer liner. On an aluminium profile rig, the cleanest solution is a $6 pack of M6 T-nuts and two L-brackets, bolted through the side of the box. Zip ties through two drilled holes also work and I won’t judge. Position matters more than the fixing: you want the encoders reachable with the left hand while the right stays on the wheel, which usually means left of the wheelbase, angled about 30 degrees toward you, not dead flat.
What breaks after a month? The Micro USB socket, as mentioned, unless you glued it. The cheap 12mm buttons occasionally develop a double-click as the dome contact wears; a 10ms debounce in code hides it. Encoders from the bottom of the AliExpress barrel have detents that feel like gravel. Spend the extra dollar on the Bourns or Alps-branded EC11 if you can find them; the difference under your fingers is real.
What it feels like in the sim
The box makes a bigger difference in some cars than others. In the GT3 cars in ACC or iRacing, having TC, ABS and brake bias on three encoders turns a menu chore into a reflex. Coming into the Bus Stop at Spa in the rain, knocking TC up two clicks by feel is the difference between finishing and spinning. In the Le Mans Ultimate Hypercars, where you’re juggling regen and engine maps and the game’s own menus are slow, encoders earn their keep every lap. In a Formula Vee, you’ll use the pit limiter and the ignition and not much else.
The other thing nobody mentions: a DIY box gets you to actually use the functions. On a wheel-mounted rim with 12 buttons, half of them end up unbound because you can’t remember which is which. Twenty labelled buttons on a box in front of you invites bindings. Label them. A $5 label maker is the best money in this whole project, and dymo tape survives sweat better than Sharpie.
FAQ
Can I use an Arduino Uno or Nano for a button box? Not sensibly. Those boards use a separate serial chip (CH340 or ATmega16U2) and cannot present themselves as a USB joystick without reflashing that chip with custom firmware. It’s possible, it’s miserable, and a Pro Micro costs six dollars. Buy the Pro Micro.
How many buttons can one Pro Micro handle? The Joystick library maxes out at 32 buttons per virtual joystick, and Windows DirectInput caps at 128, but 32 is a practical ceiling for one board. A 5×6 matrix (30 switches) plus two encoders taking four virtual buttons already hits that number. If you need more, build a second box on a second board with a different product ID rather than trying to cram.
Will iRacing and ACC recognise a homemade button box? Yes, as a generic game controller, identical in every way to a commercial box. iRacing lists it under Controls with whatever name you gave it. ACC binds it through the standard controls screen. Le Mans Ultimate and rF2 both handle multiple devices fine, though rF2’s engine has a quirk where it only detects the first device you press a button on during a given binding attempt, so press the box button, not the wheel, when mapping.
Before you order
Buy this build if you own or can borrow a soldering iron, you’re happy with an ugly box that works, and you want encoders. Buy a Leo Bodnar BBI-32 instead if your budget is $100 and you’d rather spend the evening racing than soldering. Skip the whole idea if you race only single-seaters and your wheel already has eight buttons; you’ll use two of them.
Check three things before you click order. The Pro Micro listing must say ATmega32U4, not ATmega328P, and you want the 5V/16MHz variant. The encoders should be EC11 with a push switch and 20 detents per revolution, not the 30-detent ones that feel mushy. The project box needs a lid depth of at least 45mm, because 12mm buttons with their solder tails and a diode stick down further than you think, and I have a box on a shelf with a lid that won’t close to prove it.
