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

| 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
- Upload the sketch and open Tools → Serial Plotter at 9600 baud.
- Flick the spinner hard. The rpm line jumps up and then curves slowly down to 0.
- 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.