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
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.
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
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
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).
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).
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.