Communication between a Gyro and Arduino

Hey everyone,

How are you all doing today? I have posted here regarding my autonomous Quadcopter project I have going with a professor on campus. With this project we have decided to design the flight system from the ground up in order to better understand autonomous GNC systems.

So at this stage in the project I am trying to extract the output of a Gyro we have (Tri-Axis Gyro Breakout - L3G4200D) and have the Arduino print out the angular rates. Right now I’m looking at this code:

#include <Wire.h>

#define CTRL_REG1 0x20
#define CTRL_REG2 0x21
#define CTRL_REG3 0x22
#define CTRL_REG4 0x23

int Addr = 105;                 // I2C address of gyro
int x, y, z;

void setup(){
  Wire.begin();
  Serial.begin(9600);
  writeI2C(CTRL_REG1, 0x1F);    // Turn on all axes, disable power down
  writeI2C(CTRL_REG3, 0x08);    // Enable control ready signal
  writeI2C(CTRL_REG4, 0x80);    // Set scale (500 deg/sec)
  delay(100);                   // Wait to synchronize 
}

void loop(){
  getGyroValues();              // Get new values
  // In following Dividing by 114 reduces noise
  Serial.print("Raw X:");  Serial.print(x / 114);  
  Serial.print(" Raw Y:"); Serial.print(y / 114);
  Serial.print(" Raw Z:"); Serial.println(z / 114);
  delay(500);                   // Short delay between reads
}

void getGyroValues () {
  byte MSB, LSB;

  MSB = readI2C(0x29);
  LSB = readI2C(0x28);
  x = ((MSB << 8) | LSB);

  MSB = readI2C(0x2B);
  LSB = readI2C(0x2A);
  y = ((MSB << 8) | LSB);

  MSB = readI2C(0x2D);
  LSB = readI2C(0x2C);
  z = ((MSB << 8) | LSB);
}

int readI2C (byte regAddr) {
    Wire.beginTransmission(Addr);
    Wire.write(regAddr);                // Register address to read
    Wire.endTransmission();             // Terminate request
    Wire.requestFrom(Addr, 1);          // Read a byte
    while(!Wire.available()) { };       // Wait for receipt
    return(Wire.read());                // Get result
}

void writeI2C (byte regAddr, byte val) {
    Wire.beginTransmission(Addr);
    Wire.write(regAddr);
    Wire.write(val);
    Wire.endTransmission();
}

And I was just wondering if any of you could tell me what the “writeI2c” command and the “getgyrovalues()” command are doing. I can’t seem to find any documentation regarding them.

As a side note, I JUST found this code:

/* L3G4200D 3-axis gyro example code
  by: Jim Lindblom
  SparkFun Electronics
  date: 4/18/11
  license: CC-SA 3.0 - Use this code however you'd like, all we ask
  for is attribution. And let us know if you've improved anything!
  
  Circuit:
  L3G4200D Breakout-------------Arduino Uno
  GND-----------------------------GND
  VCC-----------------------------3.3V
  SCL-----------------------------D13
  SDA-----------------------------D11
  SDO-----------------------------D12
  CS------------------------------D10
  INT2----------------------------D6
  INT1----------------------------D7
  
  This example code is intended for use with ST. Microelectronics'
  L3G4200D triple-axis digital gyroscop. The L3G4200D is capable of
  both I2C and SPI communications, but we'll use SPI in this example.
  
  This code sets up the L3G4200D's 5 control registers, and then 
  streams the data from all three axes over the Serial Monitor at 9600bps.
  
*/

#include <SPI.h>
#include "L3G4200D.h"

// pin definitions
const int int2pin = 6;
const int int1pin = 7;
const int chipSelect = 10;

// gyro readings
int x, y, z;

void setup()
{
  Serial.begin(9600);
  
  // Start the SPI library:
  SPI.begin();
  SPI.setDataMode(SPI_MODE3);
  SPI.setClockDivider(SPI_CLOCK_DIV8);
  
  pinMode(int1pin, INPUT);
  pinMode(int2pin, INPUT);
  pinMode(chipSelect, OUTPUT);
  digitalWrite(chipSelect, HIGH);
  delay(100);
  
  setupL3G4200D(2);  // Configure L3G4200 with selectabe full scale range
  // 0: 250 dps
  // 1: 500 dps
  // 2: 2000 dps
}

void loop()
{
  // Don't read gyro values until the gyro says it's ready
  while(!digitalRead(int2pin))
    ;  
  getGyroValues();  // This will update x, y, and z with new values
  
  Serial.print(x, DEC);
  Serial.print("\t");
  Serial.print(y, DEC);
  Serial.print("\t");
  Serial.print(z, DEC);
  Serial.print("\t");
  Serial.println();
  
  //delay(100); // may want to stick this in for readability
}

int readRegister(byte address)
{
  int toRead;
  
  address |= 0x80;  // This tells the L3G4200D we're reading;
  
  digitalWrite(chipSelect, LOW);
  SPI.transfer(address);
  toRead = SPI.transfer(0x00);
  digitalWrite(chipSelect, HIGH);
  
  return toRead;
}

void writeRegister(byte address, byte data)
{
  address &= 0x7F;  // This to tell the L3G4200D we're writing
  
  digitalWrite(chipSelect, LOW);
  SPI.transfer(address);
  SPI.transfer(data);
  digitalWrite(chipSelect, HIGH);
}

int setupL3G4200D(byte fullScale)
{
  // Let's first check that we're communicating properly
  // The WHO_AM_I register should read 0xD3
  if(readRegister(WHO_AM_I)!=0xD3)
    return -1;
    
  // Enable x, y, z and turn off power down:
  writeRegister(CTRL_REG1, 0b00001111);
  
  // If you'd like to adjust/use the HPF, you can edit the line below to configure CTRL_REG2:
  writeRegister(CTRL_REG2, 0b00000000);
  
  // Configure CTRL_REG3 to generate data ready interrupt on INT2
  // No interrupts used on INT1, if you'd like to configure INT1
  // or INT2 otherwise, consult the datasheet:
  writeRegister(CTRL_REG3, 0b00001000);
  
  // CTRL_REG4 controls the full-scale range, among other things:
  fullScale &= 0x03;
  writeRegister(CTRL_REG4, fullScale<<4);
  
  // CTRL_REG5 controls high-pass filtering of outputs, use it
  // if you'd like:
  writeRegister(CTRL_REG5, 0b00000000);
}

void getGyroValues()
{
  x = (readRegister(0x29)&0xFF)<<8;
  x |= (readRegister(0x28)&0xFF);
  
  y = (readRegister(0x2B)&0xFF)<<8;
  y |= (readRegister(0x2A)&0xFF);
  
  z = (readRegister(0x2D)&0xFF)<<8;
  z |= (readRegister(0x2C)&0xFF);
}

Can anyone tell me if there is much difference between the two? I prefer the first one because I have been looking at it for awhile and the second one seems more complex. But if the second one is better then I guess I should start looking at it.

And I was just wondering if any of you could tell me what the "writeI2c" command and the "getgyrovalues()" command are doing. I can't seem to find any documentation regarding them.

They are functions that you have written. The next step would then be to write the documentation. Then, you could read it.

PaulS:

And I was just wondering if any of you could tell me what the "writeI2c" command and the "getgyrovalues()" command are doing. I can't seem to find any documentation regarding them.

They are functions that you have written. The next step would then be to write the documentation. Then, you could read it.

I haven't written them. This is a code I pulled off the internet. As far as my research has came up with they are simply commands that everyone seems to use, but without any real instruction from Arduino. I was hoping to find something from Arduino that would tell me how they work, how to format them, and what their purpose is for. I have found something like that from a page called picaxe for the "writeI2c" command, but nothing for the other two.

I was hoping to find something from Arduino that would tell me how they work

A function is a series of statements. You need to look at the statements in the function to piece together what it does. It's silly to think that the Arduino team would document functions that someone else wrote.

PaulS:

I was hoping to find something from Arduino that would tell me how they work

A function is a series of statements. You need to look at the statements in the function to piece together what it does. It's silly to think that the Arduino team would document functions that someone else wrote.

How would I go about going in and seeing the statements inside this function?

How would I go about going in and seeing the statements inside this function?

They are both in the code you posted......

UKHeliBob:

How would I go about going in and seeing the statements inside this function?

They are both in the code you posted......

They are yes. My question is, when I write the command "writei2c" what inputs does it take? What is it doing? How is it doing what it is doing?

Everyone seems to us the command "writei2c" but no one can tell me how it works or what the inputs are.

My question is, when I write the command "writei2c" what inputs does it take?

When in doubt read the documentation:-

Grumpy_Mike:

My question is, when I write the command "writei2c" what inputs does it take?

When in doubt read the documentation:-
Arduino - WireWrite

Thank you, I was looking for pages such as this. However this one did turn up in my research and I discarded it because it is for the wire.write function, which I believed to be different from the writei2c function. Would the same rules apply to both functions?

Now that I think about it, am I to hung up on these commands? Should I just switch to the wire library and use there commands?

Would the same rules apply to both functions?

No!
writeI2C is a function in that code you posted, it is here:-

void writeI2C (byte regAddr, byte val) {
    Wire.beginTransmission(Addr);
    Wire.write(regAddr);
    Wire.write(val);
    Wire.endTransmission();
}

It calls 4 wire functions. Look at it, it takes two numbers, the first is a register and the second is a value. It writes the two numbers one after the other to the I2C bus.

Your problem is that you are trying to do something that is way way outside your current skill level. If you can not read code how are you ever going to write it?
Get a bit of knowledge first, look at the examples in the IDE, do a few tutorials.

I haven't written them. This is a code I pulled off the internet.

So what would you say if I said I am trying to write a novel and I am searching the internet for sentences but I can't find the right ones?

Grumpy_Mike:

Would the same rules apply to both functions?

No!
writeI2C is a function in that code you posted, it is here:-

void writeI2C (byte regAddr, byte val) {

Wire.beginTransmission(Addr);
    Wire.write(regAddr);
    Wire.write(val);
    Wire.endTransmission();
}



It calls 4 wire functions. Look at it, it takes two numbers, the first is a register and the second is a value. It writes the two numbers one after the other to the I2C bus.

Your problem is that you are trying to do something that is way way outside your current skill level. If you can not read code how are you ever going to write it?
Get a bit of knowledge first, look at the examples in the IDE, do a few tutorials.



> I haven't written them. This is a code I pulled off the internet.


So what would you say if I said I am trying to write a novel and I am searching the internet for sentences but I can't find the right ones?

I hadn't gotten that far through the code yet. I'm still in the first ten lines trying to figure out what these commands do.

I realize this is outside my skill level, which is why I'm here trying to ask questions which no one seems to be able to answer. I have never dealt with data transfer before so this is all new to me, I'm a aerospace engineer trying to learn this stuff so I can extract body roll rates from the gyro on the quadcopter I'm doing for a professor.

Okay I see. So that section at the end is defining the command writei2c. Now why is it at the end? Shouldn't we have to define the command at the beginning?

which is why I'm here trying to ask questions which no one seems to be able to answer.

This is because the questions you are asking are vague and do not make much sense. Also you do not have the knowledge to understand the answers.

I remember going to Germany and learning the phrase asking directions to the train station. When I tried it out in Germany it was no good because I could not understand the answers.

Make your questions specific and direct.

Now why is it at the end? Shouldn't we have to define the command at the beginning?

You can define the function anywhere, the Arduino IDE puts in the prototype definitions for you.

Grumpy_Mike:

which is why I'm here trying to ask questions which no one seems to be able to answer.

This is because the questions you are asking are vague and do not make much sense. Also you do not have the knowledge to understand the answers.

I remember going to Germany and learning the phrase asking directions to the train station. When I tried it out in Germany it was no good because I could not understand the answers.

Make your questions specific and direct.

Now why is it at the end? Shouldn't we have to define the command at the beginning?

You can define the function anywhere, the Arduino IDE puts in the prototype definitions for you.

I am trying to make my questions direct. However like you said I'm outside my skill level and outside my field of knowledge so asking good direct questions is difficult.

Given I'm so far outside my skill level that this forum can't help me I guess I'll abandon this forum and going back to digging my answers out of the code and datesheets

Suit your self but I did answer your last two questions that were direct.

In the very first piece of code you posted, the writeI2c( ) function is right there. It is 5 lines of code. It makes five function calls using the Wire class object.

You say that you then found the explanation of the Wire class ( which implements I2C ) and you disregarded it.

My advice would be to choose another career path.