在树莓派SD卡中存储加速度计数据

时间:2019-06-14 09:45:42

标签: python raspberry-pi accelerometer

我正在一个项目中,我的目标是存储来自电动机的加速度数据。为此,我正在使用adafruit mma8451加速度传感器。现在要存储3轴加速度数据,我正在使用Raspberry pi。我正在尝试将数据存储在CSV文件中。现在,我需要系统每秒至少存储250个样本。现在的问题是,覆盆子pi在一秒内可能存储230个样本,下一秒存储210个样本,下一秒可能存储225个样本。因此,基本上来说,pi在此速度下不稳定。如果每秒可以存储230个样本,那将永远不是问题。但是不接受不同数量的样本,因为我需要准确的采样频率来进一步分析信号。

要检查这是否是将数据存储在csv文件中的问题,我尝试查看pi是否只能打印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 个答案:

答案 0 :(得分:3)

执行此操作的一种方法是缓冲传感器读数,并有一个单独的线程将它们成组写入文件中。例如:

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()

希望这会有所帮助。

编辑:看来问题与文件I / O无关,而最有可能与打印语句有关。将文本打印到控制台是不稳定的,并且实际上是导致稳定性问题的原因。 不幸的是,没有办法使它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

作为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 :(得分:1)

将数据存储在内部缓冲区中,如果达到样本计数,则刷新缓冲区并将数据写入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) + ";")