class mpu9250: def __init__(self): self.accelerometer = vec3() self.gyroscope = vec3() self.bus = SMBus(1) self.bus.open(1) # Set accelerometers low pass filter at 5Hz self.bus.write_byte_data(MPUADDRESS,29,6) # Set gyroscope low pass filter at 5Hz self.bus.write_byte_data(MPUADDRESS,26,6) # Configure gyroscope range self.bus.write_byte_data(MPUADDRESS,27,10) # Configure accelerometers range self.bus.write_byte_data(MPUADDRESS,28,8) # Set by pass mode for the magnetometers self.bus.write_byte_data(MPUADDRESS,37,2) # Request continuous magnetometer measurements in 16 bits #self.bus.write_byte_data(MAGADDRESS,0x0A,0x16) def updateGyroscopeAndAccelerometerData(self): data = self.bus.read_i2c_block_data(MPUADDRESS, 0x3b, 14) self.accelerometer.x =-(data[0]<<8 | data[1]) self.accelerometer.y = -(data[2]<<8 | data[3]) self.accelerometer.z = data[4]<<8 | data[5] self.gyroscope.x = -(data[8]<<8 | data[9]) self.gyroscope.y = -(data[10]<<8 | data[11]) self.gyroscope.z = data[12]<<8 | data[13]
def test_open(): bus = SMBus() py.test.raises(IOError, 'bus.open(-13)') bus.open(BUS) # does not raise if hasattr(bus, '_fd'): assert bus._fd != -1
def test_open(): bus = SMBus() pytest.raises(IOError, 'bus.open(-13)') bus.open(BUS) # does not raise if hasattr(bus, '_fd'): assert bus._fd != -1
class Accelerometer: def __init__(self, par_i2c_addr, par_reg_pwr_ctl, par_reg_data_format, par_reg_data_start): self.i2c_address = par_i2c_addr self.reg_pwr_ctl = par_reg_pwr_ctl self.reg_data_format = par_reg_data_format self.reg_data_start = par_reg_data_start self.i2c = SMBus() self.i2c.open(1) self.i2c.write_byte_data(self.i2c_address, self.reg_pwr_ctl, 0x08) self.i2c.write_byte_data(self.i2c_address, self.reg_data_format, 0x0a) self.data = self.i2c.read_i2c_block_data(self.i2c_address, self.reg_data_start, 6) @staticmethod def bits_to_int(val): if val >> 15: val = ~val + 1 val = val & 0xffff # val = - val return val def read_data(self, val): if val == "x": x = self.data[1] << 8 | self.data[0] x_int = Accelerometer.bits_to_int(x) x_g = x_int * 4 / 1000 return x_g if val == "y": y = self.data[3] << 8 | self.data[2] y_int = Accelerometer.bits_to_int(y) y_g = y_int * 4 / 1000 return y_g if val == "z": z = self.data[5] << 8 | self.data[4] z_int = Accelerometer.bits_to_int(z) z_g = z_int * 4 / 1000 return z_g def get_speed(self): # X x = self.data[1] << 8 | self.data[0] x_int = Accelerometer.bits_to_int(x) x_g = x_int * 4 / 1000 # Y y = self.data[3] << 8 | self.data[2] y_int = Accelerometer.bits_to_int(y) y_g = y_int * 4 / 1000 # Z z = self.data[5] << 8 | self.data[4] z_int = Accelerometer.bits_to_int(z) z_g = z_int * 4 / 1000 gravity = math.sqrt(x_g**2 + y_g**2 + z_g**2) speed = gravity * 3.6 return speed
class MPU6050: def __init__(self, address_mpu): self.address_mpu = address_mpu self.i2c = SMBus() self.setup() def setup(self): # open bus 1 print('open bus 1') self.i2c.open(1) # sensor uit sleep modus halen print('sensor uit sleep modus halen') self.i2c.write_byte_data(self.address_mpu, 0x6B, 1) # instellen gyroscoop print('gyroscoop instellen') self.i2c.write_byte_data(self.address_mpu, 0x1B, 0x00) def read_data(self): # data inlezen raw_data = self.i2c.read_i2c_block_data(self.address_mpu, 0x43, 6) # gyro x_waarde_gyro = self.registerwaarden_omzetten(raw_data[0], raw_data[1]) y_waarde_gyro = self.registerwaarden_omzetten(raw_data[2], raw_data[3]) z_waarde_gyro = self.registerwaarden_omzetten(raw_data[4], raw_data[5]) x_waarde_gyro_in_graden, y_waarde_gyro_in_graden, z_waarde_gyro_in_graden = self.omzetten_graden_per_seconde( x_waarde_gyro, y_waarde_gyro, z_waarde_gyro) return x_waarde_gyro_in_graden, y_waarde_gyro_in_graden, z_waarde_gyro_in_graden @staticmethod def registerwaarden_omzetten(msb, lsb): msb = msb << 8 if bin(msb)[2] == '1': msb = msb - 2**16 waarde = msb | lsb waarde = waarde / 340 + 36.53 return waarde @staticmethod def omzetten_graden_per_seconde(x_waarde, y_waarde, z_waarde): rot_x = x_waarde / 131 rot_y = y_waarde / 131 rot_z = z_waarde / 131 return rot_x, rot_y, rot_z def opkuisen(self): self.i2c.close()
class VL53LOX: def __init__(self, address): self.address = address self.i2c = SMBus() self.setup() def setup(self): self.i2c.open(1) def read_data(self): self.i2c.write_byte(self.address, 0) value = self.i2c.read_byte(self.address) return value def close(self): self.i2c.close()
class BH1750: def __init__(self): self.slave_address = 0x23 self.power_down_instruct = 0x00 self.power_up_instruct = 0x01 self.reset_instruct = 0x07 # Reset data register value self.resolution = 0 self.set_resolution(0) self.i2c = SMBus() #initialize library self.i2c.open(1) # open bus1 def set_resolution(self, modus, isContinuous=True): #set used resolution resolution_array = [0x13, 0x10, 0x11] if isContinuous == False: # instructions where device powers down after 1 measurement resolution_array = [0x23, 0x20, 0x21] if modus < len(resolution_array) and modus >= 0: self.resolution = resolution_array[modus] # 0 = 4lx resolution. Time typically 16ms. # 1 = 1lx resolution. Time typically 120ms # 2 = 0.5lx resolution. Time typically 120ms def data_to_number(self, data): # convert 2 bytes of data into a decimal number return ((data[1] + (256 * data[0])) / 1.2) def reset(self): self.i2c.write_byte_data(self.slave_address, self.reset_instruct) def read_light(self): data = self.i2c.read_i2c_block_data(self.slave_address, self.resolution, 2) time.sleep(0.1) #self.reset() return self.data_to_number(data)
from RPi import GPIO from smbus import SMBus import time def setup(): GPIO.setmode(GPIO.BCM) if __name__ == '__main__': try: setup() global pcf pcf = SMBus() pcf.open(1) while True: pcf.write_byte(0x20, 0xFF) except KeyboardInterrupt as e: print(e) finally: pcf.close()
from smbus import SMBus import time i2c = SMBus() # init library i2c.open(1) # open bus 1 class MPU6050: def __init__(self, address): self.addr = address self.setup() def setup(self): # schaalfactor accelerometer self.__write_byte(0x1C, 0x00) # schaalfactor gyroscoop self.__write_byte(0x1B, 0x00) # sensor uit slaapstand self.__write_byte(0x6B, 0x01) def print_data(self): print("***") print('De temperatuur is {}°C'.format(self.read_temp())) accel = self.read_accel() print('Accel: x = {0}, y = {1}, z = {2}'.format( accel[0], accel[1], accel[2])) gyro = self.read_gyro() print('Gyro : x = {0}°/s, y = {1}°/s, z = {2}°/s'.format( gyro[0], gyro[1], gyro[2])) print()
class DS3231: def __init__(self, address=DS3231_DEFAULT_ADDRESS): self.i2c = SMBus() self.i2c.open(1) self.address = address logging.info("Klasse geinitialliseerd") @property def clock_enabled(self): value = self.i2c.read_byte_data(self.address, DS3231_REG_CONTROL) value = value >> 7 if value == 1: logging.info("Clock is off") return False else: logging.info("Clock is on") return True @clock_enabled.setter def clock_enabled(self, value): if value == 0: current_settings = self.i2c.read_byte_data(self.address, DS3231_REG_CONTROL) logging.debug("Current control: %s" % current_settings) new_settings = current_settings | 0b10000000 logging.debug("New control: %s" % new_settings) logging.info("Clock disabled") self.i2c.write_byte_data(self.address, DS3231_REG_CONTROL, new_settings) else: current_settings = self.i2c.read_byte_data(self.address, DS3231_REG_CONTROL) logging.debug("Current control: %s" % current_settings) new_settings = current_settings & 0b01111111 logging.debug("New control: %s" % new_settings) logging.info("Clock enabled") self.i2c.write_byte_data(self.address, DS3231_REG_CONTROL, new_settings) def get_datetime(self): try: year = 2000 + self.bcd2int( self.i2c.read_byte_data(self.address, DS3231_REG_YEAR)) month = self.bcd2int( self.i2c.read_byte_data(self.address, DS3231_REG_MONTH)) day = self.bcd2int( self.i2c.read_byte_data(self.address, DS3231_REG_DATE)) hour = self.bcd2int( self.i2c.read_byte_data(self.address, DS3231_REG_HOURS)) minute = self.bcd2int( self.i2c.read_byte_data(self.address, DS3231_REG_MINUTES)) sec = self.bcd2int( self.i2c.read_byte_data(self.address, DS3231_REG_SECONDS)) time = datetime.datetime(year, month, day, hour, minute, sec) logging.debug("Got datetime from module: %s" % time) return time except Exception as ex: logging.error("Error getting datetime: %s" % ex) def set_datetime(self, value=None): try: if value: if isinstance(value, datetime): date = value else: date = datetime.datetime.now() else: date = datetime.datetime.now() self.i2c.write_byte_data(self.address, DS3231_REG_YEAR, self.int2bcd(date.year - 2000)) self.i2c.write_byte_data(self.address, DS3231_REG_MONTH, self.int2bcd(date.month)) self.i2c.write_byte_data(self.address, DS3231_REG_DATE, self.int2bcd(date.day)) self.i2c.write_byte_data(self.address, DS3231_REG_HOURS, self.int2bcd(date.hour)) self.i2c.write_byte_data(self.address, DS3231_REG_MINUTES, self.int2bcd(date.minute)) self.i2c.write_byte_data(self.address, DS3231_REG_SECONDS, self.int2bcd(date.second)) logging.info("Datetime set: %s" % date) except Exception as ex: logging.error("Error setting datetime: %s" % ex) @staticmethod def int2bcd(value): bcd = (int(value / 10)) << 4 bcd += value % 10 return bcd @staticmethod def bcd2int(value): t = value >> 4 e = (value & 0b00001111) n = t * 10 + e return n
class ThePlanter(object): def __init__(self): self._min_seconds_between_breaths = 10 self._min_seconds_between_coughs = 5 self._bad_co2_threshold = 450 self._bad_voc_threshold = 50 self._seconds_until_next_breath = 0 self._seconds_until_next_possible_cough = 0 self.smbus = SMBus() baseline_file = path.join(path.dirname(path.realpath(__file__)), 'sgp30-baseline') self.sensor_thread = SensorThread(self.smbus, baseline_cache_path=baseline_file) cough_filename = path.join(path.dirname(path.realpath(__file__)), '151217__owlstorm__cough-3.wav') self.cougher = Cougher(cough_filename, (360.0, 1.0, 1.0)) self.breather = Breather((161 / 360.0, 0.98, 1.0)) def setup(self): self.cougher.setup() self.smbus.open(1) # 0 on some devices def teardown(self): if self.sensor_thread is None: return print('Waiting on sensor thread to terminate...', file=stderr) self.sensor_thread.terminate_asap = True if self.sensor_thread.is_alive(): self.sensor_thread.join() self.sensor_thread = None self.smbus.close() self.smbus = None self.cougher.teardown() self.cougher = None def main(self): min_sleep_between_loop_calls = 0.2 try: self.smbus.open(1) self.sensor_thread.start() time_at_start_of_last_loop = time() while True: now = time() loop_res = self.loop(self.sensor_thread.last_sample, now - time_at_start_of_last_loop) time_at_start_of_last_loop = now if loop_res is False: return now = time() needed_extra_sleep = min_sleep_between_loop_calls - ( now - time_at_start_of_last_loop) if needed_extra_sleep >= 0: sleep(needed_extra_sleep) except Exception as exc: print('Going down:', exc, file=stderr) finally: self.teardown() def loop(self, last_sample, dt): print(dt, self._seconds_until_next_breath, self._seconds_until_next_possible_cough, last_sample) if last_sample is None: return is_bad = last_sample.co2_ppm >= self._bad_co2_threshold or last_sample.voc_ppb >= self._bad_voc_threshold # always becomes more possible to cough self._seconds_until_next_possible_cough = self._seconds_until_next_possible_cough - dt if is_bad: # a bad sample should reset the time until the next breath self._seconds_until_next_breath = self._min_seconds_between_breaths if self._seconds_until_next_possible_cough <= 0: self.cougher.cough() self._seconds_until_next_possible_cough = self._min_seconds_between_coughs else: # a good sample should get us closer to a breath self._seconds_until_next_breath = self._seconds_until_next_breath - dt if self._seconds_until_next_breath <= 0: self.breather.breathe() self._seconds_until_next_breath = self._min_seconds_between_breaths
from flaskext.mysql import MySQL from flask_httpauth import HTTPBasicAuth from passlib import pwd from passlib.hash import argon2 from smbus import SMBus from RPi import GPIO import time from threading import Thread import random # init hardware bus = SMBus() # Rev 2 Pi uses 1 bus.open(1) DEVICE = 0x20 # Device address (A0-A2) DEVICE1 = 0x21 IODIRA = 0x00 # Pin direction register GPIOA = 0x12 # Register for inputs GPPUA = 0x0C IODIRB = 0x01 # Pin direction register GPIOB = 0x13 # Register for inputs GPPUB = 0x0D bus.write_byte_data(DEVICE, 0x04, 0b11111111) bus.write_byte_data(DEVICE, IODIRA, 0b11111111) bus.write_byte_data(DEVICE, GPPUA, 0b11111111) bus.write_byte_data(DEVICE, IODIRB, 0b11111111) bus.write_byte_data(DEVICE, GPPUB, 0b11111111)
class MCP3428(object): """ """ def __init__(self): self.LSB_12BITS = 0.001000 self.LSB_14BITS = 0.000250 self.LSB_16BITS = 0.0000625 self.CW_RDY = 0b10000000 self.CW_C1 = 0b00000000 self.CW_C2 = 0b00100000 self.CW_C3 = 0b01000000 self.CW_C4 = 0b01100000 self.CW_CC = 0b00010000 self.CW_CM = 0b00000000 self.CW_240SPS = 0b00000000 self.CW_60SPS = 0b00000100 self.CW_15SPS = 0b00001000 self.CW_G1 = 0b00000000 self.CW_G2 = 0b00000001 self.CW_G4 = 0b00000010 self.CW_G8 = 0b00000011 self.addr = 0 self.mode = self.CW_CC self.sps = self.CW_15SPS self.lsb = self.LSB_16BITS self.gain = self.CW_G1 def open(self, bus_num, bus=None): if bus != None: self.bus = bus else: self.bus = SMBus() self.bus.open(bus_num) def addr_is(self, pin0, pin1): """ Calcule l'addresse du chip avec la configuration des pin adresse pin0 et pin1 None : pin floatante True : V+ False : GND """ BASE_ADDR = 0b1101000 if pin0 == None and pin1 == None: return BASE_ADDR | 0b000 if pin0 == False and pin1 == False: return BASE_ADDR | 0b000 if pin0 == False and pin1 == None: return BASE_ADDR | 0b001 if pin0 == False and pin1 == True: return BASE_ADDR | 0b010 if pin0 == None and pin1 == False: return BASE_ADDR | 0b011 if pin0 == True and pin1 == False: return BASE_ADDR | 0b100 if pin0 == True and pin1 == None: return BASE_ADDR | 0b101 if pin0 == True and pin1 == True: return BASE_ADDR | 0b110 if pin0 == None and pin1 == True: return BASE_ADDR | 0b111 def set_addr(self, addr): self.addr = addr def set_mode(self, mode): self.mode = mode & 0b10010011 def set_channel(self, CW_Cx): self.bus.write_byte( self.addr, self.CW_RDY | CW_Cx | self.mode | self.sps | self.gain) time.sleep(0.12) return def close(self): bus.close() def get_value(self): buf = self.bus.read_i2c_block_data(self.addr, 0, 2) #print buf if self.gain == self.CW_G1: return (buf[0] << 8 | buf[1]) * self.lsb if self.gain == self.CW_G2: return (buf[0] << 8 | buf[1]) * self.lsb / 2 if self.gain == self.CW_G4: return (buf[0] << 8 | buf[1]) * self.lsb / 4 if self.gain == self.CW_G8: return (buf[0] << 8 | buf[1]) * self.lsb / 8 def set_lsb(self, lsb): self.lsb = lsb if self.lsb == self.LSB_12BITS: self.sps = self.CW_240SPS if self.lsb == self.LSB_14BITS: self.sps = self.CW_60SPS if self.lsb == self.LSB_16BITS: self.sps = self.CW_15SPS return self.sps def set_sps(self, sps): self.sps = sps if self.sps == self.CW_240SPS: self.lsb = self.LSB_12BITS if self.sps == self.CW_60SPS: self.lsb = self.LSB_14BITS if self.sps == self.CW_15SPS: self.lsb = self.LSB_16BITS return self.lsb def close(self): self.bus.close() def send_general_reset(self): self.bus.write_byte(self.addr, 0x06) time.sleep(0.5) return def send_general_latch(self): self.bus.write_byte(self.addr, 0x04) time.sleep(0.12) return def send_general_conversion(self): self.bus.write_byte(self.addr, 0x08) time.sleep(0.12) return def set_gain(self, gain): self.gain = gain
class BMP280: def __init__(self, address=BMP280_DEFAULT_ADRESS): self.i2c = SMBus() self.i2c.open(1) self.address = address self._load_calibration() self.i2c.write_byte_data(self.address, BMP280_CONTROL, 0x3F) def i2c_check(self): """Output should be 88, if not. I2c not correct""" data = self.i2c.read_byte_data(self.address, 0xD0) print(data) def _readU16(self, reg): """Reads an unsigned 16 bit value van i2c""" result = self.i2c.read_word_data(self.address, reg) return result def _readS16(self, reg): """Reads a signed 16 bit value van i2c""" result = self._readU16(reg) if result > 32767: result -= 65536 return result def _load_calibration(self): self.cal_t1 = int(self._readU16(BMP280_DIG_T1)) # UINT16 self.cal_t2 = int(self._readS16(BMP280_DIG_T2)) # INT16 self.cal_t3 = int(self._readS16(BMP280_DIG_T3)) # INT16 self.cal_p1 = int(self._readU16(BMP280_DIG_P1)) # UINT16 self.cal_p2 = int(self._readS16(BMP280_DIG_P2)) # INT16 self.cal_p3 = int(self._readS16(BMP280_DIG_P3)) # INT16 self.cal_p4 = int(self._readS16(BMP280_DIG_P4)) # INT16 self.cal_p5 = int(self._readS16(BMP280_DIG_P5)) # INT16 self.cal_p6 = int(self._readS16(BMP280_DIG_P6)) # INT16 self.cal_p7 = int(self._readS16(BMP280_DIG_P7)) # INT16 self.cal_p8 = int(self._readS16(BMP280_DIG_P8)) # INT16 self.cal_p9 = int(self._readS16(BMP280_DIG_P9)) # INT16 def read_raw_data(self, register): data = self.i2c.read_i2c_block_data(self.address, register, 3) data = self.convert_data(data[0], data[1], data[2]) return data def _compensate_temp(self, raw_temp): t1 = (((raw_temp >> 3) - (self.cal_t1 << 1)) * (self.cal_t2) >> 11) t2 = (((((raw_temp >> 4) - (self.cal_t1)) * ((raw_temp >> 4) - (self.cal_t1))) >> 12) * (self.cal_t3)) >> 14 return t1 + t2 def read_temperature(self): raw_temp = self.read_raw_data(BMP280_TEMPDATA) compensated_temp = self._compensate_temp(raw_temp) temp = float(((compensated_temp * 5 + 128) >> 8)) / 100 return temp def read_pressure(self): raw_temp = self.read_raw_data(BMP280_TEMPDATA) compensated_temp = self._compensate_temp(raw_temp) raw_pressure = self.read_raw_data(BMP280_PRESSUREDATA) p1 = compensated_temp - 128000 p2 = p1 * p1 * self.cal_p6 p2 += (p1 * self.cal_p5) << 17 p2 += self.cal_p4 << 35 p1 = ((p1 * p1 * self.cal_p3) >> 8) + ((p1 * self.cal_p2) << 12) p1 = ((1 << 47) + p1) * (self.cal_p1) >> 33 if 0 == p1: return 0 p = 1048576 - raw_pressure p = (((p << 31) - p2) * 3125) / p1 p1 = (self.cal_p9 * (int(p) >> 13) * (int(p) >> 13)) >> 25 p2 = int((self.cal_p8 * p)) >> 19 p = (int((p + p1 + p2)) >> 8) + ((self.cal_p7) << 4) return float(p / 256) def read_altitude(self, sealevel_pa=101325.0): """Calculates the altitude in meters.""" # Calculation taken straight from section 3.6 of the datasheet. pressure = float(self.read_pressure()) altitude = 44330.0 * (1.0 - pow(pressure / sealevel_pa, (1.0 / 5.255))) return altitude def read_sealevel_pressure(self, altitude_m=0.0): """Calculates the pressure at sealevel when given a known altitude in meters. Returns a value in Pascals.""" pressure = float(self.read_pressure()) p0 = pressure / pow(1.0 - altitude_m / 44330.0, 5.255) return p0 @staticmethod def convert_data(msb, lsb, xlsb): data = ((msb << 8 | lsb) << 8 | xlsb) >> 4 return data
class PM2: '''Handle display''' # Translation value from String to Display digits = { '': 0, '1': 96, '2': 167, '3': 227, '4': 106, '5': 203, '6': 207, '7': 224, '8': 239, '9': 235, '0': 237 } buffer = [0 for i in xrange(20)] # Buffer for device RAM def __init__(self, defaultBus=PI_DEFAULT_BUS, defaultAddr=PM2_DEFAULT_ADDRESS): self.bus = SMBus(defaultBus) self.busNum = defaultBus self.defaultAddr = defaultAddr self.bus.close() self.bus.open(self.busNum) self.bus.write_byte(self.defaultAddr, PM2_MODE_SET) self.clear() self.set_mode('normal') self.top_right('00') self.middle('000') self.top_left('0000') self.bottom_left('0000') def write_bit(self, addr, position, value): '''write one bit to buffer @addr : buffer address -> int @position : bit position -> int @value : bit value -> boolean ''' mask = ~(1 << position) value = value << position self.buffer[addr] = (self.buffer[addr] & mask) | value def write_digit(self, addr, value): '''write single/multiple digit(s) to buffer @addr : buffer address -> int @value : single/mutiple digit -> string ''' i = addr for x in reversed(value): intVal = self.digits[x] mask = 1 << 4 # Preserve DP bit self.buffer[i] = (self.buffer[i] & mask) | intVal i += 1 def set_mode(self, mode): '''Toggle between different possible mode : -normal -cal/hr -watts -heart rate ''' if (mode == 'normal'): """Time, /500m, Distance""" self.set_segment_colon_top_left(False) self.set_segment_colon_top_right(True) self.set_segment_dp_top(False) self.set_segment_time_top(True) self.set_segment_meters_top(False) self.set_segment_spm_top(True) self.set_segment_int_top(False) self.set_segment_1_middle(False) self.set_segment_colon_middle(True) self.set_segment_500m_middle(True) self.set_segment_calhr_middle(False) self.set_segment_watts_middle(False) self.set_segment_rest_time_middle(False) self.set_segment_int_middle(False) self.set_segment_colon_bottom_left(False) self.set_segment_colon_bottom_right(False) self.set_segment_dp_bottom(False) self.set_segment_ave_bottom(False) self.set_segment_500m_bottom(False) self.set_segment_watts_bottom(False) self.set_segment_split_bottom(False) self.set_segment_cal_bottom(False) self.set_segment_proj_bottom(False) self.set_segment_time_bottom(False) self.set_segment_meters_bottom(True) self.set_segment_dragfactor_bottom(False) elif (mode == 'watts'): """Time, Watts, Distance""" self.set_segment_colon_top_left(False) self.set_segment_colon_top_right(True) self.set_segment_dp_top(False) self.set_segment_time_top(True) self.set_segment_meters_top(False) self.set_segment_spm_top(True) self.set_segment_int_top(False) self.set_segment_1_middle(False) self.set_segment_colon_middle(False) self.set_segment_500m_middle(False) self.set_segment_calhr_middle(False) self.set_segment_watts_middle(True) self.set_segment_rest_time_middle(False) self.set_segment_int_middle(False) self.set_segment_colon_bottom_left(False) self.set_segment_colon_bottom_right(False) self.set_segment_dp_bottom(False) self.set_segment_ave_bottom(True) self.set_segment_500m_bottom(False) self.set_segment_watts_bottom(True) self.set_segment_split_bottom(False) self.set_segment_cal_bottom(False) self.set_segment_proj_bottom(False) self.set_segment_time_bottom(False) self.set_segment_meters_bottom(False) self.set_segment_dragfactor_bottom(False) elif (mode == 'heart rate'): self.set_segment_colon_middle(isHeartRate) def set_segment_colon_top_left(self, enabled): '''Set first : segment at the top from the left''' self.write_bit(13, 5, enabled) def set_segment_colon_top_right(self, enabled): '''Set 2nd : segment at the top from the left''' self.write_bit(18, 1, enabled) def set_segment_int_top(self, enabled): '''Set INT segment in the top right corner''' self.write_bit(19, 0, enabled) def set_segment_spm_top(self, enabled): '''Set SPM segment in the top right corner''' self.write_bit(14, 4, enabled) def set_segment_meters_top(self, enabled): '''Set METERS segment in at the top''' self.write_bit(19, 4, enabled) def set_segment_time_top(self, enabled): '''Set TIME segment in at the top''' self.write_bit(0, 4, enabled) def set_segment_dp_top(self, enabled): '''Set DP segment (decimal point) in at the top''' self.write_bit(1, 4, enabled) def set_segment_calhr_middle(self, enabled): '''Set CAL/HR segment in the middle''' self.write_bit(19, 7, enabled) def set_segment_500m_middle(self, enabled): '''Set /500M segment in the middle''' self.write_bit(19, 5, enabled) def set_segment_int_middle(self, enabled): '''Set INT segment in the middle''' self.write_bit(19, 2, enabled) def set_segment_watts_middle(self, enabled): '''Set WATTS segment in the middle''' self.write_bit(19, 6, enabled) def set_segment_colon_middle(self, enabled): '''Set : segment in the middle''' self.write_bit(19, 1, enabled) def set_segment_1_middle(self, enabled): '''Set '1' segment in the middle''' self.write_bit(13, 6, enabled) def set_segment_rest_time_middle(self, enabled): '''Set REST TIME segment in the middle''' self.write_bit(10, 4, enabled) def set_segment_ave_bottom(self, enabled): '''Set AVE segment in the bottom''' self.write_bit(13, 7, enabled) def set_segment_500m_bottom(self, enabled): '''Set /500M segment in the bottom''' self.write_bit(13, 4, enabled) def set_segment_watts_bottom(self, enabled): '''Set WATTS segment in the bottom''' self.write_bit(12, 4, enabled) def set_segment_split_bottom(self, enabled): '''Set SPLIT segment in the bottom''' self.write_bit(11, 4, enabled) def set_segment_cal_bottom(self, enabled): '''Set CAL segment in the bottom''' self.write_bit(9, 4, enabled) def set_segment_proj_bottom(self, enabled): '''Set PROJ segment in the bottom''' self.write_bit(8, 4, enabled) def set_segment_dp_bottom(self, enabled): '''Set DP segment (decimal point) in the bottom''' self.write_bit(6, 4, enabled) def set_segment_time_bottom(self, enabled): '''Set TIME segment in the bottom''' self.write_bit(7, 4, enabled) def set_segment_meters_bottom(self, enabled): '''Set METERS segment in the bottom''' self.write_bit(13, 0, enabled) def set_segment_dragfactor_bottom(self, enabled): '''Set DRAG FACTOR segment in the bottom''' self.write_bit(18, 0, enabled) def set_segment_heartrate_bottom(self, enabled): '''Set HEART RATE segment in the bottom''' self.write_bit(17, 4, enabled) def set_segment_colon_bottom_left(self, enabled): '''Set 1st : segment at the bottom from the left''' self.write_bit(18, 5, enabled) def set_segment_colon_bottom_right(self, enabled): '''Set 2nd : segment at the bottom from the left''' self.write_bit(13, 1, enabled) def top_right(self, value): '''Display value to the top rigth corner of the screen''' startAddr = 14 if (int(value) <= 99): self.write_digit(startAddr, value) self.refresh() return True else: return False def middle(self, value): '''Display value to the middle of the screen''' startAddr = 10 if (int(value) <= 999): self.write_digit(startAddr, value) self.refresh() return True elif (int(value) > 999 & int(value) <= 1999): self.set_segment_middle_1(True) self.write_digit(startAddr, value) self.refresh() else: return False def bottom_right(self, value): '''Display value to the bottom right corner of the screen''' startAddr = 17 if (int(value) <= 399): self.write_digit(startAddr, value) self.refrsh() return True else: return False def top_left(self, value): '''Display value to the top left corner of the screen''' startAddr = 0 if (int(value) <= 99999): self.write_digit(startAddr, value) self.refresh() return True else: return False def bottom_left(self, value): '''Display value to the bottom left corner of the screen''' startAddr = 5 if (int(value) <= 99999): self.write_digit(startAddr, value) self.refresh() return True else: return False def refresh(self): '''Push buffer content to device RAM at once for display''' # Do nothing special execpt avoiding an I2C communication error self.bus.write_byte(self.defaultAddr, 0b01100000) self.bus.write_i2c_block_data(self.defaultAddr, 0, self.buffer) # Do nothing special execpt avoiding an I2C communication error self.bus.write_byte(self.defaultAddr, 0b01100000) def clear(self): '''Clear screen''' self.buffer = [0 for x in xrange(20)] self.refresh() def display_all(self): '''Display all possible character on the screen''' self.buffer = [255 for x in xrange(20)] self.refresh() def loop(self): self.bus.write_byte_data(self.defaultAddr, 0, 255) for x in range(2, 40, 2): self.bus.write_byte_data(self.defaultAddr, x - 2, 0) self.bus.write_byte_data(self.defaultAddr, x, 255) sleep(1) if (x > 36): self.bus.write_byte(self.defaultAddr, 0b01100000)
class Monster(): """Monster class. Should only be used with a context manager! All GPIOs are BCM GPIO numbers. """ I2C_BUS_NUM = 0 SERVO_I2C_ADDR = 0xa SERVO_CMD_OPEN = 1 SERVO_CMD_CLOSE = 2 SERVO_CMD_TWITCH = 3 DISTANCE_UPDATE_SECONDS = .2 def __init__(self, solenoid_gpio_num=17, echo_trigger_gpio_num=24, echo_gpio_num=25): self._gpios = { 'solenoid': solenoid_gpio_num, 'echo_trigger': echo_trigger_gpio_num, 'echo': echo_gpio_num, } self._rangefinder_settled = False self._distance_lock = threading.Lock() self._distance = 999999999 def __enter__(self): PWM.set_loglevel(PWM.LOG_LEVEL_ERRORS) GPIO.setup(self._gpios['solenoid'], GPIO.OUT) GPIO.setup(self._gpios['echo_trigger'], GPIO.OUT) GPIO.setup(self._gpios['echo'], GPIO.IN) self._i2c_bus = SMBus() self._i2c_bus.open(Monster.I2C_BUS_NUM) self.close_door() return self def __exit__(self, exc_type, exc_value, traceback): self._cm_active = False self._i2c_bus.close() GPIO.cleanup() def activate_solenoid(self): GPIO.output(self._gpios['solenoid'], True) def deactivate_solenoid(self): GPIO.output(self._gpios['solenoid'], False) def fire_ball(self, active_time=.3): """Activate the solenoid for `active_time' seconds.""" self.activate_solenoid() time.sleep(active_time) self.deactivate_solenoid() def i2c_write(self, cmd, max_iters): for i in range(max_iters): try: self._i2c_bus.write_byte(Monster.SERVO_I2C_ADDR, cmd) return except IOError: time.sleep(.5) pass print "I2C Contention! Couldn't send command:", cmd def close_door(self): self.i2c_write(Monster.SERVO_CMD_CLOSE, 10) def open_door(self): self.i2c_write(Monster.SERVO_CMD_OPEN, 10) def twitch_door(self): self.i2c_write(Monster.SERVO_CMD_TWITCH, 10) def toggle_door(self, time_open=.8): self.open_door() time.sleep(time_open) self.close_door() def ball_and_door(self): self.twitch_door() time.sleep(1) self.fire_ball() time.sleep(1) self.fire_ball() # based on http://www.modmypi.com/blog/hc-sr04-ultrasonic-range-sensor-on-the-raspberry-pi def measure_distance(self): """Returns the distance (in meters) to the object being looked at. Probably should only happen in a thread due to all the sleeping """ if not self._rangefinder_settled: # let the sensor settle GPIO.output(self._gpios['echo_trigger'], False) time.sleep(2) self._rangefinder_settled = True # 10 us pulse GPIO.output(self._gpios['echo_trigger'], True) time.sleep(0.00001) GPIO.output(self._gpios['echo_trigger'], False) # interrupt might be better? pulse_start = time.time() cnt = 0 while not GPIO.input(self._gpios['echo']): pulse_start = time.time() # maybe pass would be better? might actually more cpu though... cnt += 1 if cnt > 20000: return 999999999 # we got a pulse, measure it's width by polling until it goes low # again. cnt = 0 pulse_end = time.time() while GPIO.input(self._gpios['echo']): pulse_end = time.time() cnt += 1 if cnt > 20000: return 999999999 pulse_duration = pulse_end - pulse_start sound_mps = 343.0 # speed of sound: 343 m/s distance = sound_mps * pulse_duration # and the pulse width is actually the time it takes to get to the # object *and back*, so we need to divide by two to get just the # distance: distance /= 2.0 # Because the datasheet says: # # we suggest to use over 60ms measurement cycle, in order to # prevent trigger signal to the echo signal. # # We'll use 80ms to be safe time.sleep(.08) return distance def print_distance(self): print 'Distance: ', self.measure_distance(), ' meters' def monitor_distance(self, iters=10): iters = int(iters) # we pass strings from the command line below... for i in xrange(iters): self.print_distance() sys.stdin.flush() def set_distance(self, distance): with self._distance_lock: self._distance = distance def get_distance(self): with self._distance_lock: return self._distance def watch_distance(self): while self._keep_watching: distance = self.measure_distance() self.set_distance(distance) time.sleep(Monster.DISTANCE_UPDATE_SECONDS) print 'done watching distance' def monster_loop(self, trigger_threshold_meters=1.0, come_closer_meters=2.0): loop_sound('background.mp3') self._keep_watching = True dist_thread = threading.Thread(target=self.watch_distance) dist_thread.start() try: last_come_closer = 0 distances = [0, 0, 0] # simple moving average... while True: distances.insert(0, self.get_distance()) distances.pop() distance = sum(distances) / 3.0 print 'distances, distance:', distances, distance if distance < come_closer_meters and \ distance > trigger_threshold_meters and \ time.time() - last_come_closer > 12: print 'come closer...' play_sound('come-closer.mp3') last_come_closer = time.time() elif distance < trigger_threshold_meters: play_sound('vocal-leave-now-happy-halloween.mp3') time.sleep(1) print 'FIRE!' self.ball_and_door() time.sleep(10) time.sleep(.3) except KeyboardInterrupt: print "Interrupt received. Exiting loop." except SystemExit: print "Exiting loop." self._keep_watching = False print 'waiting for threads to exit...' dist_thread.join() print "ok, we're outta here" def sayhi(self, sleep_s=0.5, reps=5): for i in xrange(reps): self.open_door() time.sleep(sleep_s) self.close_door() time.sleep(sleep_s)
def _open_bus(id): bus = SMBus() bus.open(id) return bus