L3GD20 noise

I am looking at the L3GD20 data stream from the L3GD20 3-Axis Gyro Carrier with Voltage Regulator board and it seems very noisy. With no movement, here is a sample of the output from the example program "serial"
I work with gyros a lot and understand that they drift, but this is not a steady drift, the readings jump all over.

I realize that this is raw data and that when scaled to dps the noise is not so bad, but still seems high. Perhaps I am using the wrong conversion? I am using full scale sensitivity (2000 dps, 70 mdps/digit) so am using a 0.07 conversion from raw data to degrees per sec. Is that correct?

I noted that if I average the readings, they are around a common mean. Is this noise level normal for this sensor?

G X: -17 Y: -56 Z: -150
G X: -57 Y: -64 Z: -212
G X: -43 Y: -72 Z: -188
G X: -27 Y: -76 Z: -151
G X: -19 Y: -74 Z: -221
G X: -25 Y: -29 Z: -137
G X: -40 Y: -54 Z: -155
G X: -40 Y: -80 Z: -198
G X: -15 Y: -63 Z: -174
G X: -36 Y: -75 Z: -155
G X: -62 Y: -70 Z: -143
G X: -46 Y: -76 Z: -183
G X: -39 Y: -50 Z: -187
G X: -15 Y: -71 Z: -159
G X: -7 Y: -60 Z: -163
G X: -9 Y: -72 Z: -170

Hello. The noise level in your data looks normal to me.

Yes, that is correct.

The “steady drift” you are referring to is probably what you see when you integrate the rotations from the gyro, but you wouldn’t see it when you look at the raw readings.

There will generally be some noise and some zero-rate offset for sensors like this. You really have to convert it to some human-understandable unit (degrees per second) to evaluate it. You can look in the sensor’s datasheet to get an idea of how much offset and how much noise is typical. You can find the datasheet by going to the pololu.com product page for your device and opening the Resources tab (below the price and short description).

If you still think that you are getting too much noise or too much of an offset from your device, please provide us with the following information:

  1. The configuration settings you used on the device. (Different settings can result in different amounts of noise and offset.)
  2. 15-50 sets of raw readings from the device, taken while it is stationary.
  3. For every axis you are concerned about, the standard deviation and average of the readings from that axis. You can use a spreadsheet program to calculate this.
  4. The standard deviation and average, converted to human units. For a gyro, convert to dps (degrees per second).
  5. The relevant information from the datasheet that makes you think your readings are atypical.


I have been playing with the ST eval board of this gyro.

Has anyone else but me noticed that ambient light level causes the output to drift? Mine sees a y-axis zero rate shift from 700 counts to 380 going from a lighted room to dark. Discovered by accident but totally reproducible.

–john d

Hi, John.

We attempted to duplicate your results, but could not. We obtained data while the sensor was exposed to office lighting, natural sunlight, and inside an enclosed container. Could you please tell us more about your setup?


The current setup is using the ST eval board and an LPXpresso LPC1114 board.

The L3GD20 is configured for 250 d/s and I am using the FIFO at a watermark of 16 readings, at which I read and average. I then run a 50 reading moving average filter to establish the zero-rate level. Here is the output of that moving average filter as I cover and uncover the board with my hand in a partially sunlit room.

143 567 -204
143 567 -204
144 568 -204
143 570 -205
144 570 -206
144 572 -206
144 573 -206
144 574 -207
144 573 -206
<---- hand covered
141 562 -204
139 550 -201
137 536 -197
134 521 -194
132 508 -191
129 494 -188
127 481 -185
124 467 -182
124 465 -182
123 464 -182
123 464 -183
123 465 -183
→ uncovered
124 468 -183
125 481 -185
127 494 -188
130 506 -191
132 519 -194
135 532 -197
138 545 -199
140 559 -203
143 573 -206
143 574 -206
144 575 -207
144 575 -206
144 576 -206
144 576 -206


Wierd huh?

maybe I got a funny sample from ST…

Thank you for sharing your settings. When I adjusted my setup to more closely match yours, I was able to notice a difference in the readings depending on whether the board was in direct sunlight or shaded by my hand. However, it is not clear to me whether the variation is due to the light itself or just the temperature difference between light and shade.


Thanks Derrill,

I have since looked at the readings before I the MA filter and yes it is still responding to light. I will get another sample and see if its the same. In the meantime I covered the chip with a piece of black electrical tape and the effect is diminished greatly (but not gone). I see a big effect from just turning the room lights off and on.

Still weird.

Thanks for the update. If you try it again, please let us know your results.


Is it useful to apply a moving average filter to this sensor? I have a ST evaluation board for this sensor and the data which I am getting is offcourse raw as mentioned in the sample code. But my question is that what could be the best way to reduce this noise either by a filter or a set-up.?

Thanks in advance for the help.


Hi, Irfan.

Yes, you can use a moving average to filter the output of this sensor.


Thank you derril sir,

I will implement it soon.

Also, does anyone has any knowledge about the IMU and micro magnetometers like MicroMag3 and Honeywell HMC5883L implementation with any board. Any example codes for that. I have an IMU from Analog devices. Sorry for asking this but I am very new to this electrical field. Please help.


Hello all,

I got the following readings with and without movement. Can anyone advise me whether to apply the moving average filter to it or the readings or fine enough.?

Please provide your recommendations.


with movement.

Note: the axis exactly takes into consideration for negative and positive axis during movement.


It seems to get the same problem. This belows are raw data reading from L3GD20.

270 49 27
346 30 -2
346 30 -2
252 67 -100
334 65 -97
334 65 -97
284 47 8
246 24 -20
246 24 -20
359 25 11
352 -30 -9
352 -30 -9
331 26 24
324 37 -22
324 37 -22
309 -8 -22
297 -9 65
297 -9 65
329 34 18
307 13 -37
307 13 -37
311 47 -31
311 47 -31
318 48 -84
306 39 -79
306 39 -79
310 43 -126
253 77 -83
253 77 -83
298 -8 -22
332 30 24
332 30 24
275 69 -86
274 51 -28
274 51 -28
233 85 -66

I collect this data when keeping gyro stationary. Is that normal level noise to this device? if not, how to reduce?

This is my hardware setup pic. Do you think there are some problems?


Some variation is normal. Are you using our L3GD20 breakout board? From the schematic you posted, it looks like you might have designed your own board. What are you using to communicate with the gyro? Could you post your code and tell me how you are setting the control registers? Could you also post pictures of your setup?

- Jeremy

Thanks. I’m sorry not buying L3GD20 breakout board, just want to do it by myself. In fact the target of this project is to use gyroscope and odemeter to make vehicle navigation testing. That be commonly konwed as deadreckon. In my project, gyroscope connected with microcontroller of stm32 serial product and communicate with I2C Interface. In the other side, odemeter give running distance, so I can get changed degree and displacement and then deduce the new position with combination of that two part of information.

In my project, I want to make deadreckon with frequency of 10HZ. so gyroscope signal was sampled in 10 times per second. fullscale was chosed to be 250dps and ODR is 190HZ. In order to statisfy designed output frequency, I set watermark as 19, so data was reading when watermark interruption happened. I write code in IAR, The code is listed below:

void L3GD20_Init(void)

  ExtInt_Init(L3GD20_INT2); //set watermark interrupt
void Set_CTRL_REG1(void)
  L3GD20_CTRL_REG1 regValue = {0};
  UINT8 data = 0;

  regValue.ODR = ODR_190Hz_BW_50;
  regValue.PD = 1; /*normal mode or sleep mode*/
  regValue.Zen = 1;/*Enable Z*/
  regValue.Yen = 1;/*Enable Y*/
  regValue.Xen = 1;/*Enable X*/
  data = (UINT8)((*((UINT8*)&regValue)) & 0xff);
  HALAPI_IIC_Write(L3GD20_Add, CTRL_REG1, &data, 1);
void Set_CTRL_REG2(void)
  L3GD20_CTRL_REG2 regValue = {0};
  UINT8 data = 0;
  regValue.Unused         = 0x00;
  regValue.HPM            = 0x00;
  regValue.HPCF           = 0x00;
  data = (UINT8)((*((UINT8*)&regValue)) & 0xff);
  HALAPI_IIC_Write(L3GD20_Add, CTRL_REG2, &data, 1);
void Set_CTRL_REG3(void)
  L3GD20_CTRL_REG3 regValue = {0};
  UINT8 data = 0;
  regValue.I1_Int1        = 0;/*disable Interrupt ON INT1 pin */
  regValue.I1_Boot        = 0;/* disable Boot status */
  regValue.H_Lactive      = 0;/* 0---INT1 output HIGH;1---INT1 output LOW */
  regValue.PP_OD          = 0;/* 0---Push-Poll;1---Open drain */
  regValue.I2_DRDY        = 0;/* Data Ready on DRDY/INT2,0--disable, 1--enable */
  regValue.I2_WTM         = 1;/*Enable FIFO watermake interrupt on DRDY/INT2 */
  regValue.I2_ORun        = 0;/* FIFO overrun interrupt on DRDY/INT2 */
  regValue.I2_Empty       = 0;/* FIFO Empty interrupt on DRDY/INT2 */
  data = (UINT8)((*((UINT8*)&regValue)) & 0xff);
  HALAPI_IIC_Write(L3GD20_Add, CTRL_REG3, &data, 1);
void Set_CTRL_REG4(void)
  L3GD20_CTRL_REG4 regValue = {0};
  UINT8 data = 0;
  regValue.BDU    = BDU_Updata;		/*default*/
  regValue.BLE    = BLE_LSB;      /*little edian*/
  regValue.FS     = FULLSCALE_250;/*full scale : 250*/
  regValue.Unused = 0x00;
  data = (UINT8)((*((UINT8*)&regValue)) & 0xff);
  HALAPI_IIC_Write(L3GD20_Add, CTRL_REG4, &data, 1);
void Set_CTRL_REG5(void)
  L3GD20_CTRL_REG5 regValue = {0};
  UINT8 data = 0;
  regValue.BOOT           = 0;/* normal mode */
  regValue.FIFO_EN        = 1;/* FIFO enable*/
  regValue.Unused         = 0;
  regValue.HPen           = 0x00;/*disenable hpf */
  regValue.INTSel         = 0x00;
  regValue.OutSel         = 0x00;
  data = (UINT8)((*((UINT8*)&regValue)) & 0xff);
  HALAPI_IIC_Write(L3GD20_Add, CTRL_REG5, &data, 1);
void Set_FIFO_CTRL_REG(void)
  L3GD20_FIFO_CTRL_REG regValue = {0};
  UINT8 data = 0;
  regValue.WTM        = 19;
  regValue.FM         = FIFO_STREAM_MODE;  
  data = (UINT8)((*((UINT8*)&regValue)) & 0xff);

  HALAPI_IIC_Write(L3GD20_Add, FIFO_CTRL_REG, &data, 1);

Above code is some operation for initialize. I migrate uc/os III for this project. followed code is some operation for collecting:

void App_Task_Gyroscope(void *pdata)
  UINT8 fifostate = 0;
  UINT8 X_L = 0, X_H = 0;
  UINT8 Y_L = 0, Y_H = 0;
  UINT8 Z_L = 0, Z_H = 0;
  INT16 X = 0, Y = 0, Z = 0;
  char buf[1024];
    fifostate = HALAPI_IIC_Read_Byte(L3GD20_Add, FIFO_SRC_REG);/*<! FIFO register */
    if((fifostate & (UINT8)(1<<6)) == 1)
      printf("fifo overflow");
      while(1) {}
    /*<! watermark signal */
    if((fifostate & (UINT8)(1<<5)) == 0)
        X_L = HALAPI_IIC_Read_Byte(L3GD20_Add, OUT_X_L);
        X_H = HALAPI_IIC_Read_Byte(L3GD20_Add, OUT_X_H);    
        Y_L = HALAPI_IIC_Read_Byte(L3GD20_Add, OUT_Y_L);
        Y_H = HALAPI_IIC_Read_Byte(L3GD20_Add, OUT_Y_H);    
        Z_L = HALAPI_IIC_Read_Byte(L3GD20_Add, OUT_Z_L);
        Z_H = HALAPI_IIC_Read_Byte(L3GD20_Add, OUT_Z_H);
        X = (INT16)(((UINT16)X_H<<8) | X_L);
        Y = (INT16)(((UINT16)Y_H<<8) | Y_L);
        Z = (INT16)(((UINT16)Z_H<<8) | Z_L);
        sprintf(buf, "%d %d %d\n", X, Y, Z);
        debugOutput(buf, strlen(buf));

By the end, sorry to get pictures of my setup because the size of board is so small. Can you find some quesiton from code? May be some problem existed when setting control register of gyroscope. Very appreciate for you help!

You might refer to our Arduino libary for the L3G gyros to see how we set the control registers. By the way in your first post, it looks like some of the readings repeat. I suspect that you are taking readings faster than what the device is sampling at.

- Jeremy

yeah, you are right, I have also notice that seems to read FIFO repeatly. This app is just a test version and only run in one task in ucos like a singl thread and reading speed is too fast. Thanks for your tips. I will check Arduino libary later. Now, I want ask another question:

From some other’s answer I find there is more noise existed in my data, at least seems to be like that in my opinion. so I want to know, If I get some new data later, how can I decide it’s good or bad data? whether the noise is distributed in normal level? I try to get standard noise range from datasheet but looks like no releated information has been detailed, so how to do it?

All the information we have for the L3GD20 gyro is from its datasheet. You should look at the digital zero-rate level and the rate noise density specifications to determine if the noise you are getting is within spec. By the way, as mentioned earlier in this thread, you might implement a moving average filter to smooth out the readings.

- Jeremy