I’m now working with mpu9250 for my master thesis, but I’m quite new to hardware device. My goal is to collect the data at the sample rate and postprocess these data via allan deviation. So I just want to get the data from 512 bytes fifo, but when I’m trying to read out the data, it always overflows which annoying me a lot.
I know the method is to set the reading speed faster than the fifo writing speed, so I remove the time sleep in my loop, but it seems overflows sooner than before. I’m a little bit confused, because the reading speed depends on the writing speed.
here are my code:
#!/usr/bin/env python3
import os
import time
import sys
import struct
import csv
from datetime import datetime
from mpu9250_FIFO import MPU9250
from navio.leds import Led
def main():
# Initialize MPU9250
mpu = MPU9250()
# Set maximum SPI bus speed in Hz, default=10000000
# MPU8250 features:
# -- 1MHz SPI serial interface for communicating with all registers
# -- 20MHz SPI serial interface for reading sensor and interrupt registers
mpu.bus_open(max_speed_hz=10000000) # Hz
# Initialize sensors
# samle_rate unit is Hz
# low_pass_filter_gt is the low pass filter for gyroscope and temperature sensors. possible values are:
# Gyroscope Sensor | Temperature Sensor | Bits
# 250 Hz | 4000 Hz | 0x00 NO_DLPF
# 184 Hz | 188 Hz | 0x01
# 92 Hz | 98 Hz | 0x02
# 41 Hz | 42 Hz | 0x03
# 20 Hz | 20 Hz | 0x04
# 10 Hz | 10 Hz | 0x05
# 5 Hz | 5 Hz | 0x06
# 3600 Hz | 4000 Hz | 0x07 NO_DLPF
# low_pass_filter_accel is the low pass filter for accelerometer, possible values are:
# Accelerometer Sensor | Bits
# 218.1 Hz | 0x00
# 218.1 Hz | 0x01
# 99 Hz | 0x02
# 44.8 Hz | 0x03
# 21.2 Hz | 0x04
# 10.2 Hz | 0x05
# 5.05 Hz | 0x06
# 420 Hz | 0x07 NO_DLPF
sampleRate = 50
sampleRateDiv = int(1000 / sampleRate - 1)
mpu.initialize(sample_rate_div=sampleRateDiv, low_pass_filter_gt=0x01, low_pass_filter_a=0x01)
# Set accelerometer scale, default is 16G
# BITS_FS_2G = 0x00
# BITS_FS_4G = 0x08
# BITS_FS_8G = 0x10
# BITS_FS_16G = 0x18
mpu.set_acc_scale(0x08) # +/-4G
# Set gyroscope scale, default is 2000DPS
# BITS_FS_250DPS = 0x00
# BITS_FS_500DPS = 0x08
# BITS_FS_1000DPS = 0x10
# BITS_FS_2000DPS = 0x18
mpu.set_gyro_scale(0x08) # +/-500dps
# Enable FIFO to collect data
mpu.enableFIFO(True)
# Test connection:
if mpu.testConnection():
print("Connection working.")
else:
print("Connection to one of the sensors is faulty.")
# find new filename
# fileending = 1
# while True:
# if os.path.isfile('/home/pi/Duan/Python/meas_data/mpufile_{}_IMU.txt'.format(fileending)) is True:
# fileending += 1
# else:
# break
#
# open('', '', 1) enables line buffering
# with open('/home/pi/Duan/Python/meas_data/mpufile_{}_IMU.txt'.format(fileending), 'w', 1) as dat_imu:
now = datetime.now().strftime('%d-%m-%Y_%H:%M:%S')
fname = '/home/pi/Duan/Python/meas_data/mpu9250_data_' + now + r'.txt'
with open(fname, 'w', 1) as data_imu:
# write headers to file
data_imu.write('Sample Rate: %d Hz\n' % sampleRate)
data_imu.write('mpu_accel_1, mpu_accel_2, mpu_accel_3, mpu_gyro_1, mpu_gyro_2, mpu_gyro_3, temp\n')
#print("----1----")
# Main loop
while True:
mpudata_a, mpudata_g, mpudata_temp = mpu.getFIFOData()
#print("----2----")
data = mpudata_a + mpudata_g + mpudata_temp
# print(data)
data_imu.write(str(data).replace("[", "").replace("]", "") + "\n")
if __name__ == "__main__":
led = Led()
led.setColor('Green')
errfile = "/home/pi/Duan/Python/errorfile.txt"
with open(errfile, 'w', 1) as efile:
try:
main()
except KeyboardInterrupt:
led.setColor('Yellow')
except Exception as e:
led.setColor('Red')
efile.write("Some error occured:\n{}".format(e))
def getFIFOData(self):
while True:
mpu_int_status = self.getIntStatus()
INT_FIFO_OFLOW_BIT = 0x10 # the 4th bit is set to 1 when FIFO buffer is overflowed
fifoCount = self.getFIFOCount()
#print("fifoCount:%d" % fifoCount)
if fifoCount < 14:
continue
# check for overflow (this shouldn't happen)
elif (mpu_int_status & 0x10 == 0x10) or fifoCount>=512:
print("fifoCount is: %d" % fifoCount)
print("FIFO is overflow!")
# print("Reset FIFO...")
# self.resetFIFO()
break
else:
packet_count = int(fifoCount/14)
# print("packet count:%d" % packet_count)
for i in range(0, packet_count):
response = self.ReadRegs(self.__MPUREG_FIFO_R_W, 14)
# print(response)
# Get Accelerometer values
for i in range(0, 3):
data = self.byte_to_float(response[i * 2:i * 2 + 2])
self.accelerometer_data[i] = self.G_SI * data / self.acc_divider
# print(self.accelerometer_data)
# Get temperature
i = 3
temp = self.byte_to_float(response[i * 2:i * 2 + 2])
self.temperature[i - 3] = (temp / 333.87) + 21.0
# print(self.temperature)
# Get gyroscope values
for i in range(4, 7):
data = self.byte_to_float(response[i * 2:i * 2 + 2])
self.gyroscope_data[i - 4] = (self.PI / 180) * data / self.gyro_divider
# print(self.gyroscope_data)
return self.accelerometer_data, self.gyroscope_data, self.temperature
def getIntStatus(self):
return self.ReadReg(self.__MPUREG_INT_STATUS)
def getFIFOCount(self):
response = self.ReadRegs(self.__MPUREG_FIFO_COUNTH, 2)
fifoCount = self.byte_to_float(response)
return fifoCount
def resetFIFO(self):
self.WriteReg(self.__MPUREG_USER_CTRL, 0x00)
self.WriteReg(self.__MPUREG_USER_CTRL, 0x04) # reset fifo mode
self.WriteReg(self.__MPUREG_USER_CTRL, 0x40) # FIFO_EN
print('fifo is reset!')
def enableFIFO(self, flag):
self.WriteReg(self.__MPUREG_FIFO_EN, 0x00)
if flag:
self.resetFIFO()
self.WriteReg(self.__MPUREG_FIFO_EN, 0xF8)
print('fifo is enabled!')`
[![enter image description here][1]][1]
[1]: https://i.stack.imgur.com/SO7tN.png
migrated from arduino.stackexchange.com yesterday
This question came from our site for developers of open-source hardware and software that is compatible with Arduino.
-
Are you sure that this code runs on an Arduino UNO. I’m not an Arduino guru, but I don’t know any possibility to run python code on a Arduino UNO. And if you have a python question it would be better to ask on the python channel. From your code I would expect it runs on a raspberry pi. So the Raspi Channel would be a better choice to ask on. – Peter Paul Kiefer 2 days ago
-
yes,it runs on raspi – 段永旭 2 days ago
-
@段永旭, Ah let me see. If you don’t sleep, then you might be reading too fast. MPU9250 gyro max output data rate is only 8kHz. So it can’t follow and becomes crazy, buffer explodes, … 🙂 BTW, SPI 10MHz is too fast for testing. Try 1MHz and MPU9250 might like it. – tlfong01 yesterday
-
If you are attempting to read as fast as possible you should not be using Python. Are you sure Python can keep up with the data rate? – joan yesterday
-
@tlfong01, I’ve tried to set it to 1MHz, but it still overflows. And I check the time cost of my main loop, every time the reading is stucked due to some unknown reasons, and the time cost rises to 1or 2 seconds, and the fifo count is then over 512 and causes overflow. It’s quite annoying T_T – 段永旭 50 mins ago
-
@段永旭, Many thanks for reporting result on my suggestion. It seems obvious that the reading function is making all the trouble. But I think this problem seems not that difficult to solve. First thing first, my troubleshooting trick is to zoom the big picture into the problem area. I must confess I have not even skimmed through your frighteningly long code. But please confirm one thing: (1) Is it possible to REMOVE everything related to MPU9250? If yes, then write a short test WITHOUT this statement: “from mpu9250_FIFO import MPU9250”. I know I might be asking too much, but / continure, … – tlfong01 14 mins ago
-
Or (1) Just input the “from mpu9250_FIFO import MPU9250”, but do not feed real realtime input from MMPU9250. Instead DIY one, yes, just one fake test byte data into the buffer, and profile / time for one or repeat 10 times the time cost. So what I am suggest is 抽絲剝繭 to the very bottom layer, … Ah sorry, I need to go to meet a friend for dinner. So see you late this evening or tomorrow, or after weekend. Good luck and cheers. – tlfong01 6 mins ago
-
Similarly, when later using real data, there is no point mixing both gyro and accelero data. Remove either one to focus just one type of data. If you find the problem of gyro, of course you know accelero have the same cause. Similarly, when DIYing fake data, just use simple integer, not even floating point (OK, if you must use float point, then use int(float(123)), hopefully 水落 and 石出. Bye. – tlfong01 just now Edit
Categories: Uncategorized