In short I'm trying to use the wireless capabilities of the WIPY unit to transfer the data from a periodic timer loop linked to an ADC pin. I'm having a bit of trouble with the setup as I also need to sync the data acquisition with an external trigger. This brings up a few questions as to how use two timers, 1 to start filling the data array and another to how to pause the daq timer so we can transfer the data via WIPY.
How do I link the start of the periodic timer to the rising edge of a digital input and start a daq timer?
Can you pause and reinitialize a timer or do you need to bring the whole timer down and instantiate a new one?
Currently my DAQ class initializes a timer using the following lines:
#############
from machine import Timer, Pin, ADC
import os, time
import array
numPnts = 1024
dataArray = array.array('H', range(numPnts))
adc = ADC()
adcPin = adc.channel(pin = 'GP3')
tim = Timer(0, mode = Timer.PERIODIC, width = 32)
timChannel = tim.channel(Timer.A, freq = 40000)
timChannel.irq(handler=_addData_, trigger = Timer.TIMEOUT)
curPos = 0
def _addData_(timer):
dataArray[curPos] = adcPin()
curPos%numPnts
curPos+=1
###########
Any help would be appreciated.
Brian
DAQ Trigger Setup and Control
- pythoncoder
- Posts: 5956
- Joined: Fri Jul 18, 2014 8:01 am
- Location: UK
- Contact:
Re: DAQ Trigger Setup and Control
I'm no expert on the WiPy so I can't answer your main point, but the circular buffer in _addData_ looks wrong to me. Try this:
Code: Select all
curPos = 0
def _addData_(timer):
global curPos
dataArray[curPos] = adcPin()
curPos += 1 # fix modular arithmetic
curPos %= numPnts
Peter Hinch
Index to my micropython libraries.
Index to my micropython libraries.
Re: DAQ Trigger Setup and Control
Thanks for picking up upon that modulo error. It seems to me there would be a general need to find a way to pause or reinitialize a timer without setting the whole thing up. Then again maybe if there is a way to remove the callback temporarily that might work to. I just hoping there is a way to pause or start a timer that is fast and doesn't take a ton of clock cycles. Again, any help would be appreciated.
Brian
Brian
Re: DAQ Trigger Setup and Control
You can set the callback to None. The timer still runs, but the callback won't be called. You can then set the callback to non-None later on and the callback will then start getting called.
Re: DAQ Trigger Setup and Control
So I've been returning to this issue and am trying to figure the approach to stopping the callback in an elegant and defined fashion. I am trying to fill an array and essentially perform some signal averaging. To do this, my idea was to loop through the array a set number of times. The question is how to stop the timer from continuing to fill the array and then figure out how to save the data?
Right now I am setting the callback to none after a certain condition has been met in the callback. I'm not sure that this actually happening and given the fact that you can't print in a callback, I'm a little stumped as to how to debug this. Any help is appreciated.
Another interesting notion, is that if I try to put this in a class an run it via REPL then it routinely freezes. That is a minor point at this stage and the more pressing question is how to figure out how to stop it after the loop has moved through enough times.
Right now I am setting the callback to none after a certain condition has been met in the callback. I'm not sure that this actually happening and given the fact that you can't print in a callback, I'm a little stumped as to how to debug this. Any help is appreciated.
Another interesting notion, is that if I try to put this in a class an run it via REPL then it routinely freezes. That is a minor point at this stage and the more pressing question is how to figure out how to stop it after the loop has moved through enough times.
Code: Select all
from machine import Timer, Pin, ADC
import os, time
import array
import gc
def uniqid(prefix=''):#this is not unique enough--need to reevalute
m = time.time()
# uniqid = '%8x%05x' %(math.floor(m),(m-math.floor(m))*1000000)
uniqid = '%8x%05x'%((m,1))
uniqid = prefix + uniqid
return uniqid
def writeData(uniqid, dataArray):
t = time.time()
curDir = os.getcwd()
os.chdir("/sd")#change directory to SD card
try:
filePath = uniqid+'.txt'
f = open(filePath, 'w')
f.write("%s\n"%uniqid)
for d in dataArray:
f.write("%s,\n"%str(d))
f.close()
os.chdir(curDir)
except:
os.chdir(curDir)
print("Saving to %s failed"%fileName)
gc.collect()
print("Write Time: %s"%(time.time()-t))
numPnts = 1024
dataArray = array.array('H', 0 for x in range(numPnts))
adc = ADC()
adcPin = adc.channel(pin = 'GP3')
numAves = 10 #number of times to loop through array
curPos = 0
countDown = numPnts*numAves
tim = Timer(0, mode = Timer.PERIODIC, width = 32)
timChannel = tim.channel(Timer.A, freq = 40000)
def stopTimer(timer):
timer.deinit()
def _addData_(timer):
'''
How to stop this at the correct time?
'''
global curPos
global countDown
global dataArray
dataArray[curPos] = adcPin()
# dataArray[curPos] = countDown
curPos+=1
curPos%=numPnts
countDown-=1
if countDown<1:
timer.callback(None)#is this really happening?
timChannel.irq(handler=_addData_, trigger = Timer.TIMEOUT)
time.sleep_ms(1000)#wait until the loop is filled.
tim.deinit()
dataID = uniqid()
writeData(dataID, dataArray)
Re: DAQ Trigger Setup and Control
You could increment a global value in the callback and look in the REPL, whether it changes or not.
Re: DAQ Trigger Setup and Control
Ahh, yes that is a sound solution. I will surely give that a try. The one aspect I'm still not clear on is whether or not the timer callback is actually changed in the loop above. Is there anyway to confirm that the callback has been changed?
Re: DAQ Trigger Setup and Control
With some nudging from folks here on the forums (thank you), I feel like I'm on the right track. The challenge that I'm now facing is how to stop or change the callback correctly. From what I read there is some disagreement for the pyb vs the wipy timer function. As it stands I put in a global "triggerBool" into the following code and depending on whether you include the timer.callback(None) line and the location of the "triggerBool" the "timer.callback(None)" function does not seem to be implemented on the wipy. This is not surprising but brings up the question, do I simply deinit the timer or is there a more subtle way to do this?
For reference:
http://docs.micropython.org/en/latest/w ... ight=timer
vs.
http://docs.micropython.org/en/latest/p ... r.callback
For reference:
http://docs.micropython.org/en/latest/w ... ight=timer
vs.
http://docs.micropython.org/en/latest/p ... r.callback
Code: Select all
from machine import Timer, Pin, ADC
import os, time
import array
import gc
def uniqid(prefix=''):#this is not unique enough--need to reevalute
m = time.time()
# uniqid = '%8x%05x' %(math.floor(m),(m-math.floor(m))*1000000)
uniqid = '%8x%05x'%((m,1))
uniqid = prefix + uniqid
return uniqid
def writeData(uniqid, dataArray):
t = time.time()
curDir = os.getcwd()
os.chdir("/sd")#change directory to SD card
try:
filePath = uniqid+'.txt'
f = open(filePath, 'w')
f.write("%s\n"%uniqid)
for d in dataArray:
f.write("%s,\n"%str(d))
f.close()
os.chdir(curDir)
except:
os.chdir(curDir)
print("Saving to %s failed"%fileName)
gc.collect()
print("Write Time: %s"%(time.time()-t))
numPnts = 1024
dataArray = array.array('H', 0 for x in range(numPnts))
adc = ADC()
adcPin = adc.channel(pin = 'GP3')
numAves = 10 #number of times to loop through array
curPos = 0
countDown = numPnts*numAves
tim = Timer(0, mode = Timer.PERIODIC, width = 32)
timChannel = tim.channel(Timer.A, freq = 40000)
triggerBool = False
def stopTimer(timer):
timer.deinit()
def _addData_(timer):
'''
How to stop this at the correct time?
'''
global curPos
global countDown
global dataArray
global triggerBool
dataArray[curPos] = adcPin()
# dataArray[curPos] = countDown
curPos+=1
curPos%=numPnts
countDown-=1
if countDown<1:
# triggerBool = True
###Is these even the correct callback set function or is this syntax a holdover form pyb?
timer.callback(None)#is this really happening?
###
triggerBool = True
timChannel.irq(handler=_addData_, trigger = Timer.TIMEOUT)
time.sleep_ms(1000)#wait until the loop is filled.
# tim.deinit()
# dataID = uniqid()
# writeData(dataID, dataArray)