hello_compass

Example of the component cube32esp/cube32_bsp v0.0.17
# Hello Compass

Tilt-compensated digital compass demo for CUBE32. Uses the LSM6DSO accelerometer
for tilt correction and the LIS3MDL magnetometer for heading. Includes hard-iron
calibration with NVS persistence and an LVGL compass-rose UI.

## Features

- Tilt-compensated heading accurate from flat to vertical orientations
- Dynamic reference axis: uses the Up edge when flat, smoothly transitions
  to the board Face direction when held vertically
- Hard-iron calibration on all three axes (X, Y, Z) for accuracy at any tilt
- Default calibration offsets in `cube32_config.h` — compass works out of the
  box without a calibration phase
- Calibration offsets saved to NVS flash — survives reboots
- **Recalibrate** button (bottom-right) to start a new calibration
- **Reset** button (bottom-left) to erase NVS calibration and revert to
  default offsets instantly — no reboot required
- **Screen-size adaptive layout**: the dial is sized from the display at start-up
  (the log shows `Screen WxH, compass dial SxS`) — 170×170 on 240×240, 250×250 on
  320×320. Ring, ticks, needle, labels and the calibration screen scale with it, and
  the cardinal labels use larger fonts (24/18/14 instead of 18/14/10) on the big dial
- Console fallback output when LVGL is not enabled

## Default Calibration

The board ships with factory default hard-iron offsets defined in
`cube32_config.h` (`CUBE32_MAG_CAL_OFFSET_X/Y/Z`). On first boot — or
whenever NVS has no saved calibration — these defaults are applied
automatically so the compass is immediately usable without a calibration
phase.

This lets the compass work immediately on first boot, but these values are
only defaults. For best accuracy, it is recommended to tap **Cal** on the
first boot and perform a full calibration for the specific board and its
current magnetic environment.

To update the defaults for a different board unit, change the values in
`cube32_config.h` and rebuild.

## Calibration Steps

Calibration does not run automatically on first boot. On first boot, the demo
uses the default calibration offsets from `cube32_config.h` if NVS does not yet
contain saved calibration data.

For best accuracy, tap **Cal** on the compass screen on first boot and perform
a full calibration. Calibration is also needed any time you want to replace the
saved NVS offsets with fresh values for the current board setup.

The goal is to sample the full range of the Earth's magnetic field vector across
all three axes so the firmware can compute hard-iron offsets.

### Step-by-Step

1. **Start the demo.** On first boot, the compass starts using the default
  calibration offsets.
2. **Tap `Cal`** to enter calibration mode. The screen shows "Calibrating"
  with a progress bar.
3. **Hold the board comfortably** and begin a slow **figure-8 motion**:
   - Rotate the board 360° around its vertical axis (yaw).
   - While rotating, **tilt** the board forward/backward and side-to-side
     so every face of the board points in multiple directions.
   - Think of tracing a large figure-8 in the air — this naturally combines
     rotation with tilting.
4. **Watch the progress bar.** It tracks four criteria equally:
   - X-axis magnetic spread (≥ 0.35 gauss)
   - Y-axis magnetic spread (≥ 0.35 gauss)
   - Z-axis magnetic spread (≥ 0.25 gauss)
   - Minimum 150 samples collected
5. **Keep moving until the bar reaches 100%.** Calibration completes
   automatically and the compass screen appears.
6. **Verify accuracy.** Point the board toward a known direction (e.g. a
   physical compass or a landmark) and confirm the heading matches. Test
   with the board both flat and tilted.

### Tips

- **Move slowly and smoothly.** Quick jerky movements add noise.
- **Tilt is essential.** If you only rotate the board while keeping it flat,
  the Z-axis will not get enough spread and calibration will stall.
- **Stay away from magnets and large metal objects** during calibration —
  they distort the Earth's field and produce bad offsets.
- **Recalibrate** if you move to a very different location or if the board
  is mounted near new ferromagnetic material (screws, motors, etc.).
- Calibration is saved to flash. You only need to redo it when the magnetic
  environment around the board changes.

### Console Output During Calibration

If LVGL is not enabled, calibration progress is printed to the serial console:

```
CAL | Spread X:0.412 Y:0.380 Z:0.105  Samples:87  Progress:62%
CAL | Spread X:0.523 Y:0.491 Z:0.271  Samples:150  Progress:93%
```

The `Spread` values show the min/max range seen so far on each axis. Once all
thresholds are met, calibration completes and heading output begins.

## On-Screen Buttons

Two buttons appear on the compass screen:

| Button | Position | Action |
|--------|----------|--------|
| **Cal** | Bottom-right | Starts a new calibration phase. The new offsets are saved to NVS when complete. |
| **Rst** | Bottom-left | Erases the NVS calibration data and immediately reverts to the default offsets from `cube32_config.h`. No reboot is needed — the change takes effect on the next sensor sample. |

## Vertical Orientation

The compass uses a dynamic reference axis that adapts to how you hold the
board:

- **Flat (pitch < 45°):** Heading indicates where the **Up edge** of the
  board points — the traditional compass behaviour.
- **Vertical (pitch > 60°):** Heading indicates where the **Face** of the
  board points, which is the natural interpretation when the board is held
  upright like a phone.
- **Transition zone (45°–60°):** The reference blends smoothly between the
  two modes to avoid abrupt jumps.

This means you can rotate the board from flat on a table to upright in your
hand and the heading remains stable and intuitive.

## Magnetic Declination

The heading output is relative to magnetic north by default. To correct for
true north, set `MAG_DECLINATION` at the top of `main.cpp` to your local
magnetic declination in degrees (east positive). Look up your value at
[NOAA's declination calculator](https://www.ngdc.noaa.gov/geomag/declination.shtml).

## Known Limitations

- **Near-vertical orientations (pitch > ~70°):** Heading accuracy may degrade
  slightly. The accelerometer-based roll estimate becomes noisier when gravity
  is nearly aligned with the X-axis. The dynamic reference axis mitigates this
  for moderate tilt, but extreme angles may still show some drift.
- **Soft-iron distortion** is not corrected. The current calibration handles
  hard-iron offsets only. Nearby ferromagnetic materials that warp the field
  ellipsoid (rather than shifting it) will reduce accuracy.

To create a project from this example, run:

idf.py create-project-from-example "cube32esp/cube32_bsp=0.0.17:hello_compass"

or download archive (~16.83 KB)