Lab 10: Build a Real Compass
This is the capstone. Everything from the last nine labs — reading the sensor, drawing on the screen, avoiding flicker, and the math to turn magnetism into a direction — comes together here into one live compass dial with a needle that points north.
Welcome to the finale, maker!
Everything we've built so far leads here — a real, working compass
with a needle that tracks true north. Let's finish this!
What You'll Learn
- How to turn X/Y readings into an angle with
atan2 - Why a compass needs two different calibration steps, not one
- A third way to avoid screen flicker — erasing a moving shape
Step 1: Turning Numbers Into an Angle
1 2 3 4 5 | |
atan2(y, x) is a trigonometry function that takes two numbers and
returns the angle between them — exactly like reading an angle off a
protractor, except the "protractor" here is the invisible shape of
Earth's magnetic field. The rest of the math converts that angle from
radians (the unit trigonometry naturally works in) into ordinary
degrees, and makes sure it always lands between 0 and 359.
Step 2: Calibration, Part 1 — Removing Magnetic Bias
Nearby metal and other magnets push on the sensor too, adding a steady bias on top of Earth's real field — the same hard-iron interference you read about on the kit's main page. The fix: rotate the board through a full flat circle and track the smallest and largest reading on each axis.
1 2 | |
The true center of the circle the sensor traces sits halfway between its minimum and maximum — subtracting that midpoint from every future reading cancels the bias out.
Try it now: run 10-draw-compass.py. When it says "Calibrating,"
slowly rotate the board flat through one full circle.
Step 3: Calibration, Part 2 — Finding "Straight Up"
Here's a real problem we hit building this exact lab: after the first calibration finished, we pointed the top of the board due north — and the screen read "E 80", not north at all!
That wasn't a bug in the math. The compass chip is mounted at some fixed angle inside its little breakout board, and that angle doesn't necessarily line up with what we consider the "top" of the assembled kit. Rotating in a circle fixes magnetic bias, but it can't fix a fixed mechanical rotation like this one.
The solution is a second calibration step: point the board due north and hold still, and let the program measure exactly what it reads at that moment.
1 2 3 4 5 6 7 8 | |
Why sin and cos instead of a plain average?
Imagine averaging the headings 359 and 1 — a plain average gives 180,
which is exactly backwards! Averaging each reading's sin and cos
first, then converting back to an angle at the end, handles that
wraparound correctly. This trick is called a circular mean.
Every reading after that subtracts this measured offset, so 0 really does mean "pointing at true north":
1 2 | |
Try it now: when the screen says "Point the board due north," aim the top of the board at true north (a phone compass app helps a lot here) and hold it steady for a few seconds.
Two calibrations, not one
It's tempting to think "we already calibrated" after the rotation
step. But that step fixes magnetism; this step fixes how the chip
is mounted. They're two completely different problems that happen
to both be called "calibration."
Step 4: Drawing a Needle That Moves
The ring around the edge is drawn once, before the loop, since it never moves. The needle is different — it changes every frame, so it needs its own flicker-avoidance trick:
1 2 3 4 5 6 7 8 | |
Instead of clearing a whole area, this remembers exactly where the previous needle pointed and redraws that same line in black — erasing only that one line — before drawing the new needle in white. That's the third flicker-avoidance trick in this kit: Lab 7 overwrote fixed-width text, Lab 9 cleared a small column, and this lab erases exactly the shape that moved.
Try It Yourself
- Walk to a different room and run the calibration again. Does the needle still track correctly?
- Hold a magnet near the sensor while the needle is live. Watch it swing — that's the same hard-iron interference the first calibration step was designed to cancel out, overwhelming the correction in real time.
What's Happening Under the Hood
A cheap sensor mounted by hand on a breadboard will never be perfectly aligned — and that's completely normal. Real engineers handle imperfect, real-world hardware by measuring what's actually true and correcting for it in software, rather than assuming everything lines up perfectly. That's exactly what both calibration steps in this lab do.
Check Your Understanding
- What does
atan2(y, x)return? - What's the difference between the two calibration steps in this lab?
- Why does averaging headings with
sin/coswork better than a plain average? - How does the needle avoid leaving a trail as it moves?
Full Code
You can find the complete program at
src/kits/smartwatch-compass-hmc5883l/10-draw-compass.py.
You built a real, working compass!
From one blinking LED all the way to a calibrated compass dial that
tracks true north — you built every piece of this yourself, and
debugged real hardware problems along the way. That's the complete
engineering process. Amazing work, maker!