Lab 4: Read the Compass Once
The scanner proved the compass is there. Now let's actually ask it a question: "what does the magnetic field look like right now?" This lab grabs one real reading, prints it, and stops.
Welcome back, maker!
Time to get our first real magnetic data. Let's see what Earth's
field looks like from right where you're sitting!
What You Need
- Your kit from Lab 3, still wired up
What You'll Learn
- What a register is, and how to read/write one over I2C
- Why sensor readings sometimes arrive in a strange order
- A real bug we hit, and how we fixed it
Step 1: Set Up the Sensor's Registers
A chip like the HMC5883L stores its settings and its measurements in small numbered storage slots called registers. Before reading a measurement, we tell it how to take one:
1 2 3 | |
Each writeto_mem() call writes one byte into one register: how many
samples to average, how sensitive to be, and — with 0x01 — to take
one single measurement and then stop, instead of measuring
continuously forever.
Step 2: Read the Measurement
1 2 | |
readfrom_mem() grabs 6 raw bytes back from the chip — two bytes for
each of the three axes. struct.unpack(">hhh", data) is a tool that
turns those raw bytes into three actual numbers your program can use.
Wait — x, z, y? Not x, y, z?
This one trips up almost everyone the first time. The HMC5883L's
registers store the axes in the order X, then Z, then Y — not the
order you'd guess. Get this wrong, and Y and Z end up swapped in
every reading you take.
A Real Bug We Hit
While building this exact lab, reading the sensor kept crashing with an
error called OSError 5 — even though Lab 3's scanner found the chip
just fine. That was confusing: if the chip answers a scan, why can't we
read it?
It turned out to be a quirk of this specific chip on this specific
board: the normal (hardware) I2C connection can find the chip, but has
trouble with the longer back-and-forth conversation a real reading
requires. Switching to machine.SoftI2C — a slightly slower, software
version of I2C — fixed it completely, with the exact same wires. That's
why this lab, and every lab after it that reads the sensor, uses
SoftI2C instead of the plain machine.I2C the scanner used.
A scan passing doesn't guarantee a read will work
A scan is a very short conversation — just "are you there?" A real
reading is a longer one. If reads keep failing with a chip that
scans fine, trying SoftI2C is worth it before assuming your wiring
is wrong.
Try it now: run 04-get-compass-values.py. You should see three
numbers print, something like X: 426, Y: -537, Z: -834. Slowly
turn the compass and run it again — the numbers should change.
Try It Yourself
- Run the program several times without moving the board. Do you get the exact same numbers every time, or do they wiggle a little?
- Point the board straight up, then straight down. Which axis changes the most?
What's Happening Under the Hood
Right now, these numbers are just raw counts from the sensor — they don't mean "north" or "south" yet. Turning them into an actual direction takes some math, which is exactly what Lab 10 builds up to. For now, just notice that the numbers really do respond to how you hold the board.
Check Your Understanding
- What is a register?
- In what order does the HMC5883L actually send X, Y, and Z?
- What kind of I2C connection did we switch to, and why?
- What does
0x01in the MODE register tell the chip to do?
Full Code
You can find the complete program at
src/kits/smartwatch-compass-hmc5883l/04-get-compass-values.py.
You read real magnetic data!
You just pulled real numbers out of a magnetic sensor — and fixed the
exact same bug real engineers hit building this kit. Next: let's put
something on that round screen!