0

This module has 3 sensors. Gyroscope, Accelerometer and Magnetometer.

I think I'm reading the raw data in the wrong way.

For example, for the magnetometer HMC5883L, I'm using this code which I copied from a library and it gives the correct values, but when I use the same code for reading the raw data from the accelerometer ADXL345 then it's not what it should be according to different sources I've read.

  1. The magnetometer HMC5883L:

    void HMC5883L_print_Serial(void)
    {
      int16_t x,z,y;
      uint8_t data[6];
      float heading,heading_in_degrees,declination_angle_YANBU;
    
      data_read(data);
    
      // This one doesn't
      x = data[1] << 8 | data[0];
      z = data[3] << 8 | data[2];
      y = data[5] << 8 | data[4]; 
    
      // This one works OK
      /*x = data[0] << 8 | data[1];
      z = data[2] << 8 | data[3];
      y = data[4] << 8 | data[5];*/
    
      heading = atan2(y,x);
      declination_angle_YANBU = ((3.0 + (52.0 / 60.0)) / (180 / M_PI));  // in yanbu city it's 
      heading += declination_angle_YANBU;
    
      // Correct for heading < 0deg and heading > 360deg
      if (heading < 0){
        heading += 2 * PI;
      }
    
      if (heading > 2 * PI){
        heading -= 2 * PI;
      } 
    
      heading_in_degrees = heading * 180 / M_PI;
      Serial.println(heading_in_degrees);
      _delay_ms(20);  
    
    }
    
  2. The accelerometer ADXL345

    void ADXL345_print_Serial(void){
      int16_t x,z,y;
      uint8_t data[6];
    
      ADXL345_read_raw(data);
    
      // This one gives values from -255 to +255
      x = data[1] << 8 | data[0];
      z = data[3] << 8 | data[2];
      y = data[5] << 8 | data[4];
    
      // This one give values from -32768 to +32768
      /*x = data[0] << 8 | data[1];
      z = data[2] << 8 | data[3];
      y = data[4] << 8 | data[5];*/
        Serial.print(x);Serial.print("\t");
        Serial.print(y);Serial.print("\t");
        Serial.println(z);
        _delay_ms(100);
    }
    

So basically I want to learn how to work with these sensors and also I want to know the principles about each one, because I'm confused between then I feel they are the same and each one provides similar functions; like, tilt sensing.

4
  • 1
    One gives you an absolute orientation using the earth's magnetic field. The other gives you changes in velocity (and gravitational pull, which is a form of acceleration). In what way are they the same?
    – Majenko
    Nov 26, 2018 at 0:00
  • 1
    Have you looked at the ADXL345 datasheet to see what the communication protocol is? Is it the same as for the HMC5883L? Or should you be implementing a different system?
    – Majenko
    Nov 26, 2018 at 0:02
  • Hi, they both use I2C protocol. All the sensors on that board use the same protocol. You're right they are different but I thought it's like similar, because they change the values when tilting! That confuses me because; for example, the accelerometer should change the values only when I move it forward, backward and up-down, so it also changes the values when I flip or tilt it .. that was confusing.
    – R1S8K
    Nov 26, 2018 at 5:31
  • OK, I started to understand the the accelerometer is actually measuring the static gravity values, that's why it gives values on each side of the module. The internal mass is tilting positions. So, I just now have to understand how to know how to prepare these values for my project.
    – R1S8K
    Nov 26, 2018 at 8:15

1 Answer 1

1

One of the places where the datasheets for the sensors of the GY-85 module can be found is here: https://www.hotmcu.com/gy85-9dof-imu-sensor-module-p-298.html
The following information comes from these datasheets:

Both the HMC5883L and the ADXL345 have internal registers which are numbered consecutively. When reading more than one register they are most efficiently read in the order they are numbered. For each of the three axes both sensors use two 8-bit registers to hold the measured value.

In the HMC5883L the register with the lower number holds the most significant byte (MSB) and the register with the higher number holds the least significant byte (LSB). This means that in a consecutive read the MSB is read first followed bij the LSB. When you combine these two bytes into one 16 bit number (datatype int) you have to shift the MSB-holding byte (the first byte received) 8 places to the left and "OR-in" the LSB-holding byte (the second byte received).
In the ADXL345 the internal numbering is the other way around: the register with the lower number holds the LSB and the register with the higher nummer holds the MSB. When reading, the LSB is red first followed by the MSB. So this time you have to shift the second byte received and "OR-in" the first byte received.

Both sensors give the measured value as a 16-bit 2-complement number, corresponding to datatype int (Arduino Uno). An 16-bit int can hold values from -32,768 to +32,767 but the sensors don't (can't) use this full range:
The ADXL345 has an adjustable range with a maximum of 13 bits (-4096 to +4095).
The HMC5883L has a range of 12 bits (-2048 to +2047).

3
  • OK, then my current HMC5883L is wrong. I put the first byte on the right of the 16-bit register. As in this code: x = data[1] << 8 | data[0]; z = data[3] << 8 | data[2]; y = data[5] << 8 | data[4]; But I have to change it.
    – R1S8K
    Dec 12, 2018 at 20:13
  • Success! Please let us know if if you new code works.
    – PimV
    Dec 12, 2018 at 20:21
  • Yeah it's working now. My current concern is that I know that taking the atan2(y,x); would give me the heading. But what is the benefit of z-axis? And how can I use the HMC5883L in a quadcopter?
    – R1S8K
    Dec 13, 2018 at 2:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.