Hi,
I played around with a L3G4200D 3DOF gyro sensor using sparkfuns example code.
Actually I only need the x-axis, but only get a sort_of_stable output, when I don't move the sensor.
I had to eliminate zero-Point Errors, to get there.
But unfortunately, I get a huge drift when I move the sensor and put it back to starting Position.
Is there any chance to eliminate drift with only one 3DOF sensor, or do we always need a 3DOF accelerometer sensor too?
I haven't found much about the L3G4200D, could using the FIFO Registers help here?
Also couldn't find out yet which bandwidth would provide best accuracy.
the math behind the x_angle value is not final by now. I'm not sure how to cope with the interupt routine and millis()-readings.
/* 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/DR-------------------------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"
#include <Wire.h>
#include <LiquidCrystal_I2C.h> //sainsmart test library for 20x4 I2C LCD
// pin definitions
const int int2pin = 6;
const int int1pin = 7;
const int chipSelect = 10;
// gyro reading
int x;
int x_angle =0; //start with sensor top down on a flat surface
int x_offset = 15; // that's the average value when sensor isn't moving
int show_angle = 0;
LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 for a 20x4 display
void setup()
{
lcd.init();
lcd.init(); // initialize the lcd twice
lcd.backlight();
lcd.setCursor(3,0);
lcd.print("L3G4200D Test");
// 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 with new values
x+= x_offset; //eliminate zero offset and ignore small changes to minimize drift
if (!( x < 7 && x > -7 )){
x_angle += x;
} // end if
show_angle += 1; // try to read data as fast as possible but send data only every 50 loops
if (show_angle == 50 ){
lcd.setCursor(2,2);
lcd.print("Raw X ");
lcd.print(x, DEC);
lcd.print(" "); // erase bigger values from screen
lcd.setCursor(2,3);
lcd.print("Pitch ");
lcd.print(x_angle, DEC);
lcd.print(" ");
show_angle = 0;
} // end if
} // end loop
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);
}
int getGyroValues()
{
x = (readRegister(0x29)&0xFF)<<8;
x |= (readRegister(0x28)&0xFF);
}