Estoy experimentando con un acelerómetro/giroscopio de seis ejes MPU6050 leyendo datos con una Raspberry Pi a través de I2C. La respuesta de seis ejes tiene sentido en general, ya que la giro con la mano, la rotación mueve el vector de gravedad correctamente según los canales del acelerómetro y las rotaciones cortas alrededor de cada eje generan valores de giroscopio que parecen razonables.
Pero cuando lo coloco en algo que debería aislarlo de las vibraciones y solo tomar datos durante mucho tiempo, veo un ruido extraño no estadístico en algunos canales.
Escribí un guión corto (que se muestra a continuación) que muestra los seis canales para 400 iteraciones, luego incrementa el filtro de paso bajo (siete niveles de a 0x00
) 0x06
y luego incrementa la ganancia tanto para aceleración como para giroscopio (cuatro niveles; 0x00, 0x08, 0x10, 0x18
). Son 28 pruebas con 400 muestras cada una. La tasa de datos es de aproximadamente 55 a 60 mediciones de los seis ejes por segundo. La frecuencia característica para cada configuración del filtro de paso bajo digital del mapa de registro pdf es:
y la ficha técnica en pdf .
A continuación muestro los datos que van desde -/+ 32.767. Lo único que he cambiado es restar la media de las 400 mediciones en cada configuración para que solo se muestre el ruido.
A medida que aumentan las siete configuraciones del filtro de paso bajo, la frecuencia disminuye y el ruido disminuye como se esperaba. Sin embargo, existen estos picos repentinos de +/- 200 a 300 recuentos de ADC. No son exactamente 256, pero en ese estadio de béisbol parece un poco sospechoso.
También muestro los datos sin procesar y las desviaciones estándar por prueba en la segunda gráfica.
Pregunta: ¿Este tipo de comportamiento, este ruido puntiagudo no estadístico, le parece familiar a alguien? Estoy esperando un segundo giroscopio para comparar, pero eso llevará muchos días y me gustaría ver si hay algo que pueda hacer mientras tanto. Cada uno de los seis canales tiene un comportamiento muy diferente al ruido. Dentro del IC hay seis dispositivos MEM separados, cada uno conectado a su propio ADC dedicado.
Script para que Raspberry Pi lea el módulo a través de 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()
Los errores parecen +/- 256 +/- desviación esperada.
Esto sugiere algún tipo de error de sincronización, como leer el LSByte de una muestra y el MSByte de la siguiente o viceversa. ¿Cómo maneja esto su giroscopio? ¿Hay alguna forma de ponerlo en espera temporalmente mientras lee los datos?
Además, examine los datos sin procesar en torno a algunos de estos errores para ver si sucede cuando una señal que se desplaza lentamente cruza un límite de MSByte. Obviamente, concéntrese en el Y Gyro, los errores se separan más claramente del ruido.
@BrianDrummong identificó la fuente del aparente ruido en la respuesta aceptada . La lectura de un byte a la vez en I2C dio como resultado un comportamiento asíncrono, de modo que los bytes alto y bajo correspondían a diferentes conversiones. El uso bus.read_i2c_block_data()
resolvió el problema de enganche. Al leer catorce bytes (siete palabras) (tres acelerómetros, temperatura, tres giroscopios) como una sola instrucción I2C, el "ruido" ha desaparecido.
def read_sevenblock():
# read fourteen bytes starting at address 0x3b. This will cycle through
# ax, ay, az, temp, gx, gy, and gz
fourteen_bytes = bus.read_i2c_block_data(0x68, 0x3b, 14) # Read them all at once
his, los = fourteen[0::2], fourteen[1::2] # high bytes are first
values = []
for hi, lo in zip(his, los):
value = (hi << 8) + lo # combine high and low byte
if value >= 0x8000:
value = -((65535 - value) + 1) # convert signed negative values
values.append(value)
return values
vals
? ¿Está en el siguiente orden: acc_x, acc_y, acc_z, temp, gyro_x, gyro_y, gyro_z? ¿ Puede explicar también por qué lo usamos 0x3b
en el comando? Pensé 0x3b
que es solo el registro para la aceleración en la dirección x.bus.read_i2c_block_data(0x68, 0x3b, 14)
dice que lea 14 bytes a partir de 0x3b
. Los ADC son de 12 bits, por lo que cada medida necesita dos bytes, para un total de 14 bytes. El orden es bits altos primero, luego bits bajos, por lo que debe combinar los dos con val = (hi << 8) + lo
(¡Ajá! ¡Hay un error tipográfico en mi guión!) Por cierto, para una lectura constante de mayor velocidad, también hay un FiFo disponible. Si pregunta sobre eso en una pregunta separada, puedo publicar ese script.
UH oh
UH oh
smbus
tienebus.read_word_data()
métodosbus.read_i2c_block_data()
, 1 , 2 . Lo intentaré y te comento que sucede.usuario_1818839
UH oh