Quarantine Life: How to Keep Your Kids Active by Turning their Bicycle into an Arcade Controller

Written by Michael_Chein | Published 2020/10/18
Tech Story Tags: arduino | kids | hackernoon-top-story | keyboard | bike-into-keyboard | bicycle-into-keyboard | parenting | gaming | web-monetization

TLDR Michael Chein walks you through the process of turning any bicycle into an arcade-like controller for computer games. The first step is turning the bicycle into indoor training bikes by getting the rear wheel to spin freely without touching the ground, and allow the handlebars to turn freely as well. Data from all sensors will be captured and transformed by an Arduino that will function as a keyboard and send keystrokes to a computer running a (most likely racing) game. You should NOT proceed to the following steps as it is your responsibility to make sure that the bicycle are secure and safe to use.via the TL;DR App

In this short tutorial, I’ll walk you through the process of turning any bicycle into an arcade-like controller for computer games.

Despite not setting the best example for leading a healthy lifestyle, my wife and I do try to eat our greens, avoid too much junk, and keep in shape. Our 5 year old on the other hand, couldn’t care less about doing any physical activity, unless it gets him closer to his (my…) iPad.
Normally, This issue is partially remedied simply by being a kid, which involves a fair amount of running, climbing, falling… and recently cycling! But unfortunately, with the advent of the COVID-19 pandemic, we can’t really do much of that.
So, I turned his bicycle into a keyboard.
Now, he can play his favorite computer games and exercise at the same time! In this short article, I’ll walk you through the process of building
your very own keyboard bike.

Foundations:

The first step is turning the bicycle into indoor training bikes by getting
the rear wheel to spin freely without touching the ground, and allow
the handlebars to turn freely as well. If your kid is propelled forward,
you should NOT proceed to the following steps.
There are many ways of getting the bike to remain in place while spinning the pedals. Hanging the bicycle from the ceiling, digging a hole in the
floor beneath the wheel and many more. I personally used the training
wheels to support the rear, but this is your place to get creative, and
more importantly, be responsible. I am deliberately avoiding getting into too much detail about my implementation of this part (you can get a pretty good idea from the various pictures and gifs in this article…) as it is your responsibility to make sure that the bicycle are secure and safe to use.

The plan

After securing the bike so that it can be pedalled in place, we will connect
sensors to capture the rotation of the rear wheel, position of the
handle bars and some buttons for extra control (these can be easily
programmed later to map any keyboard key). Data from all sensors will be captured and transformed by an Arduino that will function as a keyboard and send keystrokes to a computer running a (most likely racing) game.

Hardware

We must use a board that can function as a USB keyboard. I used Arduino Leonardo.
I used 3 types of sensors:
1. A1302 Hall Effect Sensor — This sensor changes its output voltage when in the proximity of a magnetic field. We will use it to transform the rotation of the rear wheel to a forward key press.
2. 10K ohm linear potentiometer — Used to transform the handlebar orientation to left/right keys.
3. Microswitch — used as extra controllers. I highly recommend using this type of switches (limit switch) and not going for some fancy buttons. these switches are very responsive, whereas some buttons can sometimes be challenging for a kid to press.

Connecting the parts

Hall effect sensor

By placing magnets on the rear wheel, and positioning the sensor close (as close as possible without touching the wheel), we can sense the wheel’s rotation as the magnets pass by the sensor. I used two magnets equally
spaced (that is ~180 degrees apart).
A tip for attaching the magnets -
You could probably find a more elegant solution, but the one I used here is to wrap the magnets in plastic wrap and twist the ends, like a candy wrap (I am referring to the white blobs seen spinning with the wheel in the gif above). Then use the loose ends to tie the magnets to the wheel’s spokes, and secure with hot glue.
In order to get the sensor (this is referring to the red vertical rod in
the gif, the sensor itself is located at its end) as close to the wheel
as possible I mounted it to a flexible wire (I used some heavy duty
electrical wire but any wire that will flex and keep its position will
do).

Potentiometer

The potentiometer needs to be connected to the pivot point of the
handlebars. There should be a socket for an allen wrench at that point. I used a fitting driver bit and connected it to the potentiometer.
Originally, my plan was to solder both parts together, but driver bits
have low (none) solder-ability. I ended up taking a short piece of straw (seen in the gif below in violet) sticking the potentiometer and driver bit from both sides, and injecting it with hot glue, to keep everything together. It’s solid as a rock.
As for securing the potentiometer to the bike frame, you will again need
to get creative. my solution (which can be seen in the trailer gif and
in the image at the end of the article showing all components detached
from the bike) was based on making a plexiglass “arm” to hold the
potentiometer in place, and may not work for your child’s bike. The idea is simple, the potentiometer needs to spin with the handlebars. Simple
as it is, the implementation can be quite challenging…

Switches

I placed one of the switches behind the (redundant) front wheel brake
lever, and the other one behind the not redundant back wheel brake
lever, and disconnected this brake, so that the switches are pressed by
pressing the brakes, which feels very natural.
Again, I’m not taking any responsibility here. if you feel the supports you
made in part 1 are not strong enough and are worried about obstructing
and/or disconnecting brakes, you can, and should place the buttons
somewhere else. No right or wrong, as long as it’s comfortable and safe. I limited myself to two buttons but you can obviously go as high as the board allows.

Wiring

A note on thinking ahead.

After completing keyboard-bike version 1.0, I set up to improve it by making sure I can easily disconnect all components and reassemble them again as quickly as possible, this required some tweaking, that could have been avoided if I had thought of this at the get go. It took me nearly 2 hours to upgrade to keyboard-bike version 2.0, but it now takes less than a minute to assemble/disassemble.
Another point to keep in mind is what’s the best place to secure the board. I thoughtlessly put it on the side my son gets on and off the bike. In
retrospect, I should have chosen the other side…

Code

As explained in the hardware section, the keyboard bike setup is composed of 3 types of sensors: Hall effect sensor, potentiometer, and buttons. I’ll explain the code for each component separately.

Hall effect sensor

The hall effect sensor is “activated” when the wheel spins and the magnets
pass by the sensor, inducing a change in output voltage. For this part, I switched on the key (forward key in my case) whenever there was an
absolute change in voltage above a certain threshold (hall_effect_threshold). I then keep it on and start counting back for a certain amount of time (drive_decay_const). This allows tuning the amount of motion you get from each "spike". Increase the value of drive_decay_const to get more movement.

Potentiometer

Here we’re basically trying to convert an “analog” motion of turning the
handlebars into a “binary” left or right clicks. A continuous press is
way too dramatic if you just want to make small adjustments, so the
amount of turn needs to be represented as “click amount”. I’m doing this by activating and deactivating turning movement at a set interval (interval), so that turning the handlebars beyond a certain threshold, will start
pressing intermittently. In addition, I add a delay while the button is
activated, that grows with the amount of turn. So for higher angle
turns, the button will be pressed for a longer duration (that is, each
click will be longer) resulting in a more aggressive turn. Also, notice
that I'm initialising pot_center at setup. this is helpful for cases where the potentiometer gets disconnected from the socket. Instead of having to relocate the center, you can just reset the board, and the center will be reset.

Switches

Nothing special here. Just replace the activated key to suit your needs. The code here is for playing SuperTuxKart which is a great racing game for kids, but the bike could obviously be adjusted for many other games. We also use it to play Minecraft, which works great.
/*
bicycle_keyboard
*/#include "Keyboard.h"
const int hall_effect_threshold = 1      // threshold for hall effect sensor.
const int turn_threshold = 35;           // threshold for detecting a left/right movement. 
const int drive_decay_const = 100;       // drive_decay speed of car (larger => slower decreasing / faster car)
const int turn_decay_const = 0.75;       // multiplier for intensity of turn. higher value => sharper turns. 
const char button_1_val = ' ';           // value for button 1
const char button_2_val = 'n';           // value for button 2
const long interval = 200;               // interval for allowing not allowing turns.
const int button_1 = 2;                  // button_1 pin 
const int button_2 = 3;                  // button_2 pin
int pot_center = 500;                    // center point for potentiometer. this value is being reset in setup.
int prev_hallSensorValue = 0;            // initial value for sensor
const int delay_time = 1;                // delay between reads
int drive_decay = 0;                     // initial drive_decay value
unsigned long previousMillis = 0;        // initial value
bool allow_turn = true;                  // allow turn is a boolean to only allow turns every passing interval 
int turn_amount = 0;                     // initial value

void setup() {
  Serial.begin(9600);
  Keyboard.begin();
  pinMode(button_1, INPUT);
  pinMode(button_2, INPUT);
  pot_center = analogRead(A1);
}

void loop() {
  unsigned long currentMillis = millis();
  int hallSensorValue = analogRead(A0);
  int pot = analogRead(A1);//  Serial.println(hallSensorValue);
//  Serial.println(pot);  delay(delay_time);        // delay in between reads for stability  // DRIVE:
  if (abs(hallSensorValue- prev_hallSensorValue) >1){
    prev_hallSensorValue = hallSensorValue;
    Keyboard.press(KEY_UP_ARROW);
    drive_decay = drive_decay_const;
  }
  else{
    if (drive_decay <= 0){
        Keyboard.release(KEY_UP_ARROW);
        }
    else{
      drive_decay -=1;
      }
    }if (allow_turn==true){
//TURN RIGHT
  if (pot < pot_center - turn_threshold) {
    Keyboard.press(KEY_RIGHT_ARROW);
    } 
// TURN LEFT
  if (pot > pot_center + turn_threshold){
    Keyboard.press(KEY_LEFT_ARROW);
  }}
    if (currentMillis - previousMillis >= interval) { // interval has passed
    previousMillis = currentMillis;
    turn_amount = abs(pot-pot_center);    // switch allow turn state:
    if (allow_turn == true) {
      if (turn_amount > turn_threshold){
          delay(turn_amount); //keep button pressed longer the more aggressive the turn.
        }
      allow_turn = false;
    } else {
      allow_turn = true;
      }
     // release the turn keys:
      Keyboard.release(KEY_RIGHT_ARROW);
      Keyboard.release(KEY_LEFT_ARROW);
    }  //check buttons
  if (digitalRead(button_1) == HIGH){
    Keyboard.press(button_1_val);
    }
   else{
     Keyboard.release(button_1_val);
    }  if (digitalRead(button_2) == HIGH){
    Keyboard.press(button_2_val);
    }
   else{
     Keyboard.release(button_2_val);
    }
}

Summary

To conclude, I hope I did a good job of explaining how to get the keyboard bike built. If you chose to build one, and find that I have not, don’t hesitate to send me a message.


Written by Michael_Chein | Holds a PhD in neuroscience from Tel Aviv University. Currently working as a data scientist at IBM.
Published by HackerNoon on 2020/10/18