Spin classes with competitive racing sound awesome. But rather than working to push a bike output number up, I wanted to to compete in a game like MarioKart or TrackMania. That might be ridiculously awesome, right? So I made a little Arduino gadget worn on the ankle with a recumbent exercise bike to do that. Details are below to make one yourself.
This wireless gadget (‘Cycler433’) tracks ankle motion so users can ride most any exercise bike and control racing games on a computer. It is almost magical to exercise with and doesn’t require modifying the bike. It’s just an ankle strapped motion sensor with a wireless connection to a computer. Pretty simple! All the gadget parts bought new could cost under $70 if you hunt for imports or around $80-100 for branded goods with faster delivery. Or $0 if you have the parts already. This cost excludes the bike, the computer, games, and gaming controller of course.
The bike setup is key: Bikes that don’t block the view ahead and have comfortable seats are best. I bought an inexpensive folding recumbent exercise bike for my small apartment. It rocks! For improved metric tracking, I might have considered a bike like this. Avoid anything with a tiny seat.
I used a PS4 controller with the free DS4Windows for steering and other controls; Xbox or desktop-oriented controller might require even less setup. Regarding choice of game, Trackmania games and Redout work great from Steam; I never was terribly interested in racing games before this endeavor but uh wow that sure changed.
Detailed instructions and code.
Step #1: Making the wearable transmitter
The backbone is an Arduino UNO or compatible alternatives. If you don’t have Arduino software installed already, download it here. If you’re starting and don’t have a 9V battery snap connector with DC plug, or mini breadboards and jumper wires, consider a mid-range kit with many components for future use.
The accelerometer I had on hand was a 9-axis MPU 9250 and is needed for the code below. I soldered pin headers to the 4 topmost holes (see image) and placed it in a small breadboard, then wired the accelerometer’s VCC to the Arduino’s 3.3V pin, GND to Arduino’s GND, SCL to Arduino’s to SCL, and SDA to Arduino’s SDA. The next step to add is a simple 433 MHz radio transmitter (it is packaged with a receiver); the transmitter is also placed on the small breadboard. As you face the side with transmitter’s copper coil (see below), its leftmost pin is wired to Arduino’s IO pin 12, the middle pin to Arduino’s 5V power, and the rightmost pin to GND. What else do we need? Power! I would recommend either a USB-rechargeable 9V battery with a snap connector with DC barrel jack to plug into the Arduino, or 4 AA batteries+connector. The less efficient but most convenient method is using a non-rechargeable 9V battery+connector seen below. This only lasts about 6-9 hours of usage but works in a pinch.
Once the hardware is connected, the software has to be uploaded to the chip. My Arduino code relies on Asuki Kono’s GitHub library, for the accelerometer, and also the Radiohead library. To use these libraries, download the library folders, unzip them if zipped, and save them to your Arduino/libraries folder. The Cycler433 transmitter source code is on GitHub. You can copy and paste it into a new Arduino sketch file. Save and upload this sketch to your Arduino, making sure you’ve selected the correct Arduino UNO board model and the Uno-labeled port under the Tools tab.
The overview of the transmitter code, for the curious, is in this paragraph: During setup, the initial 3-axis acceleration values are recorded, presumed to be when the device is already on the leg/ankle in cycling position; this helps correct for effects of gravity when in use. Then the code loops through cycles of taking several readings from the accelerometer in axes x, y, and z, and calculating a running average of the norm of the acceleration vector, corrected for gravity. The running average smooths out some noise from individual data points. The ankle moves in a roughly circular pattern along with the circular motion of the pedal, so with smooth pedaling its acceleration will be roughly constant in magnitude directed towards the center of the axis of rotation. With faster pedaling, the magnitude will increase. This approach is computationally fast for a little chip and functionally quite stable. Other approaches are plenty. The running-average magnitude value is sent to the radio transmitter as a string of numerical characters which is transmitted up to 10 times per second.
To check if you’ve loaded the transmitter source code into your Arduino and hooked up the accelerometer properly, make sure the Arduino is still connected to the computer via USB and click on the serial monitor icon (top-right of Arduino window, looks like a magnifying glass). You should be able to see accelerometer data coming in from the serial port. After successfully uploading the code, you can disconnect the USB from the Arduino and later plug in the battery to turn it on during bike use.
The working transmitter also needs a protective case of some sort. I used a LinkSprite clear enclosure for pcDuino/Arduino with built-in holes and open ends for ventilation, and I secured the parts inside with tape and some janky balled-up plastic wrapping tape to fill space. You might be able to use a smaller case. When biking I secured the case between a long inner sock and a more stretchy long outer sock. It never got hot for me even after 2 hours of use, but if you make it you’ll have to be careful testing your own home-made version; in any case I wouldn’t recommend having the battery or electronics in contact with the skin.
Step #2: Making the radio receiver
The second component requires an Arduino version that allows data to be sent to the computer as if it came from the keyboard. I had an Arduino Yun on hand but a Leonardo would be cost-effective. A second Arduino UNO will not work.
You can use the radio receiver chip that came with the 433 Mhz transmitter used above. The hardware setup is simply wiring the radio receiver’s leftmost pin to the Arduino’s 5V power pin, the receiver’s second pin to Arduino’s IO pin 11, and the rightmost receiver pin to Arduino’s GND, as seen below. For significantly improved reception I soldered a little antenna on the receiver at the ‘ant’ location, seen sticking out at the top left.
The Arduino is programmed again using the Radiohead library. Get the receiver source code on GitHub which takes the data from the radio receiver, converts it back to a number, and if that number is over a certain cutoff then holds down a keyboard key for a 0.5 seconds past the time the transmission was received, otherwise the key will be released. The default key is the up arrow which worked for Trackmania. Redout required switching to the ‘w’ key by replacing Keyboard.press(KEY_UP_ARROW) with Keyboard.press(‘w’).
Step #4: Putting it together
To test both parts of your setup, upload the receiver code to your receiver Arduino (checking that the Leonardo/Yun/etc. model and the correct port under the Tools tab are selected). Keep the receiver plugged into your computer via USB. Power up your newly built and encased wireless transmitter (should be disconnected from the computer) with a battery, open up the serial monitor in the Arduino software, and move the transmitter quickly up and down with your hand. Then see if your signal shows up on the Arduino serial monitor window as shown below (slow movements may not be transmitted).
If you don’t see anything like this, move the receiver and transmitter closer, or check the wire and pin connections. If you haven’t changed the default key to simulate key-presses, you should be able to move a cursor up in an open Word document by moving the transmitter in the air.
Step #4: Turn on your game. Explore! Enjoy!
Notes on usage (important):
-The simulated button press will act like keyboard presses, and by default will simulate holding down the up-arrow key on any open program. Especially if you switch the pressed key to ‘w’ or any other key, be aware other programs could be affected.
–Many high-end racing games are better suited to analog acceleration controls like pedals and controllers and may not play nicely with a simulated keyboard input. I sought keyboard-playable games and have been thrilled with the cycling experience +/- controller haptic feedback controller with Trackmania Nations Forever, Trackmania Stadium, and Redout. Redout (in the video) is most beautiful, but TrackMania is my favorite. I’m dying to try GTA V but want to pace myself on game purchases. I don’t own and haven’t tried more simulation-based games like Forza or Dirt Rally yet. I may have to simulate analog acceleration for these. TBD.
-Pedaling responsiveness: Due to mechanical pedal inertia and any delay from the Arduinos the transition between ‘no go’ and ‘go’ is slower using the device with bike resistance at workout level than using the keyboard with its instantaneous on/off button presses. Because of this I usually started pedaling a half second or so before the race started. My racing times were generally a bit slower than when using the keyboard. I could still win gold medals in Trackmania, but I doubt world-record-breaking performance is within reach yet.
-Pedaling speed: Continuous acceleration with simulated key releases was most stable when cycling quickly (at >90 rotations per minute of the bike pedal) but still less dependable than holding a button down, because of statistical noise, measurement error, movement jerkiness, etc. This was especially important on Trackmania levels that require you to hold down ‘go’ without any pauses in order to clear obstacles. Adjusting the keyboard-press sensitivity in the receiver arduino code can help with this, somewhat.
-All recorded movement controls the ‘forward’ key. Pedaling backwards does not make the user move backwards in this version. To go backwards, you’ll have to press a controller button—and probably stop pedaling meanwhile!
-The radio receiver/transmitter usually worked well, with generally <0.1 to 0.3 second delay from moving the sensor to seeing movement in the game. I occasionally had longer delays associated with poorer radio connection perhaps (?) due to noise from AM rather than other types of RF communication, or poor electrical contacts. I kept the radio transmitter and receiver within 2 meters generally and usually had clear line of sight.
-If the device seems less responsive than usual, press the Arduino reset button on the transmitter while your foot is still in position on the bike, or at the same angle as it is on the bike, to re-calibrate for the direction of gravity. Because of hardware differences, your setup may need parameter experimentation in the transmitter and receiver source code files.
-Disaster avoidance (safety)! Make sure no wires or metal parts are exposed to your skin or even directly to the sock, which can get drenched with sweat. I have not been shocked or burned, and I don’t want anyone else to be either. If you have a cardiac history (especially e.g. an implanted pacemaker/defibrillator, any arrhythmia), it might be best to get personal medical advice before proceeding. Don’t wear it in the rain, the shower, the hot tub, the ocean…don’t feed it to animals…
This gadget has turned me from a once-a-month bored exerciser to a daily sweat-drenched cycling addict. I’m not the first to connect a bike and/or Arduino to a computer. Particularly impressive hardware setups are seen also with TrackMania by Grus0 on Youtube and with VR by justanimate here. Cycler433’s distinguishing elements are its relative wireless-ness, usability with most any bike and several top-notch games, and its open-source simplicity and ease of construction. Best wishes, and happy holidays!
Detailed components list for receiver and transmitter:
Arduino UNO, Arduino Leonardo or Arduino Yun, MPU 9250 accelerometer, 433 Hz transmitter and receiver modules, 433 MHz antenna with helical spiral spring, 10 jumper wires, 2 small breadboards, 9V (preferrably rechargeable) batteries, 9V battery snap connector, soldering materials (in a beginner soldering kit), scotch tape, LinkSprite clear enclosure for pcDuino/Arduino, USB (with type B plug for Arduino UNO) and micro-USB (for Leonardo/Yun) cords.