Example #1
0
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
Example #5
0
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()
Example #6
0
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()
Example #7
0
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)
Example #8
0
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()
Example #9
0
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()
Example #10
0
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
Example #11
0
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
Example #12
0
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)
Example #13
0
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
Example #14
0
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
Example #15
0
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)
Example #16
0
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