# 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_V1.0.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_V1.0.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 ### 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: ```json {"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: ```json {"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` ### 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 `magSaved` is `0` after a good calibration: - check that `LittleFS` mounted successfully - reflash and retry ## IMU JSON Commands ### Read IMU Data ```json {"T":126} ``` Returns roll, pitch, yaw, accel, gyro, mag, temperature, and calibration state flags. ### Recalibrate Gyro/Accel Bias Keep the rover still on a stable surface, then send: ```json {"T":127} ``` This is not the same as a full magnetometer calibration. ### Get Current Magnetometer Offsets ```json {"T":128} ``` ### Set Magnetometer Offsets Manually ```json {"T":129,"x":-12,"y":0,"z":0} ``` Manual offsets are also saved to flash automatically in `V1.0`. ### Start Magnetometer Calibration ```json {"T":145} ``` ## Base Feedback Base feedback also exposes the IMU calibration state: ```json {"T":130} ``` Useful fields: - `r` - `p` - `y` - `magCal` - `magSaved` - `magCalRunning` - `magCalProgress` - `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` 4. Reboot and verify the values are still loaded. 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 - Arduino IDE: - Arduino-ESP32 install guide: - esptool install guide: