hello_spirit_level

Example of the component cube32esp/cube32_bsp v0.0.17
# hello_spirit_level

Digital spirit level (inclinometer) for the CUBE32 board. The LSM6DSO accelerometer gives roll and pitch, shown as a bubble on an LVGL canvas that moves opposite to the tilt, like a real bubble level.

## Features

- **Bubble display**: a circular bubble drawn on a 180x180 LVGL canvas, moving opposite to the tilt (4 px per degree)
- **Reference rings** at 1°, 5° and 10°
- **Adapts to the screen size**: the level is centered and scaled at start-up (the log shows `Screen WxH, canvas SxS`): 180×180 on 240×240, 260×260 on 320×320. Rings, bubble and sensitivity scale with it, so the full range stays about ±21°
- **Numeric readout**: `Roll` and `Pitch` in degrees
- **Colour feedback**: the ring, bubble and status text follow the total tilt

  | Total tilt | Colour | Status |
  |------------|--------|--------|
  | ≤ 1° | green | `LEVEL` |
  | 1° – 5° | yellow | `SLIGHT TILT` |
  | 5° – 10° | orange | `TILTED` |
  | > 10° | red | `STEEP` |

- **Smooth motion**: a low-pass filter (`FILTER_ALPHA = 0.35`) removes jitter from the accelerometer data
- **Console fallback**: the tilt is also printed twice a second, and it is the only output when LVGL is disabled

Roll is the rotation about the X axis (sideways tilt); pitch is the rotation about the Y axis (forward/backward tilt). Both are computed from the accelerometer only, so the board has to be still while measuring.

## Hardware

- CUBE32 board (ESP32-S3) with a supported display (auto-detected at boot)
- LSM6DSO IMU (on the board)

## Configuration

`sdkconfig.defaults` of the release example already has what the demo needs:

| Setting | Why |
|---------|-----|
| `CONFIG_CUBE32_LVGL_ENABLED=y` | LVGL display driver |
| `CONFIG_CUBE32_TOUCH_ENABLED=y` | Touch input (standard LVGL setup of the examples) |
| `CONFIG_CUBE32_IMU_ENABLED=y` | Accelerometer data |
| `CONFIG_LV_USE_CANVAS=y` | The bubble face is drawn on a canvas |
| `CONFIG_LV_FONT_MONTSERRAT_18=y` | Title label |
| `CONFIG_LV_FONT_MONTSERRAT_10/20/24=y` | Required by the BLE OTA UI whenever LVGL is on |

In the BSP dev project select the demo with `idf.py menuconfig` → `CUBE32 Application Selection` → `Hello Spirit Level Example` (it is only listed when LVGL and the IMU are enabled).

## Build and run

```bash
idf.py set-target esp32s3
idf.py build
idf.py -p <port> flash monitor
```

Run `idf.py set-target esp32s3` again after deleting `sdkconfig`; otherwise the target falls back to `esp32`.

## Usage

1. Put the board flat on the surface to check and flash the example.
2. The bubble sits in the centre, the ring is green and the status reads `LEVEL` when the surface is level.
3. Tilt the board: the bubble moves away from the direction of the tilt and the colour changes from green to yellow, orange and red.
4. Read the exact angles from `Roll` / `Pitch`.

If the IMU is not initialised, the bubble stays in the centre and the console prints `IMU: Not initialized`.

## Console output

```
I (xxxx) spirit_level: ========================================
I (xxxx) spirit_level: CUBE32 Spirit Level / Inclinometer
I (xxxx) spirit_level: ========================================
I (xxxx) spirit_level: IMU: LSM6DSO ready
I (xxxx) spirit_level: UI created
I (xxxx) spirit_level: Spirit level running — tilt the board to see the bubble move
Roll:   +0.3°  Pitch:   -0.2°  Total:   0.4°  [LEVEL]
Roll:   +4.8°  Pitch:   -1.1°  Total:   4.9°  [SLIGHT TILT]
```

To create a project from this example, run:

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

or download archive (~11.42 KB)