Способ сделать это состоит в том, чтобы буферизовать показания датчиков и создать отдельный поток, записывающий их в файл группами. Например:
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()
К сожалению, на самом деле нет способа обеспечить постоянную скорость измерения, однако этот код должен помочь сделать ее более последовательной, чем раньше.
Надеюсь, это поможет.