class BTMUXcontrol: def __init__(self): self.temp = 0 self.output_pins = [24, 25, 26, 27] self.IOLock = threading.Lock() # mutual lock for R/W control self.gpio = Gpio() # initialize GPIO controller # setup output pins self.IOLock.acquire() for pin in self.output_pins: self.gpio.pinMode(pin, self.gpio.OUTPUT) self.gpio.digitalWrite(pin, self.gpio.LOW) self.IOLock.release() def decToBin(self, n): num = [0, 0, 0, 0] if n == 0: return num else: for x in range(n): t = x + 1 for y in range(4): num[y] = t % 2 t = t / 2 return num def mux_channel(self, channel): bin_list = self.decToBin(channel) #binary list self.IOLock.acquire() for z in range(4): self.gpio.digitalWrite(self.output_pins[z], bin_list[z]) self.IOLock.release() #return True def read_ADC(self): self.IOLock.acquire() raw = int( open("/sys/bus/iio/devices/iio:device0/in_voltage0_raw").read()) scale = float( open("/sys/bus/iio/devices/iio:device0/in_voltage_scale").read()) vout = raw * scale self.IOLock.release() return vout
class SensorServer(Thread): """Sensor server that keeps reading sensors and provide get_sensor_output() method for user""" def __init__(self, database_name="air_pollution_data.db"): # Parent class constructor Thread.__init__(self) # Assign GPIO pins that controls MUX, LSB to MSB self.gpio_pins = [24, 25, 26, 27] self.gpio = Gpio() # Set GPIO pins to output try: for pin in self.gpio_pins: self.gpio.pinMode(pin, self.gpio.OUTPUT) except Exception as e: logger.error("Error setting GPIO pin {}, reason {}".format( pin, e.message)) # Use A0 port self.adc_raw = "/sys/bus/iio/devices/iio:device0/in_voltage0_raw" self.adc_scale = "/sys/bus/iio/devices/iio:device0/in_voltage_scale" self.sensor_names = ['temp', 'CO', 'NO2', 'SO2', 'O3', 'PM25'] # Use a dict to store sensor output, the format is: # { "time": [time stamp], # [sensor1 name]: [sensor1 output], # ... # [sensor6 name]: [sensor6 output]} self.sensor_output = {} # Create a lock to protect sensor output. That is, when updating the result, lock it on to prevent it from being # read at the same time; similarly, when reading the result, lock it on to prevent it from being updated. self.sensor_output_lock = Lock() # Here we have a decision to make. I decide to let sensor server write sensor outputs to the local database. Of # course we can do so in a different thread either in a synchronous way or in an asynchronous way. If we do it # with a synchronous approach, we need to use locks to keep synchronization; if we do it with an asynchronous # solution, then SQLite3 is already an asynchronous module and I don't see good reason of adding another layer # of complexity. Perhaps the most reasonable way would be specifying the database in the main thread and then # send it to the sensor server thread. self.database_name = database_name try: # Create the database file and get the connection object. self.db_conn = sqlite3.connect(self.database_name) # Get database cursor from the connection object. self.db_cur = self.db_conn.cursor() except Exception as e: logger.error("Error connecting the database {}, reason: {}".format( self.database_name, e.message)) self.__del__() # Create a 'history' table for history data. # TIME | Temp | SN1 | SN2 | SN3 | SN4 | PM25 # ----------------------------------------------- # int | real | real | real | real | real | real self.db_cur.execute(( "CREATE TABLE IF NOT EXISTS history (time int PRIMARY KEY NOT NULL," " {0} real, {1} real, {2} real, {3} real, {4} real, {5} real)" ).format(self.sensor_names[0], self.sensor_names[1], self.sensor_names[2], self.sensor_names[3], self.sensor_names[4], self.sensor_names[5])) # Commit the changes. When a database is accessed by multiple connections, and one of the processes modifies the # database, the SQLite database is locked until that transaction is committed. The timeout parameter specifies # how long the connection should wait for the lock to go away until raising an exception. The default for the # timeout parameter is 5.0 (five seconds). self.db_conn.commit() def __del__(self): # Gracefully close the database connection. self.db_conn.close() # Reset GPIOs. for i in xrange(0, 4): self.gpio.digitalWrite(24 + i, Gpio.LOW) def get_sensor_output(self): # Get the latest sensor output return self.sensor_output.copy() def set_mux_channel(self, m): # Set MUX channel # Convert n into a binary string bin_repr = "{0:04b}".format(m) # Assign value to pin for i in xrange(0, 4): self.gpio.digitalWrite(24 + i, bin_repr[i]) def read_sensor(self, n): # Read raw data from sensor n, we allocate 2 channels for each sensor: # sensor 0: channel 0, 1 # sensor 1: channel 2, 3 # ... # sensor 7: channel 15, 16 # Set MUX to read the first channel try: self.set_mux_channel(2 * n) # Wait for 50 ms sleep(0.05) v1 = int(open(self.adc_raw).read()) * float( open(self.adc_scale).read()) # Set MUX to read the second channel self.set_mux_channel(2 * n + 1) sleep(0.05) v2 = int(open(self.adc_raw).read()) * float( open(self.adc_scale).read()) return v1, v2 except Exception as e: logger.error("Error reading sensor {}, reason: {}".format( n, e.message)) return 0.0, 0.0 def run(self): try: # Create the database file and get the connection object. self.db_conn = sqlite3.connect(self.database_name) # Get database cursor from the connection object. self.db_cur = self.db_conn.cursor() except Exception as e: logger.error("Error connecting the database {}, reason: {}".format( self.database_name, e.message)) self.__del__() # Keep reading sensors. while True: # Acquire the lock self.sensor_output_lock.acquire() # Add time stamp epoch_time = int(time()) self.sensor_output['time'] = epoch_time # Do sensor reading here # 1. set MUX to sensor 0, read sensor 0; # 2. set MUX to sensor 1, read sensor 1; # ... # n. set MUX to sensor n - 1, read sensor n - 1. logger.info("Reading {} sensor...".format(self.sensor_names[0])) # Temperature constant t0 = 550 c0, c1 = self.read_sensor(0) temp = (1.22 * c0) - t0 # Channel 1 is not connected so we don't care about its output logger.info("{} sensor outputs {} degree".format( self.sensor_names[0], temp)) # Save output to the dict self.sensor_output[self.sensor_names[0]] = temp logger.info("Reading {} sensor...".format(self.sensor_names[1])) c2, c3 = self.read_sensor(1) sn1 = (((1.22 * c2) - 345) - ((0.03) * ((1.22 * c3) - ((1.22 * c3) - 314)))) * 3.42465753 logger.info("{} sensor outputs {} ppb".format( self.sensor_names[1], sn1)) # Save output to the dict self.sensor_output[self.sensor_names[1]] = sn1 logger.info("Reading {} sensor...".format(self.sensor_names[2])) c4, c5 = self.read_sensor(2) sn2 = (((1.22 * c4) - 287) - ((1.18) * (1.22 * c5) - ((1.22 * c5) - 292))) * 3.87596899 logger.info("{} sensor outputs {} ppb".format( self.sensor_names[2], sn2)) # Save output to the dict self.sensor_output[self.sensor_names[2]] = sn2 logger.info("Reading {} sensor...".format(self.sensor_names[3])) c6, c7 = self.read_sensor(3) sn3 = (((1.22 * c6) - 333) - ((1.15) * (1.22 * c7) - ((1.22 * c7) - 274))) * 3.47222222 logger.info("{} sensor outputs {} ppb".format( self.sensor_names[3], sn3)) # Save output to the dict self.sensor_output[self.sensor_names[3]] = sn3 logger.info("Reading {} sensor...".format(self.sensor_names[4])) c8, c9 = self.read_sensor(4) sn4 = (((1.22 * c8) - 418) - ((0.18) * (1.22 * c9) - ((1.22 * c9) - 404))) * 2.54452926 logger.info("{} sensor outputs {} ppb".format( self.sensor_names[4], sn4)) # Save output to the dict self.sensor_output[self.sensor_names[4]] = sn4 logger.info("Reading {} sensor...".format(self.sensor_names[5])) c10, c11 = self.read_sensor(5) pm25 = 0.518 + 0.00274 * (240.0 * (1.22 * c10)**6 - 2491.3 * (1.22 * c10)**5 + 9448.7 * (1.22 * c10)**4 - 14840.0 * (1.22 * c10)**3 + 10684.0 * (1.22 * c10)**2 + 2211.8 * (1.22 * c10) + 7.9623) logger.info("{} sensor outputs {} ppb".format( self.sensor_names[5], pm25)) # Save output to the dict self.sensor_output[self.sensor_names[5]] = pm25 self.db_cur.execute( "INSERT INTO history VALUES ({}, {}, {}, {}, {}, {}, {})". format(epoch_time, temp, sn1, sn2, sn3, sn4, pm25)) self.db_conn.commit() self.sensor_output_lock.release() # Idle for 3 seconds sleep(1.8)
class SensorServer(Thread): """Sensor server that keeps reading sensors and provide get_sensor_output() method for user""" def __init__(self): # Parent class constructor Thread.__init__(self) # Assign GPIO pins that controls MUX, LSB to MSB self.gpio_pins = [24, 25, 26, 27] self.gpio = Gpio() # Set GPIO pins to output try: for pin in self.gpio_pins: self.gpio.pinMode(pin, self.gpio.OUTPUT) except Exception as e: logger.error("Error setting GPIO pin, reason %s" % e.message) print "Error setting GPIO pin %d, reason %s" % e.message # Use A0 port self.adc_raw = "/sys/bus/iio/devices/iio:device0/in_voltage0_raw" self.adc_scale = "/sys/bus/iio/devices/iio:device0/in_voltage_scale" self.sensor_names = ['Temp', 'SN1', 'SN2', 'SN3', 'SN4', 'PM25'] # Use a dict to store sensor output, the format is: # { "time": [time stamp], # [sensor1 name]: [sensor1 output], # ... # [sensor6 name]: [sensor6 output]} self.sensor_output = {} # Create a lock to protect sensor output. That is, when updating the result, lock it on to prevent it from being # read at the same time; similarly, when reading the result, lock it on to prevent it from being updated. self.sensor_output_lock = Lock() #스레드의 값이 이상하게 나오는 것을 막기 위해 Lock() self.db_conn = sqlite3.connect("air_pollution_data.db") self.db_cur = self.db_conn.cursor() for sensor_name in self.sensor_names: self.db_cur.execute( "CREATE TABLE IF NOT EXISTS %s (time int PRIMARY KEY NOT NULL, value real)" % sensor_name) def get_sensor_output(self): # Get the latest sensor output return self.sensor_output.copy() def set_mux_channel(self, m): # Set MUX channel # Convert n into a binary string bin_repr = "{0:04b}".format(m) # Assign value to pin for i in xrange(0, 4): self.gpio.digitalWrite(24 + i, bin_repr[i]) def read_sensor(self, n): # Read raw data from sensor n, we allocate 2 channels for each sensor: # sensor 0: channel 0, 1 # sensor 1: channel 2, 3 # ... # sensor 7: channel 15, 16 # Set MUX to read the first channel try: self.set_mux_channel(2 * n) v1 = int(open(self.adc_raw).read()) * float( open(self.adc_scale).read()) # Set MUX to read the second channel self.set_mux_channel(2 * n + 1) v2 = int(open(self.adc_raw).read()) * float( open(self.adc_scale).read()) return v1, v2 except Exception as e: logger.error("Error reading sensor %d, reason: %s" % (n, e.message)) print "Error reading sensor %d, reason: %s" % (n, e.message) return 0.0, 0.0 def run(self): # Keep reading sensors while True: # Acquire the lock self.sensor_output_lock.acquire() # Add time stamp self.sensor_output['time'] = int(time()) # Do sensor reading here # 1. set MUX to sensor 1, read sensor 1; # 2. set MUX to sensor 2, read sensor 2; # ... # n. set MUX to sensor n, read sensor n. for i in xrange(0, 6): logger.info("Reading %s sensor..." % self.sensor_names[i]) print "Reading %s sensor..." % self.sensor_names[i] v1, v2 = self.read_sensor(i) self.sensor_output[self.sensor_names[i]] = v1 - v2 self.sensor_output_lock.release() # Idle for 3 seconds sleep(3)
from neo import Gpio # import Gpio library from time import sleep # import sleep to wait for blinks neo = Gpio() #create new Neo object pinOne = 25 #pin to use neo.pinMode(pinOne, neo.OUTPUT)# Use innerbank pin 2 and set it as output either 0 (neo.INPUT) or 1 (neo.OUTPUT) #Blink example while True: #Do for five times neo.digitalWrite(pinOne,neo.HIGH) #write high value to pin sleep(1)# wait one second neo.digitalWrite(pinOne,neo.LOW) #write low value to pin sleep(1)# wait one second
def getSamsungCode(self): # Learning mode feedback led pinLED = 26 # IR receiver pinIR = 25 command_length_samasung = 65 neo = Gpio() neo.pinMode(pinIR, neo.INPUT) neo.pinMode(pinLED, neo.OUTPUT) neo.digitalWrite(pinLED, neo.HIGH) sample_number = 0 # Compute the average result after MAX_SAMPLES bits_sum = [0] * 32 MAX_SAMPLES = 3 while True: # stop the receiver after MAX_SAMPLES if sample_number == MAX_SAMPLES: for x in range(0, len(bits_sum)): bits_sum[x] = bits_sum[x] / (MAX_SAMPLES * 1.0) break value = 1 # Loop until get IR data time_to_live = 45000 while value and time_to_live: value = neo.digitalRead(pinIR) time_to_live -= 1 if time_to_live == 0: neo.digitalWrite(pinLED, neo.LOW) return "" # Grab the start time of the command startTime = datetime.now() # Used to buffer the command pulses command = [] # The end of the "command" happens when we read more than # a certain number of 1s (1 is off for the IR receiver) numOnes = 0 # Used to keep track of transitions from 1 to 0 previousVal = 0 while True: if value != previousVal: # The value has changed, so calculate the length of this run now = datetime.now() pulseLength = now - startTime startTime = now command.append((previousVal, pulseLength.microseconds)) # print str(previousVal) + " " + str(pulseLength.microseconds) #if len(command) == command_length_samasung: # break if value: numOnes = numOnes + 1 else: numOnes = 0 if numOnes > 100: break #if numOnes > 300: # break previousVal = value value = neo.digitalRead(pinIR) # A Sony IR signal starts with 2400 microseconds on and 600 microseconds off; # that's the first wide pulse. A "1" bit is transmitted with 1200 microseconds on and 600 microseconds off, # while a "0" bit is transmitted with 600 microseconds on and 600 microseconds off. # (This encoding is also called SIRC or SIRCS encoding.) # Chop the header of the received IR signal # print command command = command[2:] command = command[:64] #print "Command length: " + str(len(command)) # Establish the payload of the received IR signal binaryString = "".join( map(lambda x: "1" if x[1] > 1080 else "0", filter(lambda x: x[0] == 1, command))) # The length of the payload, according to SONY protocol is 12 bits; skip otherwise #print len(binaryString) if len(binaryString) != 32: continue #print "Good length!" sample_number = sample_number + 1 binaryString = map(int, binaryString) bits_sum = [sum(x) for x in zip(bits_sum, binaryString)] # compute the IR code based on MAX_SAMPLES result = "" for x in bits_sum: if x < 0.5: result += '0' else: result += '1' neo.digitalWrite(pinLED, neo.LOW) print result return result
class Reader: # S0,S1,S2,S3 selector_pins = [8, 9, 10, 11] # Number of connected to MUX Board mux_channel = { 'temp1': 0, 'no2': { 'we': 1, 'ae': 2 }, 'o3': { 'we': 3, 'ae': 4 }, 'co': { 'we': 5, 'ae': 6 }, 'so2': { 'we': 7, 'ae': 8 }, 'pm2_5': 9, } # Refer to 25-000160 Alphasense Datasheet calibration = { 'no2': { 'n': [1.18, 1.18, 1.18, 1.18, 1.18, 1.18, 1.18, 2.00], 'we_zero': 295, 'ae_zero': 282, 'sensitivity': 0.228 }, 'o3': { 'n': [0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18], 'we_zero': 391, 'ae_zero': 390, 'sensitivity': 0.399 }, 'co': { 'n': [1.40, 1.03, 0.85, 0.62, 0.30, 0.03, -0.25, -0.48], 'we_zero': 347, 'ae_zero': 296, 'sensitivity': 0.267 }, 'so2': { 'n': [0.85, 0.85, 0.85, 0.85, 0.85, 1.15, 1.45, 1.75], 'we_zero': 345, 'ae_zero': 255, 'sensitivity': 0.318 } } def __init__(self): self.lock = threading.Lock() self.gpio = Gpio() # init to LOW self.lock.acquire() for pin in Reader.selector_pins: self.gpio.pinMode(pin, self.gpio.OUTPUT) self.gpio.digitalWrite(pin, self.gpio.LOW) self.lock.release() # Read NO2, SO2, O3, CO, PM2.5, TEMP def read_no2(self): # Had a problem on sensors return round(self.__calibrate('no2') * 1000, 2) def read_o3(self): return round(self.__calibrate('o3') * 100, 2) def read_co(self): return round(self.__calibrate('co'), 2) def read_so2(self): return round(self.__calibrate('so2') * 1000, 2) def read_temp(self): mV = self.__read_adc(Reader.mux_channel['temp1']) temp = (mV - 500) * 0.1 # Celcius Value ftemp = (temp * 1.8) + 32 # Celcius to Fahrenheit return round(ftemp, 2) def read_pm(self): mV = self.__read_adc(Reader.mux_channel['pm2_5']) v = mV / 1000 hppcf = 240 * (v**6) - 2491.3 * (v**5) + 9448.7 * (v**4) - 14840 * ( v**3) + 10684 * (v**2) + 2211.8 * v + 7.9623 ugm3 = .518 + .00274 * hppcf return round(ugm3, 3) def __read_adc(self, channel): s_bin = self.__dec_to_bin(channel) self.lock.acquire() # write for i in range(4): self.gpio.digitalWrite(Reader.selector_pins[i], s_bin[i]) # read raw = int( open("/sys/bus/iio/devices/iio:device0/in_voltage0_raw").read()) scale = float( open("/sys/bus/iio/devices/iio:device0/in_voltage_scale").read()) self.lock.release() return raw * scale def __calibrate(self, name): we = self.__read_adc(Reader.mux_channel[name]['we']) ae = self.__read_adc(Reader.mux_channel[name]['ae']) temperature = self.read_temp() calibration = Reader.calibration[name] we = we - calibration['we_zero'] ae = ae - calibration['ae_zero'] temp = int(temperature / 10) + 3 if temp > 7: temp = 7 ae = (calibration['n'][temp]) * ae we = (we - ae) / calibration['sensitivity'] if we / 1000 > 0: return we / 1000 else: return 0 def __dec_to_bin(self, n): num = [0, 0, 0, 0] if n == 0: return num else: for x in range(n): t = x + 1 for y in range(4): num[y] = t % 2 t = t / 2 return num
# A easy Gpio library example for the Udoo Neo created by David Smerkous # The current things this library can do # digitalWriting/Reading - Soon to come PWM from neo import Gpio # import Gpio library from time import sleep # import sleep to wait for blinks neo = Gpio() #create new Neo object pinTwo = 2 #pin to use pinThree = 3 neo.pinMode(pinTwo, neo.OUTPUT)# Use innerbank pin 2 and set it as output either 0 (neo.INPUT) or 1 (neo.OUTPUT) neo.pinMode(pinThree, neo.INPUT)# Use pin three(innerbank) and read set state to read #Blink example for a in range(0, 5): #Do for five times neo.digitalWrite(pinTwo,neo.HIGH) #write high value to pin sleep(1)# wait one second neo.digitalWrite(pinTwo,neo.LOW) #write low value to pin sleep(1)# wait one second #Read pin print "Current pin("+str(pinThree)+") state is: "+str(neo.digitalRead(pinThree)) # read current value of pinThree(To succesfully read a pin it must be either pulled to ground or 3.3v, a non connected wire will not work)
def getCode(self): # Learning mode feedback led pinLED = 26 # IR receiver pinIR = 25 neo = Gpio() neo.pinMode(pinIR, neo.INPUT) neo.pinMode(pinLED, neo.OUTPUT) neo.digitalWrite(pinLED, neo.HIGH) # Compute the average result after MAX_SAMPLES gap_number = 0 MAX_GAPS = 3 GAP_TIME = 20000 value = 1 time_to_live = 45000 while value and time_to_live: value = neo.digitalRead(pinIR) time_to_live -= 1 if time_to_live == 0: neo.digitalWrite(pinLED, neo.LOW) return "" # Grab the start time of the command startTime = datetime.now() # Used to buffer the command pulses command = [] # Used to keep track of transitions from 1 to 0 previousVal = 0 while True: if value != previousVal: # The value has changed, so calculate the length of this run now = datetime.now() pulseLength = now - startTime startTime = now if pulseLength.microseconds > GAP_TIME: gap_number = gap_number + 1 if gap_number == MAX_GAPS: break command.append((previousVal, pulseLength.microseconds)) previousVal = value value = neo.digitalRead(pinIR) neo.digitalWrite(pinLED, neo.LOW) result = "" for (i, j) in command: result = result + " " + str(j) #result = result.replace(",", "") result = result[1:] print result return result
S0 = 8 # pin to use S1 = 9 S2 = 10 S3 = 11 pinNum = [S0, S1, S2, S3] num = [0, 0, 0, 0] # Blink example for i in range(4): neo.pinMode(pinNum[i], neo.OUTPUT) #Temperature sensor neo.digitalWrite(pinNum[0], 0) neo.digitalWrite(pinNum[1], 0) neo.digitalWrite(pinNum[2], 0) neo.digitalWrite(pinNum[3], 0) sleep(0.05) raw = int( open( "/sys/bus/iio/devices/iio:device0/in_voltage0_raw").read()) scale = float( open("/sys/bus/iio/devices/iio:device0/in_voltage_scale").read( )) c0 = raw * scale temp_celsius = (c0 - 500) / 10 temp = (temp_celsius * 1.8) + 32 temp = int(temp)
class SensorServer(Thread): """Sensor server that keeps reading sensors and provide get_sensor_output() method for user""" def __init__(self, database_name="air_pollution_data.db"): # Parent class constructor Thread.__init__(self) # Assign GPIO pins that controls MUX, LSB to MSB self.gpio_pins = [24, 25, 26, 27] self.gpio = Gpio() # Set GPIO pins to output try: for pin in self.gpio_pins: self.gpio.pinMode(pin, self.gpio.OUTPUT) except Exception as e: logger.error("Error setting GPIO pin {}, reason {}".format( pin, e.message)) # Use A0 port self.adc_raw = "/sys/bus/iio/devices/iio:device0/in_voltage0_raw" self.adc_scale = "/sys/bus/iio/devices/iio:device0/in_voltage_scale" self.sensor_names = ['Temp', 'SN1', 'SN2', 'SN3', 'SN4', 'PM25'] # Use a dict to store sensor output, the format is: # { "time": [time stamp], # [sensor1 name]: [sensor1 output], # ... # [sensor6 name]: [sensor6 output]} self.sensor_output = {} # Create a lock to protect sensor output. That is, when updating the result, lock it on to prevent it from being # read at the same time; similarly, when reading the result, lock it on to prevent it from being updated. self.sensor_output_lock = Lock() # Here we have a decision to make. I decide to let sensor server write sensor outputs to the local database. Of # course we can do so in a different thread either in a synchronous way or in an asynchronous way. If we do it # with a synchronous approach, we need to use locks to keep synchronization; if we do it with an asynchronous # solution, then SQLite3 is already an asynchronous module and I don't see good reason of adding another layer # of complexity. Perhaps the most reasonable way would be specifying the database in the main thread and then # send it to the sensor server thread. self.database_name = database_name try: # Create the database file and get the connection object. self.db_conn = sqlite3.connect(self.database_name) # Get database cursor from the connection object. self.db_cur = self.db_conn.cursor() except Exception as e: logger.error("Error connecting the database {}, reason: {}".format( self.database_name, e.message)) self.__del__() # Create tables for each sensors. Each table consists a time stamp key (epoch time) in integer and a real value # to hold the result of the sensor. Create tables only if they are not exist. for sensor_name in self.sensor_names: self.db_cur.execute( "CREATE TABLE IF NOT EXISTS {} (time int PRIMARY KEY NOT NULL, value real)" .format(sensor_name)) # Commit the changes. When a database is accessed by multiple connections, and one of the processes modifies the # database, the SQLite database is locked until that transaction is committed. The timeout parameter specifies # how long the connection should wait for the lock to go away until raising an exception. The default for the # timeout parameter is 5.0 (five seconds). self.db_conn.commit() def __del__(self): # Gracefully close the database connection. self.db_conn.close() # Reset GPIOs. for i in xrange(0, 4): self.gpio.digitalWrite(24 + i, Gpio.LOW) def get_sensor_output(self): # Get the latest sensor output return self.sensor_output.copy() def set_mux_channel(self, m): # Set MUX channel # Convert n into a binary string bin_repr = "{0:04b}".format(m) # Assign value to pin for i in xrange(0, 4): self.gpio.digitalWrite(24 + i, bin_repr[i]) def read_sensor(self, n): # Read raw data from sensor n, we allocate 2 channels for each sensor: # sensor 0: channel 0, 1 # sensor 1: channel 2, 3 # ... # sensor 7: channel 15, 16 # Set MUX to read the first channel try: self.set_mux_channel(2 * n) # Wait for 50 ms sleep(0.05) v1 = int(open(self.adc_raw).read()) * float( open(self.adc_scale).read()) # Set MUX to read the second channel self.set_mux_channel(2 * n + 1) sleep(0.05) v2 = int(open(self.adc_raw).read()) * float( open(self.adc_scale).read()) return v1, v2 except Exception as e: logger.error("Error reading sensor {}, reason: {}".format( n, e.message)) return 0.0, 0.0 def run(self): try: # Create the database file and get the connection object. self.db_conn = sqlite3.connect(self.database_name) # Get database cursor from the connection object. self.db_cur = self.db_conn.cursor() except Exception as e: logger.error("Error connecting the database {}, reason: {}".format( self.database_name, e.message)) self.__del__() # Keep reading sensors. while True: # Acquire the lock self.sensor_output_lock.acquire() # Add time stamp epoch_time = int(time()) self.sensor_output['time'] = epoch_time # Do sensor reading here # 1. set MUX to sensor 0, read sensor 0; # 2. set MUX to sensor 1, read sensor 1; # ... # n. set MUX to sensor n - 1, read sensor n - 1. logger.info("Reading {} sensor...".format(self.sensor_names[0])) # Temperature constant t0 = 550 c0, c1 = self.read_sensor(0) # Channel 1 is not connected so we don't care about its output temperature = c0 - t0 logger.info("{} sensor outputs {} degree".format( self.sensor_names[0], temperature)) # Save output to the dict self.sensor_output[self.sensor_names[0]] = temperature self.db_cur.execute("INSERT INTO {} VALUES ({}, {})".format( self.sensor_names[0], epoch_time, temperature)) logger.info("Reading {} sensor...".format(self.sensor_names[1])) c2, c3 = self.read_sensor(1) # NO2 output = ((c2 - 0.215) - (1.35) * (c3 - 0.246)) / (-0.212) logger.info("{} sensor outputs {} ppb".format( self.sensor_names[1], output)) # Save output to the dict self.sensor_output[self.sensor_names[1]] = output self.db_cur.execute("INSERT INTO {} VALUES ({}, {})".format( self.sensor_names[1], epoch_time, output)) logger.info("Reading {} sensor...".format(self.sensor_names[2])) c4, c5 = self.read_sensor(2) # O3 output = ((c4 - 0.39) - (1.28) * (c5 - 0.393)) / (-0.276) logger.info("{} sensor outputs {} ppb".format( self.sensor_names[2], output)) # Save output to the dict self.sensor_output[self.sensor_names[2]] = output self.db_cur.execute("INSERT INTO {} VALUES ({}, {})".format( self.sensor_names[2], epoch_time, output)) logger.info("Reading {} sensor...".format(self.sensor_names[3])) c6, c7 = self.read_sensor(3) #CO output = ((c4 - 0.39) - (1.28) * (c5 - 0.393)) / (-0.276) logger.info("{} sensor outputs {} ppb".format( self.sensor_names[3], output)) # Save output to the dict self.sensor_output[self.sensor_names[3]] = output self.db_cur.execute("INSERT INTO {} VALUES ({}, {})".format( self.sensor_names[3], epoch_time, output)) logger.info("Reading {} sensor...".format(self.sensor_names[4])) c8, c9 = self.read_sensor(4) #SO2 output = ((c8 - 0.28) - (1.82) * (c9 - 0.306)) / (-0.296) logger.info("{} sensor outputs {} ppb".format( self.sensor_names[4], output)) # Save output to the dict self.sensor_output[self.sensor_names[4]] = output self.db_cur.execute("INSERT INTO {} VALUES ({}, {})".format( self.sensor_names[4], epoch_time, output)) logger.info("Reading {} sensor...".format(self.sensor_names[5])) c10, c11 = self.read_sensor(5) output = c10 - c11 logger.info("{} sensor outputs {} ppb".format( self.sensor_names[5], output)) # Save output to the dict self.sensor_output[self.sensor_names[5]] = output self.db_cur.execute("INSERT INTO {} VALUES ({}, {})".format( self.sensor_names[5], epoch_time, output)) self.db_conn.commit() self.sensor_output_lock.release() # Idle for 3 seconds sleep(1.8)
class SensingThread(threading.Thread): selector_pins = [16, 17, 18, 19] mux_channel = { 'no2': { 'we': 2, 'ae': 3 }, 'o3': { 'we': 4, 'ae': 5 }, 'co': { 'we': 6, 'ae': 7 }, 'so2': { 'we': 8, 'ae': 9 }, 'temp': 0, 'pm2_5': 1, } calibration = { 'no2': { 'n': [1.18, 1.18, 1.18, 1.18, 1.18, 1.18, 1.18, 2.00], 'we_zero': 287, 'ae_zero': 292, 'sensitivity': 0.258 }, 'o3': { 'n': [0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18], 'we_zero': 418, 'ae_zero': 404, 'sensitivity': 0.393 }, 'co': { 'n': [1.40, 1.03, 0.85, 0.62, 0.30, 0.03, -0.25, -0.48], 'we_zero': 345, 'ae_zero': 314, 'sensitivity': 0.292 }, 'so2': { 'n': [0.85, 0.85, 0.85, 0.85, 0.85, 1.15, 1.45, 1.75], 'we_zero': 333, 'ae_zero': 274, 'sensitivity': 0.288 } } read_time = 0.2 def __init__(self, sender): threading.Thread.__init__(self) self.sender = sender self.gpio = Gpio() # init to LOW for pin in SensingThread.selector_pins: self.gpio.pinMode(pin, self.gpio.OUTPUT) self.gpio.digitalWrite(pin, self.gpio.LOW) def run(self): while True: data = self.__read_all() print "Raw value : " + str(data) DBManager.insert_air_data(data) self.sender.send({"type": "real-time", "data": data}) def __read_all(self): """ Read all sensor values :return: json string of sensor values (temp, so2, no2, co, o3, pm25) """ temp = round(self.__read_temp(), 2) no2 = round(self.__read_no2_ppb(temp), 2) o3 = round(self.__read_o3_ppb(temp), 2) co = round(self.__read_co_ppm(temp), 2) so2 = round(self.__read_so2_ppb(temp), 2) pm2_5 = round(self.__read_pm2_5(), 2) timestamp = int(time.time()) return { 'temp': temp, 'no2': no2, 'o3': o3, 'co': co, 'so2': so2, 'pm2_5': pm2_5, 'time': timestamp } def __read_temp(self): channel = SensingThread.mux_channel['temp'] subtotal = 0.0 c = 0 start_time = time.time() while time.time() - start_time < SensingThread.read_time: mV = self.__read_adc(channel) temp = (mV - 500) / 10 - 10 subtotal += temp c += 1 result = subtotal / c if result > 50: result = 50 if result < -20: result = -20 return result #return 25 def __read_no2_ppb(self, temp): return self.__calibrate_op('no2', temp) def __read_o3_ppb(self, temp): return self.__calibrate_op('o3', temp) def __read_co_ppm(self, temp): return self.__calibrate_op('co', temp) / 1000 def __read_so2_ppb(self, temp): return self.__calibrate_op('so2', temp) def __read_pm2_5(self): subtotal = 0.0 c = 0 start_time = time.time() while time.time() - start_time < SensingThread.read_time: v = self.__read_adc(SensingThread.mux_channel['pm2_5']) / 1000 hppcf = 240.0 * (v**6) - 2491.3 * (v**5) + 9448.7 * ( v**4) - 14840.0 * (v**3) + 10684.0 * (v** 2) + 2211.8 * v + 7.9623 subtotal += .518 + .00274 * hppcf c += 1 return subtotal / c def __calibrate_op(self, name, temp): channel_we = SensingThread.mux_channel[name]['we'] channel_ae = SensingThread.mux_channel[name]['ae'] calibration = SensingThread.calibration[name] zero_we = calibration['we_zero'] zero_ae = calibration['ae_zero'] subtotal = 0.0 c = 0 start_time = time.time() while time.time() - start_time < SensingThread.read_time: we = self.__read_adc(channel_we) ae = self.__read_adc(channel_ae) we = we - zero_we ae = ae - zero_ae if temp > 50: temp = 50 elif temp < -20: temp = -20 ae = (calibration['n'][int(temp / 10) + 2]) * ae we = (we - ae) / calibration['sensitivity'] subtotal += we if we > 0 else 0 c += 1 # ppb return subtotal / c def __read_adc(self, channel): s_bin = self.__dec_to_bin(channel) # write for i in range(4): self.gpio.digitalWrite(SensingThread.selector_pins[i], s_bin[i]) # read raw = int( open("/sys/bus/iio/devices/iio:device0/in_voltage0_raw").read()) scale = float( open("/sys/bus/iio/devices/iio:device0/in_voltage_scale").read()) return raw * scale def __dec_to_bin(self, n): num = [0, 0, 0, 0] if n == 0: return num else: for x in range(n): t = x + 1 for y in range(4): num[y] = t % 2 t = t / 2 return num
from neo import Gpio from time import sleep neo = Gpio() pinNum = [0, 1, 2, 3] for i in pinNum: neo.pinMode(pinNum[i], neo.OUTPUT) for x in range(15): num = [0, 0, 0, 0] t = x + 1 for y in range(4): num[y] = t % 2 t = t / 2 neo.digitalWrite(pinNum[3], num[3]) neo.digitalWrite(pinNum[2], num[2]) neo.digitalWrite(pinNum[1], num[1]) neo.digitalWrite(pinNum[0], num[0]) sleep(1)