Fidget Spinners, Arduinos, and Flapping Birds

This past weekend, I had the pleasure of joining local St. Louis game developers and many other guests from around the nation in showcasing our latest creations at the fourth annual PixelPop Games Festival. One of my personal festival traditions is hooking up an old CRT TV with my port of FlappyNES running on an actual 1985 Nintendo Entertainment System for young gamers (many of whom have never held an NES controller before), but this year, I had a more modern surprise for curious attendees:

You didn’t play as a single bird, but rather you unleashed an entire flock. The game wasn’t just singleplayer either, and visitors would frequently shout for their friends to join them in this cooperative endeavor. To top it all off, the notable means of input on the custom-built arcade controllers was curiously a fidget spinner which seemed to trigger all manner of lights in the controller’s transparent housing. Was human strength too weak to spin the fidget spinner fast enough? No problem! Our booth-neighbors SmuggleCraft were happy to lend us their air pump for excessive spin power!

The Controller

The name of the game is Flock Off, and the controller is an Arduino-powered USB input device that reads signals from five arcade buttons and measures the rotations of a fidget spinner on each of the two controllers. Read on below to learn more about the technology behind it and find out how to build one yourself!

The Game

I had previously revealed Flock Off on April 1st as a “Not So” April Fools’ joke. While the final game is intended for mobile devices with touch controls, the gameplay translates gracefully to arcade buttons, and using fidget spinner measurements to control the power of your bird flock felt perfectly in line with the game’s already ridiculous premise.

For the Arduino-controlled version of the game, the fidget spinner’s RPM controls the “power” of your flock (size, damage rating, point multipliers, etc.) and the arcade buttons choose the height at which you launch birds. The Player Start buttons open upgrade menus navigable with the colored action buttons.

Parts

The parts needed are pretty straightforward and were gathered from a variety of local and online retailers. They should be easy to find. Remember, you will need multiples of some components if you intend to build more than one controller.

Actual assembly time was half a day once all parts and tools were available.

Arduino + USB Cable

My first version of the controller used an Arduino Uno Rev3, but most other versions should be compatible and may even add new possibilities.

Wiring, Soldering Iron, and Solder

You’ll be soldering at least 13 distinct connections for a single controller depending on your style of arcade buttons. It helps to have enough wire colors to distinguish between power, ground, and 6 kinds of input, but isn’t necessary. I prefer a kit that lets me cut and strip the wires myself, so I can control the length.

Arcade Buttons

Most any set of arcade buttons should work. You will need 5 buttons per controller. Many kits are designed for multiplayer machines, so I ended up with enough to make 4 controllers and some unused joysticks from purchasing a single set. They often come with a USB encoder board, but this will also go unused in favor of an Arduino microcontroller.

Having colored buttons is optional and was more of a game design choice as it allows for color-coded menus that may assist players too young to read or those for whom English is not their first language. Accessibility and localization are always very important in game design, and the custom controller movement is a great way for fostering connections where body and language would otherwise be barriers.

My buttons light up, which is also optional but adds to the catchy aesthetic of the controller on the show floor and gives immediate feedback to players that they’ve provided input. It’s not unusual for a booth visitor to learn how a game works by simply trying different buttons, and the fact that those buttons light up on press helps retain attention.

Fidget Spinner

These things are everywhere. I’ve seen them for sale at grocery stores and electronic stores with plenty more purchasing options available online. If you also teach, like I do, maybe you’ve confiscated one from a student. Turn the tables on your students and make a classroom distraction into an educational tool.

Neodymium Magnets

You’ll need a set of neodymium magnets with 3 available per fidget spinner. The key here is they should be thin enough as to not add substantial thickness to the fidget spinner once attached. Mine were 12mm in diameter and 3mm thick.

Super Glue, Glue Gun, Nonconductive Glue Sticks

We’ll be glueing some plastic to metal, some metal to metal, and some metal to acrylic. Most glue sticks should be nonconductive, and we’ll be using it to mount a circuit board that doesn’t otherwise have a flat glue surface.

Metal Washer

Depending on the thickness of your magnets, the washer is purely for providing the additional spacing necessary to keep the magnets from scraping the acrylic controller box once the fidget spinner has been mounted. See images in steps below.

Drill and Hole Saw

We’ll be drilling 5 holes through acrylic for the arcade buttons and an additional hole for the USB cable. I used one with a diameter of about 2.5cm. If you have different arcade buttons than mine, you may need a different hole saw sized appropriately.

Hall Effect Sensor

The Hall effect sensor allows us to sense a nearby magnet. In this controller’s use case, it allows us to sense the passing of a cycle of 3 magnets attached to a fidget spinner as it rotates its arms above the sensor. I used a Velleman VMA313 model, but most sensors should work similarly.

Case

I used an acrylic collectors case from Michaels. The walls were thin enough that the Hall effect sensor inside the case could detect magnets on the outside, and the transparent material furthers the hand-made aesthetic that many booth visitors were curious to examine.

Assembly

1) Plan button and fidget spinner layout

Depending on the size of your buttons, your layout might be a little tight. It’s best to plan ahead of time and leave enough spacing for slight variations in hole placement and for the full rotation of the fidget spinner.  Once I was happy with the layout, I marked those positions on the lid of the acrylic case.

2) Drill arcade button holes

Using the hole saw, drill through the areas you marked. The center drill bit should penetrate first in order to keep the hole saw aligned. Go fast enough to grind away the acrylic, but not so fast that the acrylic heats up to the point of deforming or cracking.

You can clean the edges of the cuts and melted debris with sandpaper or pliers.

3) Check alignment and fit

Most arcade buttons can be separated into a couple components: the plastic housing and the microswitch. Mine had an additional LED component, which will alter the wiring in a future step.

At this point, I removed the microswitch components by rotating them counterclockwise off of the plastic housing. I also unscrewed the nut and mounted the buttons in the case lid to check that all the holes were properly spaced. If no hole adjustments are necessary, you can mount the buttons onto the lid by tightening the nut.

4) Drill USB cable hole

This one is easy to forget until later, which is actually what happened to me when I started final assembly. Using the same hole saw, drill a semicircle in the case large enough for the USB cable to fit through. The actual position simply depends on where you want the cable to exit the controller toward your computer.

5) Program the Arduino

Let’s go ahead and send code over to the Arduino, so that when we test components in the following steps, the inputs are already properly set up.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// Timer1 library
// https://playground.arduino.cc/Code/Timer1

#include <TimerOne.h>
#include <Wire.h>

const byte player1 = 4;
const byte blue1 = 8;
const byte red1 = 7;
const byte green1 = 6;
const byte yellow1 = 5;
const byte spinner1 = 2;

const byte ledpin = 13; // Onboard Led

volatile float spins = 0.0; // Spin count aggregator
volatile float rps = 0.0; // The current rounds per second value

void setup() {
    Serial.begin(9600);

    pinMode(ledpin, OUTPUT); // Onboard LED output

    Timer1.initialize(1000000); // set a timer of length 1000000 microseconds (or 1 second )
    Timer1.attachInterrupt( timerIsr ); // attach the service routine

    pinMode(player1, INPUT_PULLUP);
    pinMode(blue1, INPUT_PULLUP);
    pinMode(red1, INPUT_PULLUP);
    pinMode(green1, INPUT_PULLUP);
    pinMode(yellow1, INPUT_PULLUP);
    pinMode(spinner1, INPUT_PULLUP);

    // Digital pin 2 hardware interrupt
    attachInterrupt(digitalPinToInterrupt(spinner1), countspin, RISING);
}

void loop() {
    Serial.print(!digitalRead(player1));
    Serial.print("\t");
    Serial.print(!digitalRead(blue1));
    Serial.print("\t");
    Serial.print(!digitalRead(red1));
    Serial.print("\t");
    Serial.print(!digitalRead(green1));
    Serial.print("\t");
    Serial.print(!digitalRead(yellow1));
    Serial.print("\t");
    Serial.println(rps);
}

void timerIsr() {
    rps = spins / 3.0; // Calculate rounds per second (3 magnets per rotation)
    spins = 0.0; // Reset spin counter
}

void countspin() {
    // Toggle LED for added effect
    digitalWrite(ledpin, !digitalRead(ledpin));

    // Increment spin counter
    spins++;
}

6) Position Hall effect sensor and assess wire lengths and magnet orientation

While positioning the buttons is pretty straightforward and mainly a matter of preference, it’s best to do a live test of the Hall effect sensor for determining its position. This is the main step where I thought something was defective when really it was just improperly configured.

Polarity, orientation, and distance matter with the Hall effect sensor and fidget spinner. BEFORE permanently gluing either the Hall effect sensor or the fidget spinner, we are going to confirm that everything is working.

Temporarily place a magnet on each arm of the fidget spinner. Keep the polarity consistent and don’t glue them yet.

In order to test the Hall sensor, it will need to be wired up. The S pin should be wired to Digital Pin 2 of the Arduino as detailed below. Minus (-) should be wired to ground, while the center pin is Positive (+)  and required 5v. You should confirm the voltage requirements and pin layout for your own components as they may be different. Once connected, you can power on your Arduino to test the sensor. Mine had an LED on the sensor itself to let me know when it detected a magnet, but the Arduino code I provided will also toggle the built-in LED on the Arduino board to notify you of input.

Place your fidget spinner where you plan to mount it on top of the lid with the magnet side down against the lid. Don’t glue it yet, but consider taping it down temporarily to make the next step easier. Underneath the lid, position the Hall effect sensor such that spinning the fidget spinner toggles the sensor lights whenever they pass by.

Determine the arrangement that works for your sensor:

  • You may need to flip your Hall effect sensor over such that the proper side faces up towards the lid.
  • Your fidget spinner arms may be too far from the sensor. The magnet radius and sensor should be perfectly aligned.
  • You may need to flip the orientation of the magnets attached to the fidget spinner. This is why we haven’t glued them yet.

7) Complete Wiring and Soldering

With the Hall effect sensor tested, the rest of the wiring follows next. If your buttons lack LEDs, then wiring takes the form of the diagram below.

If your buttons have built-in LEDs, you may have noticed they have a second pair of attachments. Conceptually, you can still treat this component as separate button and LED parts and wire them accordingly. For my buttons, the side attachments were for the LED, while the remaining two were the button microswitch. You may need to test to determine which is which.

My LEDs were polarized which means it matters which direction current flows from. Oddly enough, the LEDs were not mounted consistently between buttons straight out of the box, so when an LED failed to light despite consistent wiring, I had to take the bulb and reverse it inside its button housing.

The wires supplied with my arcade buttons were intended to light the buttons at all times. Instead, I designed the arrangement diagramed above so that the buttons only light when pressed.

There is always only one direct connection between LED and button, so I soldered those on each individual button first (color differs for each button).

Next I soldered the buttons and Hall effect sensor together through their common ground and common power lines (in Black and Red, respectively).

Last, I soldered the input wires for the Hall effect sensor and each of the buttons (colors differ for each button).

The code for the Hall effect sensor uses attachInterrupt which is only available on Pins 2 and 3 on my model of Arduino. Pin 3 is unused in case I make a variation with two fidget spinners on a single controller. Pins 0 and 1 were skipped because they are reserved for TX/RX when using Serial communications.

8) Glue Hall effect sensor to case

With wiring complete, it’s time to permanently mount the Hall effect sensor in the correct position AND orientation we tested previously. Nonconductive hot glue was used. While that dried, other components could be prepared in the next step.

9) Glue washer and magnets to fidget spinner

The washer is glued to the center core of the fidget spinner, while a magnet is glued to each of the arms based on the polarities we tested before. It’s best to glue the washer separately and let it dry before moving on to the magnets, otherwise, the magnets may try to pull the washer out of place. (See image from previous step.)

Show more self control than I did and resist the temptation to spin the fidget spinner while the glue is still drying, and you won’t end up with superglue everywhere.

10) Glue fidget spinner to case

Once the washer, magnets, and Hall effect sensor have sufficiently dried, the fidget spinner can be glued to the top of the lid with the washer and magnets side down against lid in the previously tested position. BEFORE gluing confirm the washer does provide enough clearance such that the magnets do not scrape against the case.

 

 

11) Connect your game code

At this point, your controller is complete and actively sending input data via USB accessible through a serial port. What remains is creating a game or app that responds to those inputs. The following is sample code for grabbing that input data from within the Unity3D game engine. Packages such as Uniduino offer more in-depth features and Arduino-specific functions for deeper two-way integration.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
using UnityEngine;
using System.IO.Ports;

public class ArduinoSerialController : MonoBehaviour {

    public SerialPort sp;

    void Start() {;
        sp = new SerialPort("/dev/cu.usbmodem1411", 9600);
        sp.Open();
        sp.ReadTimeout = 1;
    }

    void Update() {
        if(sp.IsOpen) {
            try {
                string inputRaw = sp.ReadLine();
                string[] inputs = inputRaw.Split('\t');
                string player1Button = inputs[0];
                string blue1Button = inputs[1];
                string red1Button = inputs[2];
                string green1Button = inputs[3];
                string yellow1Button = inputs[4];
                string spinner1 = inputs[5];

                // React to input values...

            } catch (System.Exception e) {
                // Handle Errors

            }
        }
    }
}

Congrats and enjoy your new custom Arduino-powered fidget spinner alternative video game controller!

Other Uses and Future Revisions

My initial version used an Arduino Uno. Because my game is built in the Unity3D game engine, I am able to read data from the Arduino using a Serial port as shown in the sample code.  How you react to the data sent over the serial connection is totally up to you and your own game.

Other input data options are available. For example, once my local store stocks some Arduino Leonardo boards, I plan to explore sending direct keyboard input over USB instead. This could lead to some interesting input opportunities within video game emulators and in software that I otherwise can’t reprogram to accept alternative input.

Until next time…

Send me any questions you have and tell me what you end up making! If you enjoy my work, please consider following me on Twitter, Twitch, and YouTube. As a game designer, university professor, and tinkerer, I explore all kinds of projects and love sharing my experiences!