Skip to content

Auto-calibration at startup #18

@jumpjack

Description

@jumpjack

I asked AI to merge calibrate.ino and and heading.ino into one single skecth wchich at first start performs calibration and saves data in EEPROM, and from second start begins printing calibrated values.

Calibration lasts 10 seconds, you must rotate the sensor 360° about all its axes during this time.

Not tested yet.

#include <Wire.h>
#include <LSM303.h>
#include <EEPROM.h>

LSM303 compass;
LSM303::vector<int16_t> running_min = {32767, 32767, 32767}, running_max = {-32768, -32768, -32768};
char report[80];

// Structure to save calibration values in EEPROM
struct CalibrationData {
  int16_t min_x;
  int16_t min_y;
  int16_t min_z;
  int16_t max_x;
  int16_t max_y;
  int16_t max_z;
  uint8_t calibrated;  // Flag to verify if calibration has been performed
};

void setup() {
  Serial.begin(9600);
  Wire.begin();
  compass.init();
  compass.enableDefault();

  // Read calibration data from EEPROM
  CalibrationData calibData;
  EEPROM.get(0, calibData);

  // Check if calibration has already been performed
  if (calibData.calibrated == 0xAA) {
    // Use saved calibration values
    compass.m_min = (LSM303::vector<int16_t>){
      calibData.min_x, 
      calibData.min_y, 
      calibData.min_z
    };
    compass.m_max = (LSM303::vector<int16_t>){
      calibData.max_x, 
      calibData.max_y, 
      calibData.max_z
    };
    Serial.println("Calibration loaded from EEPROM");
  } else {
    // Calibration mode
    Serial.println("Starting calibration. Rotate the sensor in all directions.");
  }
}

void loop() {
  // Read calibration data from EEPROM
  CalibrationData calibData;
  EEPROM.get(0, calibData);

  if (calibData.calibrated != 0xAA) {
    // Calibration mode
    compass.read();
    
    running_min.x = min(running_min.x, compass.m.x);
    running_min.y = min(running_min.y, compass.m.y);
    running_min.z = min(running_min.z, compass.m.z);
    running_max.x = max(running_max.x, compass.m.x);
    running_max.y = max(running_max.y, compass.m.y);
    running_max.z = max(running_max.z, compass.m.z);
    
    snprintf(report, sizeof(report), "min: {%+6d, %+6d, %+6d}    max: {%+6d, %+6d, %+6d}",
      running_min.x, running_min.y, running_min.z,
      running_max.x, running_max.y, running_max.z);
    Serial.println(report);
    
    // Wait a bit for calibration
    delay(100);

    // Check if we have collected sufficient data (optional)
    if (millis() > 30000) {  // 30 seconds of calibration
      // Save calibration values to EEPROM
      calibData.min_x = running_min.x;
      calibData.min_y = running_min.y;
      calibData.min_z = running_min.z;
      calibData.max_x = running_max.x;
      calibData.max_y = running_max.y;
      calibData.max_z = running_max.z;
      calibData.calibrated = 0xAA;  // Mark as calibrated
      
      EEPROM.put(0, calibData);
      
      Serial.println("Calibration completed and saved!");
      
      // Restart to switch to reading mode
      delay(2000);
      setup();
    }
  } else {
    // Reading mode
    compass.read();
    
    float heading = compass.heading();
    
    Serial.print("Heading: ");
    Serial.println(heading);
    delay(100);
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions