Hi Guys, I am a relatively new Arduino hobbyist, and I have a GY-87 10DOF Sensor working with arduino nano, it has the MPU6050, HMC5883L, and BMP180.
Important detail here is that the magnetometer cannot be accessed directly, it is connected to the external bus of the MPU6050, so data is read through MPU6050's registers allocated to slaves.
Everything is going well, but the z-axis reading for the magnetometer which seems pretty abnormal. It constantly says -6.21 when converted to Gausse. or around 4096 otherwise. I have no idea how big of a unit Gausse is, but according to sources online, it should be 0.2-0.7 Gausse on the earth's surface. Also, the reading does not change at all with a difference in altitude of 2 meters (my usb cable is 1 meter). This might not be all that important, I plan to use these values to build a gyro assisted airplane. Can someone tell me if this value is indeed abnormal or it's perfectly fine?
Here is my code(I dont think something is wrong with it, everything done according to the documentation):
/* When page number is specified, it refers to the register maps of these
modules, comment will refer to page number of the respective module that
is being communicated with i2c.
MPU6050 datasheet: https://invensense.tdk.com/wp-content/uploads/2015/02/MPU-6000-Datasheet1.pdf
MPU6050 register map: https://invensense.tdk.com/wp-content/uploads/2015/02/MPU-6000-Register-Map1.pdf
HMC5883L: https://cdn-shop.adafruit.com/datasheets/HMC5883L_3-Axis_Digital_Compass_IC.pdf*/
#include <Wire.h>
int bmpAddress = 0x77; // BMP180 i2c address 0x77
int compassAddress = 0x1E; // HMC5883L i2c address 0x1E
int mpuAddress = 0x68; // MPU6050 i2c address 0x68
float gForceX, gForceY, gForceZ, rotX, rotY, rotZ, mpuTempC, magnetX, magnetY, magnetZ;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Wire.begin(); // Initialize i2c
Wire.setClock(400000); // Set I2C to 400kHz, if does not work, set to 400000UL
setupMPU();
setupCompass();
}
void loop() {
// put your main code here, to run repeatedly:
recordMPURegisters();
printData();
}
void setupMPU() {
// 0x6B Register 107 - Power management 1, pg 40. 0x00 exit sleep.
i2c_write(mpuAddress, 0x6B, 0x00);
// 0x19 Register 25 – Sample Rate Divider, pg 11-12. 109 sample rate = 8kHz / 110 = 72.7Hz
i2c_write(mpuAddress, 0x19, 109);
// 0x1B Register 27 - Gyroscope Configuration, pg 14. 0x00 gyro full scale = +/- 250 degrees/second
i2c_write(mpuAddress, 0x1B, 0x00);
// 0x1C Register 28 - Accelerometer Configuration, pg 15. 0x00 accelerometer full scale = +/- 2g
i2c_write(mpuAddress, 0x1C, 0x00);
}
void setupCompass() {
// 0x6A Register 106 - User Control, pg 38. 0x00 Disables i2c master mode
i2c_write(mpuAddress, 0x6A, 0x00);
// 0x37 Register 55 - INT Pin/Bypass Enable Configuration, pg 26. 0x02 enables i2c master bypass mode
i2c_write(mpuAddress, 0x37, 0x02);
// 0x00 Register 0 - Configuration Register A, pg 11. 0x18 sample rate = 75Hz
i2c_write(compassAddress, 0x00, 0x18);
// 0x01 Register 1 - Configuration Register B, pg 13. 0x60 full scale = +/- 2.5 Gauss
i2c_write(compassAddress, 0x01, 0x60);
// 0x02 Register 2 - Mode Register, pg 13. 0x00 Continuous measurement mode
i2c_write(compassAddress, 0x02, 0x00);
// 0x37 Register 55 - INT Pin/Bypass Enable Configuration, pg 26. 0x00 disable i2c master bypass mode
i2c_write(mpuAddress, 0x37, 0x00);
// 0x6A Register 106 - User Control, pg 38. 0x20 enable i2c master mode
i2c_write(mpuAddress, 0x6A, 0x20);
// Configure mpu to auto read values from the compass
// 0x25 Register 37 - I2C Slave 0 Control, pg 19-21 !IMPORTANT. 0b10011110 slave 0 i2c address, first bit sets read mode
i2c_write(mpuAddress, 0x25, 0b10011110);
// 0x26 Register 38 - I2C Slave 0 Control, pg 19-21. 0x03 Slave 0 register 3 = 0x03 (x-axis)
i2c_write(mpuAddress, 0x26, 0x03);
// 0x27 Register 39 - I2C Slave 0 Control, pg 19-21. 0b10000110 slave 0 transfer size = 6, 1st bit enables I2C transaction
i2c_write(mpuAddress, 0x27, 0b10000110);
// 0x67 Register 103 - I2C Master Delay Control, pg 36. 1 enable slave 0 delay. If error, try setting 0x80
i2c_write(mpuAddress, 0x67, 1);
}
void recordMPURegisters() {
Wire.beginTransmission(mpuAddress); // I2C address of the MPU
Wire.write(0x3B); // Starting register for Accel Readings
Wire.endTransmission();
Wire.requestFrom(mpuAddress, 20); // Request Accel Registers (3B - 40)
while (Wire.available() < 20)
; // Wait for 20 registers to be available
gForceX = Wire.read() << 8 | Wire.read(); // Store first two bytes into accelX
gForceY = Wire.read() << 8 | Wire.read(); // Store middle two bytes into accelY
gForceZ = Wire.read() << 8 | Wire.read(); // Store last two bytes into accelZ
mpuTempC = Wire.read() << 8 | Wire.read(); // Store the two bytes of mpuTemp
rotX = Wire.read() << 8 | Wire.read(); // Store first two bytes into accelX
rotY = Wire.read() << 8 | Wire.read(); // Store middle two bytes into accelY
rotZ = Wire.read() << 8 | Wire.read(); // Store last two bytes into accelZ
magnetX = Wire.read() << 8 | Wire.read();
magnetZ = Wire.read() << 8 | Wire.read();
magnetY = Wire.read() << 8 | Wire.read();
// Convert accel values
gForceX /= 16384.0;
gForceY /= 16384.0;
gForceZ /= 16384.0;
// Convert temperature to degrees Celsius
mpuTempC = mpuTempC / 340.0 + 36.53;
// Convert Gyro values
rotX /= 131.0;
rotY /= 131.0;
rotZ /= 131.0;
// Values converted to Gauss(see page 13 of hmc5883l documentation)
magnetX /= 660.0;
magnetY /= 660.0;
magnetZ /= 660.0;
}
void printData() {
Serial.print("Temperature = ");
Serial.print(mpuTempC);
Serial.print("\t");
Serial.print("Gyro (deg) X = ");
Serial.print(rotX);
Serial.print("\tY = ");
Serial.print(rotY);
Serial.print("\t Z= ");
Serial.print(rotZ);
Serial.print("\tAccel (g) X = ");
Serial.print(gForceX);
Serial.print("\tY = ");
Serial.print(gForceY);
Serial.print("\tZ = ");
Serial.print(gForceZ);
Serial.print("\t");
Serial.print(magnetX);
Serial.print("\t");
Serial.print(magnetY);
Serial.print("\t");
Serial.println(magnetZ);
}
void i2c_write(uint8_t deviceAddress, uint8_t registerAddress, uint8_t data) {
Wire.beginTransmission(deviceAddress);
Wire.write(registerAddress);
Wire.write(data);
Wire.endTransmission();
}
P.S.If anyone is wondering why i didnt use a library, it's just because this was a good learning experience, and I will be short on storage after implementation of BMP180 and other stuff
This is how my module looks: