How to avoid MPU9250 FIFO overflow? - python-3.x

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.
#!/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()
mpu.bus_open(max_speed_hz=10000000) # Hz
sampleRate = 50
sampleRateDiv = int(1000 / sampleRate - 1)
mpu.initialize(sample_rate_div=sampleRateDiv, low_pass_filter_gt=0x01, low_pass_filter_a=0x01)
mpu.set_acc_scale(0x08) # +/-4G
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.")
now = datetime.now().strftime('%d-%m-%Y_%H:%M:%S')
fname = '/home/pi/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")
# FIFO READ AND WRITE
# FIFO_R_W REGISTER:
# This register is used to read and write data from the FIFO buffer. Data is written to the FIFO
# in order of register number (from lowest to highest). If all the FIFO enable flags are enabled
# and all External Sensor Data registers (Registers 73 to 96) are associated with a Slave device,
# the contents of registers 59 through 96 will be written in order that the Sample Rate.
# The contents of the sensor data registers (Registers 59 to 96) are written into the FIFO buffer
# when their corresponding FIFO enable flags are set to 1 in FIFO_EN (Register 35). An additional
# flag for the sensor data registers associated with I2C Slave 3 can be found in I2C_MST_CTRL
# (Register 46).
# If the FIFO buffer has overflowed, the status bit FIFO_OFLOW_INT is automatically set to 1.
# This bit is located in INT_STATUS (Register 58). When the FIFO buffer has overflowed, the
# oldest data will be lost and new data will be written to the FIFO.
# If the FIFO buffer is empty, reading this register will return the last byte that was previously
# read from the FIFO until new data is available. The user should check FIFO_COUNT to ensure that
# the FIFO is not read when empty.
# -----------------------------------------------------------------------------------------------
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!')
I hope to get a constant fifo reading without overflow.

Related

why SFTP parallel upload of a file is giving me recursive appended data?

I am trying to split a file into chunks and use threads to write to a file in the SFTP server.
The file name: hi.txt
The data:
hi....
file upload check.
The code to upload:
threads_count = 4
data_ap = {}
size = os.path.getsize(local_path)
part_size = int(size / threads_count)
lock = threading.Lock()
def open_ssh():
# ssh connection codes
return ssh
def upload_part(num, offset, part_size, remote_path_part):
#print(f"Running thread {num}")
try:
ssh = open_ssh()
sftp = ssh.open_sftp()
with open(local_path, "rb") as fl:
fl.seek(offset)
with lock:
with sftp.open(remote_path_part, "ab") as fr:
fr.set_pipelined(True)
size = 0
while size < part_size:
s = 32768
if size + s > part_size:
s = part_size - size
data = fl.read(s)
data_ap[num] = data
print(data)
# print({offset : data})
fr.write(str(data_ap))
#fr.write(data)
size += len(data)
if len(data) == 0:
break
except (paramiko.ssh_exception.SSHException) as x:
print(f"Thread {num} failed: {x}")
#print(f"Thread {num} done")
#ssh.close()
#start_time = time.time()
print("Starting")
offset = 0
threads = []
part_filenames = []
for num in range(threads_count):
if num == threads_count - 1:
part_size = size - offset
#remote_path_part = f"{remote_path}.{num}"
args = (num, offset, part_size, remote_path)
#print(f"Starting thread {num} offset {offset} size {part_size} " + f"part name {remote_path}")
thread = threading.Thread(target=upload_part, args=args)
threads.append(thread)
part_filenames.append(remote_path)
thread.start()
#print(f"Started thread {num}")
offset += part_size
for num in range(len(threads)):
#print(f"Waiting for thread {num}")
threads[num].join()
print("All thread done")
Now I have two problems.
First:
I am not getting the data sorted correctly since the data is divided across chunks I am getting different order
in the uploaded file
The uploaded data:
upload check. code to uploadhi ... the
Second:
To solve the above issue, I thought of using a dictionary where the key is the thread, and the value is the data, and during the download, I will reconstruct the file by order of the key. But I am getting the data recursively added like this.
The uploaded data:
{0: b'file uploa'}{0: b'file uploa', 1: b'd check.\nc'}{0: b'file uploa', 1: b'd check.\nc', 3: b' if appends'}{0: b'file uploa', 1: b'd check.\nc', 3: b' if appends', 2: b'heck again'}
How to fix this?
It would be preferable to fix the First part wherein I do not have to use any dictionary to rearrange the data when uploaded.
Reference for the upload code

how do i strip down a tuple from sqlite so i can use it as a float in python?

i am trying to use a single data reading from a sqlite3 file it is returned to me in the following way (25.5,) format. my next part of the script i want to be able to trigger a GPIO pin output to turn on a relay when the temperature drops below a certain point and off again once it gets above another point. my code is as follows
import RPi.GPIO as GPIO
import time
import sqlite3
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
#GPIO.setup(18, GPIO.OUT)
# Set up all variables #
temp_min = 25.375
temp_max = 25.5
#############
# Main Loop #
#############
while True:
def display_5sec_data():
conn = sqlite3.connect('ds18b20.db')
c = conn.cursor()
c.execute("SELECT (display1) FROM aquarium2 ORDER BY rowid DESC LIMIT 1")
data1 = c.fetchone()
conn.close()
#return data1
print(data1)
Display = display_temp()
data1= (display_5sec_data())
if data1 <= 25.25 : # if temp is less or equal to 25 deg
print("heater on")
#GPIO.output(18, GPIO.HIGH)
if data1 >= 25.80 :
print("heater off")
#GPIO.output(18, GPIO.LOW)
time.sleep(10)
display_5sec_data()
any help would be great.
Sorted was an easy fix just wished i had played a little bit more with it. i just need to add float to the if statement
here is the code.
if float(data1[0]) >= 25.60 :
print("heater off")
bus.write_pin(11, 0)
bus.write_pin(10, 0)
time.sleep(120)

I want to merge two codes but keep giving me an error

Hi I am new to python and I am trying to record the sound when there is loudness is over a certain value (in the code 200).
Initially, I had two different pieces of code. one for recording and one for the detecting loudness. I want to merge together and record the sound when the loudness is over 200.
But This keeps giving me an error so I am wondering which part am I missing.
I would very appreciate if some one help me to figure this out.
import time
import grovepi
import os
import sys
sys.path.insert(0,'.')
from audio import soundrecord
loudness_sensor = 0
while True:
try:
# Read the sound level
sensor_value = grovepi.analogRead(loudness_sensor)
print("sensor_value = %d" %sensor_value)
time.sleep(.5)
if sensor_value> 200:
soundrecord()
time.sleep(10)
except IOError:
print ("Error")
I defined the below recording code as a soundrecord function and put it in the same directory
import pyaudio
import wave
def soundrecord():
form_1 = pyaudio.paInt16 # 16-bit resolution
chans = 1 # 1 channel
samp_rate = 44100 # 44.1kHz sampling rate
chunk = 4096 # 2^12 samples for buffer
record_secs = 3 # seconds to record
dev_index = 2 # device index found by p.get_device_info_by_index(ii)
wav_output_filename = 'test1.wav' # name of .wav file
audio = pyaudio.PyAudio() # create pyaudio instantiation
# create pyaudio stream
stream = audio.open(format = form_1,rate = samp_rate,channels = chans, \
input_device_index = dev_index,input = True, \
frames_per_buffer=chunk)
print("recording")
frames = []
# loop through stream and append audio chunks to frame array
for ii in range(0,int((samp_rate/chunk)*record_secs)):
data = stream.read(chunk)
frames.append(data)
print("finished recording")
# stop the stream, close it, and terminate the pyaudio instantiation
stream.stop_stream()
stream.close()
audio.terminate()
# save the audio frames as .wav file
wavefile = wave.open(wav_output_filename,'wb')
wavefile.setnchannels(chans)
wavefile.setsampwidth(audio.get_sample_size(form_1))
wavefile.setframerate(samp_rate)
wavefile.writeframes(b''.join(frames))
wavefile.close()
expecting: Record the sound when the loudness is over 200
actual :
sensor_value = 75
sensor_value = 268
Error
sensor_value = 360
Error
sensor_value = 48
sensor_value = 39
sensor_value = 79

Using Python to read a nonfixed number of bytes through Serial

I am trying to read a nonfixed number of bytes from the Serial port. I can use read to read a fixed number of bytes, putting in a larger number than the actual number of bytes present, will cause it to wait forever. Putting in a smaller number than the actual number of bytes present will crop some of the characters out. Using read_all, the output seems to be blank. Readline() is yielding syntax error. I ran out of ideas, any ideas? Here is my code:
import time
import datetime
import serial
import os
# public variables
sensors = [] # list of sensor readings
wait = True
sensor_count = 10 # the zero based count of sensors
def pwr_solenoid(solenoid0=0, solenoid1=0, solenoid2=0, solenoid3=0):
# Defaults are for low signal values
# compile output
output = '9{solenoid0}{solenoid1}{solenoid2}{solenoid3}' \
.format(solenoid0=solenoid0, solenoid1=solenoid1, solenoid2=solenoid2, solenoid3=solenoid3).encode()
with serial.Serial('/dev/ttyACM0', baudrate=9600) as ser:
print("created connection to '/dev/ttyACM0'\n")
print("going to send:\t'{}'".format(output))
ser.write(output)
ser.reset_output_buffer()
# for testing to console
print("Value sent to the uC:\t'{}'".format(output.decode()))
# ***** READ from UART *****
#ser.in_waiting >= 12:
raw = ser.read(16)
print("printing raw value of ser.read(16)\n")
print(raw)
val = str(ser.read_all().decode()) # (3).decode()[2:])
#printing val
print("\n printing val using read_all \n")
print(val)
val1 = raw.decode()
#printing val of raw.decode()
print("\n pringting val of raw.decode() \n")
print(val1)
# print("printing value of ser.readline()\n"
# serreadlin = ser.readline() This line generates an error cannot use readline()
# print(serreadlin)
# print("printing val\n")
# print(val)
# exit()
You can use:
import serial
import time
ser = serial.Serial(port='/dev/ttyUSB0', baudrate=115200, timeout=1)
while True:
val = ser.readline().strip()
if(val):
print (val)

How to implement High pass audio filter for a wav file in python

I am working on a project related to audio processing and I want to implement a high pass audio filter for some wave files stored in memory and on live speech also. I found some previously asked question here related to my problem but not exactly like
1-> Python scipy.signal.remez high pass filter design yields strange transfer function
2-> Python: High Pass FIR Filter by Windowing
but I am not getting how can I modify the available code for saved audio files and for live speech also .
i have found a piece of code for low pass filter for saved audio file which is working fine but I am unable to find one for high pass filter.
file_input = '3.wav'
file_output = 'filter.wav'
cutOffFrequency = 400.0
def running_mean(x, windowSize):
cumsum = np.cumsum(np.insert(x, 0, 0))
return (cumsum[windowSize:] - cumsum[:-windowSize]) / windowSize
def interpret_wav(raw_bytes, n_frames, n_channels, sample_width, interleaved = True):
if sample_width == 1:
dtype = np.uint8
elif sample_width == 2:
dtype = np.int16
else:
raise ValueError("Only supports 8 and 16 bit audio formats.")
channels = np.fromstring(raw_bytes, dtype=dtype)
if interleaved:
channels.shape = (n_frames, n_channels)
channels = channels.T
else:
channels.shape = (n_channels, n_frames)
return channels
with contextlib.closing(wave.open(file_input,'rb')) as spf:
sampleRate = spf.getframerate()
ampWidth = spf.getsampwidth()
nChannels = spf.getnchannels()
nFrames = spf.getnframes()
signal = spf.readframes(nFrames*nChannels)
spf.close()
channels = interpret_wav(signal, nFrames, nChannels, ampWidth, True)
freqRatio = (cutOffFrequency/sampleRate)
N = int(math.sqrt(0.196196 + freqRatio**2)/freqRatio)
filtered = running_mean(channels[0], N).astype(channels.dtype)
wav_file = wave.open(file_output, "w")
wav_file.setparams((1, ampWidth, sampleRate, nFrames, spf.getcomptype(), spf.getcompname()))
wav_file.writeframes(filtered.tobytes('C'))
wav_file.close()
This is the code I am using for low pass filter .

Resources