jupyterpidaq.Boards.Simulated.ADCsim

  1# Random number generator substitute for actual analog to digital converter.
  2# Used to allow a 'demo' mode for JupyterPiDAQ.
  3# J. Gutow <jgutow@new.rr.com> March 16, 2019
  4# license GPL V3 or greater
  5
  6from numpy import random
  7from numpy import std
  8from numpy import sqrt
  9from numpy import around
 10from numpy import float64
 11from numpy import log10
 12from numpy import floor
 13import time
 14
 15from jupyterpidaq.Boards import Board
 16
 17# Optimized for Pi 3B+ mimicking an installed ADS1115 ADC PiHAT.
 18RATE = 475  # 475 Hz with oversampling best S/N on Pi 3B+ per unit time interval.
 19
 20
 21# other rates 8, 16, 32, 64, 128, 250, 475, 860 in Hz.
 22def find_boards():
 23    return Board_ADCsim_random('placeholder')
 24
 25
 26class Board_ADCsim_random(Board):
 27    def __init__(self, adc):
 28        super().__init__()
 29        self.name = 'ADCsym Random'
 30        self.vendor = 'JupyterPiDAQ'
 31        self.channels = (0, 1, 2, 3)
 32        self.gains = [1]
 33        self.Vdd = 3.3
 34        self.adc = adc
 35
 36    def getsensors(self):
 37        """
 38        Return a list of valid sensor object names for this board.
 39        :return: list of classnames
 40        """
 41        sensorlist = ['RawAtoD',
 42                      'VernierSSTemp',
 43                      'VernierGasP',
 44                      'VernierpH',
 45                      'VernierFlatpH'
 46                      ]
 47        # TODO: extend this list as appropriate. You can get a full list
 48        #  using the `Sensors.sensors.listSensors()` call.
 49        # The main program will use this list to access the actual sensor
 50        # objects when converting the raw board voltage and for producing
 51        # a menu of valid options for this particular board.
 52        return sensorlist
 53
 54
 55    def V_oversampchan_stats(self, chan, gain, avg_sec, data_rate=RATE):
 56        '''
 57        This routine returns the average voltage for the channel
 58        averaged at (0.0012 + 1/data_rate)^-1 Hz for avg_sec
 59        number of seconds. The 0.0012 is the required loop time
 60        on a RPI 3B+ in python3. The voltage is rounded to the number
 61        of decimals indicated by the standard deviation. The standard
 62        deviation and the estimated deviation of the mean are also
 63        returned.
 64        Parameters
 65            chan    the channel number 0, 1, 2, 3
 66            gain    2/3 (+/-6.144V), 1(+/-4.096V), 2(+/-2.048V), 4(+/-1.024V),
 67                    8 (+/-0.512V), 16 (+/-0.256V)
 68            data_rate the ADC sample rate in Hz (8, 16, 32, 64, 128, 250, 475 or 860 Hz)
 69            avg_sec seconds to average for, actual averaging interval will be as close
 70                    as possible for an integer number of samples.
 71        Returns a tuple (V_avg, V_min, V_max, time_stamp)
 72            V_avg   the averaged voltage
 73            stdev   estimated standard deviation of the measurements
 74            stdev_avg   estimated standard deviation of the mean
 75            time_stamp the time at halfway through the averaging interval in seconds
 76                    since the beginning of the epoch (OS dependent begin time).
 77
 78        '''
 79        n_samp = int(round(avg_sec / (0.0017 + 1 / data_rate)))
 80        if (n_samp < 1):
 81            n_samp = 1
 82        value = []
 83        start = 0
 84        end = 0
 85        while (len(
 86                value) == 0):  # we will try until we get some values in case of bad reads
 87            start = time.time()
 88            center = random.random()
 89            for k in range(n_samp):
 90                try:
 91                    tempval = round(
 92                        (random.normal(center, center / 10)) * 32767)
 93                    # positive only to avoid problems mimicking some sensors
 94                    # if (tempval<0):
 95                    #   tempval = -1*tempval
 96                    # if (tempval == 0):
 97                    #   tempval=1
 98                except (ValueError, OverflowError):
 99                    print('Bad adc read.')
100                    pass
101                else:
102                    if (tempval >= -32767) and (tempval <= 32767):
103                        value.append(tempval)
104                # time.sleep(0.0005)
105            end = time.time()
106        time_stamp = (start + end) / 2.0
107        V_avg = sum(value) * 4.096 / len(value) / gain / 32767
108        stdev = std(value, ddof=1, dtype=float64) * 4.096 / gain / 32767
109        stdev_avg = stdev / sqrt(float(len(value)))
110        decimals = 0
111        if (stdev_avg == 0):
112            decimals = 6
113        else:
114            if (stdev_avg != float('inf')) and (stdev_avg > 0):
115                decimals = -int(floor(log10(stdev_avg)))
116        # print('decimals = '+str(decimals))
117        V_avg = around(V_avg, decimals=decimals)
118        stdev = around(stdev, decimals=decimals)
119        stdev_avg = around(stdev_avg, decimals=decimals)
120        return V_avg, stdev, stdev_avg, time_stamp, self.Vdd
121
122    def V_oversampchan(self, chan, gain, avg_sec, data_rate=RATE):
123        '''
124        This routine returns the average voltage for the channel
125        averaged at (0.0012 + 1/data_rate)^-1 Hz for avg_sec
126        number of seconds. The 0.0012 is the required loop time
127        on a RPI 3B+ in python3. The voltage is rounded to the number
128        of decimals indicated by the standard deviation. The standard
129        deviation and the estimated deviation of the mean are also
130        returned.
131        Parameters
132            chan    the channel number 0, 1, 2, 3
133            gain    2/3 (+/-6.144V), 1(+/-4.096V), 2(+/-2.048V), 4(+/-1.024V),
134                    8 (+/-0.512V), 16 (+/-0.256V)
135            data_rate the ADC sample rate in Hz (8, 16, 32, 64, 128, 250, 475 or 860 Hz)
136            avg_sec seconds to average for, actual averaging interval will be as close
137                    as possible for an integer number of samples.
138        Returns a tuple (V_avg, V_min, V_max, time_stamp)
139            V_avg   the averaged voltage
140            stdev   estimated standard deviation of the measurements
141            stdev_avg   estimated standard deviation of the mean
142            time_stamp the time at halfway through the averaging interval in seconds
143                    since the beginning of the epoch (OS dependent begin time).
144
145        '''
146        n_samp = int(round(avg_sec / (0.0017 + 1 / data_rate)))
147        if (n_samp < 1):
148            n_samp = 1
149        value = []
150        start = 0
151        end = 0
152        while (len(
153                value) == 0):  # we will try until we get some values in case of bad reads
154            start = time.time()
155            center = random.random()
156            for k in range(n_samp):
157                try:
158                    tempval = round(
159                        (random.normal(center, center / 10)) * 32767)
160                    # positive only to avoid problems mimicking some sensors
161                    # if (tempval<0):
162                    #   tempval = -1*tempval
163                    # if (tempval == 0):
164                    #   tempval=1
165                except (ValueError, OverflowError):
166                    print('Bad adc read.')
167                    pass
168                else:
169                    if (tempval >= -32767) and (tempval <= 32767):
170                        value.append(tempval)
171                # time.sleep(0.0005)
172            end = time.time()
173        time_stamp = (start + end) / 2.0
174        V_avg = sum(value) * 4.096 / len(value) / gain / 32767
175        V_max = max(value) * 4.096 / gain / 32767
176        V_min = min(value) * 4.096 / gain / 32767
177        return V_avg, V_min, V_max, time_stamp, self.Vdd
178
179    def V_sampchan(self, chan, gain, **kwargs):
180        """
181        This function returns a single measurement and the time it was
182        collected.
183        :param chan: id of the channel to be measured
184        :param gain: gain of the channel if adjustable
185        :return: a tuple consisting of V, time_stamp, where V = the single
186        voltage measurement and time_stamp the time it was collected.
187        """
188        V = (random.random()-0.5)*6.6
189        return V, time.time(), self.Vdd
def find_boards():
23def find_boards():
24    return Board_ADCsim_random('placeholder')
class Board_ADCsim_random(jupyterpidaq.Boards.boards.Board):
 27class Board_ADCsim_random(Board):
 28    def __init__(self, adc):
 29        super().__init__()
 30        self.name = 'ADCsym Random'
 31        self.vendor = 'JupyterPiDAQ'
 32        self.channels = (0, 1, 2, 3)
 33        self.gains = [1]
 34        self.Vdd = 3.3
 35        self.adc = adc
 36
 37    def getsensors(self):
 38        """
 39        Return a list of valid sensor object names for this board.
 40        :return: list of classnames
 41        """
 42        sensorlist = ['RawAtoD',
 43                      'VernierSSTemp',
 44                      'VernierGasP',
 45                      'VernierpH',
 46                      'VernierFlatpH'
 47                      ]
 48        # TODO: extend this list as appropriate. You can get a full list
 49        #  using the `Sensors.sensors.listSensors()` call.
 50        # The main program will use this list to access the actual sensor
 51        # objects when converting the raw board voltage and for producing
 52        # a menu of valid options for this particular board.
 53        return sensorlist
 54
 55
 56    def V_oversampchan_stats(self, chan, gain, avg_sec, data_rate=RATE):
 57        '''
 58        This routine returns the average voltage for the channel
 59        averaged at (0.0012 + 1/data_rate)^-1 Hz for avg_sec
 60        number of seconds. The 0.0012 is the required loop time
 61        on a RPI 3B+ in python3. The voltage is rounded to the number
 62        of decimals indicated by the standard deviation. The standard
 63        deviation and the estimated deviation of the mean are also
 64        returned.
 65        Parameters
 66            chan    the channel number 0, 1, 2, 3
 67            gain    2/3 (+/-6.144V), 1(+/-4.096V), 2(+/-2.048V), 4(+/-1.024V),
 68                    8 (+/-0.512V), 16 (+/-0.256V)
 69            data_rate the ADC sample rate in Hz (8, 16, 32, 64, 128, 250, 475 or 860 Hz)
 70            avg_sec seconds to average for, actual averaging interval will be as close
 71                    as possible for an integer number of samples.
 72        Returns a tuple (V_avg, V_min, V_max, time_stamp)
 73            V_avg   the averaged voltage
 74            stdev   estimated standard deviation of the measurements
 75            stdev_avg   estimated standard deviation of the mean
 76            time_stamp the time at halfway through the averaging interval in seconds
 77                    since the beginning of the epoch (OS dependent begin time).
 78
 79        '''
 80        n_samp = int(round(avg_sec / (0.0017 + 1 / data_rate)))
 81        if (n_samp < 1):
 82            n_samp = 1
 83        value = []
 84        start = 0
 85        end = 0
 86        while (len(
 87                value) == 0):  # we will try until we get some values in case of bad reads
 88            start = time.time()
 89            center = random.random()
 90            for k in range(n_samp):
 91                try:
 92                    tempval = round(
 93                        (random.normal(center, center / 10)) * 32767)
 94                    # positive only to avoid problems mimicking some sensors
 95                    # if (tempval<0):
 96                    #   tempval = -1*tempval
 97                    # if (tempval == 0):
 98                    #   tempval=1
 99                except (ValueError, OverflowError):
100                    print('Bad adc read.')
101                    pass
102                else:
103                    if (tempval >= -32767) and (tempval <= 32767):
104                        value.append(tempval)
105                # time.sleep(0.0005)
106            end = time.time()
107        time_stamp = (start + end) / 2.0
108        V_avg = sum(value) * 4.096 / len(value) / gain / 32767
109        stdev = std(value, ddof=1, dtype=float64) * 4.096 / gain / 32767
110        stdev_avg = stdev / sqrt(float(len(value)))
111        decimals = 0
112        if (stdev_avg == 0):
113            decimals = 6
114        else:
115            if (stdev_avg != float('inf')) and (stdev_avg > 0):
116                decimals = -int(floor(log10(stdev_avg)))
117        # print('decimals = '+str(decimals))
118        V_avg = around(V_avg, decimals=decimals)
119        stdev = around(stdev, decimals=decimals)
120        stdev_avg = around(stdev_avg, decimals=decimals)
121        return V_avg, stdev, stdev_avg, time_stamp, self.Vdd
122
123    def V_oversampchan(self, chan, gain, avg_sec, data_rate=RATE):
124        '''
125        This routine returns the average voltage for the channel
126        averaged at (0.0012 + 1/data_rate)^-1 Hz for avg_sec
127        number of seconds. The 0.0012 is the required loop time
128        on a RPI 3B+ in python3. The voltage is rounded to the number
129        of decimals indicated by the standard deviation. The standard
130        deviation and the estimated deviation of the mean are also
131        returned.
132        Parameters
133            chan    the channel number 0, 1, 2, 3
134            gain    2/3 (+/-6.144V), 1(+/-4.096V), 2(+/-2.048V), 4(+/-1.024V),
135                    8 (+/-0.512V), 16 (+/-0.256V)
136            data_rate the ADC sample rate in Hz (8, 16, 32, 64, 128, 250, 475 or 860 Hz)
137            avg_sec seconds to average for, actual averaging interval will be as close
138                    as possible for an integer number of samples.
139        Returns a tuple (V_avg, V_min, V_max, time_stamp)
140            V_avg   the averaged voltage
141            stdev   estimated standard deviation of the measurements
142            stdev_avg   estimated standard deviation of the mean
143            time_stamp the time at halfway through the averaging interval in seconds
144                    since the beginning of the epoch (OS dependent begin time).
145
146        '''
147        n_samp = int(round(avg_sec / (0.0017 + 1 / data_rate)))
148        if (n_samp < 1):
149            n_samp = 1
150        value = []
151        start = 0
152        end = 0
153        while (len(
154                value) == 0):  # we will try until we get some values in case of bad reads
155            start = time.time()
156            center = random.random()
157            for k in range(n_samp):
158                try:
159                    tempval = round(
160                        (random.normal(center, center / 10)) * 32767)
161                    # positive only to avoid problems mimicking some sensors
162                    # if (tempval<0):
163                    #   tempval = -1*tempval
164                    # if (tempval == 0):
165                    #   tempval=1
166                except (ValueError, OverflowError):
167                    print('Bad adc read.')
168                    pass
169                else:
170                    if (tempval >= -32767) and (tempval <= 32767):
171                        value.append(tempval)
172                # time.sleep(0.0005)
173            end = time.time()
174        time_stamp = (start + end) / 2.0
175        V_avg = sum(value) * 4.096 / len(value) / gain / 32767
176        V_max = max(value) * 4.096 / gain / 32767
177        V_min = min(value) * 4.096 / gain / 32767
178        return V_avg, V_min, V_max, time_stamp, self.Vdd
179
180    def V_sampchan(self, chan, gain, **kwargs):
181        """
182        This function returns a single measurement and the time it was
183        collected.
184        :param chan: id of the channel to be measured
185        :param gain: gain of the channel if adjustable
186        :return: a tuple consisting of V, time_stamp, where V = the single
187        voltage measurement and time_stamp the time it was collected.
188        """
189        V = (random.random()-0.5)*6.6
190        return V, time.time(), self.Vdd

Base class for all boards. Each board should be an extension of this class.

Board_ADCsim_random(adc)
28    def __init__(self, adc):
29        super().__init__()
30        self.name = 'ADCsym Random'
31        self.vendor = 'JupyterPiDAQ'
32        self.channels = (0, 1, 2, 3)
33        self.gains = [1]
34        self.Vdd = 3.3
35        self.adc = adc

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):
37    def getsensors(self):
38        """
39        Return a list of valid sensor object names for this board.
40        :return: list of classnames
41        """
42        sensorlist = ['RawAtoD',
43                      'VernierSSTemp',
44                      'VernierGasP',
45                      'VernierpH',
46                      'VernierFlatpH'
47                      ]
48        # TODO: extend this list as appropriate. You can get a full list
49        #  using the `Sensors.sensors.listSensors()` call.
50        # The main program will use this list to access the actual sensor
51        # objects when converting the raw board voltage and for producing
52        # a menu of valid options for this particular board.
53        return sensorlist

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

Returns

list of classnames

def V_oversampchan_stats(self, chan, gain, avg_sec, data_rate=475):
 56    def V_oversampchan_stats(self, chan, gain, avg_sec, data_rate=RATE):
 57        '''
 58        This routine returns the average voltage for the channel
 59        averaged at (0.0012 + 1/data_rate)^-1 Hz for avg_sec
 60        number of seconds. The 0.0012 is the required loop time
 61        on a RPI 3B+ in python3. The voltage is rounded to the number
 62        of decimals indicated by the standard deviation. The standard
 63        deviation and the estimated deviation of the mean are also
 64        returned.
 65        Parameters
 66            chan    the channel number 0, 1, 2, 3
 67            gain    2/3 (+/-6.144V), 1(+/-4.096V), 2(+/-2.048V), 4(+/-1.024V),
 68                    8 (+/-0.512V), 16 (+/-0.256V)
 69            data_rate the ADC sample rate in Hz (8, 16, 32, 64, 128, 250, 475 or 860 Hz)
 70            avg_sec seconds to average for, actual averaging interval will be as close
 71                    as possible for an integer number of samples.
 72        Returns a tuple (V_avg, V_min, V_max, time_stamp)
 73            V_avg   the averaged voltage
 74            stdev   estimated standard deviation of the measurements
 75            stdev_avg   estimated standard deviation of the mean
 76            time_stamp the time at halfway through the averaging interval in seconds
 77                    since the beginning of the epoch (OS dependent begin time).
 78
 79        '''
 80        n_samp = int(round(avg_sec / (0.0017 + 1 / data_rate)))
 81        if (n_samp < 1):
 82            n_samp = 1
 83        value = []
 84        start = 0
 85        end = 0
 86        while (len(
 87                value) == 0):  # we will try until we get some values in case of bad reads
 88            start = time.time()
 89            center = random.random()
 90            for k in range(n_samp):
 91                try:
 92                    tempval = round(
 93                        (random.normal(center, center / 10)) * 32767)
 94                    # positive only to avoid problems mimicking some sensors
 95                    # if (tempval<0):
 96                    #   tempval = -1*tempval
 97                    # if (tempval == 0):
 98                    #   tempval=1
 99                except (ValueError, OverflowError):
100                    print('Bad adc read.')
101                    pass
102                else:
103                    if (tempval >= -32767) and (tempval <= 32767):
104                        value.append(tempval)
105                # time.sleep(0.0005)
106            end = time.time()
107        time_stamp = (start + end) / 2.0
108        V_avg = sum(value) * 4.096 / len(value) / gain / 32767
109        stdev = std(value, ddof=1, dtype=float64) * 4.096 / gain / 32767
110        stdev_avg = stdev / sqrt(float(len(value)))
111        decimals = 0
112        if (stdev_avg == 0):
113            decimals = 6
114        else:
115            if (stdev_avg != float('inf')) and (stdev_avg > 0):
116                decimals = -int(floor(log10(stdev_avg)))
117        # print('decimals = '+str(decimals))
118        V_avg = around(V_avg, decimals=decimals)
119        stdev = around(stdev, decimals=decimals)
120        stdev_avg = around(stdev_avg, decimals=decimals)
121        return V_avg, stdev, stdev_avg, time_stamp, self.Vdd

This routine returns the average voltage for the channel averaged at (0.0012 + 1/data_rate)^-1 Hz for avg_sec number of seconds. The 0.0012 is the required loop time on a RPI 3B+ in python3. The voltage is rounded to the number of decimals indicated by the standard deviation. The standard deviation and the estimated deviation of the mean are also returned. Parameters chan the channel number 0, 1, 2, 3 gain 2/3 (+/-6.144V), 1(+/-4.096V), 2(+/-2.048V), 4(+/-1.024V), 8 (+/-0.512V), 16 (+/-0.256V) data_rate the ADC sample rate in Hz (8, 16, 32, 64, 128, 250, 475 or 860 Hz) avg_sec seconds to average for, actual averaging interval will be as close as possible for an integer number of samples. Returns a tuple (V_avg, V_min, V_max, time_stamp) V_avg the averaged voltage stdev estimated standard deviation of the measurements stdev_avg estimated standard deviation of the mean time_stamp the time at halfway through the averaging interval in seconds since the beginning of the epoch (OS dependent begin time).

def V_oversampchan(self, chan, gain, avg_sec, data_rate=475):
123    def V_oversampchan(self, chan, gain, avg_sec, data_rate=RATE):
124        '''
125        This routine returns the average voltage for the channel
126        averaged at (0.0012 + 1/data_rate)^-1 Hz for avg_sec
127        number of seconds. The 0.0012 is the required loop time
128        on a RPI 3B+ in python3. The voltage is rounded to the number
129        of decimals indicated by the standard deviation. The standard
130        deviation and the estimated deviation of the mean are also
131        returned.
132        Parameters
133            chan    the channel number 0, 1, 2, 3
134            gain    2/3 (+/-6.144V), 1(+/-4.096V), 2(+/-2.048V), 4(+/-1.024V),
135                    8 (+/-0.512V), 16 (+/-0.256V)
136            data_rate the ADC sample rate in Hz (8, 16, 32, 64, 128, 250, 475 or 860 Hz)
137            avg_sec seconds to average for, actual averaging interval will be as close
138                    as possible for an integer number of samples.
139        Returns a tuple (V_avg, V_min, V_max, time_stamp)
140            V_avg   the averaged voltage
141            stdev   estimated standard deviation of the measurements
142            stdev_avg   estimated standard deviation of the mean
143            time_stamp the time at halfway through the averaging interval in seconds
144                    since the beginning of the epoch (OS dependent begin time).
145
146        '''
147        n_samp = int(round(avg_sec / (0.0017 + 1 / data_rate)))
148        if (n_samp < 1):
149            n_samp = 1
150        value = []
151        start = 0
152        end = 0
153        while (len(
154                value) == 0):  # we will try until we get some values in case of bad reads
155            start = time.time()
156            center = random.random()
157            for k in range(n_samp):
158                try:
159                    tempval = round(
160                        (random.normal(center, center / 10)) * 32767)
161                    # positive only to avoid problems mimicking some sensors
162                    # if (tempval<0):
163                    #   tempval = -1*tempval
164                    # if (tempval == 0):
165                    #   tempval=1
166                except (ValueError, OverflowError):
167                    print('Bad adc read.')
168                    pass
169                else:
170                    if (tempval >= -32767) and (tempval <= 32767):
171                        value.append(tempval)
172                # time.sleep(0.0005)
173            end = time.time()
174        time_stamp = (start + end) / 2.0
175        V_avg = sum(value) * 4.096 / len(value) / gain / 32767
176        V_max = max(value) * 4.096 / gain / 32767
177        V_min = min(value) * 4.096 / gain / 32767
178        return V_avg, V_min, V_max, time_stamp, self.Vdd

This routine returns the average voltage for the channel averaged at (0.0012 + 1/data_rate)^-1 Hz for avg_sec number of seconds. The 0.0012 is the required loop time on a RPI 3B+ in python3. The voltage is rounded to the number of decimals indicated by the standard deviation. The standard deviation and the estimated deviation of the mean are also returned. Parameters chan the channel number 0, 1, 2, 3 gain 2/3 (+/-6.144V), 1(+/-4.096V), 2(+/-2.048V), 4(+/-1.024V), 8 (+/-0.512V), 16 (+/-0.256V) data_rate the ADC sample rate in Hz (8, 16, 32, 64, 128, 250, 475 or 860 Hz) avg_sec seconds to average for, actual averaging interval will be as close as possible for an integer number of samples. Returns a tuple (V_avg, V_min, V_max, time_stamp) V_avg the averaged voltage stdev estimated standard deviation of the measurements stdev_avg estimated standard deviation of the mean time_stamp the time at halfway through the averaging interval in seconds since the beginning of the epoch (OS dependent begin time).

def V_sampchan(self, chan, gain, **kwargs):
180    def V_sampchan(self, chan, gain, **kwargs):
181        """
182        This function returns a single measurement and the time it was
183        collected.
184        :param chan: id of the channel to be measured
185        :param gain: gain of the channel if adjustable
186        :return: a tuple consisting of V, time_stamp, where V = the single
187        voltage measurement and time_stamp the time it was collected.
188        """
189        V = (random.random()-0.5)*6.6
190        return V, time.time(), self.Vdd

This function returns a single measurement and the time it was collected.

Parameters
  • chan: id of the channel to be measured
  • gain: gain of the channel if adjustable
Returns

a tuple consisting of V, time_stamp, where V = the single voltage measurement and time_stamp the time it was collected.