Incorect magnometer sensor Values

Hello,
I’m trying to make a vehicle with compass and a gps but i have trouble calculating magnetic values from adafruit LIS3MDL .
I am connecting this sensor with I2C interface to Arduino MEGA 2560

I do a lot of searching and use diferent tools in order to calibrate sensor. The values i am getting show strange values of degrees like the sketch bellow. Also i tried to calibrate in different locations to avoid magnetic fields in my office.

I am using this code taken mostly from adafruit examples. In the begining i am giving about 30 seconds for calibration and the values showing in an 16x2 LCD.

Any advice would be appreciated.

#include <Adafruit_SensorLab.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// Set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27, 24, 4);

Adafruit_SensorLab lab;
Adafruit_Sensor *mag;
sensors_event_t mag_event;

sensors_event_t event;
float min_x, max_x, mid_x;
float min_y, max_y, mid_y;
float min_z, max_z, mid_z;

void setup(void) {
  Serial.begin(115200);
  while (!Serial) delay(10);     // will pause Zero, Leonardo, etc until serial console opens

    // initialize the LCD
  lcd.begin();

  // Turn on the blacklight
  lcd.setBacklight((uint8_t)1);

  Serial.println(F("Sensor Lab - Magnetometer Calibration!"));
  lab.begin();
  lcd.setCursor(0,0);
  lcd.print("Looking for a magnetometer");
  lcd.setCursor(0,1);
  mag = lab.getMagnetometer();
  if (! mag) {
    lcd.print(F("Could not find a magnetometer, check wiring!"));
    while(1) delay(10);
  }

  delay(1000);
  lcd.clear();
  mag->getEvent(&event);
  min_x = max_x = event.magnetic.x;
  min_y = max_y = event.magnetic.y;
  min_z = max_z = event.magnetic.z;
  int i;
  lcd.setCursor(0,0);
  lcd.print("Calibr starts in");
  for (i=1; i <=10; i++) {
    lcd.setCursor(0,1);
    lcd.print(10-i); lcd.print("  ");
    delay(1000);
  }
  lcd.clear();
  long int sTime = millis();
  long int cTime = millis();
  Serial.println(sTime);
  while (cTime - sTime <= 30000) {
    lcd.setCursor(0,0);
    lcd.print("Calibrating...");
    Serial.println(cTime);
    calibration();
    cTime = millis(); 
  }
}

void loop() {
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Compass Mode:");
  lcd.setCursor(0,1);
  lcd.print(heading());
  delay(300);
}

void calibration() {
  mag->getEvent(&event);
  float x = event.magnetic.x;
  float y = event.magnetic.y;
  float z = event.magnetic.z;
  Serial.print("Mag: (");
  Serial.print(x); Serial.print(", ");
  Serial.print(y); Serial.print(", ");
  Serial.print(z); Serial.print(")");

  min_x = min(min_x, x);
  min_y = min(min_y, y);
  min_z = min(min_z, z);

  max_x = max(max_x, x);
  max_y = max(max_y, y);
  max_z = max(max_z, z);

  mid_x = (max_x + min_x) / 2;
  mid_y = (max_y + min_y) / 2;
  mid_z = (max_z + min_z) / 2;
  Serial.print(" Hard offset: (");

  Serial.print(mid_x); Serial.print(", ");
  Serial.print(mid_y); Serial.print(", ");
  Serial.print(mid_z); Serial.print(")");  

  Serial.print(" Field: (");
  Serial.print((max_x - min_x)/2); Serial.print(", ");
  Serial.print((max_y - min_y)/2); Serial.print(", ");
  Serial.print((max_z - min_z)/2); Serial.println(")");    
  lcd.setCursor(0,1);
  lcd.print((max_x - min_x)/2); lcd.print(" ");
  lcd.print((max_y - min_y)/2); lcd.print(" ");
  lcd.print((max_z - min_z)/2); 
  
  delay(10); 
}

float heading() {
  mag->getEvent(&event);
  float x = event.magnetic.x;
  float y = event.magnetic.y;
  float h;
  h = (atan2(y, x) * 180) / M_PI;
  if ( h < 0 ) h += 360;
  return h;  
}

Calibration is absolutely critical for good performance. You need to move the magnetometer through all possible orientations during the calibration procedure. Try it twice, and if the results are not approximately the same, improve your technique.

However, the Adafruit procedure is very crude and can be substantially improved. This tutorial explains how: