Gyro I2C

Hello, I am new to Arduino and I bought a Mega 2560 to use as a rocket controller. I want to get data from a 10-DOF gyroscope from Waveshare http://www.waveshare.com/wiki/10_DOF_IMU_Sensor_(B)

I connected the pins and tried to run this code, but the printout displays -1 (no data?)

#include <Wire.h>
byte x = 0x00;

void setup() {
        
        Wire.begin();
        Serial.begin(9600);
        
}

void loop() {
        
        Wire.beginTransmission(0xD0);
        Wire.write(0x44);
        Wire.write(1);
        Wire.endTransmission();
        
        Wire.requestFrom(0xD0, 1);
        int x = Wire.read();
        Serial.print(x);
        delay(1000);
        
}

Please help, I tried to look through the original code for the module to find a way to get the arduino to read the data, but it's very complicated. All I have found so far is a list of I2C addresses.
Thanks

The first thing that I would do is run an I2C scanner to confirm the device address and communication.

// I2C scanner by Nick Gammon.  Thanks Nick.

#include <Wire.h>

void setup() {
  Serial.begin (115200);

  // Leonardo: wait for serial port to connect
  while (!Serial) 
    {
    }

  Serial.println ();
  Serial.println ("I2C scanner. Scanning ...");
  byte count = 0;
  
  Wire.begin();
  for (byte i = 1; i < 120; i++)
  {
    Wire.beginTransmission (i);
    if (Wire.endTransmission () == 0)
      {
      Serial.print ("Found address: ");
      Serial.print (i, DEC);
      Serial.print (" (0x");
      Serial.print (i, HEX);
      Serial.println (")");
      count++;
      delay (1);  // maybe unneeded?
      } // end of good response
  } // end of for loop
  Serial.println ("Done.");
  Serial.print ("Found ");
  Serial.print (count, DEC);
  Serial.println (" device(s).");
}  // end of setup

void loop() {}

It found two addresses, 0x68 and 0x77. When I put them into my code, it just prints 0. Which is better than -1 :slight_smile:

Do a Google search for "arduino mpu9255". I think code for a mpu9250 will work for you, as well.

This might help.

Thank you that really helped!

Just one small question, in some of the very complicated official code from the Waveshare site (not the one you just showed me), it defines a bunch of addresses and the each have a high/low thing. What does high and low mean??

#define GYRO_XOUT_H 0x43
#define GYRO_XOUT_L 0x44
#define GYRO_YOUT_H 0x45
#define GYRO_YOUT_L 0x46
#define GYRO_ZOUT_H 0x47
#define GYRO_ZOUT_L 0x48

Those are the gyro data register addresses. The registers are 1 byte wide. Each reading is an int data type (2 bytes) the high or most significant byte and the low or least significant byte. To combine them back into an int, multiply the MSB by 256 and add the LSB.

The MPu9255/MPU9250 (different manometer) has a MPU6050 and a compass chip in one. the compass is linked to the MPU9055 the same way as you would if you had the MPU6050 and compass as separate chips( secondary i2c link from the MPU6050 to the manometer). So with that in mind the incredible library by by Jeff Rowberg has tons of examples that can help you access all the features available in the MPU9055. I have both the MPU6050 and the MPU9055 And can access all the features with that library including the compass. as for the altimeter you will access it directly with separate code :slight_smile:

Library: i2cdevlib/Arduino/MPU6050 at master · jrowberg/i2cdevlib · GitHub

What is the theory behind MSB and LSB? Is it that 1 byte can only be 256 which would be a crap 'resolution' for something like a gyro? Therefore two bytes are written to form a bigger number?

Also, what does something like uint8_t mean??

"unsigned int 8-bit type"

Yes, 1 byte is not enough resolution.

MSB and LSB
Most Significant Byte and least significant Byte
256 * 256 = 65,535
MSB * LSB = int
uint8_t * uint8_t = uint16_t

i2c only sends 8 bit values so you have to re-combine them at the other end :slight_smile:

1 byte can be 0 to 255, 0x00 to 0xFF.
256*256 != 65,535, it is 65,536, which is Not 0xFFFF
(255<<8 ) + 255 = 65,535 // shift MSB into upper 8 bits, add LSB into lower 8 bits
or (255 *256) + 255
or
(uint8_t * 0x100) + uint8_t = uint16_t
(uint8_t <<8 ) + uint8_t = uint16_t

My apologies,
I miss understood terminology.
They were talking about sensor resolutions which looks to me to be 16 bit.

void MPU6050::getRotation(int16_t* x, int16_t* y, int16_t* z) {
    I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_XOUT_H, 6, buffer);
    *x = (((int16_t)buffer[0]) << 8) | buffer[1];
    *y = (((int16_t)buffer[2]) << 8) | buffer[3];
    *z = (((int16_t)buffer[4]) << 8) | buffer[5];
}

What does the vertical line mean in that code?

What is the point in that!?!

It ORs the LSB with the shifted MSB effectively adding the LSB to (256 times) the MSB.

x = (((int16_t)buffer[0]) << 8) | buffer[1];

buffer[0] is 8 bit or uint8_t
buffer[1] is 8 bit or uint8_t

<< 8

tells us to shift the buffer[0] over 8 bits and stick it into a 16 bit int (int16_t) that is signed
11001101 now == 1100110100000000

   | buffer[1];

Bitwise OR (|)

The bitwise OR operator in C++ is the vertical bar symbol, |. Like the & operator, | operates independently each bit in its two surrounding integer expressions, but what it does is different (of course). The bitwise OR of two bits is 1 if either or both of the input bits is 1, otherwise it is 0. In other words:

so here's the math

buffer[0] = 11001101
buffer[1] = 11110001

1100110100000000 (int) buffer[0] << 8
        11110001 (byte) buffer[1]
 ----------
1100110111110001 (buffer[0] << 8 | buffer[1]) - returned result is a 16 bit int

Ohhh thank you very much. I didn't realize that the << 8 shifted the MSB up by 8. So I was wondering why you would want to merge two bytes XD. What is the highest that a gyro axis output can reach?

Gyroscope Features
Digital-output X-, Y-, and Z-Axis angular rate sensors (gyroscopes) with a user-programmable full scale range of ±250, ±500, ±1000, and ±2000°/sec
External sync signal connected to the FSYNC pin supports image,

Accelerometer Features
Digital-output triple-axis accelerometer with a programmable full scale range of ±2g, ±4g, ±8g and ±16g 
Integrated 16-bit ADCs enable simultaneous sampling of accelerometers while requiring no external multiplexer

Datasheet:
http://forum.arduino.cc/index.php?action=post;topic=412328.0;last_msg=2842650

So I was wondering why you would want to merge two bytes

its simple the communication protocol only uses transfers in 8 bits. so if you need a higher number than 255 you need to add more bits to the byte making it an int. and then if you need more you could add 4 bytes together to make a long

I made this quick code to see if I could get the temperature data, it just prints 0's

#include <Wire.h>

#define MPU             0x68      //Main address

#define CONF_SAMPRATE   0x19      //Addresses for configuration write registers
#define CONF_PASS       0x1A
#define CONF_GYROSCALE  0x1B
#define CONF_ACCELSCALE 0x1C

#define ACCEL_X_H       0x3B      //Accelerometer registers
#define ACCEL_X_L       0x3C
#define ACCEL_Y_H       0x3D
#define ACCEL_Y_L       0x3E
#define ACCEL_Z_H       0x3F
#define ACCEL_Z_L       0x40

#define TEMP_H          0x41      //Temperature registers
#define TEMP_L          0x42

#define GYRO_X_H        0x43      //Gyro registers
#define GYRO_X_L        0x44  
#define GYRO_Y_H        0x45
#define GYRO_Y_L        0x46
#define GYRO_Z_H        0x47
#define GYRO_Z_L        0x48

    
#define MAG_X_L         0x03      //Magnetometer registers
#define MAG_X_H         0x04
#define MAG_Y_L         0x05
#define MAG_Y_H         0x06
#define MAG_Z_L         0x07
#define MAG_Z_H         0x08



void writedata(uint8_t Add, uint8_t Reg, uint8_t Data)    //function for sending data by I2C

  {
    Wire.beginTransmission(Add);
    Wire.write(Reg);
    Wire.write(Data);
    Wire.endTransmission();
  }


void readdata( uint8_t Add, uint8_t Reg, uint8_t N, uint8_t Var)  //function for reading data from I2C

  {
    
    Wire.beginTransmission(Add);
    Wire.write(Reg);
    Wire.endTransmission();

    Wire.requestFrom(Add, N);
    while(Wire.available()){
      Var=Wire.read();
    }
  
  }

void setup()
{
  
  Wire.begin();
  Serial.begin(115200);
  
  writedata(MPU, CONF_SAMPRATE, 0x07);
  writedata(MPU, CONF_PASS, 0x06);
  writedata(MPU, CONF_GYROSCALE, 0x08);
  writedata(MPU, CONF_ACCELSCALE, 0x08);
  
}

void loop()
{
  
  uint8_t temph = 0;
  uint8_t templ = 0;
  readdata(MPU, TEMP_H, 1, temph);
  readdata(MPU, TEMP_L, 1, templ);
  int16_t temp = (temph << 8 | templ);
  Serial.println(temp);
  delay(100);
  
}