Files
WAVE_ROVER/IMU_ctrl.h
T
JoshandClaude Sonnet 4.6 9b0a5a9926 Fix compass heading direction, add magnetic declination and heading offset
- Fix atan2 sign bug: atan2(-yHeading, xHeading) per Freescale AN4248 eq.22.
  The previous atan2(yHeading, xHeading) produced counter-clockwise angles,
  causing East/West to be swapped relative to compass convention.

- Add imuSetMagneticDeclination() (T:146, field "decl") to correct the
  offset between magnetic north and true north (iPhone shows true north).
  Value is persisted in imuConfig.json across reboots.

- Add imuSetHeadingOffset() (T:147, field "off") to compensate for sensor
  mounting orientation on the rover. Also persisted.

- Persist decl and hOff in imuConfig.json (version 2, backwards compatible).

- Fix calibration feedback for web interface: T:126 now includes calDone=1
  (success) or calDone=0 (fail) once after calibration completes, plus
  decl and hOff fields. Calibration start message explains polling procedure.

- Remove duplicate #include <nvs_flash.h> and unused Adafruit ICM20948
  includes that caused build failures when libraries were not installed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 21:46:00 +02:00

182 lines
5.6 KiB
C

#include"IMU.h"
// define GPIOs for IIC.
EulerAngles stAngles;
IMU_ST_SENSOR_DATA_FLOAT stGyroRawData;
IMU_ST_SENSOR_DATA_FLOAT stAccelRawData;
IMU_ST_SENSOR_DATA stMagnRawData;
float temp;
void imu_init() {
imuInit();
}
void updateIMUData() {
imuDataGet( &stAngles, &stGyroRawData, &stAccelRawData, &stMagnRawData);
temp = imuGetTemperature();
ax = stAccelRawData.X;
ay = stAccelRawData.Y;
az = stAccelRawData.Z;
mx = stMagnRawData.s16X;
my = stMagnRawData.s16Y;
mz = stMagnRawData.s16Z;
gx = stGyroRawData.X;
gy = stGyroRawData.Y;
gz = stGyroRawData.Z;
icm_roll = stAngles.roll;
icm_pitch = stAngles.pitch;
icm_yaw = stAngles.yaw;
icm_temp = temp;
last_imu_update = millis();
}
void imuCalibration() {
const bool calibrationOk = imuRecalibrate();
updateIMUData();
jsonInfoHttp.clear();
jsonInfoHttp["T"] = FEEDBACK_IMU_DATA;
jsonInfoHttp["status"] = calibrationOk ? 1 : 0;
jsonInfoHttp["info"] = calibrationOk ? "IMU calibration finished. Rotate the rover slowly once to refine heading." : "IMU calibration failed.";
jsonInfoHttp["r"] = icm_roll;
jsonInfoHttp["p"] = icm_pitch;
jsonInfoHttp["y"] = icm_yaw;
jsonInfoHttp["magCal"] = imuHasHeadingCalibration() ? 1 : 0;
jsonInfoHttp["magSaved"] = imuHasStoredMagnCalibration() ? 1 : 0;
jsonInfoHttp["magCalRunning"] = imuIsMagnCalibrationRunning() ? 1 : 0;
jsonInfoHttp["magCalProgress"] = imuGetMagnCalibrationProgress();
String getInfoJsonString;
serializeJson(jsonInfoHttp, getInfoJsonString);
Serial.println(getInfoJsonString);
}
void startMagCalibration() {
const bool started = imuStartMagnCalibration();
jsonInfoHttp.clear();
jsonInfoHttp["T"] = FEEDBACK_IMU_DATA;
jsonInfoHttp["status"] = started ? 1 : 0;
jsonInfoHttp["info"] = started
? "Mag cal started (12s). Rotate rover slowly 360deg in horizontal plane. Poll {\"T\":126} to watch magCalProgress reach 100. Result: calDone=1 success, calDone=0 fail."
: "Mag calibration failed to start.";
jsonInfoHttp["magCal"] = imuHasHeadingCalibration() ? 1 : 0;
jsonInfoHttp["magSaved"] = imuHasStoredMagnCalibration() ? 1 : 0;
jsonInfoHttp["magCalRunning"] = imuIsMagnCalibrationRunning() ? 1 : 0;
jsonInfoHttp["magCalProgress"] = imuGetMagnCalibrationProgress();
String getInfoJsonString;
serializeJson(jsonInfoHttp, getInfoJsonString);
Serial.println(getInfoJsonString);
}
void getIMUData() {
jsonInfoHttp.clear();
jsonInfoHttp["T"] = FEEDBACK_IMU_DATA;
jsonInfoHttp["r"] = icm_roll;
jsonInfoHttp["p"] = icm_pitch;
jsonInfoHttp["y"] = icm_yaw;
jsonInfoHttp["ax"] = ax;
jsonInfoHttp["ay"] = ay;
jsonInfoHttp["az"] = az;
jsonInfoHttp["gx"] = gx;
jsonInfoHttp["gy"] = gy;
jsonInfoHttp["gz"] = gz;
jsonInfoHttp["mx"] = mx;
jsonInfoHttp["my"] = my;
jsonInfoHttp["mz"] = mz;
jsonInfoHttp["magCal"] = imuHasHeadingCalibration() ? 1 : 0;
jsonInfoHttp["magSaved"] = imuHasStoredMagnCalibration() ? 1 : 0;
jsonInfoHttp["magCalRunning"] = imuIsMagnCalibrationRunning() ? 1 : 0;
jsonInfoHttp["magCalProgress"] = imuGetMagnCalibrationProgress();
jsonInfoHttp["decl"] = imuGetMagneticDeclination();
jsonInfoHttp["hOff"] = imuGetHeadingOffset();
// Report calibration completion status once (cleared after read).
const int8_t calStatus = imuPopLastCalStatus();
if (calStatus >= 0) {
jsonInfoHttp["calDone"] = calStatus;
}
jsonInfoHttp["temp"] = temp;
String getInfoJsonString;
serializeJson(jsonInfoHttp, getInfoJsonString);
Serial.println(getInfoJsonString);
}
void getIMUOffset() {
IMU_ST_SENSOR_DATA offsetData;
imuGetMagnOffsets(&offsetData);
jsonInfoHttp.clear();
jsonInfoHttp["T"] = CMD_GET_IMU_OFFSET;
jsonInfoHttp["x"] = offsetData.s16X;
jsonInfoHttp["y"] = offsetData.s16Y;
jsonInfoHttp["z"] = offsetData.s16Z;
jsonInfoHttp["saved"] = imuHasStoredMagnCalibration() ? 1 : 0;
String getInfoJsonString;
serializeJson(jsonInfoHttp, getInfoJsonString);
Serial.println(getInfoJsonString);
}
void setIMUOffset(int16_t inputX, int16_t inputY, int16_t inputZ) {
imuSetMagnOffsets(inputX, inputY, inputZ);
imuSaveMagnCalibration();
getIMUOffset();
}
// {"T":146,"decl":4.5}
// Sets magnetic declination in degrees (positive = East of true North).
// Find yours at: https://www.magnetic-declination.com/
// Example: Germany ~+3 to +5, USA East Coast ~-13, Australia ~+12
void setMagDeclination(float deg) {
imuSetMagneticDeclination(deg);
imuSaveMagnCalibration(); // persist across reboots
jsonInfoHttp.clear();
jsonInfoHttp["T"] = CMD_GET_IMU_OFFSET;
jsonInfoHttp["decl"] = imuGetMagneticDeclination();
jsonInfoHttp["hOff"] = imuGetHeadingOffset();
jsonInfoHttp["saved"] = imuHasStoredMagnCalibration() ? 1 : 0;
jsonInfoHttp["info"] = "Magnetic declination set and saved.";
String getInfoJsonString;
serializeJson(jsonInfoHttp, getInfoJsonString);
Serial.println(getInfoJsonString);
}
// {"T":147,"off":90.0}
// Sets a fixed heading offset in degrees.
// Use this to compensate for sensor mounting orientation on the rover.
// Procedure: point rover to known direction (e.g. phone compass North = 0),
// send {"T":126} to read current yaw, then set offset = 0 - current_yaw.
void setHeadingOffset(float deg) {
imuSetHeadingOffset(deg);
imuSaveMagnCalibration(); // persist across reboots
jsonInfoHttp.clear();
jsonInfoHttp["T"] = CMD_GET_IMU_OFFSET;
jsonInfoHttp["decl"] = imuGetMagneticDeclination();
jsonInfoHttp["hOff"] = imuGetHeadingOffset();
jsonInfoHttp["saved"] = imuHasStoredMagnCalibration() ? 1 : 0;
jsonInfoHttp["info"] = "Heading offset set and saved.";
String getInfoJsonString;
serializeJson(jsonInfoHttp, getInfoJsonString);
Serial.println(getInfoJsonString);
}