jupyterpidaq.Boards.vernier.labquest

  1# Utility sampling routines Vernier LabQuest interfaces.
  2# Only Analog channels.
  3# J. Gutow <gutow@uwosh.edu> April 2023
  4# license GPL V3 or greater
  5import time
  6import numpy as np
  7from multiprocessing import Lock, Value
  8
  9import logging
 10
 11try:
 12    import labquest
 13    labquestdrvs = True
 14    starttime = Value('d',time.time())
 15    samples = []
 16    for k in range(3):
 17        samples.append(Value('i',0))
 18except Exception as e:
 19    print("\nLabQuest: "+str(e))
 20    labquestdrvs = False
 21
 22from jupyterpidaq.Boards import Board
 23
 24logger = logging.getLogger(__name__)
 25
 26# Optimized for Pi 3B+ for an installed ADS1115 ADC PiHAT. This is
 27# actually ignored by this board, but necessary for ADC call
 28# compatibility.
 29RATE = 500 #maximum 10 kHz
 30
 31def find_boards():
 32    """
 33    A rountine like this must be implemented by all board packages.
 34
 35    :return: list of LabQuests (Types too?)
 36    """
 37    boards = []
 38    # The following is a hack to get around the fact that the whole module
 39    # needs to be reinstantiated on the new thread. I think the best option
 40    # is to upon discovery spawn a process and then just communicate with it.
 41    if labquestdrvs:
 42        try:
 43            LabQuests = labquest.LabQuest()
 44            if LabQuests.open() == 0:
 45                # Count number of boards
 46                nboards = len(labquest.config.hDevice)
 47                # Close things
 48                LabQuests.close()
 49                # launch a process to talk to, need Pipes to communicate.
 50                from multiprocessing import Process, Pipe
 51                cmdsend, cmdrcv = Pipe()
 52                datasend, datarcv = Pipe()
 53                LQ = Process(target = LQProc,
 54                             args = (cmdrcv, datasend, starttime, samples))
 55                LQ.start()
 56                # append an object for each board that knows how to talk to the
 57                # process and get information from that particular device
 58                addr = 0
 59                for addr in range(nboards):
 60                    boards.append(Board_LQ(addr, cmdsend, datarcv))
 61                    addr+=1
 62        except Exception as e:
 63            print ("\nLabQuest(s) not found.", end='')
 64            logger.debug(e)
 65    return boards
 66
 67class Board_LQ(Board):
 68    """
 69    Class defining the properties of the analog-to-digital block of the
 70    LabQuests. Key characteristics:
 71
 72    * 3 channels (1, 2, 3) a range of +/- 10 V.
 73    * 12 bit resolution
 74    * Other available but not implemented facilities are Digital I/O.
 75    """
 76    def __init__(self, addr, send, rcv):
 77        super().__init__()
 78        self.name = 'LabQuest'
 79        self.vendor = 'Vernier'
 80        self.channels = (1, 2, 3)
 81        self.addr = addr
 82        self.send = send
 83        self.rcv = rcv
 84        self.Vdd = 5.00
 85        # samples taken from a channel and starttime kept track of in
 86        #  shared memory samples[i].value = # of samples taken from channel
 87        #   i. starttime.value = time.time() immediately after las clearing
 88        #   of the buffers.
 89
 90    def getsensors(self):
 91        """
 92        Return a list of valid sensor object names for this board.
 93        :return: list of classnames
 94        """
 95        sensorlist = ['RawAtoD',
 96                      'VernierSSTemp',
 97                      'VernierGasP',
 98                      'VernierGasP_OLD',
 99                      'VernierpH',
100                      'VernierFlatpH'
101                      ]
102        # TODO: extend this list as appropriate. You can get a full list
103        #  using the `Sensors.sensors.listSensors()` call.
104        # The main program will use this list to access the actual sensor
105        # objects when converting the raw board voltage and for producing
106        # a menu of valid options for this particular board.
107        return sensorlist
108
109    def V_oversampchan(self, chan, gain, avg_sec, data_rate=RATE):
110        """
111        This routine returns the average voltage for the channel
112        averaged at the default rate for the board and returns an
113        average and observed range.
114
115        Returns a tuple of the following 5 objects:
116            V_avg -- float, the averaged voltage
117
118            V_min -- float, the minimum voltage read during
119            the interval
120
121            V_max -- float, the maximum voltage read during the
122            interval
123
124            time_stamp -- float, the time at halfway through the averaging
125            interval in seconds since the beginning of the epoch (OS
126            dependent begin time)
127
128            Vdd_avg -- float, the reference voltage (Vdd) collected
129            simultaneously.
130
131        :param int chan: the channel number (1, 2, 3)
132
133        :param gain: ignored by board. Defaults to 1.
134
135        :param int data_rate: maximum
136
137        :param float avg_sec: seconds to average for, actual
138         averaging interval will be as close as possible for an integer
139         number of samples
140
141        :returns: V_avg, V_min, V_max, time_stamp, Vdd_avg
142        :return float V_avg: description
143        :return float V_min:
144        :return float V_max:
145        :return float time_stamp:
146        :return float Vdd_avg:
147        """
148        nsamples = round(data_rate*avg_sec)
149        self.send.send(['send',self.addr, chan, nsamples])
150        while not self.rcv.poll():
151            #we wait for data
152            pass
153        value = self.rcv.recv()
154        samples[chan - 1].value = samples[chan - 1].value + nsamples
155        endtime = starttime.value + samples[chan-1].value/data_rate
156        time_stamp = endtime - avg_sec / 2
157        ndata = len(value)
158        V_avg = sum(value) / ndata
159        Vdd_avg = 5.00
160        V_min = min(value)
161        V_max = max(value)
162        return V_avg, V_min, V_max, time_stamp, Vdd_avg
163
164    def V_oversampchan_stats(self, chan, gain, avg_sec, data_rate=RATE):
165        '''
166        This routine returns the average voltage for the channel
167        averaged at the maximum rate for the board. The standard
168        deviation and the estimated deviation of the mean are also
169        returned.
170
171        Returns a tuple of the following 5 objects:
172            V_avg -- float, the averaged voltage
173
174            stdev -- float, the standard deviation of the measured values
175            during the averaging interval
176
177            stdev_avg -- float, the estimated standard deviation of the
178            returned average
179
180            time_stamp -- float, the time at halfway through the averaging
181            interval in seconds since the beginning of the epoch (OS
182            dependent begin time)
183
184            Vdd_avg -- float, returned as None.
185
186        :param int chan: the channel number (1, 2, 3)
187
188        :param gain: ignored by board. Defaults to 1.
189
190        :param int data_rate:
191
192        :param float avg_sec: seconds to average for, actual
193         averaging interval will be as close as possible for an integer
194         number of samples
195
196        :returns: V_avg, stdev, stdev_avg, time_stamp, Vdd_avg
197        :return float V_avg:
198        :return float stdev:
199        :return float stdev_avg:
200        :return float time_stamp:
201        :return float Vdd_avg:
202        '''
203        nsamples = round(data_rate * avg_sec)
204        self.send.send(['send', self.addr, chan, nsamples])
205        while  not self.rcv.poll():
206            # we wait for data
207            pass
208        value = self.rcv.recv()
209        samples[chan - 1].value = samples[chan - 1].value + nsamples
210        endtime = starttime.value + samples[chan-1].value/data_rate
211        time_stamp = endtime - avg_sec / 2
212        ndata = len(value)
213        V_avg = sum(value) / ndata
214        Vdd_avg = 5.00
215        stdev = np.std(value, ddof=1, dtype=np.float64)
216        stdev_avg = stdev / np.sqrt(float(ndata))
217        return V_avg, stdev, stdev_avg, time_stamp, Vdd_avg
218
219    def V_sampchan(self, chan, gain, data_rate=RATE):
220        '''
221        This routine returns a single reading of the voltage for the channel.
222
223        Returns a tuple of the following 5 objects:
224            V -- float, the measured voltage
225
226            time_stamp -- float, the time of the measurement in seconds since
227            the beginning of the epoch (OS dependent begin time)
228
229            ref -- float, the reference voltage (Vdd) collected
230            simultaneously.
231
232        :param int chan: the channel number (1, 2, 3).
233
234        :param gain: ignored by board. Defaults to 1.
235
236        :param int data_rate:
237
238        :returns float value:
239
240        :return float time_stamp:
241
242        :return float Vdd:
243        '''
244        nsamples = 1
245        self.send.send(['start', ])
246        self.send.send(['send', self.addr, chan, nsamples])
247        while not self.rcv.poll():
248            # we wait for data
249            pass
250        value = self.rcv.recv()[0]
251        samples[chan - 1].value = samples[chan - 1].value + nsamples
252        time_stamp = starttime.value
253        Vdd = 5.00
254        return value, time_stamp, Vdd
255
256def LQProc(cmdrcv, datasend, starttime, samples):
257    """Process to spawn that continuously collects from the LabQuests(s)
258    Parameters
259    ----------
260    cmdrcv: Pipe
261        Where commands are received.
262
263    datasend: Pipe
264        Where data is sent in response to a command.
265    """
266    # First set up the LabQuest(s)
267    import labquest
268    from collections import deque
269    lqs = labquest.LabQuest()
270    cmd_deque = deque()
271    PERIOD = 1000/RATE # msec
272    if lqs.open() == 0:
273        # we're good to go
274        # make a list of boards
275        boards = []
276        nboards = len(labquest.config.hDevice)
277        for i in range(nboards):
278            # Tell the board we will monitor all three channels
279            lqs.select_sensors(ch1="raw_voltage", ch2="raw_voltage",
280                               ch3="raw_voltage",
281                               device=i)
282        lqs.start(PERIOD)
283        starttime.value = time.time()
284        running = True
285        while running:
286            # check for a command: start (clears buffers), send (sends content
287            # of buffers, removing the sent content), close (shutdown the process).
288            # Each command is a list ['cmd str',<cmd data>]:
289            #    ['start',]
290            #    ['close',]
291            #    ['send',board#, ch#, num_pts].
292            while cmdrcv.poll():
293                cmd_deque.append(cmdrcv.recv())
294            # Start responding to commands
295            while len(cmd_deque) > 0:
296                cmd = cmd_deque.popleft()
297                if cmd[0] == 'close':
298                    # stop thread
299                    running = False
300                if cmd[0] == 'start':
301                    # restart data collection to get good zero
302                    lqs.stop()
303                    lqs.start(PERIOD)
304                    starttime.value = time.time()
305                    for k in range(3):
306                        samples[k].value = 0
307                if cmd[0] == 'send':
308                    # return requested amount of data for the channel
309                    chan = 'ch'+str(cmd[2])
310                    data = []
311                    for k in range(cmd[3]):
312                        data.append(lqs.read(chan, device=cmd[1]))
313                    datasend.send(data)
314        lqs.close()
315        return
316    else:
317        # something happened
318        lqs.close()
319        raise IOError("")
320    return
def find_boards():
32def find_boards():
33    """
34    A rountine like this must be implemented by all board packages.
35
36    :return: list of LabQuests (Types too?)
37    """
38    boards = []
39    # The following is a hack to get around the fact that the whole module
40    # needs to be reinstantiated on the new thread. I think the best option
41    # is to upon discovery spawn a process and then just communicate with it.
42    if labquestdrvs:
43        try:
44            LabQuests = labquest.LabQuest()
45            if LabQuests.open() == 0:
46                # Count number of boards
47                nboards = len(labquest.config.hDevice)
48                # Close things
49                LabQuests.close()
50                # launch a process to talk to, need Pipes to communicate.
51                from multiprocessing import Process, Pipe
52                cmdsend, cmdrcv = Pipe()
53                datasend, datarcv = Pipe()
54                LQ = Process(target = LQProc,
55                             args = (cmdrcv, datasend, starttime, samples))
56                LQ.start()
57                # append an object for each board that knows how to talk to the
58                # process and get information from that particular device
59                addr = 0
60                for addr in range(nboards):
61                    boards.append(Board_LQ(addr, cmdsend, datarcv))
62                    addr+=1
63        except Exception as e:
64            print ("\nLabQuest(s) not found.", end='')
65            logger.debug(e)
66    return boards

A rountine like this must be implemented by all board packages.

Returns

list of LabQuests (Types too?)

class Board_LQ(jupyterpidaq.Boards.boards.Board):
 68class Board_LQ(Board):
 69    """
 70    Class defining the properties of the analog-to-digital block of the
 71    LabQuests. Key characteristics:
 72
 73    * 3 channels (1, 2, 3) a range of +/- 10 V.
 74    * 12 bit resolution
 75    * Other available but not implemented facilities are Digital I/O.
 76    """
 77    def __init__(self, addr, send, rcv):
 78        super().__init__()
 79        self.name = 'LabQuest'
 80        self.vendor = 'Vernier'
 81        self.channels = (1, 2, 3)
 82        self.addr = addr
 83        self.send = send
 84        self.rcv = rcv
 85        self.Vdd = 5.00
 86        # samples taken from a channel and starttime kept track of in
 87        #  shared memory samples[i].value = # of samples taken from channel
 88        #   i. starttime.value = time.time() immediately after las clearing
 89        #   of the buffers.
 90
 91    def getsensors(self):
 92        """
 93        Return a list of valid sensor object names for this board.
 94        :return: list of classnames
 95        """
 96        sensorlist = ['RawAtoD',
 97                      'VernierSSTemp',
 98                      'VernierGasP',
 99                      'VernierGasP_OLD',
100                      'VernierpH',
101                      'VernierFlatpH'
102                      ]
103        # TODO: extend this list as appropriate. You can get a full list
104        #  using the `Sensors.sensors.listSensors()` call.
105        # The main program will use this list to access the actual sensor
106        # objects when converting the raw board voltage and for producing
107        # a menu of valid options for this particular board.
108        return sensorlist
109
110    def V_oversampchan(self, chan, gain, avg_sec, data_rate=RATE):
111        """
112        This routine returns the average voltage for the channel
113        averaged at the default rate for the board and returns an
114        average and observed range.
115
116        Returns a tuple of the following 5 objects:
117            V_avg -- float, the averaged voltage
118
119            V_min -- float, the minimum voltage read during
120            the interval
121
122            V_max -- float, the maximum voltage read during the
123            interval
124
125            time_stamp -- float, the time at halfway through the averaging
126            interval in seconds since the beginning of the epoch (OS
127            dependent begin time)
128
129            Vdd_avg -- float, the reference voltage (Vdd) collected
130            simultaneously.
131
132        :param int chan: the channel number (1, 2, 3)
133
134        :param gain: ignored by board. Defaults to 1.
135
136        :param int data_rate: maximum
137
138        :param float avg_sec: seconds to average for, actual
139         averaging interval will be as close as possible for an integer
140         number of samples
141
142        :returns: V_avg, V_min, V_max, time_stamp, Vdd_avg
143        :return float V_avg: description
144        :return float V_min:
145        :return float V_max:
146        :return float time_stamp:
147        :return float Vdd_avg:
148        """
149        nsamples = round(data_rate*avg_sec)
150        self.send.send(['send',self.addr, chan, nsamples])
151        while not self.rcv.poll():
152            #we wait for data
153            pass
154        value = self.rcv.recv()
155        samples[chan - 1].value = samples[chan - 1].value + nsamples
156        endtime = starttime.value + samples[chan-1].value/data_rate
157        time_stamp = endtime - avg_sec / 2
158        ndata = len(value)
159        V_avg = sum(value) / ndata
160        Vdd_avg = 5.00
161        V_min = min(value)
162        V_max = max(value)
163        return V_avg, V_min, V_max, time_stamp, Vdd_avg
164
165    def V_oversampchan_stats(self, chan, gain, avg_sec, data_rate=RATE):
166        '''
167        This routine returns the average voltage for the channel
168        averaged at the maximum rate for the board. The standard
169        deviation and the estimated deviation of the mean are also
170        returned.
171
172        Returns a tuple of the following 5 objects:
173            V_avg -- float, the averaged voltage
174
175            stdev -- float, the standard deviation of the measured values
176            during the averaging interval
177
178            stdev_avg -- float, the estimated standard deviation of the
179            returned average
180
181            time_stamp -- float, the time at halfway through the averaging
182            interval in seconds since the beginning of the epoch (OS
183            dependent begin time)
184
185            Vdd_avg -- float, returned as None.
186
187        :param int chan: the channel number (1, 2, 3)
188
189        :param gain: ignored by board. Defaults to 1.
190
191        :param int data_rate:
192
193        :param float avg_sec: seconds to average for, actual
194         averaging interval will be as close as possible for an integer
195         number of samples
196
197        :returns: V_avg, stdev, stdev_avg, time_stamp, Vdd_avg
198        :return float V_avg:
199        :return float stdev:
200        :return float stdev_avg:
201        :return float time_stamp:
202        :return float Vdd_avg:
203        '''
204        nsamples = round(data_rate * avg_sec)
205        self.send.send(['send', self.addr, chan, nsamples])
206        while  not self.rcv.poll():
207            # we wait for data
208            pass
209        value = self.rcv.recv()
210        samples[chan - 1].value = samples[chan - 1].value + nsamples
211        endtime = starttime.value + samples[chan-1].value/data_rate
212        time_stamp = endtime - avg_sec / 2
213        ndata = len(value)
214        V_avg = sum(value) / ndata
215        Vdd_avg = 5.00
216        stdev = np.std(value, ddof=1, dtype=np.float64)
217        stdev_avg = stdev / np.sqrt(float(ndata))
218        return V_avg, stdev, stdev_avg, time_stamp, Vdd_avg
219
220    def V_sampchan(self, chan, gain, data_rate=RATE):
221        '''
222        This routine returns a single reading of the voltage for the channel.
223
224        Returns a tuple of the following 5 objects:
225            V -- float, the measured voltage
226
227            time_stamp -- float, the time of the measurement in seconds since
228            the beginning of the epoch (OS dependent begin time)
229
230            ref -- float, the reference voltage (Vdd) collected
231            simultaneously.
232
233        :param int chan: the channel number (1, 2, 3).
234
235        :param gain: ignored by board. Defaults to 1.
236
237        :param int data_rate:
238
239        :returns float value:
240
241        :return float time_stamp:
242
243        :return float Vdd:
244        '''
245        nsamples = 1
246        self.send.send(['start', ])
247        self.send.send(['send', self.addr, chan, nsamples])
248        while not self.rcv.poll():
249            # we wait for data
250            pass
251        value = self.rcv.recv()[0]
252        samples[chan - 1].value = samples[chan - 1].value + nsamples
253        time_stamp = starttime.value
254        Vdd = 5.00
255        return value, time_stamp, Vdd

Class defining the properties of the analog-to-digital block of the LabQuests. Key characteristics:

  • 3 channels (1, 2, 3) a range of +/- 10 V.
  • 12 bit resolution
  • Other available but not implemented facilities are Digital I/O.
Board_LQ(addr, send, rcv)
77    def __init__(self, addr, send, rcv):
78        super().__init__()
79        self.name = 'LabQuest'
80        self.vendor = 'Vernier'
81        self.channels = (1, 2, 3)
82        self.addr = addr
83        self.send = send
84        self.rcv = rcv
85        self.Vdd = 5.00
86        # samples taken from a channel and starttime kept track of in
87        #  shared memory samples[i].value = # of samples taken from channel
88        #   i. starttime.value = time.time() immediately after las clearing
89        #   of the buffers.

Should be overridden by each board and define at minimum: self.name = 'board name/adc name/type' Short an useful to end user self.vendor = 'Vendor/Manufacturer name` self.channels = tuple of available channel IDs self.gains = list of gains self.Vdd = voltage provided by board to sensors

def getsensors(self):
 91    def getsensors(self):
 92        """
 93        Return a list of valid sensor object names for this board.
 94        :return: list of classnames
 95        """
 96        sensorlist = ['RawAtoD',
 97                      'VernierSSTemp',
 98                      'VernierGasP',
 99                      'VernierGasP_OLD',
100                      'VernierpH',
101                      'VernierFlatpH'
102                      ]
103        # TODO: extend this list as appropriate. You can get a full list
104        #  using the `Sensors.sensors.listSensors()` call.
105        # The main program will use this list to access the actual sensor
106        # objects when converting the raw board voltage and for producing
107        # a menu of valid options for this particular board.
108        return sensorlist

Return a list of valid sensor object names for this board.

Returns

list of classnames

def V_oversampchan(self, chan, gain, avg_sec, data_rate=500):
110    def V_oversampchan(self, chan, gain, avg_sec, data_rate=RATE):
111        """
112        This routine returns the average voltage for the channel
113        averaged at the default rate for the board and returns an
114        average and observed range.
115
116        Returns a tuple of the following 5 objects:
117            V_avg -- float, the averaged voltage
118
119            V_min -- float, the minimum voltage read during
120            the interval
121
122            V_max -- float, the maximum voltage read during the
123            interval
124
125            time_stamp -- float, the time at halfway through the averaging
126            interval in seconds since the beginning of the epoch (OS
127            dependent begin time)
128
129            Vdd_avg -- float, the reference voltage (Vdd) collected
130            simultaneously.
131
132        :param int chan: the channel number (1, 2, 3)
133
134        :param gain: ignored by board. Defaults to 1.
135
136        :param int data_rate: maximum
137
138        :param float avg_sec: seconds to average for, actual
139         averaging interval will be as close as possible for an integer
140         number of samples
141
142        :returns: V_avg, V_min, V_max, time_stamp, Vdd_avg
143        :return float V_avg: description
144        :return float V_min:
145        :return float V_max:
146        :return float time_stamp:
147        :return float Vdd_avg:
148        """
149        nsamples = round(data_rate*avg_sec)
150        self.send.send(['send',self.addr, chan, nsamples])
151        while not self.rcv.poll():
152            #we wait for data
153            pass
154        value = self.rcv.recv()
155        samples[chan - 1].value = samples[chan - 1].value + nsamples
156        endtime = starttime.value + samples[chan-1].value/data_rate
157        time_stamp = endtime - avg_sec / 2
158        ndata = len(value)
159        V_avg = sum(value) / ndata
160        Vdd_avg = 5.00
161        V_min = min(value)
162        V_max = max(value)
163        return V_avg, V_min, V_max, time_stamp, Vdd_avg

This routine returns the average voltage for the channel averaged at the default rate for the board and returns an average and observed range.

Returns a tuple of the following 5 objects: V_avg -- float, the averaged voltage

V_min -- float, the minimum voltage read during
the interval

V_max -- float, the maximum voltage read during the
interval

time_stamp -- float, the time at halfway through the averaging
interval in seconds since the beginning of the epoch (OS
dependent begin time)

Vdd_avg -- float, the reference voltage (Vdd) collected
simultaneously.
Parameters
  • int chan: the channel number (1, 2, 3)

  • gain: ignored by board. Defaults to 1.

  • int data_rate: maximum

  • float avg_sec: seconds to average for, actual averaging interval will be as close as possible for an integer number of samples

:returns: V_avg, V_min, V_max, time_stamp, Vdd_avg

Returns

description

Returns

Returns

Returns

Returns
def V_oversampchan_stats(self, chan, gain, avg_sec, data_rate=500):
165    def V_oversampchan_stats(self, chan, gain, avg_sec, data_rate=RATE):
166        '''
167        This routine returns the average voltage for the channel
168        averaged at the maximum rate for the board. The standard
169        deviation and the estimated deviation of the mean are also
170        returned.
171
172        Returns a tuple of the following 5 objects:
173            V_avg -- float, the averaged voltage
174
175            stdev -- float, the standard deviation of the measured values
176            during the averaging interval
177
178            stdev_avg -- float, the estimated standard deviation of the
179            returned average
180
181            time_stamp -- float, the time at halfway through the averaging
182            interval in seconds since the beginning of the epoch (OS
183            dependent begin time)
184
185            Vdd_avg -- float, returned as None.
186
187        :param int chan: the channel number (1, 2, 3)
188
189        :param gain: ignored by board. Defaults to 1.
190
191        :param int data_rate:
192
193        :param float avg_sec: seconds to average for, actual
194         averaging interval will be as close as possible for an integer
195         number of samples
196
197        :returns: V_avg, stdev, stdev_avg, time_stamp, Vdd_avg
198        :return float V_avg:
199        :return float stdev:
200        :return float stdev_avg:
201        :return float time_stamp:
202        :return float Vdd_avg:
203        '''
204        nsamples = round(data_rate * avg_sec)
205        self.send.send(['send', self.addr, chan, nsamples])
206        while  not self.rcv.poll():
207            # we wait for data
208            pass
209        value = self.rcv.recv()
210        samples[chan - 1].value = samples[chan - 1].value + nsamples
211        endtime = starttime.value + samples[chan-1].value/data_rate
212        time_stamp = endtime - avg_sec / 2
213        ndata = len(value)
214        V_avg = sum(value) / ndata
215        Vdd_avg = 5.00
216        stdev = np.std(value, ddof=1, dtype=np.float64)
217        stdev_avg = stdev / np.sqrt(float(ndata))
218        return V_avg, stdev, stdev_avg, time_stamp, Vdd_avg

This routine returns the average voltage for the channel averaged at the maximum rate for the board. The standard deviation and the estimated deviation of the mean are also returned.

Returns a tuple of the following 5 objects: V_avg -- float, the averaged voltage

stdev -- float, the standard deviation of the measured values
during the averaging interval

stdev_avg -- float, the estimated standard deviation of the
returned average

time_stamp -- float, the time at halfway through the averaging
interval in seconds since the beginning of the epoch (OS
dependent begin time)

Vdd_avg -- float, returned as None.
Parameters
  • int chan: the channel number (1, 2, 3)

  • gain: ignored by board. Defaults to 1.

  • int data_rate:

  • float avg_sec: seconds to average for, actual averaging interval will be as close as possible for an integer number of samples

:returns: V_avg, stdev, stdev_avg, time_stamp, Vdd_avg

Returns

Returns

Returns

Returns

Returns
def V_sampchan(self, chan, gain, data_rate=500):
220    def V_sampchan(self, chan, gain, data_rate=RATE):
221        '''
222        This routine returns a single reading of the voltage for the channel.
223
224        Returns a tuple of the following 5 objects:
225            V -- float, the measured voltage
226
227            time_stamp -- float, the time of the measurement in seconds since
228            the beginning of the epoch (OS dependent begin time)
229
230            ref -- float, the reference voltage (Vdd) collected
231            simultaneously.
232
233        :param int chan: the channel number (1, 2, 3).
234
235        :param gain: ignored by board. Defaults to 1.
236
237        :param int data_rate:
238
239        :returns float value:
240
241        :return float time_stamp:
242
243        :return float Vdd:
244        '''
245        nsamples = 1
246        self.send.send(['start', ])
247        self.send.send(['send', self.addr, chan, nsamples])
248        while not self.rcv.poll():
249            # we wait for data
250            pass
251        value = self.rcv.recv()[0]
252        samples[chan - 1].value = samples[chan - 1].value + nsamples
253        time_stamp = starttime.value
254        Vdd = 5.00
255        return value, time_stamp, Vdd

This routine returns a single reading of the voltage for the channel.

Returns a tuple of the following 5 objects: V -- float, the measured voltage

time_stamp -- float, the time of the measurement in seconds since
the beginning of the epoch (OS dependent begin time)

ref -- float, the reference voltage (Vdd) collected
simultaneously.
Parameters
  • int chan: the channel number (1, 2, 3).

  • gain: ignored by board. Defaults to 1.

  • int data_rate:

:returns float value:

Returns

Returns
def LQProc(cmdrcv, datasend, starttime, samples):
257def LQProc(cmdrcv, datasend, starttime, samples):
258    """Process to spawn that continuously collects from the LabQuests(s)
259    Parameters
260    ----------
261    cmdrcv: Pipe
262        Where commands are received.
263
264    datasend: Pipe
265        Where data is sent in response to a command.
266    """
267    # First set up the LabQuest(s)
268    import labquest
269    from collections import deque
270    lqs = labquest.LabQuest()
271    cmd_deque = deque()
272    PERIOD = 1000/RATE # msec
273    if lqs.open() == 0:
274        # we're good to go
275        # make a list of boards
276        boards = []
277        nboards = len(labquest.config.hDevice)
278        for i in range(nboards):
279            # Tell the board we will monitor all three channels
280            lqs.select_sensors(ch1="raw_voltage", ch2="raw_voltage",
281                               ch3="raw_voltage",
282                               device=i)
283        lqs.start(PERIOD)
284        starttime.value = time.time()
285        running = True
286        while running:
287            # check for a command: start (clears buffers), send (sends content
288            # of buffers, removing the sent content), close (shutdown the process).
289            # Each command is a list ['cmd str',<cmd data>]:
290            #    ['start',]
291            #    ['close',]
292            #    ['send',board#, ch#, num_pts].
293            while cmdrcv.poll():
294                cmd_deque.append(cmdrcv.recv())
295            # Start responding to commands
296            while len(cmd_deque) > 0:
297                cmd = cmd_deque.popleft()
298                if cmd[0] == 'close':
299                    # stop thread
300                    running = False
301                if cmd[0] == 'start':
302                    # restart data collection to get good zero
303                    lqs.stop()
304                    lqs.start(PERIOD)
305                    starttime.value = time.time()
306                    for k in range(3):
307                        samples[k].value = 0
308                if cmd[0] == 'send':
309                    # return requested amount of data for the channel
310                    chan = 'ch'+str(cmd[2])
311                    data = []
312                    for k in range(cmd[3]):
313                        data.append(lqs.read(chan, device=cmd[1]))
314                    datasend.send(data)
315        lqs.close()
316        return
317    else:
318        # something happened
319        lqs.close()
320        raise IOError("")
321    return

Process to spawn that continuously collects from the LabQuests(s)

Parameters

cmdrcv: Pipe Where commands are received.

datasend: Pipe Where data is sent in response to a command.