I'm experimenting with an MPU6050 six-axis accelerometer/gyro reading data with a Raspberry Pi via I2C. The six-axis response makes sense in general as I rotate it by hand, rotating moves the gravity vector correctly per the accelerometer channels, and short rotations around each axis generate reasonable-looking gyroscope values.
But when I set it down on something that should isolate it from vibrations and just take data for a long time, I see strange non-statistical noise in some channels.
I wrote a short script (shown below) that samples all six channels for 400 iterations, then increments the low pass filter (seven levels from 0x00
to 0x06
) and then increments the gain for both accel and gyro (four levels; 0x00, 0x08, 0x10, 0x18
). So that's 28 tests with 400 samples each. The data rate is about 55 to 60 measurements of all six axes per second. The characteristic frequency for each setting of the digital low-pass filter from the register map pdf is:
and the data sheet pdf.
Below I show the data which ranges from -/+ 32,767. The only thing I've changed is to subtract the mean of the 400 measurements at each setting so just the noise is displayed.
As the seven low-pass filter settings increase, the frequency decreases and the noise decreases as expected. However, there are these sudden spikes of +/- 200 to 300 ADC counts. They are not exactly 256, but in that ballpark with seems slightly suspicious.
I also show the raw data and standard deviations per test in the second plot.
Question: Does this kind of behavior - this non-statistical, spiky noise - look familliar to anyone? I'm waiting on a second gyro to compare, but that will take many days, and I'd like to see if there is anything I can do in the mean time. Each of the six channels has a very different behavior wrt noise. Inside the IC there are six separate MEMs devices each connected to its own dedicated ADC.
Script for the Raspberry Pi to read the module via I2C:
#!/usr/bin/python
import web
import smbus
import math
import time
urls = ('/', 'index')
pwrmgmt_1 = 0x6b
pwrmgmt_2 = 0x6c
dlpf_set_addr = 0x1a
gyro_scale_addr = 0x1b
accel_scale_addr = 0x1c
scales = 0x00, 0x08, 0x10, 0x18
dlpfs = 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06
pairs = ((0x3b, 0x3c), (0x3d, 0x3e), (0x3f, 0x40),
(0x43, 0x44), (0x45, 0x46), (0x47, 0x48))
setups = []
for scale in scales:
for dlpf in dlpfs:
setups.append((scale, dlpf))
nsetups = len(setups)
bus = smbus.SMBus(1)
address = 0x68
ic = 0
isetup = 0
nsamples = 400
def read_six():
vals = []
for ahi, alo in pairs:
high = bus.read_byte_data(address, ahi)
low = bus.read_byte_data(address, alo)
val = (high << 8) + low
if val >= 0x8000:
val = -((65535 - val) + 1)
vals.append(val)
return vals
class index:
def GET(self):
global ic, nsamples
global isetup, nsetups, setups
global accel_scale_addr, gyro_scale_addr, dlpf_set_addr
six = read_six()
six_str = str(six)[1:-1]
ic += 1
if not ic % nsamples:
isetup += 1
scale, dlpf = setups[isetup % nsetups]
bus.write_byte_data(address, accel_scale_addr, scale)
bus.write_byte_data(address, gyro_scale_addr, scale)
bus.write_byte_data(address, dlpf_set_addr, dlpf)
return six_str + ", " + str(isetup)
if __name__ == "__main__":
# wake the 6050 up since it starts in sleep mode
bus.write_byte_dta(address, pwrmgmt_1, 0)
time.sleep(0.5)
scale, dlpf = setups[isetup]
bus.write_byte_data(address, accel_scale_addr, scale)
bus.write_byte_data(address, gyro_scale_addr, scale)
bus.write_byte_data(address, dlpf_set_addr, dlpf)
print "setup scale: ", scale
print "setup dlpf: ", dlpf
time.sleep(0.1)
ic = 0
app = web.application(urls, globals())
app.run()