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.