jupyterpidaq.DAQProc

  1# Separate process to read data from an analog to digital converter.
  2# It buffers the data so that a slow plotting process can run as slowly
  3# as necessary. The separate process takes advantage of timesliced multitasking
  4# to get reasonably consistent time spacing between the datapoints even when
  5# the drawing process gets bogged down.
  6# J. Gutow <gutow@uwosh.edu> May 19, 2019
  7# license GPL V3 or greater.
  8
  9# utilities for timing and queues
 10from collections import deque
 11import time
 12from jupyterpidaq.Boards.vernier.labquest import Board_LQ
 13
 14def DAQProc(whichchn, gains, avgtime, timedelta, DAQconn, DAQCTL):
 15    """
 16    This function is to be run in a separate thread to asynchronously
 17    communicate with the ADC board.
 18
 19    :param list whichchn: a list of dictionaries. Each dictionary is of the
 20     form:{'board': board_object, 'chnl': chnlID}.
 21
 22    :param list gains: a list of the numerical gain for each channel.
 23
 24    :param float avgtime: the averaging time in seconds for a data point.
 25
 26    :param float timedelta: the target time between data points.
 27
 28    :param pipe DAQconn: the connection pipe
 29
 30    :param pipe DAQCTL: the control pipe
 31
 32    :return: Data is returned via the pipes.
 33        On the DAQCTL pipe this only returns 'done'
 34        On the DAQconn pipe a list of lists with data is returned.
 35    """
 36    #f=open('daq.log','w')
 37    databuf = deque()
 38    collect = True
 39    transmit = False
 40    chncnt = 0
 41    for i in range(len(whichchn)):
 42        if (whichchn[i]):
 43            chncnt += 1
 44    starttime = time.time()
 45    while collect:
 46        pkg = []
 47        times = []
 48        values = []
 49        stdevs = []
 50        avg_stdevs = []
 51        avg_vdds = []
 52        calltime = time.time()
 53        for i in range(len(whichchn)):
 54            if (whichchn[i]):
 55                time.sleep(0.001)
 56                #f.write('Calling adc...')
 57                if isinstance(whichchn[i]["board"],Board_LQ):
 58                    v_avg, v_std, avg_std, meastime, vdd_avg = \
 59                    whichchn[i]['board'].V_oversampchan_stats(whichchn[i][
 60                                                                  'chnl'],
 61                                                              gains[i],
 62                                                              timedelta)
 63                else:
 64                    v_avg, v_std, avg_std, meastime, vdd_avg = \
 65                    whichchn[i]['board'].V_oversampchan_stats(whichchn[i][
 66                                                                   'chnl'],
 67                                                              gains[i],
 68                                                           avgtime)
 69                #f.write('Successful return from call to adc.\n')
 70                times.append(meastime - starttime)
 71                values.append(v_avg)
 72                stdevs.append(v_std)
 73                avg_stdevs.append(avg_std)
 74                avg_vdds.append(vdd_avg)
 75        pkg.append(times)
 76        pkg.append(values)
 77        pkg.append(stdevs)
 78        pkg.append(avg_stdevs)
 79        pkg.append(avg_vdds)
 80        databuf.append(pkg)
 81        #f.write('Buffer length: '+str(len(databuf))+'\n')
 82        #f.write('Buffer[0]: ' + str(databuf) + '\n')
 83        if DAQCTL.poll():
 84            CTLmsg = DAQCTL.recv()
 85            if (CTLmsg == 'Send' or CTLmsg == 'send'):
 86                transmit = True
 87            if (CTLmsg == 'Stop' or CTLmsg == 'stop'):
 88                collect = False
 89            #f.write('Received msg: '+str(CTLmsg)+'\n')
 90        if transmit:  # the other end is ready
 91            navail = len(databuf)
 92            nsend = 60
 93            if (navail <= 60):
 94                nsend = navail
 95            for i in range(nsend):
 96                DAQconn.send(databuf.popleft())
 97                #f.write('Sent '+str(nsend)+' buffer chunks.\n')
 98            transmit = False  # we've done our burst of sending.
 99        elapsedtime = time.time() - calltime
100        if elapsedtime < timedelta:
101            time.sleep(timedelta -elapsedtime- 0.002)
102    # We should now send anything left...
103    #f.write('Left in buffer: '+str(len(databuf))+'\n')
104    while len(databuf) > 1:
105        if DAQCTL.poll():
106            CTLmsg = DAQCTL.recv()
107            if (CTLmsg == 'Send' or CTLmsg == 'send'):
108                transmit = True
109        if transmit:  # the other end is ready
110            navail = len(databuf)
111            nsend = 60
112            if (navail <= 60):
113                nsend = navail
114            for i in range(nsend):
115                DAQconn.send(databuf.popleft())
116            transmit = False  # we've done our burst of sending.
117    DAQCTL.send('done')
118    # Wait a while to terminate so that the Pipe is up for the other end to
119    # collect the data.
120    #f.flush()
121    #f.close()
122    time.sleep(5)
123    return
def DAQProc(whichchn, gains, avgtime, timedelta, DAQconn, DAQCTL):
 15def DAQProc(whichchn, gains, avgtime, timedelta, DAQconn, DAQCTL):
 16    """
 17    This function is to be run in a separate thread to asynchronously
 18    communicate with the ADC board.
 19
 20    :param list whichchn: a list of dictionaries. Each dictionary is of the
 21     form:{'board': board_object, 'chnl': chnlID}.
 22
 23    :param list gains: a list of the numerical gain for each channel.
 24
 25    :param float avgtime: the averaging time in seconds for a data point.
 26
 27    :param float timedelta: the target time between data points.
 28
 29    :param pipe DAQconn: the connection pipe
 30
 31    :param pipe DAQCTL: the control pipe
 32
 33    :return: Data is returned via the pipes.
 34        On the DAQCTL pipe this only returns 'done'
 35        On the DAQconn pipe a list of lists with data is returned.
 36    """
 37    #f=open('daq.log','w')
 38    databuf = deque()
 39    collect = True
 40    transmit = False
 41    chncnt = 0
 42    for i in range(len(whichchn)):
 43        if (whichchn[i]):
 44            chncnt += 1
 45    starttime = time.time()
 46    while collect:
 47        pkg = []
 48        times = []
 49        values = []
 50        stdevs = []
 51        avg_stdevs = []
 52        avg_vdds = []
 53        calltime = time.time()
 54        for i in range(len(whichchn)):
 55            if (whichchn[i]):
 56                time.sleep(0.001)
 57                #f.write('Calling adc...')
 58                if isinstance(whichchn[i]["board"],Board_LQ):
 59                    v_avg, v_std, avg_std, meastime, vdd_avg = \
 60                    whichchn[i]['board'].V_oversampchan_stats(whichchn[i][
 61                                                                  'chnl'],
 62                                                              gains[i],
 63                                                              timedelta)
 64                else:
 65                    v_avg, v_std, avg_std, meastime, vdd_avg = \
 66                    whichchn[i]['board'].V_oversampchan_stats(whichchn[i][
 67                                                                   'chnl'],
 68                                                              gains[i],
 69                                                           avgtime)
 70                #f.write('Successful return from call to adc.\n')
 71                times.append(meastime - starttime)
 72                values.append(v_avg)
 73                stdevs.append(v_std)
 74                avg_stdevs.append(avg_std)
 75                avg_vdds.append(vdd_avg)
 76        pkg.append(times)
 77        pkg.append(values)
 78        pkg.append(stdevs)
 79        pkg.append(avg_stdevs)
 80        pkg.append(avg_vdds)
 81        databuf.append(pkg)
 82        #f.write('Buffer length: '+str(len(databuf))+'\n')
 83        #f.write('Buffer[0]: ' + str(databuf) + '\n')
 84        if DAQCTL.poll():
 85            CTLmsg = DAQCTL.recv()
 86            if (CTLmsg == 'Send' or CTLmsg == 'send'):
 87                transmit = True
 88            if (CTLmsg == 'Stop' or CTLmsg == 'stop'):
 89                collect = False
 90            #f.write('Received msg: '+str(CTLmsg)+'\n')
 91        if transmit:  # the other end is ready
 92            navail = len(databuf)
 93            nsend = 60
 94            if (navail <= 60):
 95                nsend = navail
 96            for i in range(nsend):
 97                DAQconn.send(databuf.popleft())
 98                #f.write('Sent '+str(nsend)+' buffer chunks.\n')
 99            transmit = False  # we've done our burst of sending.
100        elapsedtime = time.time() - calltime
101        if elapsedtime < timedelta:
102            time.sleep(timedelta -elapsedtime- 0.002)
103    # We should now send anything left...
104    #f.write('Left in buffer: '+str(len(databuf))+'\n')
105    while len(databuf) > 1:
106        if DAQCTL.poll():
107            CTLmsg = DAQCTL.recv()
108            if (CTLmsg == 'Send' or CTLmsg == 'send'):
109                transmit = True
110        if transmit:  # the other end is ready
111            navail = len(databuf)
112            nsend = 60
113            if (navail <= 60):
114                nsend = navail
115            for i in range(nsend):
116                DAQconn.send(databuf.popleft())
117            transmit = False  # we've done our burst of sending.
118    DAQCTL.send('done')
119    # Wait a while to terminate so that the Pipe is up for the other end to
120    # collect the data.
121    #f.flush()
122    #f.close()
123    time.sleep(5)
124    return

This function is to be run in a separate thread to asynchronously communicate with the ADC board.

Parameters
  • list whichchn: a list of dictionaries. Each dictionary is of the form:{'board': board_object, 'chnl': chnlID}.

  • list gains: a list of the numerical gain for each channel.

  • float avgtime: the averaging time in seconds for a data point.

  • float timedelta: the target time between data points.

  • pipe DAQconn: the connection pipe

  • pipe DAQCTL: the control pipe

Returns

Data is returned via the pipes. On the DAQCTL pipe this only returns 'done' On the DAQconn pipe a list of lists with data is returned.