# Thread: L3G4200D Gyro Integration on Arduino

1. ## L3G4200D Gyro Integration on Arduino

I have been banging my head against the wall with this for days and I know I am missing something obvious but I can't quite wrap my head around what I am doing wrong. I am trying to use the L3G4200D gyro with an arduino and integrate the z-axis value using trapezoidal approximation. The code I started with came from here "I know it is a different break out board but the same pins are broken out".

I am running in 200 degrees per second mode. To integrate I convert my reading to milli-degrees by multiplying the voltage reading by the 200 DPS scale "8.75" then divide that by 100 to convert to milli-degrees per second "the loops cycles every 10 milliseconds".
Code:
`degreesPerSecond = (((float)z * 8.75))/100;`
Then I check if the gyro is actually moving and if so integrate my currentAngle using code based off this tutorial:
Code:
`currentAngle += ((p_z + degreesPerSecond) * 10)/2000;`
p_z is the previous reading for the z axis in degrees per second.

However this dose not work. When I print currentAngle/1000 "to convert from milli-degrees" it is < 1 degree when I move the gyro 90 degrees.

I know I am missing something obvious most likely because I have yet to take calculus .
Any help would be appreciated!

The code is attached:
L3G4200D_V3.zip

2. Optical Processor
Join Date
Feb 2012
Location
Sydney, Australia
Posts
364
Rep Power
35

## Re: L3G4200D Gyro Integration on Arduino

I'm not sure what troubleshooting steps you've taken, so apologies if this is stuff you've already done.

I only had a brief look at your code (not having any Arduino development tools, I opened your code using Notepad...), and I've got a sneaking suspicion that you might have something wrong with your scaling factors. Personally I just convert everything to radians immediately, but I digress. I'm curious as to what exactly you're changing currentAngle by when you turn your gyro 90 deg. If that "<1 degree" when you move the gyro 90 degrees turns out to be "0.9 degrees", then there's a clue that it's a scaling issue.

Edit: Maybe I'm reading this bit wrong:
Originally Posted by ROBOTMAN
I am running in 200 degrees per second mode. To integrate I convert my reading to milli-degrees by multiplying the voltage reading by the 200 DPS scale "8.75" then divide that by 100 to convert to milli-degrees per second "the loops cycles every 10 milliseconds".
You have an initial input that's multiplied by 8.75. What exactly are the units for input*8.75? You say you convert milli-degrees to milli-degrees per second by dividing by 100, but that doesn't make sense. It's like me saying I've converted metres to metres per second by dividing by 100.

Edit 2: On a hunch, multiply by 100 instead of dividing, and tell me what happens.
Last edited by Th232; 04-14-2012 at 04:07 AM.

3. ## Re: L3G4200D Gyro Integration on Arduino

If I actually understand any of this in my rather sleep deprived state, the L3F4200D gives you a signed 16-bit integer without any units. In 250 dps mode, you multiply by 8.5 [mdps/digit] to get the rotational rate in [millidegrees/second]. To then get [degrees/second], you will need to divide by 1000 [mdeg/deg], not 100.

z [digits] * 8.5 [mdeg/s/digit] * (1/1000) [deg/mdeg] => [deg/s]

The integration step seems fine although the math might be a little bit unusual. Since p_z and degreesPerSecond are already float's, why not just multiply by 0.005 instead of multiplying by 10 and dividing by 2000? Then again, the compiler probably automatically optimizes that since 10 and 2000 are not going to be changing.

It would appear to be the Serial.println(currentAngle/1000) that is causing the confusion. 'currentAngle' is already in [deg], if you want to to get [mdeg], you multiply by 1000 [mdeg/deg], not divide. As is, your code is giving you [kdeg], which will be pretty low unless you are spinning the board really quickly. It is a matter of scale. The sensor measures in [mdeg/s], 1 [digit] * 8.5 [mdeg/s/digit] * (1/1000) [deg/mdeg] * (1/1000) [kdeg/deg] = 0.0000085 [kdeg/s] (which becomes [kdeg] after the integration step).
Last edited by tician; 04-14-2012 at 05:44 AM. Reason: forgot how integration works

4. ## Re: L3G4200D Gyro Integration on Arduino

Thanks a ton for the help! Yeah you where correct and I am now getting much more reasonable readings. However things seem to be a little bit off because a manual rotation of 90 reads 70, I am wondering if this is because I am not factoring in the sample rate anywhere? Also there seems to be a high level of data loss. When rotating from 0 to 90 then back to zero currentAngle reads 11... This is not due to drift because I take 10,000 samples and use the peak values from that to make sure the gyro is actually moving before integrating.

My experience with gyros comes from FTC where we use the nxt's hi-tech gyro and basic trapezoidal approximation. With the NXT gyro we have no drift or data loss. We can rotate it back and forth from 90 degress all day and only lose 1 degree.

I expected to be able to achieve the same thing with this gyro but so far something seems to be different. I wrote most of the code for integrating the gyro on the NXT and there is noting special or different about it that I can tell.

Also I am wondering if the fact that I am running at 3.3 volts could make a difference? Those scales where for 3 volts but because of the wide range of voltages the breakout board can accept I am sure there is a regulator.

5. Optical Processor
Join Date
Feb 2012
Location
Sydney, Australia
Posts
364
Rep Power
35

## Re: L3G4200D Gyro Integration on Arduino

How fast are you moving the gyro? Might be a saturation issue if you're moving it really fast.

When going 0->90->0, is it always reading 11 degrees, and if not how much does it vary by?

6. ## Re: L3G4200D Gyro Integration on Arduino

I think my test rig was the source of the data loss. It is fixed now. I switched to 3v but it still claims 90 is 70... I could manually configure the sensitivity but I should not have to right?

7. Optical Processor
Join Date
Feb 2012
Location
Sydney, Australia
Posts
364
Rep Power
35

## Re: L3G4200D Gyro Integration on Arduino

I personally calibrate all my sensors anyway, but being off by over 20% doesn't sound right to me. If you rotate it by 360 degrees, will it say you're at 280 degrees, or something else?

Or maybe it's the part of your code where you decide whether the gyro's actually moving or not. Try removing that bit and see what happens.

8. ## Re: L3G4200D Gyro Integration on Arduino

Without the calibration code it still goes to 70 and 360 resulted in exactly 278.5 So I am guessing that it just needs manual calibration? 20% off sounds pretty ridiculous but I suppose it is what it is. Any tips for getting accurate manual calibration?

Thanks again for the help everyone!

9. Optical Processor
Join Date
Feb 2012
Location
Sydney, Australia
Posts
364
Rep Power
35

## Re: L3G4200D Gyro Integration on Arduino

Bummer. If you're doing it manually, just put a multiplier in as early as you can, e.g. along with the 8.75 multiplier. So in your case multiply your result by 1.293 (360/278.5 = 1.293). Don't forget to comment it, I've calibrated before then come back and wondered why the heck I put such a strange number in there... Then do multiple tests using varying angles (e.g. 30, 60, 180, 270 deg) and at varying speeds to confirm that it's right.
Last edited by Th232; 04-15-2012 at 01:50 AM.

10. ## Re: L3G4200D Gyro Integration on Arduino

How sure are you that the loop is actually taking 10 ms? That delay function is not taking into account the length of time required to actually run through the loop (to retrieve the gyro values, perform the data processing, and finally print out the value). A big problem I had with first attempting to use the HaViMo2 for tracking a target was that the time taken to print out just the basic x,y coordinates of the target drastically reduced the ability of the pan-tilt servo arrangement to actually track a moving target (the lower the baud rate, the longer the delay while printing).

It would be a much better idea to use the pastMillis variable. Record pastMillis at the beginning of the loop function and add a while loop at the end of the loop function that keeps repeating until the change in time is greater than or equal to 10 milliseconds.

Code:
```unsigned long pastMillis = 0;
void loop()
{
pastMillis = millis();

getGyroValues();  // This will update x, y, and z with new values

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

if(z >= gyroHigh || z <= gyroLow)
{
currentAngle += ((p_z + degreesPerSecond) * 10)/2000;
}

Serial.println(currentAngle);

p_z = degreesPerSecond;

while ( (millis()-pastMillis)<10)
{
delayMicroseconds(200);
}
}```
Last edited by tician; 04-15-2012 at 02:13 AM.

##### 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
•