Measure how fast a fidget spinner turns

Print a spinner with a magnet in one arm, flick it, and the Hall sensor counts every turn. The Serial Plotter draws the speed in revolutions per minute as it slows down.
  • Level:Beginner
  • Duration: 45 min
  • Ages 10+
  • Platform: Arduino

Tools for this lesson

Helpful for this build. Open a tool to see tips and more projects that use it.

Measure how fast a fidget spinner turns – EEMENTOR STEM™ lesson

How fast can you spin it? A fidget spinner can turn several hundred times a minute, far too fast to count. In this lesson a magnet in one arm of a printed spinner passes over a Hall sensor once per turn. The sensor feels the magnetic field and gives the UNO a pulse, and the UNO works out the speed from the time between two pulses. Open the Serial Plotter and you can watch the spinner slow down, and the buzzer beeps when you beat your record.

What you'll learn

  • How a Hall sensor detects a magnet without touching it
  • How an interrupt catches pulses that are too fast for loop()
  • How to turn the time for one turn into revolutions per minute
  • How to show changing values in the Serial Plotter

What you need

  • UNO R3 board and USB cable (UNO R3 Starter Kit)
  • Linear Hall sensor module (45-in-1 Sensor Kit)
  • Passive buzzer (UNO R3 Starter Kit)
  • 1 small magnet, about 10 mm across (a craft or fridge magnet)
  • 4 female-to-male jumper wires
  • The printed parts from the 3D printing box below (spinner and base), or the cardboard version described there
  • Breadboard and jumper wires (UNO R3 Starter Kit)

Wiring

Breadboard wiring diagram: Measure how fast a fidget spinner turns
Breadboard view. Check each connection against the wiring table below.
From To
Hall sensor module DO UNO pin 2
Hall sensor module + and G 5V and GND
Hall sensor module AO Not used
Passive buzzer + UNO pin 8
Passive buzzer − GND

Sensor modules from different makers can label and order their pins differently. Always follow the labels printed on your module.

Hold the magnet over the sensor: the module's second LED should light. If it doesn't, turn the magnet over (the sensor reacts to one pole) or turn the small screw on the module until it does.

The sketch

const int HALL_PIN = 2;          // pin 2 can wake an interrupt
const int BUZZER_PIN = 8;

volatile unsigned long lastPass = 0;   // time of the last magnet pass, in microseconds
volatile unsigned long turnTime = 0;   // time for one full turn
volatile unsigned long turns = 0;
unsigned long record = 0;

// Runs by itself every time the magnet passes, even in the middle of loop()
void magnetPassed() {
  unsigned long now = micros();
  if (now - lastPass > 3000) {         // ignore wobbles shorter than 3 ms
    turnTime = now - lastPass;
    lastPass = now;
    turns++;
  }
}

void setup() {
  Serial.begin(9600);
  pinMode(HALL_PIN, INPUT);
  attachInterrupt(digitalPinToInterrupt(HALL_PIN), magnetPassed, FALLING);
}

void loop() {
  noInterrupts();                      // copy the values while the interrupt can't change them
  unsigned long t = turnTime;
  unsigned long last = lastPass;
  unsigned long count = turns;
  interrupts();

  unsigned long rpm = 0;
  if (t > 0 && micros() - last < 2000000) rpm = 60000000UL / t;   // stopped after 2 s without a pass

  if (rpm > record && count > 3) {
    record = rpm;
    tone(BUZZER_PIN, 1500, 60);        // new record!
  }

  Serial.print("rpm:");
  Serial.print(rpm);
  Serial.print(" record:");
  Serial.print(record);
  Serial.print(" turns:");
  Serial.println(count);
  delay(200);
}

Watch it slow down

  1. Upload the sketch and open Tools → Serial Plotter at 9600 baud.
  2. Flick the spinner hard. The rpm line jumps up and then curves slowly down to 0.
  3. The record line only goes up. Can you beat it? Try flicking with a different finger, or after oiling the peg.

How it works

A Hall sensor measures magnetic fields. On the module, a comparator turns its reading into a clean digital signal on DO: it switches every time the magnet comes close. With the magnet in one arm, that happens exactly once per turn.

At 600 rpm the magnet passes every 100 ms, but the pulse lasts only a few milliseconds. loop() spends most of its time printing and could easily miss it. An interrupt fixes that: attachInterrupt() tells the UNO to drop whatever it's doing and run magnetPassed() the moment pin 2 changes. Variables shared with an interrupt are marked volatile, and loop() copies them with interrupts switched off for a moment, so it never reads a half-changed number.

If one turn takes t microseconds, there are 60,000,000 microseconds in a minute, so the speed is 60,000,000 ÷ t revolutions per minute.

Try this next

  • Count how many turns one flick gives you in total, and print it when the spinner stops.
  • Put a magnet in all three arms and divide the result by three. Is the reading smoother?
  • Use the same sensor to measure a bicycle wheel, with a magnet on a spoke.

Troubleshooting

  • The rpm stays at 0: hold the magnet over the sensor and check that the module's LED lights. Turn the magnet over or adjust the screw.
  • The numbers are double what you expect: the sensor sees the magnet twice per pass. Bring it a little further away, or make the 3000 µs filter bigger.
  • The spinner stops quickly: sand the hole and the peg smooth and add a drop of oil.
  • A printed part is too tight or too loose: printers differ by a few tenths of a millimetre. Sand or file a tight hole, and fix a loose part with a drop of hot glue or a strip of tape.

Build it yourself

Everything used in this lesson comes in one kit, with parts tested by our engineers.

45-in-1 Sensor Kit | Compatible with Arduino IDE and ESP32 $37.00

Shop the kit