logging data on SD at constant frequency
Posted: Mon Mar 04, 2019 11:10 am
Hello,
I am kind of new to pyboard and thus maybe the answer is available somewhere but I haven't found it. Here is my problem : I am using the pyboard to sample voltage from a sensor. I need the acquisition to be at high frequency and rather constant. The issue is that as soon as I start writing to the SD, the code slows down... I can't figure out how to prevent this while continuously saving the data... Here is the code I use. It is largely inspired from this topic :
viewtopic.php?t=601
[code]
# main.py -- put your code here!
import pyb
import micropython
import os
import sys
micropython.alloc_emergency_exception_buf(200)
#LED 1 is red
#LED 2 is green
#LED 3 is orange
#LED 4 is blue
class T_4(object):
def __init__(self):
# Initialise timer 4 and ADC
self.status = 'Sample'
self.file = open('log.txt','w')
self.tim = pyb.Timer(4)
self.tim.init(freq=1000)
self.set_start()
self.adc = pyb.ADC('X1')
self.buf_index = 0
self.meanval = 3500
self.stdval = 100
self.tempval = 0
self.buf_flag = 0
self.buf_0 = [[0, 0] for i in range(1000)]
self.buf_1 = [[0, 0] for i in range(1000)]
self.tim.callback(self.t_4_callback)
def set_start(self):
# Remember time of start
self.t_start = pyb.micros()
def store_data_0(self):
self.status = 'log'
# Store buffer data to log file
for i in range(len(self.buf_0)):
t = self.buf_0[i][0]
d = self.buf_0[i][1]
value_string = '%i \t %i\n' %(t, d)
self.file.write(value_string)
def store_data_1(self):
# Store buffer data to log file
self.status = 'Log'
for i in range(len(self.buf_0)):
t = self.buf_1[i][0]
d = self.buf_1[i][1]
value_string = '%i \t %i\n' %(t, d)
self.file.write(value_string)
def t_4_callback(self, tim):
# Read ADC value and current time
value = self.adc.read() - self.meanval
t = pyb.micros() - self.t_start
# Add value and time to buffer
if (self.buf_flag==0):
self.buf_0[self.buf_index][0] = t
self.buf_0[self.buf_index][1] = value
else:
self.buf_1[self.buf_index][0] = t
self.buf_1[self.buf_index][1] = value
# Increment buffer index until buffer is filled,
# then disable interrupt and change status
self.buf_index += 1
if (self.buf_index >= len(self.buf_0)):
self.buf_index = 0
if (self.buf_flag == 0):
self.status = 'Store_0'
else:
self.status = 'Store_1'
self.buf_flag += 1
if (self.buf_flag==2):
self.buf_flag =0
self.tempval = value
ledred = pyb.LED(1)
ledgreen = pyb.LED(2)
ledorange = pyb.LED(3)
ledblue = pyb.LED(4)
ledred.on()
info = open('info.txt','a')
info.write('\nStart the code\n')
info.close()
t = T_4()
pyb.delay(1000)
# Check if logging is finished, store data if so
# Was unable to call store data or call method storing data from callback
go_on = True
while (go_on):
if(t.status == 'Store_0'):
ledgreen.on()
t.store_data_0()
go_on = True
ledgreen.off()
elif (t.status == 'Store_1'):
ledgreen.on()
t.store_data_1()
t.status = 'Done'
go_on = False
ledgreen.off()
else :
pyb.delay(100)
t.tim.callback(None)
t.file.close()
ledgreen.off()
ledred.off()
[/code]
(Sorry my BBCode is not activated...)
This code is a bit silly but I am debugging right now. So the first 1000 points are correctly sampled but then once the SD card is used to write the performance drops... In this example it does only one loop. The goal is to continue with the two buffers in a loop.
I tried to avoid opening the file (this is why I added the t.file entry).
Any idea how to improve the performance?
I would like to get the highest possible frequency rate.
Thank you!
I am kind of new to pyboard and thus maybe the answer is available somewhere but I haven't found it. Here is my problem : I am using the pyboard to sample voltage from a sensor. I need the acquisition to be at high frequency and rather constant. The issue is that as soon as I start writing to the SD, the code slows down... I can't figure out how to prevent this while continuously saving the data... Here is the code I use. It is largely inspired from this topic :
viewtopic.php?t=601
[code]
# main.py -- put your code here!
import pyb
import micropython
import os
import sys
micropython.alloc_emergency_exception_buf(200)
#LED 1 is red
#LED 2 is green
#LED 3 is orange
#LED 4 is blue
class T_4(object):
def __init__(self):
# Initialise timer 4 and ADC
self.status = 'Sample'
self.file = open('log.txt','w')
self.tim = pyb.Timer(4)
self.tim.init(freq=1000)
self.set_start()
self.adc = pyb.ADC('X1')
self.buf_index = 0
self.meanval = 3500
self.stdval = 100
self.tempval = 0
self.buf_flag = 0
self.buf_0 = [[0, 0] for i in range(1000)]
self.buf_1 = [[0, 0] for i in range(1000)]
self.tim.callback(self.t_4_callback)
def set_start(self):
# Remember time of start
self.t_start = pyb.micros()
def store_data_0(self):
self.status = 'log'
# Store buffer data to log file
for i in range(len(self.buf_0)):
t = self.buf_0[i][0]
d = self.buf_0[i][1]
value_string = '%i \t %i\n' %(t, d)
self.file.write(value_string)
def store_data_1(self):
# Store buffer data to log file
self.status = 'Log'
for i in range(len(self.buf_0)):
t = self.buf_1[i][0]
d = self.buf_1[i][1]
value_string = '%i \t %i\n' %(t, d)
self.file.write(value_string)
def t_4_callback(self, tim):
# Read ADC value and current time
value = self.adc.read() - self.meanval
t = pyb.micros() - self.t_start
# Add value and time to buffer
if (self.buf_flag==0):
self.buf_0[self.buf_index][0] = t
self.buf_0[self.buf_index][1] = value
else:
self.buf_1[self.buf_index][0] = t
self.buf_1[self.buf_index][1] = value
# Increment buffer index until buffer is filled,
# then disable interrupt and change status
self.buf_index += 1
if (self.buf_index >= len(self.buf_0)):
self.buf_index = 0
if (self.buf_flag == 0):
self.status = 'Store_0'
else:
self.status = 'Store_1'
self.buf_flag += 1
if (self.buf_flag==2):
self.buf_flag =0
self.tempval = value
ledred = pyb.LED(1)
ledgreen = pyb.LED(2)
ledorange = pyb.LED(3)
ledblue = pyb.LED(4)
ledred.on()
info = open('info.txt','a')
info.write('\nStart the code\n')
info.close()
t = T_4()
pyb.delay(1000)
# Check if logging is finished, store data if so
# Was unable to call store data or call method storing data from callback
go_on = True
while (go_on):
if(t.status == 'Store_0'):
ledgreen.on()
t.store_data_0()
go_on = True
ledgreen.off()
elif (t.status == 'Store_1'):
ledgreen.on()
t.store_data_1()
t.status = 'Done'
go_on = False
ledgreen.off()
else :
pyb.delay(100)
t.tim.callback(None)
t.file.close()
ledgreen.off()
ledred.off()
[/code]
(Sorry my BBCode is not activated...)
This code is a bit silly but I am debugging right now. So the first 1000 points are correctly sampled but then once the SD card is used to write the performance drops... In this example it does only one loop. The goal is to continue with the two buffers in a loop.
I tried to avoid opening the file (this is why I added the t.file entry).
Any idea how to improve the performance?
I would like to get the highest possible frequency rate.
Thank you!