The GY-9255 sensor uses MPU-9255 chip. The MPU9255 is a 9-axis sensor which packages the accelerometer, gyroscope, magnetometer together each provides data for x, y and z axes. Other than the three mentioned sensors, it also has other features like Pedometer, Motion and Tap detection, and Temperature (if I recall correctly).
Explanation of the pins:
- VCC: This pin goes to 3.3 volt pin of the Arduino
- GND: This pin goes to GND pin
- SCL: Clock line for I2C or SPI communication. I use it as I2C which connects to pin 5 of the Arduino or pin 21 of the Mega 2560. In SPI mode this is the clock line.
- SDA: Data line for I2C or SPI. For I2C it connects to Arduino pin 4 or Mega 2560 pin 20. For SPI it is data input line.
- EDA and ECL: These two pins are for serial communication to external sensor or device.
- ADO: In I2C mode, it is used to define the address of the sensor. In SPI mode, this is data output line.
- INT: Interrupt line where the sensor can notify the Arduino when data is ready or motion is detected, depending on the configuration.
- nCS: Chip select pin, used in SPI mode.
- FSYNC: Can be used for different purposes depending on the configuration.
Summing up on the pins, to get this device working in I2C mode, pins VCC, GND, SCL, SDA, ADO and FSYNC are used. Before going into programming, I want to briefly mention a little information about the device. There are two specification for the MPU-9255 that you may want to read. The first one is the MPU-9255 Product Specification (PS-MPU-9255) and the second one is the MPU-9255 Register Map and Description (RM-MPU-92551). In general you would need the Register Map document most but there are scattered information in the Product Specification that you would need. First lets look at the block diagram of the MPU-9255:
There is one thing I want to point out in the diagram above. It has the master I2C and Slave I2C. The master I2C connects to the AUX_CL and AUX_DA (which are the ECL and EDA pins) through the Serial Interface Bypass Mux. When enabled, the master I2C talks to the external sensor that is connected to AUX_CL and AUX_DA, feed to data register to be read from the SCL and SDA lines. When disabled, aka the Serial Interface Bypass Mux is set to bypass mode, the external sensor's data go directly to the SDA line. The compass sensor is really the "external sensor" according to the block diagram. In this tutorial, I will disable the master I2C and have the Arduino or Mega board talking to the magnetometer directly. In the I2C mode, the ADO pin is used as part of the sensor address designation. When ADO grounded (LOW) the sensor address is 0x68 and when pulled up to VDD (HIGH) the address is 0x69.
Steps to configure the sensor:
- Initialize the Power Management Register 0x6B
- Configure User Control Register 0x6A to disable master I2C
- Configure Interrup Configuration Register 0x37 to bypass master I2C
- Setup magnetic sensor's Control Register 0x0A to take continuous measurement.
Arduino has the I2C library called Wire that does all of the heavy labor. To read the sensor you need to specify the address of the sensor and the register where data to be read. To write to the sensor you will need address of the sensor, the register to write to and the value. Here I write the two functions so that they can be used in the code.
byte read(int reg)
{
Wire.beginTransmission(0x68); // starting the transmission to sensor address 0x68
Wire.write(reg);
Wire.endTransmission(false);
Wire.requestFrom(0x68, 1, false); // requestone byte of data
byte val = Wire.read();
Wire.endTransmission(true);
return val;
}
void write(int reg, int data)
{
Wire.beginTransmission(0x68); // starting the transmission to sensor address 0x68
Wire.write(reg);
Wire.write(data);
Wire.endTransmission(true);
}
Since I use bypass mode, the Arduino will talk to the magnetic sensor directly. Thus I need the read and write for the magnetic sensor also. The magnetic sensor address is 0x0C (from the Product Specification).
byte readMag(int reg)
{
Wire.beginTransmission(0x0C);
Wire.write(reg);
Wire.endTransmission(false);
Wire.requestFrom(0x0C, 1, false); // requestone byte of data
byte val = Wire.read();
Wire.endTransmission(true);
return val;
}
void writeMag(int reg, int data)
{
Wire.beginTransmission(0x0C);
Wire.write(reg);
Wire.write(data);
Wire.endTransmission(true);
}
The main code:
#include <Wire.h>readMag(0x09); //This tells the Mag Module to take another measurement.
void setup()
{
Serial.begin(115200); // Setup serial output to 115.2k
Wire.begin(); // Initialize I2C communication
write(0x6B, 0); //Initialize Power Manager Register to 0
write(0x6A, 0); // Disable master I2C, enable value is 0x20, so disable it should be just bit 5 = 0, since I don't use other bits and they are all 0.
write(0x37, 0x02); // Enable bypass mode
writeMag(0x0A, 0x12); // Setup magnetic sensor to measure contiuously.
}
void loop()
{
int xh = readMag(0x04); // read x axis, high byte
int xl = readMag(0x03); // read x axis, lowbyte
int yh = readMag(0x06);
int yl = readMag(0x05);
int zh = readMag(0x08);
int zl = readMag(0x07);
// Combine the valuesGoodluck on your project!
int x = (xh << 8) | (xl & 0xff);
int y = (yh << 8) | (yl & 0xff);
int z = (zh << 8) | (zl & 0xff);
// Print out
Serial.print("X,Y,Z=");
Serial.print(x);
Serial.print(",");
Serial.print(y);
Serial.print(",");
Serial.println(z);
// delay(1000);
}