ITG-3200 strange readings

Hello,

I’m new to Arduino coding. I’m currently working with the ITG-3200 gyro (with I2C interface) and using the sample code provided here: https://www.sparkfun.com/products/11977 with some modifications (my code is at the bottom of this message).
I’m trying to do a basic read of the value in each axis and display it on the PC screen via a serial connection.
I’m reading the WHO_I_AM register fine, which means that my connections are good and the basic communication is working properly.
When I try to read the axis data and print it to the screen (which is supposed to be 16bit), I get a much longer hexadecimal output, with the first chars all ‘F’ and only the last few chars changing. When I move the gyro, I sometime get a 2-char result (in HEXA). What am I doing wrong?

Also, in the original reference, they’re using the following method (instead of simply reading the result), but when I tried it I get a constant 0. I couldn’t understand the purpose of this calculation.

int xRate, yRate, zRate;
float range = 3000.0;
int divisor;

divisor = range / 8;

//Read the x,y and z output rates from the gyroscope.
xRate = int(float(readX()) / divisor - 0.5) * -1;
yRate = int(float(readY()) / divisor - 0.5) * -1;
zRate = int(float(readZ()) / divisor - 0.5);

My code:

#include <SPI.h>
#include <Wire.h>

//This is a list of registers in the ITG-3200.
char WHO_AM_I = 0x00;
char SMPLRT_DIV= 0x15;
char DLPF_FS = 0x16;
char GYRO_XOUT_H = 0x1D;
char GYRO_XOUT_L = 0x1E;
char GYRO_YOUT_H = 0x1F;
char GYRO_YOUT_L = 0x20;
char GYRO_ZOUT_H = 0x21;
char GYRO_ZOUT_L = 0x22;

//This is a list of settings that can be loaded into the registers.
//DLPF, Full Scale Register Bits
//FS_SEL must be set to 3 for proper operation
//Set DLPF_CFG to 3 for 1kHz Fint and 42 Hz Low Pass Filter
//Set DLPF_CFG to
char DLPF_CFG_0 = 1;
char DLPF_CFG_1 = 2;
char DLPF_CFG_2 = 4;
//Set FS_SEL to b11
char DLPF_FS_SEL_0 = 8;
char DLPF_FS_SEL_1 = 16;

char itgAddress = 0x69; //device address b1101001

void setup() {
Serial.begin(9600); //Initiate serial communication
Wire.begin(); // join i2c bus

//Read the WHO_AM_I register and print the result
char id=0;
id = itgRead(itgAddress, 0x00);
Serial.print("ID: ");
Serial.println(id, HEX);

//Configure the gyroscope
//Set the gyroscope scale for the outputs to +/-2000 degrees per second
itgWrite(itgAddress, DLPF_FS, (DLPF_FS_SEL_0|DLPF_FS_SEL_1|DLPF_CFG_1|DLPF_CFG_0));
//Set the sample rate to 100 hz
itgWrite(itgAddress, SMPLRT_DIV, 9); //Fsample = Finternal / (divider+1) = 1Khz/(9+1) = 100hz
}

void loop() {

//Read the WHO_AM_I register and print the result
char Xdata = 0;
char Ydata = 0;
char Zdata = 0;
Xdata = readX();
Ydata = readY();
Zdata = readZ();

Serial.print("X: ");
Serial.println(Xdata, HEX);

/* Serial.print("Y: ");
Serial.println(Ydata, HEX);
Serial.print("Z: ");
Serial.println(Zdata, HEX); */
delay(100);

}

// This function will write a value to a register on the itg-3200.
// Parameters:
// char address: The I2C address of the sensor. For the ITG-3200 breakout the address is 0x69.
// char registerAddress: The address of the register on the sensor that should be written to.
// char data: The value to be written to the specified register.
void itgWrite(char address, char registerAddress, char data)
{
//Initiate a communication sequence with the desired i2c device
Wire.beginTransmission(address);
//Tell the I2C address which register we are writing to
Wire.write(registerAddress);
//Send the value to write to the specified register
Wire.write(data);
//End the communication sequence
Wire.endTransmission();
}

//This function will read the data from a specified register on the ITG-3200 and return the value.
//Parameters:
// char address: The I2C address of the sensor. For the ITG-3200 breakout the address is 0x69.
// char registerAddress: The address of the register on the sensor that should be read
//Return:
// unsigned char: The value currently residing in the specified register
unsigned char itgRead(char address, char registerAddress)
{
//This variable will hold the contents read from the i2c device.
unsigned char data=0;

//Send the register address to be read.
Wire.beginTransmission(address);
//Send the Register Address
Wire.write(registerAddress);
//End the communication sequence.
Wire.endTransmission();

//Ask the I2C device for data
Wire.beginTransmission(address);
Wire.requestFrom(address, 1);

//Wait for a response from the I2C device
if(Wire.available()){
//Save the data sent from the I2C device
data = Wire.read();
}

//End the communication sequence.
Wire.endTransmission();

//Return the data read during the operation
return data;
}

//This function is used to read the X-Axis rate of the gyroscope. The function returns the ADC value from the Gyroscope
//NOTE: This value is NOT in degrees per second.
//Usage: int xRate = readX();
int readX(void)
{
int data=0;
data = itgRead(itgAddress, GYRO_XOUT_H)<<8;
data |= itgRead(itgAddress, GYRO_XOUT_L);

return data;
}

//This function is used to read the Y-Axis rate of the gyroscope. The function returns the ADC value from the Gyroscope
//NOTE: This value is NOT in degrees per second.
//Usage: int yRate = readY();
int readY(void)
{
int data=0;
data = itgRead(itgAddress, GYRO_YOUT_H)<<8;
data |= itgRead(itgAddress, GYRO_YOUT_L);

return data;
}

//This function is used to read the Z-Axis rate of the gyroscope. The function returns the ADC value from the Gyroscope
//NOTE: This value is NOT in degrees per second.
//Usage: int zRate = readZ();
int readZ(void)
{
int data=0;
data = itgRead(itgAddress, GYRO_ZOUT_H)<<8;
data |= itgRead(itgAddress, GYRO_ZOUT_L);

return data;
}

Thanks in advance

  xRate = int(float(readX()) / divisor - 0.5) * -1;
  yRate = int(float(readY()) / divisor - 0.5) * -1;
  zRate = int(float(readZ()) / divisor - 0.5);

The WTF light exploded.

  char Xdata = 0;
  char Ydata = 0;
  char Zdata = 0;
  Xdata = readX();
  Ydata = readY();
  Zdata = readZ();

The readX(), readY(), and readZ() functions return ints. It is stupid to loose half the data by storing the int in a char.

Then, casting the char to a float, doing the division, and then casting the result as an int is pointless. Why do you want to lose the precision by doing that?

Use the appropriate types.

Hi,

I changed the data types to int but the result hasn’t changed. Attached is a print screen of the data I’m getting. The updated code is below. How can I fix it?

Thanks

#include <SPI.h>
#include <Wire.h>

//This is a list of registers in the ITG-3200.
char WHO_AM_I = 0x00;
char SMPLRT_DIV= 0x15;
char DLPF_FS = 0x16;
char GYRO_XOUT_H = 0x1D;
char GYRO_XOUT_L = 0x1E;
char GYRO_YOUT_H = 0x1F;
char GYRO_YOUT_L = 0x20;
char GYRO_ZOUT_H = 0x21;
char GYRO_ZOUT_L = 0x22;

//This is a list of settings that can be loaded into the registers.
//DLPF, Full Scale Register Bits
//FS_SEL must be set to 3 for proper operation
//Set DLPF_CFG to 3 for 1kHz Fint and 42 Hz Low Pass Filter
//Set DLPF_CFG to
char DLPF_CFG_0 = 1;
char DLPF_CFG_1 = 2;
char DLPF_CFG_2 = 4;
//Set FS_SEL to b11
char DLPF_FS_SEL_0 = 8;
char DLPF_FS_SEL_1 = 16;

char itgAddress = 0x69; //device address b1101001

void setup() {
Serial.begin(9600); //Initiate serial communication
Wire.begin(); // join i2c bus

//Read the WHO_AM_I register and print the result
char id=0;
id = itgRead(itgAddress, 0x00);
Serial.print("ID: ");
Serial.println(id, HEX);

//Configure the gyroscope
//Set the gyroscope scale for the outputs to +/-2000 degrees per second
itgWrite(itgAddress, DLPF_FS, (DLPF_FS_SEL_0|DLPF_FS_SEL_1|DLPF_CFG_1|DLPF_CFG_0));
//Set the sample rate to 100 hz
itgWrite(itgAddress, SMPLRT_DIV, 9); //Fsample = Finternal / (divider+1) = 1Khz/(9+1) = 100hz
}

void loop() {

//Read the WHO_AM_I register and print the result
int Xdata = 0;
int Ydata = 0;
int Zdata = 0;
Xdata = readX();
Ydata = readY();
Zdata = readZ();

Serial.print("X: ");
Serial.println(Xdata, HEX);

/* Serial.print("Y: ");
Serial.println(Ydata, HEX);
Serial.print("Z: ");
Serial.println(Zdata, HEX); */
delay(100);

}

// This function will write a value to a register on the itg-3200.
// Parameters:
// char address: The I2C address of the sensor. For the ITG-3200 breakout the address is 0x69.
// char registerAddress: The address of the register on the sensor that should be written to.
// char data: The value to be written to the specified register.
void itgWrite(char address, char registerAddress, char data)
{
//Initiate a communication sequence with the desired i2c device
Wire.beginTransmission(address);
//Tell the I2C address which register we are writing to
Wire.write(registerAddress);
//Send the value to write to the specified register
Wire.write(data);
//End the communication sequence
Wire.endTransmission();
}

//This function will read the data from a specified register on the ITG-3200 and return the value.
//Parameters:
// char address: The I2C address of the sensor. For the ITG-3200 breakout the address is 0x69.
// char registerAddress: The address of the register on the sensor that should be read
//Return:
// unsigned char: The value currently residing in the specified register
unsigned char itgRead(char address, char registerAddress)
{
//This variable will hold the contents read from the i2c device.
unsigned char data=0;

//Send the register address to be read.
Wire.beginTransmission(address);
//Send the Register Address
Wire.write(registerAddress);
//End the communication sequence.
Wire.endTransmission();

//Ask the I2C device for data
Wire.beginTransmission(address);
Wire.requestFrom(address, 1);

//Wait for a response from the I2C device
if(Wire.available()){
//Save the data sent from the I2C device
data = Wire.read();
}

//End the communication sequence.
Wire.endTransmission();

//Return the data read during the operation
return data;
}

//This function is used to read the X-Axis rate of the gyroscope. The function returns the ADC value from the Gyroscope
//NOTE: This value is NOT in degrees per second.
//Usage: int xRate = readX();
int readX(void)
{
int data=0;
data = itgRead(itgAddress, GYRO_XOUT_H)<<8;
data |= itgRead(itgAddress, GYRO_XOUT_L);

return data;
}

//This function is used to read the Y-Axis rate of the gyroscope. The function returns the ADC value from the Gyroscope
//NOTE: This value is NOT in degrees per second.
//Usage: int yRate = readY();
int readY(void)
{
int data=0;
data = itgRead(itgAddress, GYRO_YOUT_H)<<8;
data |= itgRead(itgAddress, GYRO_YOUT_L);

return data;
}

//This function is used to read the Z-Axis rate of the gyroscope. The function returns the ADC value from the Gyroscope
//NOTE: This value is NOT in degrees per second.
//Usage: int zRate = readZ();
int readZ(void)
{
int data=0;
data = itgRead(itgAddress, GYRO_ZOUT_H)<<8;
data |= itgRead(itgAddress, GYRO_ZOUT_L);

return data;
}

Capture.JPG

You still haven't learned how to post code properly. I'm done until you do.

Do NOT post pictures of text. It wastes bandwidth unnecessarily.

Why are you printing the X, Y, and Z values in HEX?

I'm sorry, where can I find instructions for proper posting?

HEX was just a random choice, all I need is to transmit the values to the PC (and use the serial monitor for debugging).

dvido: I'm sorry, where can I find instructions for proper posting?

There are three stickies at the top of the forum. THIS is the one you need to read. How to use this forum - please read.

and use the serial monitor for debugging

Would you convert each digit in the value to some wingdings character, to make things easier to understand? Of course not. Print the values in the base that matches the number of fingers you have.