Files
2026-04-24 00:31:47 +02:00

10 KiB

WAVE_ROVER Firmware

ESP32 firmware for the Waveshare WAVE_ROVER platform.

This repository tracks the V1.0 source tree and is the main place for future versioning, fixes, and feature work.

Current State

  • Base firmware updated from the local V0.9 source tree toward the observed 0.95 factory behavior
  • Internal firmware version set to 1.00
  • IMU stack reworked for better stability
  • Web UI updated
  • Persistent magnetometer calibration added

Main Changes In V1.0

  • Fixed several IMU/AHRS bugs in the quaternion filter
  • Hardened QMI8658 and AK09918 I2C reads
  • Added proper IMU temperature reporting
  • Added working IMU offset get/set commands
  • Added runtime magnetometer calibration with flash persistence
  • Added automatic reload of saved mag offsets on boot
  • Added IMU calibration state flags to feedback JSON

Repository Layout

  • WAVE_ROVER.ino Main Arduino sketch
  • IMU.cpp, IMU.h, IMU_ctrl.h IMU fusion, calibration, and command handling
  • QMI8658.cpp, QMI8658.h 6-axis accelerometer/gyro driver
  • AK09918.cpp, AK09918.h Magnetometer driver
  • web_page.h Built-in web UI and JSON helper panel
  • data/ Example LittleFS content such as devConfig.json and wifiConfig.json

Build Requirements

Recommended setup:

  • Arduino IDE 2.x
  • ESP32 board support by Espressif
  • Board target: ESP32 Dev Module

ESP32 board manager URL:

  • https://espressif.github.io/arduino-esp32/package_esp32_index.json

Libraries used by this project:

  • ArduinoJson
  • SCServo
  • Adafruit SSD1306
  • INA219_WE
  • ESP32Encoder
  • PID_v2
  • SimpleKalmanFilter
  • Adafruit ICM20X
  • Adafruit ICM20948
  • Adafruit Unified Sensor

Provided by the ESP32 core and normally not installed separately:

  • WiFi
  • WebServer
  • LittleFS
  • esp_now
  • nvs_flash
  • esp_system

Build And Upload

Arduino IDE

  1. Install Arduino IDE 2.x.
  2. Add the ESP32 board manager URL in Arduino IDE preferences.
  3. Install esp32 via Boards Manager.
  4. Install the libraries listed above with Library Manager.
  5. Open WAVE_ROVER.ino.
  6. Select ESP32 Dev Module.
  7. Select the correct serial port.
  8. Upload the sketch.

LittleFS

The firmware uses LittleFS.

  • imuConfig.json is created automatically by the firmware when magnetometer offsets are saved
  • data/devConfig.json and data/wifiConfig.json are example files in the repo
  • If you want the data/ folder flashed as a filesystem image, use your preferred ESP32 LittleFS upload workflow

The firmware also calls LittleFS.begin(true), so an empty filesystem can be formatted automatically at boot if needed.

IMU And Yaw Guide

AK09918C Compass Investigation

This firmware contains a best-effort fix and diagnostic pass for the onboard compass path. It is intentionally documented here so anyone finding this repo can see what was tested instead of repeating the same blind firmware changes.

Waveshare documents the board as using QMI8658C + AK09918/AK09918C for the onboard 9-axis IMU. The big marked QST chip on the PCB is the QMI8658C accelerometer/gyro. The AK09918C compass is a much smaller AKM WLCSP part; AKM lists the package as a 4-pin 0.76 mm x 0.76 mm x 0.5 mm device, so it will not look like a normal large labelled IC.

Relevant upstream references:

Observed I2C bus on the tested board:

  • 0x0C: AKM-compatible compass address
  • 0x3C: SSD1306 OLED
  • 0x42: INA219 voltage/current monitor
  • 0x6B: QMI8658C accelerometer/gyro

The firmware now probes the compass more defensively:

  • checks AKM-compatible identity on 0x0C
  • also probes 0x06 to catch confusion between 7-bit and 8-bit I2C address notation
  • transitions through power-down before measurement modes
  • tries continuous 100 Hz, 50 Hz, 20 Hz, 10 Hz, then single-measurement mode
  • reads ST1, CNTL2, raw data, and ST2 for every mode probe
  • runs a bounded AK09918 self-test diagnostic instead of hanging forever
  • scans the I2C bus at boot when the compass does not produce data
  • keeps yaw from using fake 0/0/0 magnetometer samples
  • exposes magSrc, magStatus, magLive, magAddr, magWIA2, and magSamples

Important diagnostic pattern from the tested board:

I2C scan: 0x0C 0x3C 0x42 0x6B
AK09918 addr=0x0C ... WIA2=0x0C or 0x0D
CNTL2 writes/readbacks work, e.g. 0x08 for continuous-100Hz
ST1 remains 0x00
raw remains 0/0/0
self-test sets CNTL2=0x10 but times out with no DRDY
QMI8658 mag fallback also reports raw=0/0/0

Interpretation:

  • I2C wiring and the digital register interface are alive because the chip ACKs, identity registers can be read, reset works, and CNTL2 mode writes stick.
  • The magnetic measurement core is not producing DRDY or non-zero raw samples.
  • This is not the same as bad calibration; calibration needs live changing mag samples first.
  • If the same pattern appears on another board, likely causes include a board revision issue, AK09918C supply/decoupling/soldering problem, damaged compass die, or an AKM-compatible variant/clone that does not behave like the public AK09918C register model.

This does not prove every General Driver board has a hardware fault. It means this firmware has exhausted the obvious software-side address, mode, transaction, and calibration fixes for this observed failure mode.

What Was Fixed

The original IMU path had multiple issues that could produce unstable or misleading yaw:

  • filter integrator terms were not preserved correctly
  • sample timing was effectively fixed instead of using real elapsed time
  • quaternion integration used unsafe update ordering
  • I2C reads for the IMU sensors were fragile
  • magnetometer offsets were not handled in a reliable workflow

Current Yaw Behavior

yaw now works in two stages:

  • relative orientation from the gyro/fusion path
  • absolute heading correction from the magnetometer when a valid mag calibration is available

Without a valid magnetometer calibration, yaw can still move, but absolute heading quality will be poor.

Magnetometer Calibration

Goal

Create a good heading calibration once, save it to flash, and automatically reload it on every boot.

Start Calibration

Send:

{"T":145}

This starts a magnetometer calibration session.

During Calibration

For about 12 seconds:

  • rotate the rover slowly through a full turn
  • change orientation gently so the sensor sees different magnetic angles
  • avoid fast shaking
  • avoid strong magnets, steel tables, speakers, power bricks, or large metal objects nearby

Check Progress

Send:

{"T":126}

Important feedback fields:

  • magCal 1 means a valid heading calibration is active
  • magSaved 1 means offsets were saved to flash
  • magCalRunning 1 while calibration is still collecting data
  • magCalProgress progress from 0 to 100
  • magSrc active compass source: ak09918, qmi8658, or none
  • magStatus compass health: ok, no_drdy, lost, or not_found
  • magLive 1 only after at least one real magnetometer sample was received

Successful Result

After a successful run:

  • offsets are written to /imuConfig.json
  • saved offsets are loaded automatically at boot
  • manual rotation on every startup is no longer required

If Calibration Fails

If magCal stays 0:

  • run {"T":145} again
  • rotate slower
  • cover more angles
  • move away from magnetic or metal interference

If magStatus is no_drdy and magLive is 0, firmware can talk to the AKM-compatible chip but the magnetic measurement core is not producing data. That is different from a calibration problem: check the board revision, IMU chip marking, AK09918C supply rails, and soldering around the IMU.

If magSaved is 0 after a good calibration:

  • check that LittleFS mounted successfully
  • reflash and retry

IMU JSON Commands

Read IMU Data

{"T":126}

Returns roll, pitch, yaw, accel, gyro, mag, temperature, and calibration state flags. It also returns magSrc, magStatus, magLive, magAddr, magWIA2, and magSamples for compass diagnosis.

Recalibrate Gyro/Accel Bias

Keep the rover still on a stable surface, then send:

{"T":127}

This is not the same as a full magnetometer calibration.

Get Current Magnetometer Offsets

{"T":128}

Set Magnetometer Offsets Manually

{"T":129,"x":-12,"y":0,"z":0}

Manual offsets are also saved to flash automatically in V1.0.

Start Magnetometer Calibration

{"T":145}

Base Feedback

Base feedback also exposes the IMU calibration state:

{"T":130}

Useful fields:

  • r
  • p
  • y
  • magCal
  • magSaved
  • magCalRunning
  • magCalProgress
  • magSrc
  • magStatus
  • magLive
  • temp

Yaw Troubleshooting

If yaw still looks wrong:

  1. Run {"T":145}.
  2. Rotate the rover slowly until calibration completes.
  3. Check {"T":126} and confirm:
    • magCal = 1
    • magSaved = 1
    • magCalRunning = 0
    • magStatus = ok
  4. Reboot and verify the values are still loaded.

If yaw drifts while magStatus is not ok, the rover is running gyro/accel AHRS without a live compass. Fix the magnetometer hardware path first.

If yaw is stable but mirrored or rotated by a fixed amount, the next thing to tune is axis convention or declination, not the calibration storage itself.

Notes

  • Build artifacts such as build/, *.bin, *.elf, and *.map are ignored in Git
  • imuConfig.json is generated on-device and is not meant to be versioned in this repo
  • This repo currently tracks source, not release binaries

Official References