Pages: [1]   Go Down
Author Topic: L3G4200D 3-axis Gyro Odd Outputs  (Read 4055 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 12
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

I have written a piece of code (based on some existing code-thankyou http://bildr.org/2011/06/l3g4200d-arduino/)
and the outputs from the gyro seem very very high to me.  The author of the above noted something similar-but if I move my gryo slowly even a bit I get values in the range of 300+ d/s. 

Can someone check over the gyro portions of the code for me?  Just to make sure everything looks relatively correct?  If the noise floor is that high and the code is correct I may want to change gyros.  If anyone has recommendations for a new gyro they have used with arduino and i2c, would also be much appreciated.

Thanks much;
Code:
#include <Wire.h>

//Registers for the 3-axis Gyro
#define CTRL_REG1 0x20
#define CTRL_REG2 0x21
#define CTRL_REG3 0x22
#define CTRL_REG4 0x23
#define CTRL_REG5 0x24


//Define Constant Values

const int ledPin = 3;   //Digital pin the LED is attached to
const int ledPin2 = 4;
const int tempPin = 0;  //pin the onboard Temperature sensor is connected to

//General Constants
//These are the analog pins
//If you have a pressure or humidity sensor, it is located on APin1
//If you have temeprature sensors, all of these pins are utilized

const int APin1 = 1;
const int APin2 = 2;
const int APin3 = 3;
const int APin4 = 4;
const int APin5 = 5;

//Set variables

int ledState1 = LOW;
int ledState2 = LOW;
long previousMillis = 0;       //stores last time LED was updated
long previousTransmit = 0;      //stores the last time a transmission was made
double temp = 0;              //stores the on board temperature value

//Group Specific Variables

//Pressure Sensor
double pvolts = 0;         
double pressure = 0;

//Humidity Sensor
double hvolts = 0;
double humidity = 0;

//Temperature Sensor(s)
double temp1 = 0;
double temp2 = 0;
double temp3 = 0;
double temp4 = 0;
double temp5 = 0;

//Acceleration Units
double x1 = 0;
double y1 = 0;
double z1 = 0;
double xzero = 1.57;
double yzero = 1.56;
double znormal = 1.93;

//Gyro Units
int L3G4200D_Address = 104; //I2C address of the L3G4200D
int xg;
int yg;
int zg;

long interval = 1000;        //interval at which to blink/send-10 secs 10000/1000
long transmitint = 4000;    //interval at which to transmit

int PID = 2;    //Your payload ID number
int TXNUM = 0;   //stores the number of transmissions made

// The setup() method runs once, when the sketch starts

void setup()   { 
 
  // initialize the digital pins as outputs:
  pinMode(ledPin, OUTPUT); 
  pinMode(ledPin2, OUTPUT);
  Wire.begin();
  setupL3G4200D(500); // Configure L3G4200  - 250, 500 or 2000 deg/sec
  delay(1500); //wait for the sensor to be ready-take this out if not using the 3-axis gyro
  Serial.begin(4800);        //Set the serial datarate for the digital radio-baud rate 4800 bits per second
}

// the loop() method runs over and over again,
// as long as the Arduino has power

void loop()                     
{
 
  //read the raw value from the temperature sensor
    temp = analogRead(tempPin);
     
    //convert it to voltage
    temp=( temp/1023 )*5;

    //calibrate the temperature sensor->convert from voltage to temperature (celcius) according to the
    //datasheet. We are using a parabolic approximation to lower temperature error in the conversion
    temp = -1481.96 + sqrt( (2.1962*pow(10,6)) + (1.8639-temp) / (3.88*pow(10,-6)) );
   
    //The following code is for the pressure sensor group and should be commented out (//) if unused on your board
    //pvolts=analogRead(APin1);  //Read the voltage
    //pvolts=(pvolts/1023)*5; 
    //pressure=((pvolts/5)+0.095)/.009;  //Pressure conversion equation from datasheet
   
    //The following code is for the humidity sensor and should be commented out (//) if unused on your board)
    //hvolts=analogRead(APin1);
    //hvolts=(hvolts/1023)*5; 
    //You will notice there is no equation to convert.  In the data sheet there is a graph of relative humidity (look this up if you need to) versus voltage.  This is a hard conversion to make mid-flight.  Therefore,
    //we will send doen the voltage and compare to the graph after the flight as part of the data processing.
   
    //The following is for an accelerometer
      //Change is 300 mV/g
    //xzero = 1.57V
    x1 = analogRead(APin1);
    x1 = (x1/1023)*5;
    x1 = (x1-xzero)*1000/300;
   
    //yzero = 1.56V
    y1 = analogRead(APin2);
    y1 = (y1/1023)*5;
   y1 = (y1-yzero)*1000/300;
   
    //z normal = 1.93 V
    z1 = analogRead(APin3);
    z1 = (z1/1023)*5;
    z1 = (z1-znormal)*1000/300;
   
    //Get the gyrovalues
    getGyroValues();
    //The following is for the remaining temperature sensors
    /*temp1 = analogRead(APin1);
    temp1 = ( temp1/1023 )*5;
    temp1 = -1481.96 + sqrt( (2.1962*pow(10,6)) + (1.8639-temp1) / (3.88*pow(10,-6)) );
   
    temp2 = analogRead(APin2);
    temp2 = ( temp2/1023 )*5;
    temp2 = -1481.96 + sqrt( (2.1962*pow(10,6)) + (1.8639-temp2) / (3.88*pow(10,-6)) );
   
    temp3 = analogRead(APin3);
    temp3 = ( temp3/1023 )*5;
    temp3 = -1481.96 + sqrt( (2.1962*pow(10,6)) + (1.8639-temp3) / (3.88*pow(10,-6)) );
   
    temp4 = analogRead(APin4);
    temp4 = ( temp4/1023 )*5;
    temp4 = -1481.96 + sqrt( (2.1962*pow(10,6)) + (1.8639-temp4) / (3.88*pow(10,-6)) );
   
    temp5 = analogRead(APin5);
    temp5 = ( temp5/1023 )*5;
    temp5 = -1481.96 + sqrt( (2.1962*pow(10,6)) + (1.8639-temp5) / (3.88*pow(10,-6)) );
*/
   
  if (millis()-previousTransmit > transmitint)
  {
   
    previousTransmit=millis();
    //increment the number of time transmitted
    TXNUM++;
   
    //Send all relevant data
    Serial.print("$PUMD,");
    Serial.print(PID);
    Serial.print(",");
    Serial.print(TXNUM);
    Serial.print(",");
    Serial.print(temp);
    Serial.print(",");
    //Group Specific Values
    Serial.print(x1);  //You must place here instead of "VALUE", either "pressure", "hvolts", "temp1", or "x1"
    Serial.print(",");
    Serial.print(y1);  //You must place here instead of "VALUE", either "temp2", or "y1", if neither apply, discard these 2 lines
    Serial.print(",");
    Serial.print(z1);  //You must place here instead of "VALUE", "temp3", or "z1", if not applicable, discard these 2 lines
    Serial.print(",");
    Serial.print(xg);
   Serial.print(",");
    Serial.print(yg);
   Serial.print(",");
    Serial.print(zg); 
    Serial.println("*");
  } 
   
  if (millis()-previousMillis > interval)
  {
    //save the last time the LED was blinked
    previousMillis = millis();
   
    //if the LED is off, turn it on and vice versa for each LED
    if(ledState2 == LOW)
    {
      ledState2 = HIGH;
      ledState1 = LOW;
    }
    else
    {
      ledState2 = LOW;   
      ledState1 = HIGH;
    }
   
    //set the LEDs to the state of the variable
    digitalWrite(ledPin2, ledState2);
    digitalWrite(ledPin, ledState1);
 
  }
}
//Functions are placed after the main code
void getGyroValues(){

  byte xMSB = readRegister(L3G4200D_Address, 0x29);
  byte xLSB = readRegister(L3G4200D_Address, 0x28);
  xg = ((xMSB << 8) | xLSB);

  byte yMSB = readRegister(L3G4200D_Address, 0x2B);
  byte yLSB = readRegister(L3G4200D_Address, 0x2A);
  yg = ((yMSB << 8) | yLSB);

  byte zMSB = readRegister(L3G4200D_Address, 0x2D);
  byte zLSB = readRegister(L3G4200D_Address, 0x2C);
  zg = ((zMSB << 8) | zLSB);
}

int setupL3G4200D(int scale){
  //From  Jim Lindblom of Sparkfun's code

  // Enable x, y, z and turn off power down:
  writeRegister(L3G4200D_Address, CTRL_REG1, 0b00001111);

  // If you'd like to adjust/use the HPF, you can edit the line below to configure CTRL_REG2:
  writeRegister(L3G4200D_Address, 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(L3G4200D_Address, CTRL_REG3, 0b00001000);

  // CTRL_REG4 controls the full-scale range, among other things:

  if(scale == 250){
    writeRegister(L3G4200D_Address, CTRL_REG4, 0b00000000);
  }else if(scale == 500){
    writeRegister(L3G4200D_Address, CTRL_REG4, 0b00010000);
  }else{
    writeRegister(L3G4200D_Address, CTRL_REG4, 0b00110000);
  }

  // CTRL_REG5 controls high-pass filtering of outputs, use it
  // if you'd like:
  writeRegister(L3G4200D_Address, CTRL_REG5, 0b00000000);
}

void writeRegister(int deviceAddress, byte address, byte val) {
    Wire.beginTransmission(deviceAddress); // start transmission to device
    Wire.send(address);       // send register address
    Wire.send(val);         // send value to write
    Wire.endTransmission();     // end transmission
}

int readRegister(int deviceAddress, byte address){

    int v;
    Wire.beginTransmission(deviceAddress);
    Wire.send(address); // register to read
    Wire.endTransmission();

    Wire.requestFrom(deviceAddress, 1); // read a byte

    while(!Wire.available()) {
        // waiting
    }

    v = Wire.receive();
    return v;
}
Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 179
Posts: 8075
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

When you set full scale to 500 degrees per second each count is equal to 17.50 milli-degrees per second.  A value of 300 would be 5,250 milli-degrees per second or 5.25 dps.  The "Digital zero-rate level" is +/-15 dps so a resting value of +/- 857 should be expected.

"Zero-rate level describes the actual output signal if there is no angular rate present. The zero-rate level of precise MEMS sensors is, to some extent, a result of stress to the sensor and, therefore, the zero-rate level can slightly change after mounting the sensor onto a printed circuit board or after exposing it to extensive mechanical stress. This value changes very little over temperature and time."

What is the value when you are NOT moving the gyroscope?

If you have a clock with a continuous second hand, putting the gyroscope on the second hand should give you a 6 dps (360/60) change or about 343 counts.
Logged

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

0
Offline Offline
Newbie
*
Karma: 0
Posts: 12
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

okay, so to fix in the code I would just use:

Code:
xg = xg *17.5/1000-(-5);
yg = yg*17.5/1000-5;
zg = zg*17.5/1000-1;

Where the -5,5,1 are my actual read zero values (they seem to be within the limits.)

My only question is where did the 17.5 come from?  how is that calculated?

Thanks.
Logged

Pages: [1]   Go Up
Jump to: