LIS3MDL Problems with magnetometer values

Hey All!

I have a problem with this code. I use a LIS3MDL here.
The problem is, that i don´t get correct values.

Maybe I have mistakes in the setup part of the sensor?

Can anybody helps?

#include <Wire.h>



#define Magnetometer_mX0 0x28  
#define Magnetometer_mX1 0x29  
#define Magnetometer_mZ0 0x2A  
#define Magnetometer_mZ1 0x2B  
#define Magnetometer_mY0 0x2C  
#define Magnetometer_mY1 0x2D  
int mX0, mX1, mX_out;
int mY0, mY1, mY_out;
int mZ0, mZ1, mZ_out;
float Xm,Ym,Zm;
int Magnetometer = 0x1E; //I2C 7bit address of HMC5883


void setup() {
  //Initialize Serial and I2C communications
  Serial.begin(9600);
  Wire.begin();
  delay(100);

 Wire.beginTransmission(Magnetometer); 
  Wire.write(0x20); // Select mode register
  Wire.write(0x02); // Continuous measurement mode
  Wire.endTransmission();


  Wire.beginTransmission(Magnetometer); 
  Wire.write(0x22); // Select mode register
  Wire.write(0x00); // Continuous measurement mode
  Wire.endTransmission();

}

void loop() {
 //---- X-Axis
  Wire.beginTransmission(Magnetometer); // transmit to device
  Wire.write(Magnetometer_mX1);
  Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1); 
  if(Wire.available()<=1)   
  {
    mX0 = Wire.read();
  }
  Wire.beginTransmission(Magnetometer); // transmit to device
  Wire.write(Magnetometer_mX0);
  Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1); 
  if(Wire.available()<=1)   
  {
    mX1 = Wire.read();
  }
  //---- Y-Axis
  Wire.beginTransmission(Magnetometer); // transmit to device
  Wire.write(Magnetometer_mY1);
  Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1); 
  if(Wire.available()<=1)   
  {
    mY0 = Wire.read();
  }
  Wire.beginTransmission(Magnetometer); // transmit to device
  Wire.write(Magnetometer_mY0);
  Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1); 
  if(Wire.available()<=1)   
  {
    mY1 = Wire.read();
  }
  
  //---- Z-Axis
  Wire.beginTransmission(Magnetometer); // transmit to device
  Wire.write(Magnetometer_mZ1);
  Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1); 
  if(Wire.available()<=1)   
  {
    mZ0 = Wire.read();
  }
  Wire.beginTransmission(Magnetometer); // transmit to device
  Wire.write(Magnetometer_mZ0);
  Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1); 
  if(Wire.available()<=1)   
  {
    mZ1 = Wire.read();
  }
  
  //---- X-Axis
  mX1=mX1<<8;
  mX_out =mX0+mX1; // Raw data
  // From the datasheet: 0.92 mG/digit
  Xm = mX_out*0.00092; // Gauss unit
  //* Earth magnetic field ranges from 0.25 to 0.65 Gauss, so these are the values that we need to get approximately.
  //---- Y-Axis
  mY1=mY1<<8;
  mY_out =mY0+mY1;
  Ym = mY_out*0.00092;
  //---- Z-Axis
  mZ1=mZ1<<8;
  mZ_out =mZ0+mZ1;
  Zm = mZ_out*0.00092;
 
  //Print out values of each axis
  Serial.print("x: ");
  Serial.print(mX_out);
  Serial.print("  y: ");
  Serial.print(mY_out);
  Serial.print("  z: ");
  Serial.println(mZ_out);
  
  delay(100);

}

please help me

you say you arn’t getting correct values, but didn’t give any examples of what values you ARE getting.

one thing thats jumping out at me right away, is your ‘Wire.available()’ requests.

1  Wire.requestFrom(Magnetometer,1); 
2    if(Wire.available()<=1)   
3    {
4      mX0 = Wire.read();
5    }

in the above:
line 1, is asking the magnetometor to send data
line 2, is saying "if the available information on the wire is less than or equal to 1, then read it.
line 4, which is only triggering when there is EXACTLY 1 byte of data on the wire, reads that one byte.

as such, it LOOKS LIKE the system is reading that first byte of data that comes in, then never reads any more because there is probably going to be more than the 1 byte of data it’s interested in.

try changing line 2 to:

if(Wire.available()>=1)

that SHOULD allow it to read the incomming data.

a more common method of reading from the I2C interface that i’ve seen, is to read each character in, and append it to a string until there is no further data on the bus, this does a coouple of things.
first, it allows slave devices to send multiple sets of data in one discreet transmission
second it clears the slave’s buffer
third it ensures that when the master wants to talk to a slave device, that device isn’t still tying up the lines.

unfortunately, reading all the data into a string before processing it means you do in fact have to then PROCESS the data… which can get complicated.

Hi Kalnedrilith!

Thanks for you answer. So I think I have the solution. The function less than or equal 1 seems to be right.

Look at Wire.write, I used mX1 and in Wire.read mX0. I changed to mx1 in Wire.read and now I have correct values.

Its strange because the sketch was correct for another magnetometer?!

Greetings

heads up on that, looking closer, it looks like you're dealing with a magnetometer that's sending 2 bytes of data, the value you're looking at might be the least significant byte, but without the other one, you limit how high the sensor can go...

looks a LOT like my magnetometer..

take a look at the code on https://www.sparkfun.com/tutorials/301

it handles combining least and most significant bytes... (also handles getting all 3 axis

You have mentioned in your code that I2C address as 0x1E as that of HMC5883. So, you can also refer this code also to check the order in which the commands can work for you.HMC5883 Arduino code. You can change the register values as per the datasheet for your magnetometer.