DAQ Trigger Setup and Control

Questions and discussion about The WiPy board.
You can buy one at the store.
Target audience: Users with a WiPy.
machdisk
Posts: 10
Joined: Sun May 22, 2016 1:35 am

DAQ Trigger Setup and Control

Postby machdisk » Sun Jun 26, 2016 3:28 am

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

User avatar
pythoncoder
Posts: 1439
Joined: Fri Jul 18, 2014 8:01 am

Re: DAQ Trigger Setup and Control

Postby pythoncoder » Sun Jun 26, 2016 6:57 am

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

machdisk
Posts: 10
Joined: Sun May 22, 2016 1:35 am

Re: DAQ Trigger Setup and Control

Postby machdisk » Sun Jun 26, 2016 2:09 pm

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

User avatar
dhylands
Posts: 2318
Joined: Mon Jan 06, 2014 6:08 pm
Location: Shuswap, BC, Canada
Contact:

Re: DAQ Trigger Setup and Control

Postby dhylands » Sun Jun 26, 2016 10:41 pm

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.

machdisk
Posts: 10
Joined: Sun May 22, 2016 1:35 am

Re: DAQ Trigger Setup and Control

Postby machdisk » Sun Nov 06, 2016 5:39 am

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.

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)


User avatar
Roberthh
Posts: 583
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: DAQ Trigger Setup and Control

Postby Roberthh » Sun Nov 06, 2016 8:23 am

You could increment a global value in the callback and look in the REPL, whether it changes or not.

machdisk
Posts: 10
Joined: Sun May 22, 2016 1:35 am

Re: DAQ Trigger Setup and Control

Postby machdisk » Sun Nov 06, 2016 2:29 pm

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?

machdisk
Posts: 10
Joined: Sun May 22, 2016 1:35 am

Re: DAQ Trigger Setup and Control

Postby machdisk » Mon Nov 07, 2016 12:53 am

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

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)



Return to “The WiPy”

Who is online

Users browsing this forum: No registered users and 1 guest