Хранение данных акселерометра в SD-карте Raspberry Pi - PullRequest
2 голосов
/ 14 июня 2019

Я работаю над проектом, целью которого является сохранение данных об ускорении двигателя.Для этого я использую ускорение sesnsor adafruit mma8451.Теперь для хранения данных ускорения по 3 осям я использую Raspberry pi.Я пытаюсь сохранить данные в файле CSV.Теперь мне нужна система для хранения не менее 250 образцов в секунду.Теперь проблема в том, что малиновый пи хранится в одну секунду, может быть 230 выборок, в следующую секунду 210, а в следующую, может быть 225. Таким образом, в сущности, пи не стабилен на этой скорости.Если бы он хранил 230 сэмплов каждую секунду, это никогда не было бы проблемой.Но другое количество выборок не принимается, потому что мне нужна точная частота выборки для дальнейшего анализа сигнала.

Чтобы проверить, является ли это проблемой с хранением данных в CSV-файле, я попытался выяснить, может ли пипечатать только 250 раз "Hello World" или нет.Кажется, это нестабильно, если я использую таймер с помощью команды time.sleep ().Теперь я хотел бы показать код, который я использую для своего проекта

count=0
Path = 0

with open('/home/pi/TrialV10/VibrationsDevice1.csv', 'a+') as csvfile:
    sensorwriter = csv.writer(csvfile) #, delimiter=' ',
                            #quotechar='|', quoting=csv.QUOTE_MINIMAL)
    sensorwriter.writerow(['Datetime', 'Time', 'X_Accel (m/s^2)', 'Y_Accel (m/s^2)', 'Z_Accel (m/s^2)', 'Count', 'Path'])



    if MotoDetection == 1:
        sensor.MotionSetup()
        while True:
            sensor.Motion()
            time.sleep(0)  
            if sensor.Motion() == True:
                if count==0:
                    TimeStart = time.time()
                    Timer = 0                    
                    pass
                while True: 
                    x, y, z = sensor.acceleration
                    time_now = datetime.datetime.now().strftime("%Y-%m-%d")
                    TimePresent = time.time()
                    Timer = TimePresent - TimeStart
                    X = x #+ Calcx
                    Y = y #+ Calcy
                    Z = z #+ Calcz
                    count = count + 1                  
                    print('DateTime={0}  Time ={1} X={2:0.3f} m/s^2  Y:{3:0.3f} m/s^2  Z:{4:0.3f} m/s^2 count={5}'.format(time_now, Timer, X, Y, Z, count))
                    sensorwriter.writerow([time_now, Timer, X, Y, Z, count])
                    time.sleep(0.004) 
                    if Timer > TimingA:
                        exit()

Ответы [ 2 ]

3 голосов
/ 14 июня 2019

Способ сделать это состоит в том, чтобы буферизовать показания датчиков и создать отдельный поток, записывающий их в файл группами. Например:

import threading
class FileWriterThread(threading.Thread):
    def __init__(self,filename,header):
        threading.Thread.__init__(self)
        self.buffer = []
        self.filename = filename
        self.header = header
    def run(self):
        with open(self.filename,"a+") as f:
            csvwriter = csv.writer(f)
            csvwriter.writerow(self.header)
            while True:
                time.sleep(1) #Wait 1 second between writes to the file.
                writebuffer = []
                while len(self.buffer) > 0: #Clear the current buffer
                    writebuffer.append(self.buffer.pop(0))
                while len(writebuffer) > 0:
                    csvwriter.writerow(writebuffer.pop(0))
    def writerow(self,row):
        self.buffer.append(row)

Чтобы открыть файл и запустить поток, вы должны выполнить:

sensorwriter = FileWriterThread(filename,header)
sensorwriter.start()

Чтобы сохранить строку для записи в файл, вы должны использовать:

sensorwriter.writerow(row)

Наконец, чтобы остановить поток и сохранить файл, вы должны использовать:

sensorwriter.cancel()

Просто помните, что вам нужно создать новый поток, чтобы перезапустить его. Реализовано в ваш текущий код, это приведет к:

import threading
class FileWriterThread(threading.Thread):
    def __init__(self,filename,header):
        threading.Thread.__init__(self)
        self.buffer = []
        self.filename = filename
        self.header = header
    def run(self):
        with open(self.filename,"a+") as f:
            csvwriter = csv.writer(f)
            csvwriter.writerow(self.header)
            while True:
                time.sleep(1) #Wait 1 second between writes to the file.
                writebuffer = []
                while len(self.buffer) > 0: #Clear the current buffer
                    writebuffer.append(self.buffer.pop(0))
                while len(writebuffer) > 0:
                    csvwriter.writerow(writebuffer.pop(0))
    def writerow(self,row):
        self.buffer.append(row)

sensorwriter = FileWriterThread('/home/pi/TrialV10/VibrationsDevice1.csv',['Datetime', 'Time', 'X_Accel (m/s^2)', 'Y_Accel (m/s^2)', 'Z_Accel (m/s^2)', 'Count', 'Path'])
sensorwriter.start()

count=0
Path = 0

if MotoDetection == 1:
    sensor.MotionSetup()
    while True:
        sensor.Motion()
        time.sleep(0)  
        if sensor.Motion() == True:
            if count==0:
                TimeStart = time.time()
                Timer = 0                    
                pass
            while True: 
                x, y, z = sensor.acceleration
                time_now = datetime.datetime.now().strftime("%Y-%m-%d")
                TimePresent = time.time()
                Timer = TimePresent - TimeStart
                X = x #+ Calcx
                Y = y #+ Calcy
                Z = z #+ Calcz
                count = count + 1                  
                print('DateTime={0}  Time ={1} X={2:0.3f} m/s^2  Y:{3:0.3f} m/s^2  Z:{4:0.3f} m/s^2 count={5}'.format(time_now, Timer, X, Y, Z, count))
                sensorwriter.writerow([time_now, Timer, X, Y, Z, count])
                time.sleep(0.004) 
                if Timer > TimingA:
                    sensorwriter.cancel()
                    exit()

Надеюсь, это поможет.

Редактировать: Похоже, что проблема не связана с файловым вводом-выводом, и скорее всего, вместо этого связана с оператором печати. Печать текста на консоль нестабильна, и именно это на самом деле вызывает проблемы со стабильностью. К сожалению, сделать его стабильным на 100% невозможно, однако вы можете немного стабилизировать его, заменив

print('DateTime={0}  Time ={1} X={2:0.3f} m/s^2  Y:{3:0.3f} m/s^2  Z:{4:0.3f} m/s^2 count={5}'.format(time_now, Timer, X, Y, Z, count))

с

sys.stdout.write('DateTime={0}  Time ={1} X={2:0.3f} m/s^2  Y:{3:0.3f} m/s^2  Z:{4:0.3f} m/s^2 count={5}\n'.format(time_now, Timer, X, Y, Z, count))

, поскольку sys.stdout.write () выглядит более стабильным, чем print (). Просто не забудьте импортировать sys в начале программы. К сожалению, всегда будет некоторая нестабильность, в зависимости от того, какие другие задачи в данный момент выполняется ОС.

Один из способов добиться максимальной стабильности - попытаться ограничить частоту дискретизации. Поставь код

import time
SAMPLERATE = 150 #Number of samples per second.
SAMPLEDELAY = 1/SAMPLERATE
loopwait = 0

в начале вашей программы и код

while time.time() < loopwait:
    pass
loopwait = time.time()+SAMPLEDELAY

как первая инструкция в вашем цикле while True. Это делает окончательный код:

import threading,time
class FileWriterThread(threading.Thread):
    def __init__(self,filename,header):
        threading.Thread.__init__(self)
        self.buffer = []
        self.filename = filename
        self.header = header
    def run(self):
        with open(self.filename,"a+") as f:
            csvwriter = csv.writer(f)
            csvwriter.writerow(self.header)
            while True:
                time.sleep(1) #Wait 1 second between writes to the file.
                writebuffer = []
                while len(self.buffer) > 0: #Clear the current buffer
                    writebuffer.append(self.buffer.pop(0))
                while len(writebuffer) > 0:
                    csvwriter.writerow(writebuffer.pop(0))
    def writerow(self,row):
        self.buffer.append(row)

sensorwriter = FileWriterThread('/home/pi/TrialV10/VibrationsDevice1.csv',['Datetime', 'Time', 'X_Accel (m/s^2)', 'Y_Accel (m/s^2)', 'Z_Accel (m/s^2)', 'Count', 'Path'])
sensorwriter.start()

SAMPLERATE = 150 #Number of samples per second
SAMPLEDELAY = 1/SAMPLERATE
loopwait = 0

count=0
Path = 0

if MotoDetection == 1:
    sensor.MotionSetup()
    while True:
        sensor.Motion()
        time.sleep(0)  
        if sensor.Motion() == True:
            if count==0:
                TimeStart = time.time()
                Timer = 0                    
                pass
            while True: 
                while time.time() < loopwait:
                    pass
                loopwait = time.time()+SAMPLEDELAY
                x, y, z = sensor.acceleration
                time_now = datetime.datetime.now().strftime("%Y-%m-%d")
                TimePresent = time.time()
                Timer = TimePresent - TimeStart
                X = x #+ Calcx
                Y = y #+ Calcy
                Z = z #+ Calcz
                count = count + 1                  
                sys.stdout.write('DateTime={0}  Time ={1} X={2:0.3f} m/s^2  Y:{3:0.3f} m/s^2  Z:{4:0.3f} m/s^2 count={5}\n'.format(time_now, Timer, X, Y, Z, count))
                sensorwriter.writerow([time_now, Timer, X, Y, Z, count])
                time.sleep(0.004) 
                if Timer > TimingA:
                    sensorwriter.cancel()
                    exit()

К сожалению, на самом деле нет способа обеспечить постоянную скорость измерения, однако этот код должен помочь сделать ее более последовательной, чем раньше. Надеюсь, это поможет.

1 голос
/ 14 июня 2019

Сохраните данные во внутреннем буфере и очистите буфер, если вы достигнете количества отсчетов и запишите данные в файл CSV. Вот пример (не проверено):

Buffer = list()
Count = 0

if(MotoDetection == 1):
    sensor.MotionSetup()
    while True:
        sensor.Motion()
        if(sensor.Motion() == True):
            if(count == 0):
                TimeStart = time.time()
                Timer = 0
            else: 
                x, y, z = sensor.acceleration
                time_now = datetime.datetime.now().strftime("%Y-%m-%d")
                TimePresent = time.time()
                Timer = TimePresent - TimeStart
                X = x #+ Calcx
                Y = y #+ Calcy
                Z = z #+ Calcz
                count = count + 1

                Buffer.append([time_now, Timer, X, Y, Z])

                time.sleep(0.004)

                if(len(Buffer) == 230):

                    del Buffer

                    # Save the buffer
                    with open('/home/pi/TrialV10/VibrationsDevice1.csv', 'a+') as csvfile:
                        for Entry in Buffer:
                            csvfile.write(str(Entry) + ";")
...