# Thread: L3G4200D Gyro Integration on Arduino

1. ## Re: L3G4200D Gyro Integration on Arduino

Ah you are correct!

Code:
`while((millis() - pastMillis)<9);`
Insted of dealy(10); results in about 93 degrees for every 90. I am guessing the easiest way to eliminate inconsistent sample rate as a factor would be to use millis() in the math itself but "excuse my stupidity here " in the formula where are the "kilo-degrees per sample time" coveted to kilo-degrees per second?

2. ## Re: L3G4200D Gyro Integration on Arduino

Not sure if the even more severe sleep deprivation is making me miss sarcasm or not.

Code:
```current_rotational_rate [degrees/s] = sensor_value [digits] * 8.25 [millidegrees/s/digit] * (1/1000) [degree/millidegree]

// Raw Integration of rotational rate to produce current angle
// omega = dtheta/dt -> omega*dt = dtheta -> theta1 - theta0 = omega*(t1-t0) -> theta1 = theta0 + omega*(t1-t0)
current_angle [deg] = last_angle [deg] + { (current_rotational_rate) [deg/s] * (time_current - time_last) [s] }
// The Averaged/Smoothed Integration imlemented in your code
current_angle [deg] = last_angle [deg] + { ((last_rotational_rate+current_rotational_rate)/2) [deg/s] * (time_current - time_last) [s] }```
so this should work
Code:
```unsigned long pastMicros = 0;
unsigned long currMicros = 0;
float dt = 0.0;

void loop()
{
pastMillis = millis();
getGyroValues();  // This will update x, y, and z with new values
pastMicros = currMicros;
currMicros = micros();

// if we are considering a certain range of z to be noise, should we even bother doing any calculations or updating any values when z is considered noise?  Seriously asking because of aforementioned sleep deprivation.
if(z >= gyroHigh || z <= gyroLow)
{
// determine time interval between sensor readings with a bit more accuracy than available just using millis()
// of course, micros() only updates in intervals of 4 [us], but still far better resolution/sig-figs than millis()
if (currMicros>pastMicros)  //micros() overflows/resets every ~70 minutes
dt = (float) (currMicros-pastMicros)/1000000.0;
else
dt = (float) ((4294967295-pastMicros)+currMicros)/1000000.0;

degreesPerSecond = (((float)z * 8.75))/100;

// here we do an averaged/smoothed integration of rotational rate to produce current angle.
currentAngle += ((p_z + degreesPerSecond)/2) * dt;

// Should p_z be updated if z is insufficient to change the current angle?  Again, seriously asking because I trust my mind even less than usual.
p_z = degreesPerSecond;
}

Serial.println(currentAngle);

// wait ~10 milliseconds
while ( (millis()-pastMillis)<10 ) // millis() overflows once every ~50 days, so less inclined to worry
{
delayMicroseconds(50);
}
}```
Last edited by tician; 04-15-2012 at 03:13 AM. Reason: i'm goin' bed

3. ## Re: L3G4200D Gyro Integration on Arduino

Lol it was not sarcasm I have been devoting every hour to getting our FTC bot up and running and I was pretty burned out Totally missed a basic concept, but everything is working now. There was a bit of left over error but I tuned it out manually.

Because I got a few pm's about the final code here it is for refrence.

L3G4200D_V3-120417a.zip

Thanks again!

4. ## Re: L3G4200D Gyro Integration on Arduino

Went back to a fixed 10 [ms] delay? If so, you could remove the "pastMillis = millis();" line in loop(), since it is just wasting cycles with an invariant delay.

5. Abacus
Join Date
Aug 2012
Posts
2
Rep Power
0

## Re: L3G4200D Gyro Integration on Arduino

I've had a look at your code, thanks for sharing it.

However, I have a question.

I read values from my L3G4200D using the SPI bus.
Angular rate values when the sensor is in steady state are not 0. Typically I have a value around 100 when the sensor is steady around the z axys. Let's consider this as an example.

I use a calibration method similar to yours, detecting a max and min threshold inside which I consider samples to be noise around the steady state condition.

Now, if the z-sample is 130, I want to integrate it, however, when calculating the DegreesPerSecond I think I should consider only the delta from the steady state value (100) to the sampled valid value (130), that is 30.

Basically I've had expected to see a line like this in your code:

Code:
`z -= steadyStateValue`
Resulting in something like this:

Code:
```  if(z >= gyroHigh || z <= gyroLow)
{
degreesPerSecond = (float)z * 0.00000908; //this value was 0.0000085 but was manually calibrated to its current value
if (currMicros>pastMicros)  //micros() overflows/resets every ~70 minutes
dt = (float) (currMicros-pastMicros)/1000000.0;
else
dt = (float) ((4294967295-pastMicros)+currMicros)/1000000.0;
currentAngle += ((p_z + degreesPerSecond)/2) * dt;
p_z = degreesPerSecond;
}
else
{
p_z = 0;
}```
It sounds starnge to me that this has not been pointed out during the discussion.

Am I missing something?

Thanks.

6. ## Re: L3G4200D Gyro Integration on Arduino

I am pretty sure there was the assumption that the sensors was assembled and functioning well and that the steady state value was essentially zero with noise varying between gyroHigh and gyroLow. I do not recall the steady state value from the gyro in any of the CM-730's in the lab being that far from a zero value, but I may be mistaken. Is the sensor on a custom board you assembled or is it a breakout board from a manufacturer/re-seller? The L3G4200D datasheet does mention improper soldering and/or mechanical stress introducing error into the zero/steady-state value*. That said, if you do not have any trouble with the sensor other than the steady state value, then just compensate for it. If there are other problems, like improper scaling or non-responsive axes, then you might want to contact the manufacturer/seller of the board.

* Under the heading 2.6.2 "Zero-rate Level":
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.

7. ## Re: L3G4200D Gyro Integration on Arduino

You don't want to use millis() at all if you want accurate timing. You want the microsecond function, whose name escapes me (micros()?)
Also, to get consistent sample rates, you probably want to set a timer to fire for each time you should sample, and sample from the interrupt handler.

8. ## Re: L3G4200D Gyro Integration on Arduino

Originally Posted by jwatte
You don't want to use millis() at all if you want accurate timing. You want the microsecond function, whose name escapes me (micros()?)
Also, to get consistent sample rates, you probably want to set a timer to fire for each time you should sample, and sample from the interrupt handler.
The code posted above uses only micros() for math and uses millis() with a 50 [us] delay interval for a roughly consistent sample rate, although the final code ROBOTMAN uploaded dumped that for a simple fixed delay irrespective of the time taken to process the loop. Ideally one would just use a timer interrupt for sampling sensors, but I'm pretty sure the arduino was dedicated purely to sampling the gyro, calculating the current angle, and pushing that value out over the UART to the PC, so I think that plus frustration/deadline led to a situation of "good enough."

9. Abacus
Join Date
Aug 2012
Posts
2
Rep Power
0

## Re: L3G4200D Gyro Integration on Arduino

My L3G4200D is mounted on a Sparkfun breakout.
Here below you can find actual samples of my sensor for 1 second interval:

Code:
```X:95 Y:-10 Z:6
X:91 Y:-17 Z:9
X:96 Y:-10 Z:4
X:94 Y:-7 Z:6
X:93 Y:-16 Z:4
X:97 Y:-15 Z:2
X:101 Y:-16 Z:3
X:96 Y:-8 Z:2
X:92 Y:-10 Z:5```
However, no problem to compensate that, maybe ROBOTMAN was luckier with the zero-rate level being closer to 0 .

Thank you for the datasheet quote.

10. Join Date
Mar 2013
Posts
7
Rep Power
16

## Re: L3G4200D Gyro Integration on Arduino

I am also using the same gyro L3G4200D.
I am trying to get angle from it...
I've used ADXL 335 accelerometer.

I am trying to get angles with respect to roll, yaw & pitch

Here is my code:

Code:
```float Rx,Ry,Rz,Yd,Xd,Zd,Rxe,Rye,Rze,Xavg,Yavg,Zavg,T,Rxg,Ryg,Rzg,c,Re,R,Rx1,Ry1,Rz1;
Th = 5;
c = 180/3.14;
T = 0.0155;  //15.5 ms (verified by using counter)
while(1)
{
get_accl_data();                    // Accl data from ADC
accelerometer();                    // Converting ADC values in "g" - Rx, Ry, Rz
inclination();                         // Normalizing Rx, Ry, Rz
gyro();                                // Computing Xavg, Yavg, Zavg by using two consecutive readings

if((Xavg >= Th)||(Xavg <= -Th))
{
Xd = atan2(Rye, Rze);
Xd =(Xd + (Xavg*T));
Xd *= c;
ftoal(Xd,str);
UARTprintf("Xd : %s            \n\r",str);
Xd /= c;
}
if((Yavg >= Th)||(Yavg <= -Th))
{
Yd = atan2(Rxe, Rze);
Yd =(Yd + (Yavg*T));
Yd *= c;
ftoal(Yd,str1);
UARTprintf("        Yd : %s    \n\r",str1);
Yd /= c;
}
if((Zavg >= Th)||(Zavg <= -Th))
{
Zd = atan2(Rye, Rxe);
Zd =Zd + (Zavg*T);
Zd *= c;
ftoal(Zd,str2);
UARTprintf("                    Zd : %s\n\r",str2);
Zd /= c;
}

Rxg = sin(Yd) / (sqrt(1 + ( (cos(Yd)*cos(Yd) )*(tan(Xd) * tan(Xd) ))));
Ryg = sin(Xd) / (sqrt(1 + ( (cos(Xd) * cos(Xd) ) *( tan(Yd) * tan(Yd) ))));
Rzg = ((Rzg > 0) ? 1 : ((Rzg < 0) ? -1 : 1))*(sqrt(1 - (Rxg*Rxg)-(Ryg*Ryg)));

Rxe = (Rx*0.02)+(Rxg*0.98);
Rye = (Ry*0.02)+(Ryg*0.98);
Rze = (Rz*0.02)+(Rzg*0.98);

Re = sqrt((Rxe*Rxe) + (Rye*Rye) + (Rze*Rze) );

Rxe = Rxe/Re;
Rye = Rye/Re;
Rze = Rze/Re;

SysCtlDelay(800000);     // 10 ms delay
}```

I am not getting the accurate angles...
I am getting some angles proportional to acceleration at a time when I move it.
And after moving it from angle 0 to angle 45 (for example) it stabilizes after a 1-2 sec. and giving stable values of Xd, Yd, Zd again!!

What I am missing??

##### Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•