Skip to content

BMM150 magnetometer for Waveshare S3 Touch #29

Description

@Dasqez

Programming is my new hobby and I thought I do something extra for this amazing project. I got myself BMM150 3-axis magentometer and I incorporated it into ESP32Flight project.

Adds support for an optional BMM150 magnetometer wired to the same I2C bus
the display already uses. When present and calibrated, the "spotter line"
on the flight detail screen (the one that currently says e.g. Look NW, 20° above horizon) shows a device-relative hint instead — Look right, 20° above horizon — telling you which way to physically turn the
board rather than a fixed compass point. Without the sensor (or before
it's calibrated), behavior is unchanged: the original geographic 8-sector
label is used, so this is a strict opt-in with no regression for boards
that don't have the chip.

Built and tested on a Waveshare ESP32-S3-Touch-LCD-7, ESP-IDF 5.5.5.
Not tested on the other 9 supported board variants — the code is written
to fail safe (reports "not detected") if the chip doesn't answer, so it
shouldn't affect boards without the sensor, but I only have the one board
to verify against.

Hardware

  • Sensor: Bosch BMM150, I2C address 0x13, chip ID 0x32.
  • Wiring: SDA -> GPIO8, SCL -> GPIO9 (the same bus the board already
    brings up for the GT911 touch controller at 0x5D and the CH422G I/O
    expander at 0x24/0x38 — no address conflicts, no extra pins needed),
    VCC -> 3.3V, GND -> GND. INT is left unconnected (polling is used,
    not interrupts).
  • No wiring changes needed on a board that already has the chip present;
    boards without it simply never detect anything and the feature is a
    no-op.

What's new

New files (main/compass.c, main/compass.h): a small module
following the existing _poll()/_get() module convention used
elsewhere in the codebase (see ships.h). On compass_init() it detects
the chip and, if found, starts a background FreeRTOS task that polls it
every 200ms, computes a heading, and (during calibration) tracks a
per-axis min/max envelope. compass_get() returns a snapshot safe to call
from any task. compass_dir_word() is the one call site UI code needs —
it returns a localized direction word for a given true bearing, using the
device heading when calibrated and transparently falling back to the
existing lang_compass() 8-sector label otherwise.

Calibration (a 30-second "rotate the board" sweep) is stored in NVS under
its own namespace (compass / key cal) rather than on an SD card, since
most boards here don't have one — this is a difference from how a similar
feature was implemented in an unrelated personal project this was ported
from.

The whole module is guarded #ifndef APKFLIGHT: in the Android build it
compiles to trivial stubs (compass_get() always reports
detected = false), since there's no I2C bus to talk to there and several
of the files it touches (ui.c, ui_settings.c, lang.c) are shared
between the ESP-IDF and Android targets.

New dependency (main/idf_component.yml): lewisxhe/sensorlib "0.4.1", which vendors Bosch's official BMM150 sensor API
(bmm150_init, bmm150_read_mag_data, etc.) — pulled automatically by
the IDF component manager on the next build, no manual step needed.

(Above is an extract from readme file I prepared).

If you would like to get a .zip file with all the modified files and readme - ping me. If it fits your roadmap or just expanding features - feel free to use it within this project!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions