Beispiel #1
0
    def test_read(self):
        res = []
        res2 = []
        res3 = []

        bus = SMBus(1)

        # Read bytes
        for k in range(2):
            x = bus.read_byte_data(80, k)
            res.append(x)
        self.assertEqual(len(res), 2, msg="Result array of incorrect length.")

        # Read word
        x = bus.read_word_data(80, 0)
        res2.append(x & 255)
        res2.append(x / 256)
        self.assertEqual(len(res2), 2, msg="Result array of incorrect length.")
        self.assertListEqual(res, res2, msg="Byte and word reads differ")

        # Read block of N bytes
        n = 2
        x = bus.read_i2c_block_data(80, 0, n)
        res3.extend(x)
        self.assertEqual(len(res3), n, msg="Result array of incorrect length.")
        self.assertListEqual(res, res3, msg="Byte and block reads differ")

        bus.close()
Beispiel #2
0
    def __init__(self, input_dev, testing=False):
        super(InputModule, self).__init__()
        self.logger = logging.getLogger("mycodo.inputs.sht2x")

        if not testing:
            from smbus2 import SMBus
            self.logger = logging.getLogger(
                "mycodo.sht2x_{id}".format(id=input_dev.unique_id.split('-')[0]))

            self.device_measurements = db_retrieve_table_daemon(
                DeviceMeasurements).filter(
                    DeviceMeasurements.device_id == input_dev.unique_id)

            self.i2c_address = int(str(input_dev.i2c_location), 16)
            self.i2c_bus = input_dev.i2c_bus
            self.sht2x = SMBus(self.i2c_bus)
Beispiel #3
0
    def __init__(self, bus=0):
        """
        Initialize the AXP209 object
        :param bus: i2c bus number or a SMBus object
        :type bus: Integer or SMBus object
        """

        if isinstance(bus, int):
            self.bus = SMBus(bus, force=True)
            self.autocleanup = True
        else:
            self.bus = bus
            self.autocleanup = False

        # force ADC enable for battery voltage and current
        self.adc_enable1 = 0xc3
Beispiel #4
0
    def __init__(self, input_dev, testing=False):
        super(InputModule, self).__init__()
        self.logger = logging.getLogger("mycodo.inputs.mh_z16")

        if not testing:
            self.logger = logging.getLogger(
                "mycodo.mh_z16_{id}".format(id=input_dev.unique_id.split('-')[0]))

            self.interface = input_dev.interface
            self.uart_location = input_dev.uart_location

            if self.interface == 'UART':
                import serial

                # Check if device is valid
                self.serial_device = is_device(self.uart_location)
                if self.serial_device:
                    try:
                        self.ser = serial.Serial(self.serial_device, timeout=1)
                    except serial.SerialException:
                        self.logger.exception('Opening serial')
                else:
                    self.logger.error(
                        'Could not open "{dev}". '
                        'Check the device location is correct.'.format(
                            dev=self.uart_location))

            elif self.interface == 'I2C':
                from smbus2 import SMBus

                self.i2c_address = int(str(input_dev.i2c_location), 16)
                self.i2c_bus = input_dev.i2c_bus
                self.cmd_measure = [0xFF, 0x01, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63]
                self.IOCONTROL = 0X0E << 3
                self.FCR = 0X02 << 3
                self.LCR = 0X03 << 3
                self.DLL = 0x00 << 3
                self.DLH = 0X01 << 3
                self.THR = 0X00 << 3
                self.RHR = 0x00 << 3
                self.TXLVL = 0X08 << 3
                self.RXLVL = 0X09 << 3
                self.i2c = SMBus(self.i2c_bus)
                self.begin()
Beispiel #5
0
    def __init__(self, input_dev, testing=False):
        super(InputModule, self).__init__()
        self.logger = logging.getLogger("mycodo.inputs.bh1750")

        if not testing:
            from smbus2 import SMBus
            self.logger = logging.getLogger(
                "mycodo.bh1750_{id}".format(id=input_dev.unique_id.split('-')[0]))

            self.device_measurements = db_retrieve_table_daemon(
                DeviceMeasurements).filter(
                    DeviceMeasurements.device_id == input_dev.unique_id)

            self.i2c_address = int(str(input_dev.i2c_location), 16)
            self.resolution = input_dev.resolution
            self.sensitivity = input_dev.sensitivity
            self.i2c_bus = SMBus(input_dev.i2c_bus)
            self.power_down()
            self.set_sensitivity(sensitivity=self.sensitivity)
Beispiel #6
0
    def __init__(self, input_dev, testing=False):
        super(InputModule, self).__init__()
        self.logger = logging.getLogger('mycodo.inputs.am2320')
        self.powered = False
        self.sensor = None
        self.i2c_address = 0x5C

        if not testing:
            from smbus2 import SMBus
            self.logger = logging.getLogger(
                'mycodo.am2320_{id}'.format(
                    id=input_dev.unique_id.split('-')[0]))

            self.device_measurements = db_retrieve_table_daemon(
                DeviceMeasurements).filter(
                    DeviceMeasurements.device_id == input_dev.unique_id)

            self.i2c_bus = input_dev.i2c_bus
            self.power_output_id = input_dev.power_output_id
            self.start_sensor()
            self.sensor = SMBus(self.i2c_bus)
 def __init__(self):
     self.sensor = Si7021(SMBus(1))
Beispiel #8
0
class InputModule(AbstractInput):
    """ A sensor support class that monitors the DS18B20's lux """
    def __init__(self, input_dev, testing=False):
        super(InputModule, self).__init__()
        self.logger = logging.getLogger("mycodo.inputs.bh1750")

        if not testing:
            from smbus2 import SMBus
            self.logger = logging.getLogger(
                "mycodo.bh1750_{id}".format(id=input_dev.unique_id.split('-')[0]))

            self.device_measurements = db_retrieve_table_daemon(
                DeviceMeasurements).filter(
                    DeviceMeasurements.device_id == input_dev.unique_id)

            self.i2c_address = int(str(input_dev.i2c_location), 16)
            self.resolution = input_dev.resolution
            self.sensitivity = input_dev.sensitivity
            self.i2c_bus = SMBus(input_dev.i2c_bus)
            self.power_down()
            self.set_sensitivity(sensitivity=self.sensitivity)

    @property
    def lux(self):
        """ BH1750 luminosity in lux """
        if self._measurements is None:  # update if needed
            self.read()
        return self._measurements

    def get_measurement(self):
        """ Gets the BH1750's lux """
        return_dict = measurements_dict.copy()

        if self.resolution == 0:
            lux = self.measure_low_res()
        elif self.resolution == 1:
            lux = self.measure_high_res()
        elif self.resolution == 2:
            lux = self.measure_high_res2()
        else:
            return None

        return_dict[0]['value'] = lux

        return return_dict

    def _set_mode(self, mode):
        self.mode = mode
        self.i2c_bus.write_byte(self.i2c_address, self.mode)

    def power_down(self):
        self._set_mode(POWER_DOWN)

    def power_on(self):
        self._set_mode(POWER_ON)

    def reset(self):
        self.power_on()  # It has to be powered on before resetting
        self._set_mode(RESET)

    def cont_low_res(self):
        self._set_mode(CONTINUOUS_LOW_RES_MODE)

    def cont_high_res(self):
        self._set_mode(CONTINUOUS_HIGH_RES_MODE_1)

    def cont_high_res2(self):
        self._set_mode(CONTINUOUS_HIGH_RES_MODE_2)

    def oneshot_low_res(self):
        self._set_mode(ONE_TIME_LOW_RES_MODE)

    def oneshot_high_res(self):
        self._set_mode(ONE_TIME_HIGH_RES_MODE_1)

    def oneshot_high_res2(self):
        self._set_mode(ONE_TIME_HIGH_RES_MODE_2)

    def set_sensitivity(self, sensitivity=69):
        """
        Set the sensor sensitivity.
        Valid values are 31 (lowest) to 254 (highest), default is 69.
        """
        if sensitivity < 31:
            self.mtreg = 31
        elif sensitivity > 254:
            self.mtreg = 254
        else:
            self.mtreg = sensitivity
        self.power_on()
        self._set_mode(0x40 | (self.mtreg >> 5))
        self._set_mode(0x60 | (self.mtreg & 0x1f))
        self.power_down()

    def get_result(self):
        """ Return current measurement result in lx. """
        data = self.i2c_bus.read_word_data(self.i2c_address, self.mode)
        count = data >> 8 | (data & 0xff) << 8
        mode2coeff = 2 if (self.mode & 0x03) == 0x01 else 1
        ratio = 1 / (1.2 * (self.mtreg / 69.0) * mode2coeff)
        return ratio * count

    def wait_for_result(self, additional=0):
        basetime = 0.018 if (self.mode & 0x03) == 0x03 else 0.128
        time.sleep(basetime * (self.mtreg / 69.0) + additional)

    def do_measurement(self, mode, additional_delay=0):
        """
        Perform complete measurement using command specified by parameter
        mode with additional delay specified in parameter additional_delay.
        Return output value in Lx.
        """
        self.reset()
        self._set_mode(mode)
        self.wait_for_result(additional=additional_delay)
        return self.get_result()

    def measure_low_res(self, additional_delay=0):
        return self.do_measurement(ONE_TIME_LOW_RES_MODE, additional_delay)

    def measure_high_res(self, additional_delay=0):
        return self.do_measurement(ONE_TIME_HIGH_RES_MODE_1, additional_delay)

    def measure_high_res2(self, additional_delay=0):
        return self.do_measurement(ONE_TIME_HIGH_RES_MODE_2, additional_delay)
Beispiel #9
0
class BNO080_I2C:

    # I2C packet read delay in microseconds
    I2CDELAY = 400
    # Packets can be up to 32k.
    MAX_PACKET_SIZE = 32762
    # This is in words, we only care about the first 9 (Qs, range, etc)
    MAX_METADATA_SIZE = 9
    # SHTP cmd channel: byte-0=command, byte-1=parameter, byte-n=parameter
    CHANNEL_COMMAND = 0
    # SHTP exec channel: write 1=reset, 2=on, 3=sleep, read 1=reset complete
    CHANNEL_EXECUTABLE = 1
    # Sensor Hub control channel for sensor config commands and responses
    CHANNEL_CONTROL = 2
    # Input Sensor reports only sends data from sensor to host
    CHANNEL_REPORTS = 3
    # Wake Input Sensor reports sends data from wake sensors to host
    CHANNEL_WAKE_REPORTS = 4
    # Gyro rotation vector in extra channel to allow prioritization
    CHANNEL_GYRO = 5
    # Control channel commands (BNO8X datasheet figure 1-30)
    COMMAND_RESPONSE = 0xF1
    COMMAND_REQUEST = 0xF2
    FRS_READ_RESPONSE = 0xF3  # Flash Record System read response
    FRS_READ_REQUEST = 0xF4  # Flash Record System read request
    FRS_WRITE_RESPONSE = 0xF5  # Flash Record System write response
    FRS__WRITE_DATA = 0xF6  # Flash Record System write data
    FRS__WRITE_REQUEST = 0xF7  # Flash Record System write request
    PRODUCT_ID_RESPONSE = 0xF8
    PRODUCT_ID_REQUEST = 0xF9
    GET_TIME_REFERENCE = 0xFB
    GET_TIMESTAMP_REBASE = 0xFA
    GET_FEATURE_RESPONSE = 0xFC
    SET_FEATURE_COMMAND = 0xFD
    GET_FEATURE_REQUEST = 0xFE
    #All the different sensors and features we can get reports from
    #These are used when enabling a given sensor
    SENSOR_REPORTID_ACC = 0x01  # Accelerometer
    SENSOR_REPORTID_GYR = 0x02  # Gyroscope
    SENSOR_REPORTID_MAG = 0x03  # Magnetometer
    SENSOR_REPORTID_LIN = 0x04  # Linear Acceleration
    SENSOR_REPORTID_ROT = 0x05  # Rotation Vector
    SENSOR_REPORTID_GRA = 0x06  # Gravity
    SENSOR_REPORTID_GAM = 0x08  # Game Rotation Vector
    SENSOR_REPORTID_GEO = 0x09  # Geomagnetic Rotation
    SENSOR_REPORTID_TAP = 0x10  # Tap Detector
    SENSOR_REPORTID_STP = 0x11  # Step Counter
    SENSOR_REPORTID_STA = 0x13  # Stability Classifier
    SENSOR_REPORTID_PER = 0x1E  # Personal Activity Classifier

    REPORT_SIZES = {
        SENSOR_REPORTID_ACC: 10,
        SENSOR_REPORTID_GYR: 10,
        SENSOR_REPORTID_MAG: 10,
        SENSOR_REPORTID_LIN: 10,
        SENSOR_REPORTID_ROT: 14,
        SENSOR_REPORTID_GRA: 10,
        SENSOR_REPORTID_GAM: 12,
        SENSOR_REPORTID_GEO: 14,
        SENSOR_REPORTID_TAP: 5,
        SENSOR_REPORTID_STP: 12,
        SENSOR_REPORTID_STA: 6,
        SENSOR_REPORTID_PER: 4,
        GET_TIME_REFERENCE: 5,
        GET_TIMESTAMP_REBASE: 5
    }

    def __init__(self, addr, port):
        self.addr = addr
        self.bus = SMBus(port)
        self.sequence = [0] * 5
        self.get_ad()

    @classmethod
    def _i2c_delay(cls):
        time.sleep(cls.I2CDELAY / 1000000)

    def start_calib(self):
        me_calib = [
            self.COMMAND_REQUEST, self.sequence[self.CHANNEL_CONTROL], 0x07,
            0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
        ]
        self.send_shtp(self.CHANNEL_CONTROL, me_calib)

        res_head, res_data = self.receive_shtp_until(self.CHANNEL_CONTROL,
                                                     [self.COMMAND_RESPONSE])
        count = 0
        while res_data[2] != 0x07 and count < 3:
            res_head, res_data = self.receive_shtp_until(
                self.CHANNEL_COMMAND, [self.COMMAND_RESPONSE])
            count += 1
        if res_data[2] == 0x07 and res_data[5] != 0:
            print(f"ERROR: ME calibration set command failed: {res_data}")

        self.start_game_rot(10)
        self.start_mag(50)

        report_dict = self.get_report([self.SENSOR_REPORTID_MAG])
        mag_rep = report_dict.get(
            self.SENSOR_REPORTID_MAG,
            [[0x00, 0x00, 0x00]])[-1]  # most recent mag report

        while mag_rep[2] & 0x03 != 0x03:
            print(mag_rep[2] & 0x03)
            time.sleep(1 / 50)
            delete_last_lines(1)
            report_dict = self.get_report([self.SENSOR_REPORTID_MAG])
            mag_rep = report_dict.get(
                self.SENSOR_REPORTID_MAG,
                [[0x00, 0x00, 0x00]])[-1]  # most recent mag report

        print("Calibration Success!")
        self.save_dcd()
        return True

    def set_feature(self, sensor, features, sensitivity, rate, batch,
                    sensor_spec):
        feat_cmd = [
            self.SET_FEATURE_COMMAND,
            sensor,
            features,
            sensitivity & 0xff,  # sensitvity LSB
            sensitivity >> 8,  # sensitivty MSB 
            rate & 0xff,  # rate LSB
            (rate & 0xff00) >> 8,  # rate
            (rate & 0xff0000) >> 16,  # rate 
            (rate) >> 24,  # rate MSB  
            (batch & 0xff),  # batch rate LSB
            (batch & 0xff00) >> 8,  # batch rate
            (batch & 0xff0000) >> 16,  # batch rate 
            (batch >> 24),  # batch rate MSB  
            (sensor_spec & 0xff),
            (sensor_spec & 0xff00) >> 8,
            (sensor_spec & 0xff0000) >> 16,
            (sensor_spec >> 24)
        ]
        self.send_shtp(self.CHANNEL_CONTROL, feat_cmd)
        time.sleep(0.1)  # letting sensor catch up
        self.send_shtp(self.CHANNEL_CONTROL,
                       [self.GET_FEATURE_REQUEST, sensor])
        self._i2c_delay()
        res_head, res_data = self.receive_shtp_until(
            self.CHANNEL_CONTROL, [self.GET_FEATURE_RESPONSE])

        # TODO: Log this on debug and check the values
        # print(f"Sensor: {res_data[1]}");
        # print(f"Feature Flags: {res_data[2]}");
        # print(f"Sensitivity byte: {res_data[4]}, {res_data[3]}");
        # print(f"Report Interval word:  {res_data[8]} {res_data[7]} {res_data[6]} {res_data[5]}");
        # print(f"Sensor Specific Config word: {res_data[13]}, {res_data[14]}, {res_data[15]}, {res_data[16]}");

        return True

    def save_dcd(self):
        '''
        saves the current dynamic calibration data, should be done after a calibration
        '''
        dcd_cmd = [
            self.COMMAND_REQUEST, self.sequence[self.CHANNEL_CONTROL], 0x06,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
        ]
        self.send_shtp(self.CHANNEL_CONTROL, dcd_cmd)
        count = 0
        res_head, res_data = self.receive_shtp_until(self.CHANNEL_CONTROL,
                                                     [self.COMMAND_RESPONSE])
        while res_data[2] != 0x06 and count < 3:
            count += 1

        if res_data[2] == 0x06 and res_data[5] != 0:
            print(
                f"ERROR: DCD Save failed after calibration: {self.print_hex(res_data)}"
            )
            return False
        else:
            return True

    def start_acc(self, rate):
        return self.set_feature(self.SENSOR_REPORTID_ACC, 0, 0, rate, 0, 0)

    def start_rot(self, rate):
        return self.set_feature(self.SENSOR_REPORTID_ROT, 0, 0, rate, 0, 0)

    def start_game_rot(self, rate):
        return self.set_feature(self.SENSOR_REPORTID_GAM, 0, 0, rate, 0, 0)

    def start_mag(self, rate):
        return self.set_feature(self.SENSOR_REPORTID_MAG, 0, 0, rate, 0, 0)

    def get_report(self, report_types):
        report_types.append(self.GET_TIME_REFERENCE)
        res_head, res_data = self.receive_shtp_until(self.CHANNEL_REPORTS,
                                                     report_types, 20)
        report_ind = 0
        reports = {}
        while report_ind < len(res_data):
            inc = self.REPORT_SIZES.get(res_data[report_ind], None)
            if inc is None:
                print(f"WARNING: unrecognized input report: {res_data[0]}")
                return None
            else:
                if not reports.get(res_data[report_ind], False):
                    reports[res_data[report_ind]] = [
                        res_data[report_ind:report_ind + inc]
                    ]
                else:
                    reports[res_data[report_ind]].append(
                        res_data[report_ind:report_ind + inc])
                report_ind += inc
        return reports

    def get_report_cont(self, report_types, rate, reports):
        while True:
            report_types.append(self.GET_TIME_REFERENCE)
            res_head, res_data = self.receive_shtp_until(
                self.CHANNEL_REPORTS, report_types, 20)
            report_ind = 0
            while report_ind < len(res_data):
                inc = self.REPORT_SIZES.get(res_data[report_ind], None)
                if inc is None:
                    print(f"WARNING: unrecognized input report: {res_data[0]}")
                    return None
                else:
                    reports[res_data[report_ind]] = [
                        res_data[report_ind:report_ind + inc]
                    ]
                    report_ind += inc
            time.sleep(rate)

    def get_shtp_errors(self):
        self.send_shtp(self.CHANNEL_COMMAND, [0x01])
        res_head, res_data = self.receive_shtp_until(self.CHANNEL_COMMAND,
                                                     [0x01], 5)

    def get_prod_inf(self):
        self.send_shtp(self.CHANNEL_CONTROL, [self.PRODUCT_ID_REQUEST])
        _res_head1, res_data1 = self.receive_shtp_until(
            self.CHANNEL_CONTROL, [self.PRODUCT_ID_RESPONSE])
        _res_head2, res_data2 = self.receive_shtp_until(
            self.CHANNEL_CONTROL, [self.PRODUCT_ID_RESPONSE])
        return [res_data1, res_data2]

    def send_shtp(self, channel, data):
        '''
        sends a single SHTP message to the IMU
        '''
        self.sequence[channel] += 1
        packetlen = len(data) + 4
        packet = [
            packetlen & 0xFF, (packetlen >> 8) & 0xFF, channel,
            self.sequence[channel], *data
        ]

        # TODO: add to debug log
        # print("Sending: ")
        # print(print_hex(packet))

        write = i2c_msg.write(self.addr, packet)
        write.flags = 0x0000
        self.bus.i2c_rdwr(write)

    def receive_shtp_until(self, chan_type, res_types, max_count=3):
        '''
        asks IMU for I2C SHTP messages until the one with the correct channel and report type(s) shows up
        '''
        count = 0
        res_head, res_data = self.receive_shtp()
        while (res_head[2] != chan_type
               or res_data[0] not in res_types) and count < max_count:
            self._i2c_delay()
            res_head, res_data = self.receive_shtp()
            count += 1
        return [
            res_head, res_data
        ] if res_head[2] == chan_type and res_data[0] in res_types else [
            None, []
        ]

    def receive_shtp(self):
        '''
        reads a single SHTP message from the IMU
        '''
        read_head = i2c_msg.read(self.addr, 4)
        self.bus.i2c_rdwr(read_head)
        header = list(read_head)

        packetlen = (
            header[1] << 8) | header[0]  # stitch the two length bytes together
        packetlen &= ~(1 << 15)  # clear MSB
        datalen = packetlen - 4  # subtract header
        subtransfer = header[
            1] & 0x80 != 0x00  # see if the data is not all ready at once

        read = i2c_msg.read(self.addr, packetlen)
        time.sleep(1000 / 1000000)  # sleep 1000 us between reads
        self.bus.i2c_rdwr(read)
        msg = list(read)

        if len(msg) != packetlen or len(msg) == 0:
            # print ("Packet Error")
            return [[0] * 4, [0] * 4]

        if msg[2] == 0 and msg[0 + 4] == 0x01:
            self.print_shtp_errs(msg[4:])

        self.sequence[msg[2]] = msg[3]  # sync the sequence with the IMU

        # print("Received: ")
        # print(print_hex(msg))

        return [msg[0:4], msg[4:]]

    @staticmethod
    def print_shtp_errs(err_data):
        if len(err_data) == 1:
            return None

        err_dict = [
            "No Error",
            "Hub application attempted to exceed maximum read cargo length",
            "Hub application attempted to exceed maximum read cargo length",
            "Host wrote a header with length greater than maximum write cargo length",
            "Host wrote a header with length <= header length (invalid or no payload)",
            "Host tried to fragment cargo (transfer length < full cargo length)",
            "Host wrote continuation of fragmented cargo (continuation bit set)",
            "Unrecognized command on control channel (2)",
            "Unrecognized parameter to get-advertisement command",
            "Host wrote to unrecognized channel",
            "Advertisement request received while Advertisement Response was pending",
            "Host write before the hub finished sending advertisement response",
            "Error list too long to send, truncated"
        ]

        print("ERROR: the following errors were reported from the IMU:")
        for err in err_data[1:]:
            print(f"\t{err_dict[err]}")

    def get_ad(self):
        res_head, res_data = self.receive_shtp()
        if res_head[2] == self.CHANNEL_COMMAND and res_data[0] == 0x00:
            # TODO: log not print, and get something out of this ad
            print("Got advertisement")
        else:
            print("Did not get advertisement, moving on")

    @classmethod
    def parse_rep(cls, rep):
        rep_methods = {
            -1: cls._print_missing,
            cls.SENSOR_REPORTID_ACC: cls._print_acc,
            cls.SENSOR_REPORTID_GYR: cls._print_gyr,
            cls.SENSOR_REPORTID_MAG: cls._print_mag,
            cls.SENSOR_REPORTID_LIN: cls._print_lin,
            cls.SENSOR_REPORTID_ROT: cls._print_rot,
            cls.SENSOR_REPORTID_GRA: cls._print_gra,
            cls.SENSOR_REPORTID_GAM: cls._print_gam,
            cls.SENSOR_REPORTID_GEO: cls._print_geo,
            cls.SENSOR_REPORTID_TAP: cls._print_tap,
            cls.SENSOR_REPORTID_STP: cls._print_stp,
            cls.SENSOR_REPORTID_STA: cls._print_sta,
            cls.SENSOR_REPORTID_PER: cls._print_per
        }
        return rep_methods[rep[0]](rep)

    @classmethod
    def _print_missing(cls, rep):
        return {"name": "err", "message": "no report available"}

    @classmethod
    def _print_acc(cls, rep):
        return {
            "name": "acc",
            "stat": hex(rep[2]),
            "delay": hex(rep[3]),
            "x": cls.print_hex(rep[5:3:-1]),
            "y": cls.print_hex(rep[7:5:-1]),
            "z": cls.print_hex(rep[9:7:-1])
        }

    @classmethod
    def _print_gyr(cls, rep):
        pass

    @classmethod
    def _print_mag(cls, rep):
        pass

    @classmethod
    def _print_lin(cls, rep):
        pass

    @classmethod
    def _print_rot(cls, rep):
        return {
            "name": "rot",
            "stat": hex(rep[2]),
            "delay": hex(rep[3]),
            "i": cls.print_hex(rep[5:3:-1]),
            "j": cls.print_hex(rep[7:5:-1]),
            "k": cls.print_hex(rep[9:7:-1]),
            "r": cls.print_hex(rep[11:9:-1]),
            "accuracy": cls.print_hex(rep[13:11:-1])
        }

    @classmethod
    def _print_gra(cls, rep):
        pass

    @classmethod
    def _print_gam(cls, rep):
        pass

    @classmethod
    def _print_geo(cls, rep):
        pass

    @classmethod
    def _print_tap(cls, rep):
        pass

    @classmethod
    def _print_stp(cls, rep):
        pass

    @classmethod
    def _print_sta(cls, rep):
        pass

    @classmethod
    def _print_per(cls, rep):
        pass

    @classmethod
    def print_hex(cls, hexs):
        return '0x' + ''.join([hex(h).strip('0x').zfill(2) for h in hexs])
Beispiel #10
0
 def __init__(self, bus):
     self.smbus = SMBus(bus=bus)
     self.write_seq_num = 0
     sleep(1)  # give the bus a chance to settle
Beispiel #11
0
class InputModule(AbstractInput):
    """
    A sensor support class that measures the SHT2x's humidity and temperature
    and calculates the dew point

    """

    def __init__(self, input_dev, testing=False):
        super(InputModule, self).__init__()
        self.logger = logging.getLogger("mycodo.inputs.sht2x")

        if not testing:
            from smbus2 import SMBus
            self.logger = logging.getLogger(
                "mycodo.sht2x_{id}".format(id=input_dev.unique_id.split('-')[0]))

            self.device_measurements = db_retrieve_table_daemon(
                DeviceMeasurements).filter(
                    DeviceMeasurements.device_id == input_dev.unique_id)

            self.i2c_address = int(str(input_dev.i2c_location), 16)
            self.i2c_bus = input_dev.i2c_bus
            self.sht2x = SMBus(self.i2c_bus)

    def get_measurement(self):
        """ Gets the humidity and temperature """
        return_dict = measurements_dict.copy()

        for _ in range(2):
            try:
                # Send temperature measurement command
                # 0xF3(243) NO HOLD master
                self.sht2x.write_byte(self.i2c_address, 0xF3)
                time.sleep(0.5)
                # Read data back, 2 bytes
                # Temp MSB, Temp LSB
                data0 = self.sht2x.read_byte(self.i2c_address)
                data1 = self.sht2x.read_byte(self.i2c_address)
                temperature = -46.85 + (((data0 * 256 + data1) * 175.72) / 65536.0)
                # Send humidity measurement command
                # 0xF5(245) NO HOLD master
                self.sht2x.write_byte(self.i2c_address, 0xF5)
                time.sleep(0.5)
                # Read data back, 2 bytes
                # Humidity MSB, Humidity LSB
                data0 = self.sht2x.read_byte(self.i2c_address)
                data1 = self.sht2x.read_byte(self.i2c_address)
                humidity = -6 + (((data0 * 256 + data1) * 125.0) / 65536.0)

                if self.is_enabled(0):
                    return_dict[0]['value'] = temperature

                if self.is_enabled(1):
                    return_dict[1]['value'] = humidity

                if (self.is_enabled(2) and
                        self.is_enabled(0) and
                        self.is_enabled(1)):
                    return_dict[2]['value'] = calculate_dewpoint(
                        return_dict[0]['value'], return_dict[1]['value'])

                if (self.is_enabled(3) and
                        self.is_enabled(0) and
                        self.is_enabled(1)):
                    return_dict[3]['value'] = calculate_vapor_pressure_deficit(
                        return_dict[0]['value'], return_dict[1]['value'])

                return return_dict
            except Exception as e:
                self.logger.exception(
                    "Exception when taking a reading: {err}".format(err=e))
            # Send soft reset and try a second read
            self.sht2x.write_byte(self.i2c_address, 0xFE)
            time.sleep(0.1)
Beispiel #12
0
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""

from smbus2 import SMBus
import time

bus_number = 1
i2c_address = 0x76

bus = SMBus(bus_number)

dig_temp = []
dig_pres = []
dig_hum = []

t_fine = 0.0


def writeReg(reg_address, data):
    bus.write_byte_data(i2c_address, reg_address, data)


def get_calib_param():
    calib = []
                                                      self.vinReg[1])
            adinVal = self.bus.read_word_data(self.addr, self.adinReg[0])
            adinVal = adinVal << 4
            adinVal = adinVal | self.bus.read_word_data(
                self.addr, self.adinReg[1])
            self.post([('vin', vinVal), ('adin', adinVal)])

    def post(self, vals):
        if self.debug: print('[+] Recv post vals of:', vals)
        cols = vals[0][0]
        values = vals[0][1]
        if len(vals) > 1:
            for val in vals[1:]:
                cols += ', ' + val[0]
                values += ', ' + str(val[1])
        insertString = 'INSERT INTO {table} ({columns}) VALUES ({vals})'.format(
            columns=cols, table=self.table, vals=values)
        self.execute(insertString)

    def execute(self, string):
        if self.debug: print('[+] Executing:', string)
        self.curs.execute(string)


if __name__ == '__main__':
    bus = SMBus(1)
    ip = raw_input('ip address of brix?')
    print('ip is set to:', ip)
    poller = LtcPoll.__init__(bus, ip)
    poller.start()
Beispiel #14
0
 def __init__(self, addr=0x8):
     self.arduino_i2c_addr = addr
     self.i2c_bus = SMBus(1)
Beispiel #15
0
class MQ():

    ######################### Hardware Related Macros #########################
    MQ_PIN = 0  # define which analog input channel you are going to use (MCP3008)
    RL_VALUE = 5  # define the load resistance on the board, in kilo ohms
    RO_CLEAN_AIR_FACTOR = 9.83  # RO_CLEAR_AIR_FACTOR=(Sensor resistance in clean air)/RO,
    # which is derived from the chart in datasheet

    ######################### Software Related Macros #########################
    CALIBARAION_SAMPLE_TIMES = 50  # define how many samples you are going to take in the calibration phase
    CALIBRATION_SAMPLE_INTERVAL = 500  # define the time interal(in milisecond) between each samples in the
    # cablibration phase
    READ_SAMPLE_INTERVAL = 50  # define how many samples you are going to take in normal operation
    READ_SAMPLE_TIMES = 5  # define the time interal(in milisecond) between each samples in
    # normal operation

    ######################### Application Related Macros ######################
    GAS_LPG = 0
    GAS_CO = 1
    GAS_SMOKE = 2

    def __init__(self, Ro=10, analogPin=1):
        self.Ro = Ro
        self.MQ_PIN = analogPin
        self.adc = SMBus(1)

        self.LPGCurve = [2.3, 0.21,
                         -0.47]  # two points are taken from the curve.
        # with these two points, a line is formed which is "approximately equivalent"
        # to the original curve.
        # data format:{ x, y, slope}; point1: (lg200, 0.21), point2: (lg10000, -0.59)
        self.COCurve = [2.3, 0.72,
                        -0.34]  # two points are taken from the curve.
        # with these two points, a line is formed which is "approximately equivalent"
        # to the original curve.
        # data format:[ x, y, slope]; point1: (lg200, 0.72), point2: (lg10000,  0.15)
        self.SmokeCurve = [2.3, 0.53,
                           -0.44]  # two points are taken from the curve.
        # with these two points, a line is formed which is "approximately equivalent"
        # to the original curve.
        # data format:[ x, y, slope]; point1: (lg200, 0.53), point2: (lg10000,  -0.22)

        print("Calibrating...")
        self.Ro = self.MQCalibration(self.MQ_PIN)
        print("Calibration is done...\n")
        print("Ro=%f kohm" % self.Ro)

    def MQPercentage(self):
        val = {}
        read = self.MQRead(self.MQ_PIN)
        val["GAS_LPG"] = self.MQGetGasPercentage(read / self.Ro, self.GAS_LPG)
        val["CO"] = self.MQGetGasPercentage(read / self.Ro, self.GAS_CO)
        val["SMOKE"] = self.MQGetGasPercentage(read / self.Ro, self.GAS_SMOKE)
        return val

    ######################### MQResistanceCalculation #########################
    # Input:   raw_adc - raw value read from adc, which represents the voltage
    # Output:  the calculated sensor resistance
    # Remarks: The sensor and the load resistor forms a voltage divider. Given the voltage
    #          across the load resistor and its resistance, the resistance of the sensor
    #          could be derived.
    ############################################################################
    def MQResistanceCalculation(self, raw_adc):
        return float(self.RL_VALUE * (1023.0 - raw_adc) / float(raw_adc))

    ######################### MQCalibration ####################################
    # Input:   mq_pin - analog channel
    # Output:  Ro of the sensor
    # Remarks: This function assumes that the sensor is in clean air. It use
    #          MQResistanceCalculation to calculates the sensor resistance in clean air
    #          and then divides it with RO_CLEAN_AIR_FACTOR. RO_CLEAN_AIR_FACTOR is about
    #          10, which differs slightly between different sensors.
    ############################################################################
    def MQCalibration(self, mq_pin):
        val = 0.0
        for i in range(self.CALIBARAION_SAMPLE_TIMES):  # take multiple samples
            self.adc.write_byte(0x48, 0)
            val += self.MQResistanceCalculation(self.adc.read_byte(0x48))
            time.sleep(self.CALIBRATION_SAMPLE_INTERVAL / 1000.0)

        val = val / self.CALIBARAION_SAMPLE_TIMES  # calculate the average value

        val = val / self.RO_CLEAN_AIR_FACTOR  # divided by RO_CLEAN_AIR_FACTOR yields the Ro
        # according to the chart in the datasheet

        return val

    #########################  MQRead ##########################################
    # Input:   mq_pin - analog channel
    # Output:  Rs of the sensor
    # Remarks: This function use MQResistanceCalculation to caculate the sensor resistenc (Rs).
    #          The Rs changes as the sensor is in the different consentration of the target
    #          gas. The sample times and the time interval between samples could be configured
    #          by changing the definition of the macros.
    ############################################################################
    def MQRead(self, mq_pin):
        rs = 0.0

        for i in range(self.READ_SAMPLE_TIMES):
            self.adc.write_byte(0x48, 0)
            rs += self.MQResistanceCalculation(self.adc.read_byte(0x48))
            time.sleep(self.READ_SAMPLE_INTERVAL / 1000.0)

        rs = rs / self.READ_SAMPLE_TIMES

        return rs

    #########################  MQGetGasPercentage ##############################
    # Input:   rs_ro_ratio - Rs divided by Ro
    #          gas_id      - target gas type
    # Output:  ppm of the target gas
    # Remarks: This function passes different curves to the MQGetPercentage function which
    #          calculates the ppm (parts per million) of the target gas.
    ############################################################################
    def MQGetGasPercentage(self, rs_ro_ratio, gas_id):
        if (gas_id == self.GAS_LPG):
            return self.MQGetPercentage(rs_ro_ratio, self.LPGCurve)
        elif (gas_id == self.GAS_CO):
            return self.MQGetPercentage(rs_ro_ratio, self.COCurve)
        elif (gas_id == self.GAS_SMOKE):
            return self.MQGetPercentage(rs_ro_ratio, self.SmokeCurve)
        return 0

    #########################  MQGetPercentage #################################
    # Input:   rs_ro_ratio - Rs divided by Ro
    #          pcurve      - pointer to the curve of the target gas
    # Output:  ppm of the target gas
    # Remarks: By using the slope and a point of the line. The x(logarithmic value of ppm)
    #          of the line could be derived if y(rs_ro_ratio) is provided. As it is a
    #          logarithmic coordinate, power of 10 is used to convert the result to non-logarithmic
    #          value.
    ############################################################################
    def MQGetPercentage(self, rs_ro_ratio, pcurve):
        return (math.pow(
            10,
            (((math.log(rs_ro_ratio) - pcurve[1]) / pcurve[2]) + pcurve[0])))
def smbus_init():
    # Initialise the bme280
    bus = SMBus(1)
    bme280 = BME280(i2c_dev=bus)
    print("smbus_init Init ...")
    return bme280
Beispiel #17
0
class IOE():
    def __init__(self, i2c_addr=I2C_ADDR, interrupt_timeout=1.0, interrupt_pin=None, gpio=None, skip_chip_id_check=False):
        self._i2c_addr = i2c_addr
        self._i2c_dev = SMBus(1)
        self._debug = False
        self._vref = 3.3
        self._timeout = interrupt_timeout
        self._interrupt_pin = interrupt_pin
        self._gpio = gpio
        self._encoder_offset = [0, 0, 0, 0]
        self._encoder_last = [0, 0, 0, 0]

        if self._interrupt_pin is not None:
            if self._gpio is None:
                import RPi.GPIO as GPIO
                self._gpio = GPIO
            self._gpio.setwarnings(False)
            self._gpio.setmode(GPIO.BCM)
            self._gpio.setup(self._interrupt_pin, GPIO.IN, pull_up_down=GPIO.PUD_OFF)
            self.enable_interrupt_out()

        self._pins = [
            PWM_PIN(1, 5, 5, REG_PIOCON1),
            PWM_PIN(1, 0, 2, REG_PIOCON0),
            PWM_PIN(1, 2, 0, REG_PIOCON0),
            PWM_PIN(1, 4, 1, REG_PIOCON0),
            PWM_PIN(0, 0, 3, REG_PIOCON0),
            PWM_PIN(0, 1, 4, REG_PIOCON0),
            ADC_OR_PWM_PIN(1, 1, 7, 1, REG_PIOCON0),
            ADC_OR_PWM_PIN(0, 3, 6, 5, REG_PIOCON0),
            ADC_OR_PWM_PIN(0, 4, 5, 3, REG_PIOCON1),
            ADC_PIN(3, 0, 1),
            ADC_PIN(0, 6, 3),
            ADC_OR_PWM_PIN(0, 5, 4, 2, REG_PIOCON1),
            ADC_PIN(0, 7, 2),
            ADC_PIN(1, 7, 0)
        ]

        if not skip_chip_id_check:
            chip_id = (self.i2c_read8(REG_CHIP_ID_H) << 8) | self.i2c_read8(REG_CHIP_ID_L)
            if chip_id != CHIP_ID:
                raise RuntimeError("Chip ID invalid: {:04x} expected: {:04x}.".format(chip_id, CHIP_ID))

    def i2c_read8(self, reg):
        """Read a single (8bit) register from the device."""
        msg_w = i2c_msg.write(self._i2c_addr, [reg])
        self._i2c_dev.i2c_rdwr(msg_w)
        msg_r = i2c_msg.read(self._i2c_addr, 1)
        self._i2c_dev.i2c_rdwr(msg_r)

        return list(msg_r)[0]

    def i2c_write8(self, reg, value):
        """Write a single (8bit) register to the device."""
        msg_w = i2c_msg.write(self._i2c_addr, [reg, value])
        self._i2c_dev.i2c_rdwr(msg_w)

    def setup_rotary_encoder(self, channel, pin_a, pin_b, pin_c=None, count_microsteps=False):
        """Set up a rotary encoder."""
        channel -= 1
        self.set_mode(pin_a, PIN_MODE_PU, schmitt_trigger=True)
        self.set_mode(pin_b, PIN_MODE_PU, schmitt_trigger=True)
        if pin_c is not None:
            self.set_mode(pin_c, PIN_MODE_OD)
            self.output(pin_c, 0)

        self.i2c_write8([REG_ENC_1_CFG, REG_ENC_2_CFG, REG_ENC_3_CFG, REG_ENC_4_CFG][channel], pin_a | (pin_b << 4))
        self.change_bit(REG_ENC_EN, channel * 2 + 1, count_microsteps)
        self.set_bit(REG_ENC_EN, channel * 2)

    def read_rotary_encoder(self, channel):
        """Read the step count from a rotary encoder."""
        channel -= 1
        last = self._encoder_last[channel]
        reg = [REG_ENC_1_COUNT, REG_ENC_2_COUNT, REG_ENC_3_COUNT, REG_ENC_4_COUNT][channel]
        value = self.i2c_read8(reg)

        if value & 0b10000000:
            value -= 256

        if last > 64 and value < -64:
            self._encoder_offset[channel] += 256
        if last < -64 and value > 64:
            self._encoder_offset[channel] -= 256

        self._encoder_last[channel] = value

        return self._encoder_offset[channel] + value

    def set_rotary_encoder(self, channel,number):
        """set the step count from a rotary encoder."""
        channel -= 1
        last = self._encoder_last[channel]
        offset = self._encoder_offset[channel]
        #print("lastdiff_rotary_encoder  layst: " + str(last))
        #print("diff_rotary_encoder  offset: " + str(offset))

        reg = [REG_ENC_1_COUNT, REG_ENC_2_COUNT, REG_ENC_3_COUNT, REG_ENC_4_COUNT][channel]
        #print("read before write : " + str(self.i2c_read8(reg)))
        self.i2c_write8(reg,number)
        #print("read after write REG: " + str(self.i2c_read8(reg)))


    def diff_rotary_encoder(self, channel):
        """Read the step count from a rotary encoder and return diff."""
        channel -= 1
        last = self._encoder_last[channel]
        offset = self._encoder_offset[channel]
        #print("lastdiff_rotary_encoder  layst: " + str(last))
        #print("diff_rotary_encoder  offset: " + str(offset))

        reg = [REG_ENC_1_COUNT, REG_ENC_2_COUNT, REG_ENC_3_COUNT, REG_ENC_4_COUNT][channel]
        value = self.i2c_read8(reg)
        #print("readREG: " + str(self.i2c_read8(reg)))
        if value & 0b10000000:
            value -= 256

        if last > 64 and value < -64:
            self._encoder_offset[channel] += 256
        if last < -64 and value > 64:
            self._encoder_offset[channel] -= 256

        self._encoder_last[channel] = value
        #print("new value diff_rotary_encoder: " + str(value))
        diff=offset + value - last
        #print("new value diff_rotary_encoder: " + str(diff))
        return  diff


    def set_bits(self, reg, bits):
        """Set the specified bits (using a mask) in a register."""
        if reg in BIT_ADDRESSED_REGS:
            for bit in range(8):
                if bits & (1 << bit):
                    self.i2c_write8(reg, 0b1000 | (bit & 0b111))
        else:
            value = self.i2c_read8(reg)
            time.sleep(0.001)
            self.i2c_write8(reg, value | bits)

    def set_bit(self, reg, bit):
        """Set the specified bit (nth position from right) in a register."""
        self.set_bits(reg, (1 << bit))

    def clr_bits(self, reg, bits):
        """Clear the specified bits (using a mask) in a register."""
        if reg in BIT_ADDRESSED_REGS:
            for bit in range(8):
                if bits & (1 << bit):
                    self.i2c_write8(reg, 0b0000 | (bit & 0b111))
        else:
            value = self.i2c_read8(reg)
            time.sleep(0.001)
            self.i2c_write8(reg, value & ~bits)

    def clr_bit(self, reg, bit):
        """Clear the specified bit (nth position from right) in a register."""
        self.clr_bits(reg, (1 << bit))

    def get_bit(self, reg, bit):
        """Returns the specified bit (nth position from right) from a register."""
        return self.i2c_read8(reg) & (1 << bit)

    def change_bit(self, reg, bit, state):
        """Toggle one register bit on/off."""
        if state:
            self.set_bit(reg, bit)
        else:
            self.clr_bit(reg, bit)

    def enable_interrupt_out(self, pin_swap=False):
        """Enable the IOE interrupts."""
        self.set_bit(REG_INT, BIT_INT_OUT_EN)
        self.change_bit(REG_INT, BIT_INT_PIN_SWAP, pin_swap)

    def disable_interrupt_out(self):
        """Disable the IOE interrupt output."""
        self.clr_bit(REG_INT, BIT_INT_OUT_EN)

    def get_interrupt(self):
        """Get the IOE interrupt state."""
        if self._interrupt_pin is not None:
            return self._gpio.input(self._interrupt_pin) == 0
        else:
            return self.get_bit(REG_INT, BIT_INT_TRIGD)

    def clear_interrupt(self):
        """Clear the interrupt flag."""
        self.clr_bit(REG_INT, BIT_INT_TRIGD)

    def set_pin_interrupt(self, pin, enabled):
        """Enable/disable the input interrupt on a specific pin.

        :param pin: Pin from 1-14
        :param enabled: True/False for enabled/disabled

        """
        if pin < 1 or pin > len(self._pins):
            raise ValueError("Pin should be in range 1-14.")

        io_pin = self._pins[pin - 1]

        self.change_bit(io_pin.reg_int_mask_p, io_pin.pin, enabled)

    def on_interrupt(self, callback):
        """Attach an event handler to be run on interrupt.

        :param callback: Callback function to run: callback(pin)

        """
        if self._interrupt_pin is not None:
            print("set Callbackfunction to run  : " + str(callback) + " and enable event detect for Pin: "  str(self._interrupt_pin))
            try:
                self._gpio.add_event_detect(self._interrupt_pin, self._gpio.FALLING, callback=callback, bouncetime=1)
            except Exception as e:
                print("add event_detect failed_:  self._gpio.add_event_detect(self._interrupt_pin, self._gpio.FALLING, callback=callback, bouncetime=1)")
                print("Oops Problem within rgb_Volume(self)! ", e.__class__, "occurred.")
                
    def _wait_for_flash(self):
        """Wait for the IOE to finish writing non-volatile memory."""
        t_start = time.time()
        while self.get_interrupt():
            if time.time() - t_start > self._timeout:
                raise RuntimeError("Timed out waiting for interrupt!")
            time.sleep(0.001)

        t_start = time.time()
        while not self.get_interrupt():
            if time.time() - t_start > self._timeout:
                raise RuntimeError("Timed out waiting for interrupt!")
            time.sleep(0.001)

    def set_i2c_addr(self, i2c_addr):
        """Set the IOE i2c address."""
        self.set_bit(REG_CTRL, 4)
        self.i2c_write8(REG_ADDR, i2c_addr)
        self._i2c_addr = i2c_addr
        time.sleep(0.25)  # TODO Handle addr change IOError better
        # self._wait_for_flash()
        self.clr_bit(REG_CTRL, 4)

    def set_adc_vref(self, vref):
        """Set the ADC voltage reference."""
        self._vref = vref

    def get_adc_vref(self):
        """Get the ADC voltage reference."""
        return self._vref

    def get_chip_id(self):
        """Get the IOE chip ID."""
        return (self.i2c_read8(REG_CHIP_ID_H) << 8) | self.i2c_read8(REG_CHIP_ID_L)

    def _pwm_load(self):
        # Load new period and duty registers into buffer
        t_start = time.time()
        self.set_bit(REG_PWMCON0, 6)    # Set the "LOAD" bit of PWMCON0
        while self.get_bit(REG_PWMCON0, 6):
            time.sleep(0.001)           # Wait for "LOAD" to complete
            if time.time() - t_start >= self._timeout:
                raise RuntimeError("Timed out waiting for PWM load!")

    def set_pwm_control(self, divider):
        """Set PWM settings.

        PWM is driven by the 24MHz FSYS clock by default.

        :param divider: Clock divider, one of 1, 2, 4, 8, 16, 32, 64 or 128

        """
        try:
            pwmdiv2 = {
                1: 0b000,
                2: 0b001,
                4: 0b010,
                8: 0b011,
                16: 0b100,
                32: 0b101,
                64: 0b110,
                128: 0b111}[divider]
        except KeyError:
            raise ValueError("A clock divider of {}".format(divider))

        # TODO: This currently sets GP, PWMTYP and FBINEN to 0
        # It might be desirable to make these available to the user
        # GP - Group mode enable (changes first three pairs of pAM to PWM01H and PWM01L)
        # PWMTYP - PWM type select: 0 edge-aligned, 1 center-aligned
        # FBINEN - Fault-break input enable

        self.i2c_write8(REG_PWMCON1, pwmdiv2)

    def set_pwm_period(self, value):
        """Set the PWM period.

        The period is the point at which the PWM counter is reset to zero.

        The PWM clock runs at FSYS with a divider of 1/1.

        Also specifies the maximum value that can be set in the PWM duty cycle.

        """
        value &= 0xffff
        self.i2c_write8(REG_PWMPL, value & 0xff)
        self.i2c_write8(REG_PWMPH, value >> 8)

        self._pwm_load()

    def get_mode(self, pin):
        """Get the current mode of a pin."""
        return self._pins[pin - 1].mode

    def set_mode(self, pin, mode, schmitt_trigger=False, invert=False):
        """Set a pin output mode.

        :param mode: one of the supplied IN, OUT, PWM or ADC constants

        """
        if pin < 1 or pin > len(self._pins):
            raise ValueError("Pin should be in range 1-14.")

        io_pin = self._pins[pin - 1]
        if io_pin.mode == mode:
            return

        gpio_mode = mode & 0b11
        io_mode = (mode >> 2) & 0b11
        initial_state = mode >> 4

        if io_mode != PIN_MODE_IO and mode not in io_pin.type:
            raise ValueError("Pin {} does not support {}!".format(pin, MODE_NAMES[io_mode]))

        io_pin.mode = mode
        if self._debug:
            print("Setting pin {pin} to mode {mode} {name}, state: {state}".format(pin=pin, mode=MODE_NAMES[io_mode], name=GPIO_NAMES[gpio_mode], state=STATE_NAMES[initial_state]))

        if mode == PIN_MODE_PWM:
            self.set_bit(io_pin.reg_iopwm, io_pin.pwm_channel)
            self.change_bit(REG_PNP, io_pin.pwm_channel, invert)
            self.set_bit(REG_PWMCON0, 7)  # Set PWMRUN bit

        else:
            if PIN_MODE_PWM in io_pin.type:
                self.clr_bit(io_pin.reg_iopwm, io_pin.pwm_channel)

        pm1 = self.i2c_read8(io_pin.reg_m1)
        pm2 = self.i2c_read8(io_pin.reg_m2)

        # Clear the pm1 and pm2 bits
        pm1 &= 255 - (1 << io_pin.pin)
        pm2 &= 255 - (1 << io_pin.pin)

        # Set the new pm1 and pm2 bits according to our gpio_mode
        pm1 |= (gpio_mode >> 1) << io_pin.pin
        pm2 |= (gpio_mode & 0b1) << io_pin.pin

        self.i2c_write8(io_pin.reg_m1, pm1)
        self.i2c_write8(io_pin.reg_m2, pm2)

        # Set up Schmitt trigger mode on inputs
        if mode in [PIN_MODE_PU, PIN_MODE_IN]:
            self.change_bit(io_pin.reg_ps, io_pin.pin, schmitt_trigger)

        # 5th bit of mode encodes default output pin state
        self.i2c_write8(io_pin.reg_p, (initial_state << 3) | io_pin.pin)

    def input(self, pin, adc_timeout=1):
        """Read the IO pin state.

        Returns a 12-bit ADC reading if the pin is in ADC mode
        Returns True/False if the pin is in any other input mode
        Returns None if the pin is in PWM mode

        :param adc_timeout: Timeout (in seconds) for an ADC read (default 1.0)

        """
        if pin < 1 or pin > len(self._pins):
            raise ValueError("Pin should be in range 1-14.")

        io_pin = self._pins[pin - 1]

        if io_pin.mode == PIN_MODE_ADC:
            if self._debug:
                print("Reading ADC from pin {}".format(pin))
            self.clr_bits(REG_ADCCON0, 0x0f)
            self.set_bits(REG_ADCCON0, io_pin.adc_channel)
            self.i2c_write8(REG_AINDIDS, 0)
            self.set_bit(REG_AINDIDS, io_pin.adc_channel)
            self.set_bit(REG_ADCCON1, 0)

            self.clr_bit(REG_ADCCON0, 7)  # ADCF - Clear the conversion complete flag
            self.set_bit(REG_ADCCON0, 6)  # ADCS - Set the ADC conversion start flag

            # Wait for the ADCF conversion complete flag to be set
            t_start = time.time()
            while not self.get_bit(REG_ADCCON0, 7):
                time.sleep(0.01)
                if time.time() - t_start >= adc_timeout:
                    raise RuntimeError("Timeout waiting for ADC conversion!")

            hi = self.i2c_read8(REG_ADCRH)
            lo = self.i2c_read8(REG_ADCRL)
            return ((hi << 4) | lo) / 4095.0 * self._vref

        else:
            if self._debug:
                print("Reading IO from pin {}".format(pin))
            pv = self.get_bit(io_pin.reg_p, io_pin.pin)

            return HIGH if pv else LOW

    def output(self, pin, value):
        """Write an IO pin state or PWM duty cycle.

        :param value: Either True/False for OUT, or a number between 0 and PWM period for PWM.

        """
        if pin < 1 or pin > len(self._pins):
            raise ValueError("Pin should be in range 1-14.")

        io_pin = self._pins[pin - 1]

        if io_pin.mode == PIN_MODE_PWM:
            if self._debug:
                print("Outputting PWM to pin: {pin}".format(pin=pin))
            self.i2c_write8(io_pin.reg_pwml, value & 0xff)
            self.i2c_write8(io_pin.reg_pwmh, value >> 8)
            self._pwm_load()

        else:
            if value == LOW:
                if self._debug:
                    print("Outputting LOW to pin: {pin}".format(pin=pin, value=value))
                self.clr_bit(io_pin.reg_p, io_pin.pin)
            elif value == HIGH:
                if self._debug:
                    print("Outputting HIGH to pin: {pin}".format(pin=pin, value=value))
                self.set_bit(io_pin.reg_p, io_pin.pin)
Beispiel #18
0
            if array[i]:
                retVal |= 0x1 << (5 - i)
        # get list and convert to boolean
        return retVal

    def read(self, n=None) -> List[bool]:
        return [x > self.THRESHOLD for x in self.read_raw(n)]

    def __getitem__(self, item):
        if isinstance(item, slice):
            data = self.read()
            return data.__getitem__(item)
        elif isinstance(item, int):
            return self.read(item)
        else:
            logger.error(
                'Bad type (not int or slice) passed to receptors.__getitem__()'
            )
            return []


if __name__ == '__main__':
    master = SMBus(1)
    read = ReceptorControl(master)
    while True:
        print("Raw Data:  {}".format(read.read_raw()))
        print("Integer:   {}".format(read.read_int()))
        print("Bit Array: {}".format(read.read()))
        print(''.join(['1' if x else '0' for x in read[:]]))
        sleep(1)
Beispiel #19
0
class VL53L1X:
    """VL53L1X ToF."""
    def __init__(self, i2c_bus=1):
        """Initialize the VL53L1X ToF Sensor from ST"""
        self._i2c_bus = i2c_bus
        self._i2c = SMBus(1)
        self._default_dev = None
        self._dev_list = None
        self._ok = True
        self._distance = 0

        # Resgiter Address
        self.ADDR_UNIT_ID_HIGH = 0x16  # Serial number high byte
        self.ADDR_UNIT_ID_LOW = 0x17  # Serial number low byte
        self.ADDR_I2C_ID_HIGH = 0x18  # Write serial number high byte for I2C address unlock
        self.ADDR_I2C_ID_LOW = 0x19  # Write serial number low byte for I2C address unlock
        self.ADDR_I2C_SEC_ADDR = 0x8a  # Write new I2C address after unlock

    def open(self):
        self._i2c.open(bus=self._i2c_bus)
        self._configure_i2c_library_functions()
        self._default_dev = _TOF_LIBRARY.initialise()
        self._dev_list = dict()

    def add_sensor(self, sensor_id, address):
        self._dev_list[sensor_id] = _TOF_LIBRARY.copy_dev(self._default_dev)
        _TOF_LIBRARY.init_dev(self._dev_list[sensor_id], c_uint8(address))

    def close(self):
        self._i2c.close()
        self._default_dev = None
        self._dev_list = None

    def _configure_i2c_library_functions(self):
        # I2C bus read callback for low level library.
        def _i2c_read(address, reg, data_p, length):
            ret_val = 0

            msg_w = i2c_msg.write(address, [reg >> 8, reg & 0xff])
            msg_r = i2c_msg.read(address, length)

            # print("R: a: %x\tr:%d" % (address,reg))
            try:
                self._i2c.i2c_rdwr(msg_w, msg_r)
            except:
                print("Cannot read on 0x%x I2C bus, reg: %d" % (address, reg))

            if ret_val == 0:
                for index in range(length):
                    data_p[index] = ord(msg_r.buf[index])

            return ret_val

        # I2C bus write callback for low level library.
        def _i2c_write(address, reg, data_p, length):
            ret_val = 0
            data = []

            for index in range(length):
                data.append(data_p[index])

            msg_w = i2c_msg.write(address, [reg >> 8, reg & 0xff] + data)
            # print("W: a: %x\tr:%d" % (address,reg))

            try:
                self._i2c.i2c_rdwr(msg_w)
            except:
                print("Cannot write on 0x%x I2C bus, reg: %d" % (address, reg))

            return ret_val

        # Pass i2c read/write function pointers to VL53L1X library.
        self._i2c_read_func = _I2C_READ_FUNC(_i2c_read)
        self._i2c_write_func = _I2C_WRITE_FUNC(_i2c_write)
        _TOF_LIBRARY.VL53L1_set_i2c(self._i2c_read_func, self._i2c_write_func)

    def start_ranging(self, sensor_id, mode=VL53L1xDistanceMode.LONG):
        """Start VL53L1X ToF Sensor Ranging"""
        dev = self._dev_list[sensor_id]
        _TOF_LIBRARY.startRanging(dev, mode)

    def stop_ranging(self, sensor_id):
        """Stop VL53L1X ToF Sensor Ranging"""
        dev = self._dev_list[sensor_id]
        _TOF_LIBRARY.stopRanging(dev)

    def get_distance(self, sensor_id):
        dev = self._dev_list[sensor_id]
        return _TOF_LIBRARY.getDistance(dev)

    def get_address(self, sensor_id):
        dev = self._dev_list[sensor_id]
        return _TOF_LIBRARY.get_address(dev)

    def change_address(self, sensor_id, new_address):
        dev = self._dev_list[sensor_id]
        _TOF_LIBRARY.setDeviceAddress(dev, new_address)

    def update(self, sensor_id):
        """Read raw distance for homeassistant"""
        self._distance = self.get_distance(sensor_id)

    @property
    def sample_ok(self):
        """Return True for a valid measurement data."""
        return self._ok and self._distance >= 0

    @property
    def distance(self):
        """Distance in mm"""
        return self._distance
Beispiel #20
0
 def __init__(self, addr, port):
     self.addr = addr
     self.bus = SMBus(port)
     self.sequence = [0] * 5
     self.get_ad()
Beispiel #21
0
 def __init__(self, bus, addr, alt):
     self.addr = addr
     self.alt = alt
     self.bus = SMBus(bus)
     self.init()
Beispiel #22
0
 def __init__(self):
     self._device = SMBus(2)
     self.led_current = 20
     self.frequency = FREQUENCY_390K625
     self._write_u8(_VCNL4010_INTCONTROL, 0x08)
Beispiel #23
0
def set_eon_fan(val):
  global LEON, last_eon_fan_val

  if last_eon_fan_val is None or last_eon_fan_val != val:
    bus = SMBus(7, force=True)
    if LEON:
      try:
        i = [0x1, 0x3 | 0, 0x3 | 0x08, 0x3 | 0x10][val]
        bus.write_i2c_block_data(0x3d, 0, [i])
      except IOError:
        # tusb320
        if val == 0:
          bus.write_i2c_block_data(0x67, 0xa, [0])
          #bus.write_i2c_block_data(0x67, 0x45, [1<<2])
        else:
          #bus.write_i2c_block_data(0x67, 0x45, [0])
          bus.write_i2c_block_data(0x67, 0xa, [0x20])
          bus.write_i2c_block_data(0x67, 0x8, [(val - 1) << 6])
    else:
      bus.write_byte_data(0x21, 0x04, 0x2)
      bus.write_byte_data(0x21, 0x03, (val*2)+1)
      bus.write_byte_data(0x21, 0x04, 0x4)
    bus.close()
    last_eon_fan_val = val
Beispiel #24
0
 def _read_u8(self, address):
     # Read an 8-bit unsigned value from the specified 8-bit address.
     with SMBus(2) as self._device:
         read = self._device.read_byte_data(_VCNL4010_I2CADDR_DEFAULT, address)
     return read
Beispiel #25
0
from evdev import InputDevice, list_devices, ecodes
from smbus2 import SMBus

from pi_wars import Controller, Stick, drive_from_vector
from yrk_oo.motors import Motors, MotorDriver

if __name__ == "__main__":
    device = InputDevice(list_devices()[0])
    stick = Stick(ecodes.ABS_X, ecodes.ABS_Y, deadzone=0.1)
    controller = Controller(device, [stick])
    bus = SMBus(13)
    m1 = MotorDriver(Motors.MOTOR1, bus, 0.1)
    m2 = MotorDriver(Motors.MOTOR4, bus, 0.1)
    m11 = MotorDriver(Motors.MOTOR2, bus, 0.1)
    m22 = MotorDriver(Motors.MOTOR3, bus, 0.1)

    for _ in controller.read_loop():
        m1_v, m2_v = drive_from_vector(*stick.value)
        print(stick.value, m1_v, m2_v)
        m1.set(m1_v)
        m11.set(m1_v)
        m22.set(m2_v)
        m2.set(m2_v)
Beispiel #26
0
 def _write_u8(self, address, val):
     # Write an 8-bit unsigned value to the specified 8-bit address.
     with SMBus(2) as self._device:
         self._device.write_byte_data(_VCNL4010_I2CADDR_DEFAULT, address, val)
Beispiel #27
0
class I2C_Comm:
    def __init__(self, bus):
        self.smbus = SMBus(bus=bus)
        self.write_seq_num = 0
        sleep(1)  # give the bus a chance to settle

    def get_device_info(self, adr):

        board_info = {
            "inventoryVersion": 0,
            "i2cAddress": 0,
            "boardType": 0,
            "boardDescription": "unknown",
            "boardVersion": 0,
            "i2cCommSwVersion": "unknown",
            "inventorySwVersion": "unknown",
            "applicationSwVersion": "unknown"
        }

        reg, dev_info = self.read_register(
            adr, tcc.I2C_REG_INVENTORY_VERSION,
            tcc.I2C_REG_ID_LEN + tcc.I2C_INVENTORY_VERSION_LEN)
        if reg == tcc.I2C_REG_INVENTORY_VERSION and dev_info[0] == 1:
            # ####################################
            # inventory structure version 1
            # ####################################
            board_info["inventoryVersion"] = dev_info[0]
            #
            reg, dev_info = self.read_register(
                adr, tcc.I2C_REG_I2C_ADR,
                tcc.I2C_REG_ID_LEN + tcc.I2C_I2C_ADR_LEN)
            if reg > 0:
                board_info["i2cAddress"] = dev_info[0]
            #
            reg, dev_info = self.read_register(
                adr, tcc.I2C_REG_BOARD_TYPE,
                tcc.I2C_REG_ID_LEN + tcc.I2C_BOARD_TYPE_LEN)
            if reg > 0:
                board_info["boardType"] = dev_info[0]
            #
            reg, dev_info = self.read_register(
                adr, tcc.I2C_REG_BOARD_DESCRIPTION,
                tcc.I2C_REG_ID_LEN + tcc.I2C_BOARD_DESCRIPTION_LEN)
            if reg > 0:
                board_info["boardDescription"] = self.char_list_to_string(
                    dev_info)

            reg, dev_info = self.read_register(
                adr, tcc.I2C_REG_BOARD_VERSION,
                tcc.I2C_REG_ID_LEN + tcc.I2C_BOARD_VERSION_LEN)
            if reg > 0:
                board_info["boardVersion"] = dev_info[0]
            reg, dev_info = self.read_register(
                adr, tcc.I2C_REG_I2C_COMM_SW_VERSION,
                tcc.I2C_REG_ID_LEN + tcc.I2C_I2C_COMM_SW_VERSION_LEN)
            if reg > 0:
                board_info["i2cCommSwVersion"] = self.char_list_to_string(
                    dev_info)

            reg, dev_info = self.read_register(
                adr, tcc.I2C_REG_INVENTORY_SW_VERSION,
                tcc.I2C_REG_ID_LEN + tcc.I2C_INVENTORY_SW_VERSION_LEN)
            if reg > 0:
                board_info["inventorySwVersion"] = self.char_list_to_string(
                    dev_info)

            reg, dev_info = self.read_register(
                adr, tcc.I2C_REG_APP_SW_VERSION,
                tcc.I2C_REG_ID_LEN + tcc.I2C_APP_SW_VERSION_LEN)
            if reg > 0:
                board_info["applicationSwVersion"] = self.char_list_to_string(
                    dev_info)

        return board_info

    @staticmethod
    def char_list_to_string(char_list):
        return ''.join([chr(c) for c in char_list if 31 < c and c < 128])

    def read_register(self, adr, reg, data_length):
        """
        :param adr: I2C Bus address
        :param reg: board register
        :param data_length: of data to read (not counting the checksum)
        :return: reg or -1 (on error),
                 reg_data (remaining bytes read)
        """
        cmd = -1  # Assume error return
        reg_data = []
        length = data_length + tcc.I2C_CHECKSUM_LEN
        for retry in range(0, 4):
            try:
                reg_data = self.smbus.read_i2c_block_data(adr, reg, length)
                if len(reg_data) == length:
                    if self.validate_checksum(reg_data) == 0:
                        cmd = reg_data.pop(
                            0)  # todo - checksum is still attached !
                        reg_data.pop(-1)  # remove the checksum
                        if cmd == reg:
                            break
                    else:
                        print("read_register checksum error {}".format(
                            self.validate_checksum(reg_data)))
                else:
                    print("read_register length error {}".format(length))
            except IOError:
                print("IOError read_register at adr {} / reg {}".format(
                    adr, reg))

        return cmd, reg_data

    """
    def set_register(self, adr, reg, send_data):
        try:
            self.smbus.write_i2c_block_data(adr, reg, send_data)
        except IOError:
            print("Error setRegister at adr {} / reg {}".format(adr, reg))

    
    def get_byte_reg(self, adr, reg):
        Read one byte of data from the specified register at the specified address.

        This would be a useful function for collecting inventory data except the Arduino
        code would need to be rewritten. The Arduino code sends multiple bytes back, starting
        with the regId. It would need to send only the requested data.

        To make use of this method, the Arduino code would need to send a single byte back
        in response to a request. Maybe later there will be registers where I need to do this.
        This method would be appropriate where higher performance is required.

        :param adr:
        :param reg:
        :return: reg or -1 on error
                 reg_data
        
        for retry in range(0, 4):
            try:
                reg_data = self.smbus.read_byte_data(adr, reg)
                return_reg = reg
                break
            except IOError:
                print("Error get_byte_reg at adr {} / reg {}".format(adr, reg))
                # Note the following values may be overwritten by a successful retry
                return_reg = -1  # assume error
                reg_data = 0

        return return_reg, reg_data
     """

    @staticmethod
    def get_controller_list():
        """ Find all active I2C devices on the bus

        :return: list of I2C addresses of all active devices
        """
        arduino_list = []

        run_cmd = "i2cdetect -y 1"

        try:
            i2c_detect_output = subprocess.run(run_cmd,
                                               shell=True,
                                               check=True,
                                               stdout=subprocess.PIPE,
                                               universal_newlines=True)

            i2c_detect_output.check_returncode()
            i2c_rows = i2c_detect_output.stdout.splitlines()
            del i2c_rows[0]  # delete top row, its the heading
            for row in i2c_rows:
                adr_list = row.split()
                # delete the row identifier
                del adr_list[0]
                for adr in adr_list:
                    if adr != '--':
                        arduino_list.append(adr)
        except subprocess.CalledProcessError:
            print("CallProcessError encountered")

        return arduino_list

    def block_read_test(self, adr):
        """Execute a block read test on the given address.

        A loopback test consists of the following message sent 256 times
        to the given adr:
             block data read to
             - register : I2C_REG_UP_COUNTER
        The data read is expected to increment on each read.

        The  return value is a tuple (messagesSent, readExceptions, data_mismatches).
           data_mismatches = length_failures + Checksum fail + regId fail + data (up_counter) fail
        """
        messages_to_send = 256
        read_exception = 0
        data_mismatch = 0
        length = 3  # reg, count, cs
        reg = tcc.I2C_REG_UP_COUNTER

        # Reset the upCounter
        uncorrected_error, re, we, dm = self.write_register_verify(
            adr, reg, [0])
        if uncorrected_error > 0:
            print(
                "An attempt to reset the UP_COUNTER at adr {} resulted in an uncorrectable error: {}"
                .format(adr, uncorrected_error))

        # now do the reads
        expected_data = 0
        for i in range(messages_to_send):
            try:
                read_data = self.smbus.read_i2c_block_data(adr, reg, length)
                if len(read_data) == length:
                    if self.validate_checksum(read_data) == 0:
                        read_data.pop(-1)  # remove the checksum
                        if read_data[0] != reg or read_data[1] != expected_data:
                            data_mismatch += 1
                            print("Read error. S/B {} Is {}".format(
                                expected_data, read_data[1]))
                    else:
                        data_mismatch += 1  # todo - verify the following byte assignments
                        print("Checksum error: {} {} ".format(
                            read_data[1], read_data[2]))
                else:
                    data_mismatch += 1
                    print("Length read error")
                expected_data += 1
            except IOError:
                read_exception += 1
                print("Read IOerror at adr {}".format(adr))
            #sleep(0.00001)

        return messages_to_send, read_exception, data_mismatch

    def block_write_test(self, adr):
        """Execute a loopback test on the given address

        A loopback test consists of the following message sent 256 times to the given adr:
             write_register_verify to write_test reg
             - data [d1, d2, d3]
             - read back the seqNum to verify

        The  return value is a tuple (
                 messages_sent,
                 read_exception,
                 write_exception,
                 data_mismatch,
                 uncorrectable_errors
        """
        messages_to_send = 256

        write_exception = 0
        read_exception = 0
        data_mismatch = 0
        uncorrectable_err = 0
        reg = tcc.I2C_REG_WRITE_TEST

        for i in range(messages_to_send):
            # generate the data
            data = [i % 256, (i + 1) % 256, (i + 2) % 256]
            # do the write
            ue, re, we, dm = self.write_register_verify(adr, reg, data)

            # update the results
            uncorrectable_err += ue
            read_exception += re
            write_exception += we
            data_mismatch += dm

        return messages_to_send, read_exception, write_exception, \
               data_mismatch, uncorrectable_err

    def write_register_verify(self, adr, reg, data):
        """Do a single write / verify test with retries on the write and read back

        return -
           uncorrected_errors
           read_exception
           write_exception
           data_mismatch
        """
        #print("Adr: {}, reg {}, data {}".format(adr, reg,data));
        write_exception = 0
        read_exception = 0
        data_mismatch = 0
        uncorrected_errors = 0
        read_result = -1

        for attempt in range(1, 5):
            write_result, we = self.write_func(adr, reg, data)
            write_exception += we
            if write_result == 0:
                # todo - .5 slows things down enough to print in the main Arduino loop if necessary
                #   I also used .1 to process buffers in the main loop prior to changing verify
                #   from reading data back to reading sequence number back.
                # sleep(.001)
                read_result, re, dm = self.read_verify(adr, 19,
                                                       [self.write_seq_num])

                read_exception += re
                data_mismatch += dm
                if read_result == 0:
                    break
        if read_result != 0:
            uncorrected_errors = 1
        """
        errors = write_exception + read_exception + data_mismatch + uncorrected_errors
        
        if errors > 0:
        print("we {}, re {}, dm {}, unerr {}".format(write_exception,
        read_exception,
        data_mismatch,
        uncorrected_error))
        """
        return uncorrected_errors, read_exception, write_exception, data_mismatch

    def write_func(self, adr, reg, data):
        """Write given data to the given address / register
        Inputs
           adr - I2C bus adr
           reg - register to write to
           data - list of bytes to write
        Generate a checksum and append it to the data. Make n attempts to
        write the data to adr/register. If an IOError occurs during the
        write, count it and retry. If a retry is required, use a new
        write_seq_num.

        return
            result  0 : success, data was written, (may have taken retries)
                   -1 : failure, unable to write data
            write_exception - number of IOErrors encountered
        """
        write_exception = 0
        result = -1  # assume failure

        for attempt in range(1, 5):
            try:
                self.write_seq_num = (self.write_seq_num + 1) % 256
                cs = self.gen_checksum(reg, [self.write_seq_num] + data)
                self.smbus.write_i2c_block_data(adr,
                                                reg, [self.write_seq_num] +
                                                data + [cs],
                                                force=True)
                result = 0
                break
            except IOError:
                print("Write exception {}".format(self.write_seq_num))
                write_exception += 1

        return result, write_exception

    def read_verify(self, adr, reg, data):
        """Read from the given address/register and verify the expected_data
        Inputs
           adr - I2C bus adr
           reg - register to read from
           data - list of bytes expected

        Make n attempts to read from the given adr/register and verify the expected_data.
        If an IOError occurs during the read, count it and retry.
        If a checksum error occurs during the read, count it and retry.

        return
            result  0 : success, data was verified (may have taken retries)
                   -1 : failure, unable to verify data
            read_exception - number of IOErrors encountered
            data_mismatch - number of read failures
        """
        read_exception = 0
        data_mismatch = 0
        result = -1  # assume failure

        expected_data = [
            reg
        ] + data  # Put the reg in the data list. Its part of the return data

        for attempt in range(1, 5):  # 4 retries for now
            try:
                # do the read/verify
                read_data = self.smbus.read_i2c_block_data(
                    adr, reg,
                    len(expected_data) + 1)  # +1 for checksum
                if self.validate_checksum(read_data) == 0:
                    read_data.pop(-1)  # removed the trailing checksum
                    if read_data == expected_data:
                        result = 0
                    else:
                        data_mismatch += 1
                    break  # OK, we were able to successfully read the register - we're done trying
                else:
                    data_mismatch += 1
                    print("Read Verify Checksum error")
            except IOError:
                read_exception += 1

        return result, read_exception, data_mismatch

    def loopback_test(self, adr):
        """Execute a loopback test on the given address

        A loopback test consists of the following message sent 256 times
        to the given adr
        block data read to
        - register 99
        - seq number

        The  return value is a tuple (messagesSent, resendCount).
        """
        messages_to_send = 256
        errors = 0
        for i in range(messages_to_send):
            try:
                self.smbus.read_i2c_block_data(adr, 99, 2)  # 2=length
            except IOError:
                errors += 1
                print("Oops - error at adr {}".format(adr))
            sleep(0.001)

        return messages_to_send, errors

    @staticmethod
    def validate_checksum(data):
        """Return zero is the checksum is valid"""
        checksum = 0
        for element in data:
            checksum += element
        return checksum % 256

    @staticmethod
    def gen_checksum(reg, buffer):
        check_sum = reg
        for element in buffer:
            check_sum += element
        return -(check_sum % 256)
Beispiel #28
0
 def _read_u16BE(self, address):
     with SMBus(2) as self._device:
         read_block = self._device.read_i2c_block_data(_VCNL4010_I2CADDR_DEFAULT, address, 2)
     return (read_block[0] << 8) | read_block[1]
Beispiel #29
0
class SGP30:
    def __init__(self, i2c_dev=None, i2c_msg=None, i2c_addr=SGP30_I2C_ADDR):
        """Mapping table of SGP30 commands.

        Friendly-name, followed by 16-bit command,
        then the number of parameter and response words.

        Each word is two bytes followed by a third CRC
        checksum byte. So a response length of 2 would
        result in the transmission of 6 bytes total.
        """
        self.commands = {
            'init_air_quality': (0x2003, 0, 0),
            'measure_air_quality': (0x2008, 0, 2),
            'get_baseline': (0x2015, 0, 2),
            'set_baseline': (0x201e, 2, 0),
            'set_humidity': (0x2061, 1, 0),
            # 'measure_test': (0x2032, 0, 1),  # Production verification only
            'get_feature_set_version': (0x202f, 0, 1),
            'measure_raw_signals': (0x2050, 0, 2),
            'get_serial_id': (0x3682, 0, 3)
        }

        self._i2c_addr = i2c_addr
        self._i2c_dev = i2c_dev
        self._i2c_msg = i2c_msg
        if self._i2c_dev is None:
            from smbus2 import SMBus, i2c_msg
            self._i2c_msg = i2c_msg
            self._i2c_dev = SMBus(1)

    def command(self, command_name, parameters=None):
        if parameters is None:
            parameters = []
        parameters = list(parameters)
        cmd, param_len, response_len = self.commands[command_name]
        if len(parameters) != param_len:
            raise ValueError("{} requires {} parameters. {} supplied!".format(
                command_name, param_len, len(parameters)))

        parameters_out = [cmd]

        for i in range(len(parameters)):
            parameters_out.append(parameters[i])
            parameters_out.append(self.calculate_crc(parameters[i]))

        data_out = struct.pack('>H' + ('HB' * param_len), *parameters_out)

        msg_w = self._i2c_msg.write(self._i2c_addr, data_out)
        self._i2c_dev.i2c_rdwr(msg_w)
        time.sleep(0.025)  # Suitable for all commands except 'measure_test'

        if response_len > 0:
            # Each parameter is a word (2 bytes) followed by a CRC (1 byte)
            msg_r = self._i2c_msg.read(self._i2c_addr, response_len * 3)
            self._i2c_dev.i2c_rdwr(msg_r)

            buf = msg_r.buf[0:response_len * 3]

            response = struct.unpack('>' + ('HB' * response_len), buf)

            verified = []
            for i in range(response_len):
                offset = i * 2
                value, crc = response[offset:offset + 2]
                if crc != self.calculate_crc(value):
                    raise RuntimeError(
                        "Invalid CRC in response from SGP30: {:02x} != {:02x}",
                        crc, self.calculate_crc(value), buf)
                verified.append(value)
            return verified

    def calculate_crc(self, data):
        """Calculate an 8-bit CRC from a 16-bit word

        Defined in section 6.6 of the SGP30 datasheet.

        Polynominal: 0x31 (x8 + x5 + x4 + x1)
        Initialization: 0xFF
        Reflect input/output: False
        Final XOR: 0x00

        """
        crc = 0xff  # Initialization value
        # calculates 8-Bit checksum with given polynomial
        for byte in [(data & 0xff00) >> 8, data & 0x00ff]:
            crc ^= byte
            for _ in range(8):
                if crc & 0x80:
                    crc = (crc << 1) ^ 0x31  # XOR with polynominal
                else:
                    crc <<= 1
        return crc & 0xff

    def get_unique_id(self):
        result = self.command('get_serial_id')
        return result[0] << 32 | result[1] << 16 | result[0]

    def get_feature_set_version(self):
        result = self.command('get_feature_set_version')[0]
        return (result & 0xf000) >> 12, result & 0x00ff

    def start_measurement(self, run_while_waiting=None):
        """Start air quality measurement on the SGP30.

        The first 15 readings are discarded so this command will block for 15s.

        :param run_while_waiting: Function to call for every discarded reading.

        """
        self.command('init_air_quality')
        testsamples = 0
        while True:
            # Discard the initialisation readings as per page 8/15 of the datasheet
            eco2, tvoc = self.command('measure_air_quality')
            # The first 15 readings should return as 400, 0 so abort when they change
            # Break after 20 test samples to avoid a potential infinite loop
            if eco2 != 400 or tvoc != 0 or testsamples >= 20:
                break
            if callable(run_while_waiting):
                run_while_waiting()
            time.sleep(1.0)
            testsamples += 1

    def get_air_quality(self):
        """Get an air quality measurement.

        Returns an instance of SGP30Reading with the properties equivalent_co2 and total_voc.

        This should be called at 1s intervals to ensure the dynamic baseline compensation on the SGP30 operates correctly.

        """
        eco2, tvoc = self.command('measure_air_quality')
        return SGP30Reading(eco2, tvoc)

    def get_baseline(self):
        """Get the current baseline setting.

        Returns an instance of SGP30Reading with the properties equivalent_co2 and total_voc.

        """
        eco2, tvoc = self.command('get_baseline')
        return SGP30Reading(eco2, tvoc)

    def set_baseline(self, eco2, tvoc):
        self.command('set_baseline', [tvoc, eco2])

    def __del__(self):
        self._i2c_dev.close()
Beispiel #30
0
class InputModule(AbstractInput):
    """
    A sensor support class that measures the AM2320's humidity and temperature
    and calculates the dew point

    """
    def __init__(self, input_dev, testing=False):
        super(InputModule, self).__init__()
        self.logger = logging.getLogger('mycodo.inputs.am2320')
        self.powered = False
        self.sensor = None
        self.i2c_address = 0x5C

        if not testing:
            from smbus2 import SMBus
            self.logger = logging.getLogger(
                'mycodo.am2320_{id}'.format(
                    id=input_dev.unique_id.split('-')[0]))

            self.device_measurements = db_retrieve_table_daemon(
                DeviceMeasurements).filter(
                    DeviceMeasurements.device_id == input_dev.unique_id)

            self.i2c_bus = input_dev.i2c_bus
            self.power_output_id = input_dev.power_output_id
            self.start_sensor()
            self.sensor = SMBus(self.i2c_bus)

    def get_measurement(self):
        """ Gets the humidity and temperature """
        return_dict = measurements_dict.copy()

        temperature, humidity = self.read()

        if self.is_enabled(0):
            return_dict[0]['value'] = temperature

        if self.is_enabled(1):
            return_dict[1]['value'] = humidity

        if (self.is_enabled(2) and
                self.is_enabled(0) and
                self.is_enabled(1)):
            return_dict[2]['value'] = calculate_dewpoint(
                return_dict[0]['value'], return_dict[1]['value'])

        if (self.is_enabled(3) and
                self.is_enabled(0) and
                self.is_enabled(1)):
            return_dict[3]['value'] = calculate_vapor_pressure_deficit(
                return_dict[0]['value'], return_dict[1]['value'])

        return return_dict

    def read(self):
        try:
            self.sensor.write_i2c_block_data(
                self.i2c_address, 0x03, [0x00, 0x04])
        except OSError as e:
            self.logger.error(e)
        time.sleep(0.02)

        blocks = self.sensor.read_i2c_block_data(self.i2c_address, 0, 6)

        humidity = ((blocks[2] << 8) + blocks[3]) / 10.0
        temperature = ((blocks[4] << 8) + blocks[5]) / 10.0

        return temperature, humidity

    def setup(self):
        try:
            self.sensor.write_i2c_block_data(self.i2c_address, 0x00, [])
        except OSError as e:
            self.logger.error(e)
        time.sleep(0.1)
Beispiel #31
0
class LCD_Grove_LCD_RGB:
    """Output to a Grove I2C LCD RGB display (16x2 LCD with RGB or monochrome backlight)"""

    def __init__(self, lcd_dev):
        self.logger = logging.getLogger(
            "{}_{}".format(__name__, lcd_dev.unique_id.split('-')[0]))

        self.lcd_initialized = False
        self.lcd_is_on = False
        self.red = 255
        self.green = 255
        self.blue = 255

        self.i2c_address = int(lcd_dev.location, 16)
        self.i2c_address_backlight = int(lcd_dev.location_backlight, 16)
        # self.i2c_address_backlight = 0x62
        self.i2c_bus = lcd_dev.i2c_bus
        self.lcd_x_characters = lcd_dev.x_characters
        self.lcd_y_lines = lcd_dev.y_lines

        self.LCD_WIDTH = self.lcd_x_characters  # Max characters per line
        self.I2C_ADDR = self.i2c_address

        # Commands, etc
        self.LCD_CLEARDISPLAY = 0x01
        self.LCD_RETURNHOME = 0x02
        self.LCD_ENTRYMODESET = 0x04
        self.LCD_DISPLAYCONTROL = 0x08
        self.LCD_CURSORSHIFT = 0x10
        self.LCD_FUNCTIONSET = 0x20
        self.LCD_SETCGRAMADDR = 0x40
        self.LCD_SETDDRAMADDR = 0x80

        # flags for function set
        self.LCD_8BITMODE = 0x10
        self.LCD_4BITMODE = 0x00
        self.LCD_2LINE = 0x08
        self.LCD_1LINE = 0x00
        self.LCD_5x10DOTS = 0x04
        self.LCD_5x8DOTS = 0x00

        # flags for display on/off control
        self.LCD_DISPLAYON = 0x04
        self.LCD_DISPLAYOFF = 0x00
        self.LCD_CURSORON = 0x02
        self.LCD_CURSOROFF = 0x00
        self.LCD_BLINKON = 0x01
        self.LCD_BLINKOFF = 0x00

        # flags for display entry mode
        self.LCD_ENTRYRIGHT = 0x00
        self.LCD_ENTRYLEFT = 0x02
        self.LCD_ENTRYSHIFTINCREMENT = 0x01
        self.LCD_ENTRYSHIFTDECREMENT = 0x00

        # RGB backlight registers
        self.REG_MODE1 = 0x00
        self.REG_MODE2 = 0x01
        self.REG_OUTPUT = 0x08

        # Setup I2C bus
        try:
            self.bus = SMBus(self.i2c_bus)
        except Exception as except_msg:
            self.logger.exception(
                "Could not initialize I2C bus: {err}".format(
                    err=except_msg))

        # set configuration
        displayConfig = self.LCD_FUNCTIONSET
        if self.lcd_y_lines == 2:
            displayConfig = displayConfig | self.LCD_2LINE
        self.writeCommand(displayConfig)
        time.sleep(0.005)
        self.writeCommand(displayConfig)
        time.sleep(0.001)
        self.writeCommand(displayConfig)
        self.writeCommand(displayConfig)
        # set state
        displayState = self.LCD_DISPLAYCONTROL | self.LCD_DISPLAYON | self.LCD_CURSOROFF | self.LCD_BLINKOFF
        self.writeCommand(displayState)

        self.clearDisplay()

        # set the entry mode
        entryMode = self.LCD_ENTRYMODESET | self.LCD_ENTRYLEFT | self.LCD_ENTRYSHIFTDECREMENT
        self.writeCommand(entryMode)

        # Initialize the backlight
        self.bus.write_byte_data(self.i2c_address_backlight, self.REG_MODE1, 0)
        # set LEDs controllable by both PWM and GRPPWM registers
        self.bus.write_byte_data(self.i2c_address_backlight, self.REG_OUTPUT, 0xff)
        # set MODE2 values
        # 0010 0000 -> 0x20  (DMBLNK to 1, ie blinky mode)
        self.bus.write_byte_data(self.i2c_address_backlight, self.REG_MODE2, 0x20)
        self.setRGB(self.red, self.green, self.blue)
        
    def writeCommand(self, cmd):
        self.bus.write_byte_data(self.i2c_address,0x80,cmd)

    def writeData(self, data):
        self.bus.write_byte_data(self.i2c_address,0x40,data)

    def setRGB(self, r, g, b):
        self.bus.write_byte_data(self.i2c_address_backlight, 4, r)
        self.bus.write_byte_data(self.i2c_address_backlight, 3, g)
        self.bus.write_byte_data(self.i2c_address_backlight, 2, b)

    def clearDisplay(self):
        self.writeCommand(self.LCD_CLEARDISPLAY) # clear display
        time.sleep(0.002)

    def setCursor(self, col, row):
        if row == 0:
            location = col | 0x80
        else:
            location = col | 0xc0
        self.writeCommand(location)
        time.sleep(0.001)

    def setText(self, text):
        self.clearDisplay()
        self.setCursor(0, 0)
        count = 0
        row = 0
        for c in text:
            if c == '\n' or count == 16:
                count = 0
                row += 1
                if row == 2:
                    break
                self.writeCommand(0xc0)
                if c == '\n':
                    continue
            count += 1
            self.writeData(ord(c))

    def lcd_init(self):
        """ Clear LCD display """
        self.clearDisplay()

    def lcd_backlight(self, state):
        """ Turn the backlight on or off """
        if state:
            self.setRGB(self.red, self.green, self.blue)
        else:
            self.setRGB(0,0,0)

    def lcd_backlight_color(self, color_tuple):
        try:
            tuple_colors = color_tuple.split(",")
            self.red = int(tuple_colors[0])
            self.green = int(tuple_colors[1])
            self.blue = int(tuple_colors[2])
            self.setRGB(self.red, self.green, self.blue)
        except:
            self.logger.error("Could not set color. Invalid color string: '{}'".format(color_tuple))

    def lcd_byte(self, bits, mode, backlight=None):
        """ Send byte to data pins """
        # bits = the data
        # mode = 1 for data
        #        0 for command
        if mode == 0:
            self.writeCommand(bits)
        else:
            self.writeData(bits)

    def lcd_toggle_enable(self, bits):
        """ Toggle enable """
        pass

    def lcd_string_write(self, message, line):
        """ Send strings to display """
        self.setCursor(0, line)
        for c in message:
            self.writeData(ord(c))

    def lcd_write_lines(self, line_1, line_2, line_3, line_4):
        msg = ""
        if line_1:
            msg += line_1
        msg += "\n"
        if line_2:
            msg += line_2
        msg += "\n"
        if line_3:
            msg += line_3
        msg += "\n"
        if line_4:
            msg += line_4
        self.setText(msg)
Beispiel #32
0
class InputModule(AbstractInput):
    """ A sensor support class that monitors the MH-Z16's CO2 concentration """

    def __init__(self, input_dev, testing=False):
        super(InputModule, self).__init__()
        self.logger = logging.getLogger("mycodo.inputs.mh_z16")

        if not testing:
            self.logger = logging.getLogger(
                "mycodo.mh_z16_{id}".format(id=input_dev.unique_id.split('-')[0]))

            self.interface = input_dev.interface
            self.uart_location = input_dev.uart_location

            if self.interface == 'UART':
                import serial

                # Check if device is valid
                self.serial_device = is_device(self.uart_location)
                if self.serial_device:
                    try:
                        self.ser = serial.Serial(self.serial_device, timeout=1)
                    except serial.SerialException:
                        self.logger.exception('Opening serial')
                else:
                    self.logger.error(
                        'Could not open "{dev}". '
                        'Check the device location is correct.'.format(
                            dev=self.uart_location))

            elif self.interface == 'I2C':
                from smbus2 import SMBus

                self.i2c_address = int(str(input_dev.i2c_location), 16)
                self.i2c_bus = input_dev.i2c_bus
                self.cmd_measure = [0xFF, 0x01, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63]
                self.IOCONTROL = 0X0E << 3
                self.FCR = 0X02 << 3
                self.LCR = 0X03 << 3
                self.DLL = 0x00 << 3
                self.DLH = 0X01 << 3
                self.THR = 0X00 << 3
                self.RHR = 0x00 << 3
                self.TXLVL = 0X08 << 3
                self.RXLVL = 0X09 << 3
                self.i2c = SMBus(self.i2c_bus)
                self.begin()

    def get_measurement(self):
        """ Gets the MH-Z16's CO2 concentration in ppmv via UART"""
        return_dict = measurements_dict.copy()

        co2 = None

        if self.interface == 'UART':
            if not self.serial_device:  # Don't measure if device isn't validated
                return None

            self.ser.flushInput()
            time.sleep(1)
            self.ser.write(bytearray([0xff, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79]))
            time.sleep(.01)
            resp = self.ser.read(9)
            if len(resp) != 0:
                high = resp[2]
                low = resp[3]
                co2 = (high * 256) + low

        elif self.interface == 'I2C':
            self.write_register(self.FCR, 0x07)
            self.send(self.cmd_measure)
            try:
                co2 = self.parse(self.receive())
            except Exception:
                co2 = None

        return_dict[0]['value'] = co2

        return return_dict

    def begin(self):
        try:
            self.write_register(self.IOCONTROL, 0x08)
        except IOError:
            pass

        self.write_register(self.FCR, 0x07)
        self.write_register(self.LCR, 0x83)
        self.write_register(self.DLL, 0x60)
        self.write_register(self.DLH, 0x00)
        self.write_register(self.LCR, 0x03)

    @staticmethod
    def parse(response):
        checksum = 0

        if len(response) < 9:
            return None

        for i in range(0, 9):
            checksum += response[i]

        if response[0] == 0xFF:
            if response[1] == 0x9C:
                if checksum % 256 == 0xFF:
                    return (response[2] << 24) + (response[3] << 16) + (response[4] << 8) + response[5]

        return None

    def read_register(self, reg_addr):
        time.sleep(0.01)
        return self.i2c.read_byte_data(self.i2c_address, reg_addr)

    def write_register(self, reg_addr, val):
        time.sleep(0.01)
        self.i2c.write_byte_data(self.i2c_address, reg_addr, val)

    def send(self, command):
        if self.read_register(self.TXLVL) >= len(command):
            self.i2c.write_i2c_block_data(self.i2c_address, self.THR, command)

    def receive(self):
        n = 9
        buf = []
        start = time.clock()

        while n > 0:
            rx_level = self.read_register(self.RXLVL)

            if rx_level > n:
                rx_level = n

            buf.extend(self.i2c.read_i2c_block_data(self.i2c_address, self.RHR, rx_level))
            n = n - rx_level

            if time.clock() - start > 0.2:
                break
        return buf
Beispiel #33
0
    def __init__(self, lcd_dev):
        self.logger = logging.getLogger(
            "{}_{}".format(__name__, lcd_dev.unique_id.split('-')[0]))

        self.lcd_initialized = False
        self.lcd_is_on = False
        self.red = 255
        self.green = 255
        self.blue = 255

        self.i2c_address = int(lcd_dev.location, 16)
        self.i2c_address_backlight = int(lcd_dev.location_backlight, 16)
        # self.i2c_address_backlight = 0x62
        self.i2c_bus = lcd_dev.i2c_bus
        self.lcd_x_characters = lcd_dev.x_characters
        self.lcd_y_lines = lcd_dev.y_lines

        self.LCD_WIDTH = self.lcd_x_characters  # Max characters per line
        self.I2C_ADDR = self.i2c_address

        # Commands, etc
        self.LCD_CLEARDISPLAY = 0x01
        self.LCD_RETURNHOME = 0x02
        self.LCD_ENTRYMODESET = 0x04
        self.LCD_DISPLAYCONTROL = 0x08
        self.LCD_CURSORSHIFT = 0x10
        self.LCD_FUNCTIONSET = 0x20
        self.LCD_SETCGRAMADDR = 0x40
        self.LCD_SETDDRAMADDR = 0x80

        # flags for function set
        self.LCD_8BITMODE = 0x10
        self.LCD_4BITMODE = 0x00
        self.LCD_2LINE = 0x08
        self.LCD_1LINE = 0x00
        self.LCD_5x10DOTS = 0x04
        self.LCD_5x8DOTS = 0x00

        # flags for display on/off control
        self.LCD_DISPLAYON = 0x04
        self.LCD_DISPLAYOFF = 0x00
        self.LCD_CURSORON = 0x02
        self.LCD_CURSOROFF = 0x00
        self.LCD_BLINKON = 0x01
        self.LCD_BLINKOFF = 0x00

        # flags for display entry mode
        self.LCD_ENTRYRIGHT = 0x00
        self.LCD_ENTRYLEFT = 0x02
        self.LCD_ENTRYSHIFTINCREMENT = 0x01
        self.LCD_ENTRYSHIFTDECREMENT = 0x00

        # RGB backlight registers
        self.REG_MODE1 = 0x00
        self.REG_MODE2 = 0x01
        self.REG_OUTPUT = 0x08

        # Setup I2C bus
        try:
            self.bus = SMBus(self.i2c_bus)
        except Exception as except_msg:
            self.logger.exception(
                "Could not initialize I2C bus: {err}".format(
                    err=except_msg))

        # set configuration
        displayConfig = self.LCD_FUNCTIONSET
        if self.lcd_y_lines == 2:
            displayConfig = displayConfig | self.LCD_2LINE
        self.writeCommand(displayConfig)
        time.sleep(0.005)
        self.writeCommand(displayConfig)
        time.sleep(0.001)
        self.writeCommand(displayConfig)
        self.writeCommand(displayConfig)
        # set state
        displayState = self.LCD_DISPLAYCONTROL | self.LCD_DISPLAYON | self.LCD_CURSOROFF | self.LCD_BLINKOFF
        self.writeCommand(displayState)

        self.clearDisplay()

        # set the entry mode
        entryMode = self.LCD_ENTRYMODESET | self.LCD_ENTRYLEFT | self.LCD_ENTRYSHIFTDECREMENT
        self.writeCommand(entryMode)

        # Initialize the backlight
        self.bus.write_byte_data(self.i2c_address_backlight, self.REG_MODE1, 0)
        # set LEDs controllable by both PWM and GRPPWM registers
        self.bus.write_byte_data(self.i2c_address_backlight, self.REG_OUTPUT, 0xff)
        # set MODE2 values
        # 0010 0000 -> 0x20  (DMBLNK to 1, ie blinky mode)
        self.bus.write_byte_data(self.i2c_address_backlight, self.REG_MODE2, 0x20)
        self.setRGB(self.red, self.green, self.blue)
Beispiel #34
0
class Sonar:

    __units = {"mm":0, "cm":1}
    __dist_reg = 0

    __RGB_MODE = 2
    __RGB1_R = 3
    __RGB1_G = 4
    __RGB1_B = 5
    __RGB2_R = 6
    __RGB2_G = 7
    __RGB2_B = 8

    __RGB1_R_BREATHING_CYCLE = 9
    __RGB1_G_BREATHING_CYCLE = 10
    __RGB1_B_BREATHING_CYCLE = 11
    __RGB2_R_BREATHING_CYCLE = 12
    __RGB2_G_BREATHING_CYCLE = 13
    __RGB2_B_BREATHING_CYCLE = 14
    def __init__(self):
        self.i2c_addr = 0x77
        self.i2c = 1
        self.R1 = 0
        self.G1 = 0
        self.B1 = 0
        self.R2 = 0
        self.G2 = 0
        self.B2 = 0
        self.RGBMode = 0
        self.bus = SMBus(self.i2c)

    def __getattr(self, attr):
        if attr in self.__units:
            return self.__units[attr]
        if attr == "Distance":
            return self.getDistance()
        else:
            raise AttributeError('Unknow attribute : %s'%attr)
    
    #设置灯的模式,0为彩灯模式,1为呼吸灯模式
    def setRGBMode(self, mode):
        try:
            self.bus.write_byte_data(self.i2c_addr, self.__RGB_MODE, mode)
        except:
            print('Sensor not connected!')
    
    #设置灯的颜色
    #参数1:0表示左边的灯,1表示右边
    #参数2:颜色的rgb比例值,以元组形式传入,范围0-255, 依次为r,g,b
    def setRGB(self, index, rgb):
        start_reg = 3 if index == 1 else 6
        try:
            self.bus.write_byte_data(self.i2c_addr, start_reg, rgb[0])
            self.bus.write_byte_data(self.i2c_addr, start_reg+1, rgb[1])
            self.bus.write_byte_data(self.i2c_addr, start_reg+2, rgb[2])
        except:
            print('Sensor not connected!')
    
    #呼吸灯模式
    #参数1:0表示左边的灯,1表示右边
    #参数2:颜色通道, 0表示然,1表示g, 2表示b
    #参数3:颜色变化周期,单位ms
    def setBreathCycle(self, index, rgb, cycle):
        start_reg = 9 if index == 1 else 12
        cycle = int(cycle / 100)
        try:
            self.bus.write_byte_data(self.i2c_addr, start_reg + rgb, cycle)
        except:
            print('Sensor not connected!')

    def startSymphony(self):
        self.setRGBMode(1)
        self.setBreathCycle(1, 0, 2000)
        self.setBreathCycle(1, 1, 3300)
        self.setBreathCycle(1, 2, 4700)
        self.setBreathCycle(0, 0, 4600)
        self.setBreathCycle(0, 1, 2000)
        self.setBreathCycle(0, 2, 3400)

    #获取距离, 单位mm
    def getDistance(self):
        dist = 5000
        try:
            msg = i2c_msg.write(self.i2c_addr, [0,])
            self.bus.i2c_rdwr(msg)
            read = i2c_msg.read(self.i2c_addr, 2)
            self.bus.i2c_rdwr(read)
            dist = int.from_bytes(bytes(list(read)), byteorder='little', signed=False)
            if dist > 5000:
                dist = 5000
        except BaseException as e:
            print('Sensor not connected!', e)
        return dist
Beispiel #35
0
class AXP209(object):

    def __init__(self, bus=0):
        """
        Initialize the AXP209 object
        :param bus: i2c bus number or a SMBus object
        :type bus: Integer or SMBus object
        """

        if isinstance(bus, int):
            self.bus = SMBus(bus, force=True)
            self.autocleanup = True
        else:
            self.bus = bus
            self.autocleanup = False

        # force ADC enable for battery voltage and current
        self.adc_enable1 = 0xc3


    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        if self.autocleanup:
            self.close()

    def close(self):
        self.bus.close()

    @property
    def gpio2_output(self):
        pass

    @gpio2_output.setter
    def gpio2_output(self, val):
        flags = GPIO012_FEATURE_SET_FLAGS()
        if bool(val):
            flags.gpio_function = 0b111
        else:
            flags.gpio_function = 0b000
        self.bus.write_byte_data(AXP209_ADDRESS, GPIO2_FEATURE_SET_REG, flags.asbyte)

    @property
    def adc_enable1(self):
        flags = ADC_ENABLE1_FLAGS()
        flags.asbyte = self.bus.read_byte_data(AXP209_ADDRESS, ADC_ENABLE1_REG)
        return flags

    @adc_enable1.setter
    def adc_enable1(self, flags):
        if hasattr(flags, "asbyte"):
            flags = flags.asbyte
        self.bus.write_byte_data(AXP209_ADDRESS, ADC_ENABLE1_REG, flags)

    @property
    def power_input_status(self):
        flags = POWER_INPUT_STATUS_FLAGS()
        flags.asbyte = self.bus.read_byte_data(AXP209_ADDRESS, POWER_INPUT_STATUS_REG)
        return flags

    @property
    def battery_current_direction(self):
        return bool(self.power_input_status.battery_current_direction)

    @property
    def power_operating_mode(self):
        flags = POWER_OPERATING_STATUS_FLAGS()
        flags.asbyte = self.bus.read_byte_data(AXP209_ADDRESS, POWER_OPERATING_MODE_REG)
        return flags

    @property
    def battery_exists(self):
        return bool(self.power_operating_mode.battery_exists)

    @property
    def battery_charging(self):
        return bool(self.power_operating_mode.battery_charging)

    @property
    def battery_voltage(self):
        """ Returns voltage in mV """
        msb = self.bus.read_byte_data(AXP209_ADDRESS, BATTERY_VOLTAGE_MSB_REG)
        lsb = self.bus.read_byte_data(AXP209_ADDRESS, BATTERY_VOLTAGE_LSB_REG)
        voltage_bin = msb << 4 | lsb & 0x0f
        return voltage_bin * 1.1

    @property
    def battery_charge_current(self):
        """ Returns current in mA """
        msb = self.bus.read_byte_data(AXP209_ADDRESS, BATTERY_CHARGE_CURRENT_MSB_REG)
        lsb = self.bus.read_byte_data(AXP209_ADDRESS, BATTERY_CHARGE_CURRENT_LSB_REG)
        # (12 bits)
        charge_bin = msb << 4 | lsb & 0x0f
        # 0 mV -> 000h,	0.5 mA/bit	FFFh -> 1800 mA
        return charge_bin * 0.5

    @property
    def battery_discharge_current(self):
        """ Returns current in mA """
        msb = self.bus.read_byte_data(AXP209_ADDRESS, BATTERY_DISCHARGE_CURRENT_MSB_REG)
        lsb = self.bus.read_byte_data(AXP209_ADDRESS, BATTERY_DISCHARGE_CURRENT_LSB_REG)
        # 13bits
        discharge_bin = msb << 5 | lsb & 0x1f
        # 0 mV -> 000h,	0.5 mA/bit	1FFFh -> 1800 mA
        return discharge_bin * 0.5

    @property
    def internal_temperature(self):
        """ Returns temperature in celsius C """
        temp_msb = self.bus.read_byte_data(AXP209_ADDRESS, INTERNAL_TEMPERATURE_MSB_REG)
        temp_lsb = self.bus.read_byte_data(AXP209_ADDRESS, INTERNAL_TEMPERATURE_LSB_REG)
        # MSB is 8 bits, LSB is lower 4 bits
        temp = temp_msb << 4 | temp_lsb & 0x0f
        # -144.7c -> 000h,	0.1c/bit	FFFh -> 264.8c
        return temp*0.1-144.7

    @property
    def battery_gauge(self):
        gauge_bin = self.bus.read_byte_data(AXP209_ADDRESS, BATTERY_GAUGE_REG)
        gauge = gauge_bin & 0x7f
        if gauge > 100:
            return -1
        return gauge
Beispiel #36
0
class InputModule(AbstractInput):
    """
    A sensor support class that measures the SHT2x's humidity and temperature
    and calculates the dew point

    """

    def __init__(self, input_dev, testing=False):
        super(InputModule, self).__init__()
        self.logger = logging.getLogger("mycodo.inputs.sht2x")
        self._dew_point = None
        self._humidity = None
        self._temperature = None

        if not testing:
            from smbus2 import SMBus
            self.logger = logging.getLogger(
                "mycodo.sht2x_{id}".format(id=input_dev.unique_id.split('-')[0]))
            self.i2c_address = int(str(input_dev.i2c_location), 16)
            self.i2c_bus = input_dev.i2c_bus
            self.convert_to_unit = input_dev.convert_to_unit
            self.sht2x = SMBus(self.i2c_bus)

    def __repr__(self):
        """  Representation of object """
        return "<{cls}(dewpoint={dpt})(humidity={hum})(temperature={temp})>".format(
            cls=type(self).__name__,
            dpt="{0:.2f}".format(self._dew_point),
            hum="{0:.2f}".format(self._humidity),
            temp="{0:.2f}".format(self._temperature))

    def __str__(self):
        """ Return measurement information """
        return "Dew Point: {dpt}, Humidity: {hum}, Temperature: {temp}".format(
            dpt="{0:.2f}".format(self._dew_point),
            hum="{0:.2f}".format(self._humidity),
            temp="{0:.2f}".format(self._temperature))

    def __iter__(self):  # must return an iterator
        """ SHT2xSensor iterates through live measurement readings """
        return self

    def next(self):
        """ Get next measurement reading """
        if self.read():  # raised an error
            raise StopIteration  # required
        return dict(dewpoint=float('{0:.2f}'.format(self._dew_point)),
                    humidity=float('{0:.2f}'.format(self._humidity)),
                    temperature=float('{0:.2f}'.format(self._temperature)))

    @property
    def dew_point(self):
        """ SHT2x dew point in Celsius """
        if self._dew_point is None:  # update if needed
            self.read()
        return self._dew_point

    @property
    def humidity(self):
        """ SHT2x relative humidity in percent """
        if self._humidity is None:  # update if needed
            self.read()
        return self._humidity

    @property
    def temperature(self):
        """ SHT2x temperature in Celsius """
        if self._temperature is None:  # update if needed
            self.read()
        return self._temperature

    def get_measurement(self):
        """ Gets the humidity and temperature """
        self._dew_point = None
        self._humidity = None
        self._temperature = None

        dew_point = None
        humidity = None
        temperature = None

        for _ in range(2):
            try:
                # Send temperature measurement command
                # 0xF3(243) NO HOLD master
                self.sht2x.write_byte(self.i2c_address, 0xF3)
                time.sleep(0.5)
                # Read data back, 2 bytes
                # Temp MSB, Temp LSB
                data0 = self.sht2x.read_byte(self.i2c_address)
                data1 = self.sht2x.read_byte(self.i2c_address)
                temperature = -46.85 + (((data0 * 256 + data1) * 175.72) / 65536.0)
                # Send humidity measurement command
                # 0xF5(245) NO HOLD master
                self.sht2x.write_byte(self.i2c_address, 0xF5)
                time.sleep(0.5)
                # Read data back, 2 bytes
                # Humidity MSB, Humidity LSB
                data0 = self.sht2x.read_byte(self.i2c_address)
                data1 = self.sht2x.read_byte(self.i2c_address)
                humidity = -6 + (((data0 * 256 + data1) * 125.0) / 65536.0)
                dew_point = calculate_dewpoint(temperature, humidity)
                return dew_point, humidity, temperature
            except Exception as e:
                self.logger.exception(
                    "Exception when taking a reading: {err}".format(err=e))
            # Send soft reset and try a second read
            self.sht2x.write_byte(self.i2c_address, 0xFE)
            time.sleep(0.1)

        dew_point = convert_units(
            'dewpoint', 'C', self.convert_to_unit, dew_point)

        temperature = convert_units(
            'temperature', 'C', self.convert_to_unit, temperature)

        humidity = convert_units(
            'humidity', 'percent', self.convert_to_unit,
            humidity)

        return dew_point, humidity, temperature

    def read(self):
        """
        Takes a reading from the SHT2x and updates the self.dew_point,
        self._humidity, and self._temperature values

        :returns: None on success or 1 on error
        """
        try:
            (self._dew_point,
             self._humidity,
             self._temperature) = self.get_measurement()
            if self._dew_point is not None:
                return  # success - no errors
        except Exception as e:
            self.logger.exception(
                "{cls} raised an exception when taking a reading: "
                "{err}".format(cls=type(self).__name__, err=e))
        return 1
Beispiel #37
0
"""
@author: root
"""

import time
from smbus2 import SMBus 

tgtAddress = 0x0B
voltcmd = 0x09

def printHex(data):
    hexChar = ''
    for val in data:
        hexChar += format('0x%02x ' % val) 

commObj = SMBus(2)
if commObj == None:
    print('Not able to open driver')
    quit()


for i in range(200): 
    b = commObj.read_word_data(tgtAddress, voltcmd)
    #print('Byte Word: ', b)

    commObj.write_i2c_block_data(tgtAddress, 0x44, [2,0])
    verString = commObj.read_i2c_block_data(tgtAddress, 0x44, 13)
    print('Result ', verString)

commObj.close()
Beispiel #38
0
 def __init__(self, motorsList):
     self.motors = motorsList
     self.motorCount = 0
     self.bus = SMBus(1)
Beispiel #39
0
 def test_func(self):
     bus = SMBus(1)
     print("\nSupported I2C functionality: %x" % bus.funcs)
     bus.close()
Beispiel #40
0
def set_eon_fan(val):
  global last_eon_fan_val

  if last_eon_fan_val is None or last_eon_fan_val != val:
    bus = SMBus(7, force=True)
    try:
      i = [0x1, 0x3 | 0, 0x3 | 0x08, 0x3 | 0x10][val]
      bus.write_i2c_block_data(0x3d, 0, [i])
    except IOError:
      # tusb320
      if val == 0:
        bus.write_i2c_block_data(0x67, 0xa, [0])
      else:
        bus.write_i2c_block_data(0x67, 0xa, [0x20])
        bus.write_i2c_block_data(0x67, 0x8, [(val - 1) << 6])
    bus.close()
    last_eon_fan_val = val
Beispiel #41
0
class MPL3115A2:
    def __init__(self, bus, addr, alt):
        self.addr = addr
        self.alt = alt
        self.bus = SMBus(bus)
        self.init()

    # Initialise the MPL3115A2
    def init(self):
        self.reset()
        self.w_pt_data_cfg(drem=1, pdefe=0, tdefe=0)
        self.w_ctrl_reg1(alt=self.alt, os=1, sbyb=1)
        self.r_ctrl_reg1()
        self.r_ctrl_reg2()

    # Reset device
    def reset(self):
        # Reset by writing to CTRL2
        try:
            self.bus.write_byte_data(self.addr, 0x26, 0x04)
        except:
            print("MPL3115A2 SMBus reset on device reset, please wait...")

        time.sleep(1)
        self.r_ctrl_reg1()
        self.r_ctrl_reg2()

    # Write data config register
    def w_pt_data_cfg(self, drem=0, pdefe=0, tdefe=0):
        # Parse
        data = ((drem & 0x1) << 2) + ((pdefe & 0x1) << 1) + (
            (tdefe & 0x1) << 0)
        # Debug
        print("MPL3115A2 PT_DATA_CFG: 0x%02X" % data)
        # Write to device
        self.bus.write_byte_data(self.addr, 0x13, data)

    # Write control register 1
    def w_ctrl_reg1(self, alt=0, os=0, ost=0, sbyb=0):
        # Parse
        data = ((alt & 0x1) << 7) + ((os & 0x7) << 3) + ((ost & 0x1) << 1) + (
            (sbyb & 0x1) << 0)
        # Debug
        print("MPL3115A2 CTRL1: 0x%02X" % data)
        # Write to device
        self.bus.write_byte_data(self.addr, 0x26, data)

    # Write control register 2
    def w_ctrl_reg2(self, load=0, alarm=0, st=0):
        # Parse
        data = ((load & 0x1) << 5) + ((alarm & 0x1) << 4) + ((st & 0xF) << 0)
        # Debug
        print("MPL3115A2 CTRL2: 0x%02X" % data)
        # Write to device
        self.bus.write_byte_data(self.addr, 0x27, data)

    # Read pressure from device
    def p_read(self):
        # Read data from device
        data = self.bus.read_i2c_block_data(self.addr, 0x01, 3)
        # Is alt mode or pressure
        if (self.alt):
            print("MPL3115A2 Compute altitude")
            # Parse
            aint = ((data[0] & 0x7F) << 8) + ((data[1] & 0xFF) << 0)
            sign = (data[0] & 0x80)
            afrc = ((data[2] & 0xF0) >> 4)
            alt = 0.0
            if (sign):
                alt -= 2**16
            alt += aint
            alt += (afrc * 0.0625)
            print("MPL3115A2 Altitude: %.4f" % alt)
            # Return
            return "{:.2f}".format(round(alt, 2))

        else:
            print("MPL3115A2 Compute pressure")
            # Parse
            pint = ((data[0] & 0xFF) << 10) + ((data[1] & 0xFF) << 2) + (
                (data[2] & 0xC0) >> 6)
            pfrc = ((data[2] & 0x30) >> 4)
            p = pint + (pfrc * 0.25)
            hPa = p / 100
            print("MPL3115A2 Pressure: %.2f" % p)
            # Return
            return "{:.2f}".format(round(hPa, 2))

    # Read temperature data
    def t_read(self):
        self.r_ctrl_reg1()
        self.r_ctrl_reg2()
        self.r_dr_status()
        # Read data from device
        data = self.bus.read_i2c_block_data(self.addr, 0x04, 2)
        # Parse
        temp = 0.0
        tint = ((data[0] & 0x7F) << 0)
        tfrc = ((data[1] & 0xF0) >> 4)
        sign = (data[0] & 0x80)
        # Compute
        if (sign):
            temp -= 128
        temp += tint
        temp += (tfrc * 0.0625)
        print("MPL3115A2 Temp: %.4f" % temp)
        # Return
        return "{:.2f}".format(round(temp, 2))

    # Read data config register
    def r_pt_data_cfg(self):
        # Read byte from device
        data = self.bus.read_byte_data(self.addr, 0x13)
        # Parse
        drem = ((data & 0x04) >> 2)
        pdefe = ((data & 0x02) >> 1)
        tdefe = ((data & 0x01) >> 0)
        # Debug
        print("MPL3115A2 DREM: 0x%02X, PDEFE: 0x%02X, TDEFE: 0x%02X" %
              (drem, pdefe, tdefe))
        # Return
        return drem, pdefe, tdefe

    # Read sensor status register
    def r_dr_status(self):
        # Read byte from device
        data = self.bus.read_byte_data(self.addr, 0x07)
        # Parse
        ptow = ((data & 0x80) >> 7)
        poww = ((data & 0x40) >> 6)
        tow = ((data & 0x20) >> 5)
        ptdr = ((data & 0x08) >> 3)
        pdr = ((data & 0x04) >> 2)
        tdr = ((data & 0x02) >> 1)
        # Debug
        print(
            "MPL3115A2 PTOW: 0x%02X, POW: 0x%02X, TOW: 0x%02X, PTDR: 0x%02X, PDR: 0x%02X, TDR: 0x%02X"
            % (ptow, poww, tow, ptdr, pdr, tdr))
        # Return
        return ptow, poww, tow, ptdr, pdr, tdr

    # Read control register 1
    def r_ctrl_reg1(self):
        # Read byte from device
        data = self.bus.read_byte_data(self.addr, 0x26)
        # Parse
        alt = ((data & 0x80) >> 7)
        os = ((data & 0x38) >> 3)
        rst = ((data & 0x04) >> 2)
        ost = ((data & 0x02) >> 1)
        sbyb = ((data & 0x01) >> 0)
        # Debug
        print(
            "MPL3115A2 ALT: 0x%02X, OS: 0x%02X, RST: 0x%02X, OST: 0x%02X, SBYB: 0x%02X"
            % (alt, os, rst, ost, sbyb))
        # Return
        return alt, os, rst, ost, sbyb

    # Read control register 2
    def r_ctrl_reg2(self):
        # Read byte from device
        data = self.bus.read_byte_data(self.addr, 0x27)
        # Parse
        load = ((data & 0x20) >> 5)
        alarm = ((data & 0x10) >> 4)
        st = ((data & 0x0F) >> 0)
        # Debug
        print("MPL3115A2 LOAD: 0x%02X, ALARM: 0x%02X, ST: 0x%02X" %
              (load, alarm, st))
        # Return
        return load, alarm, st
Beispiel #42
0
class InputModule(AbstractInput):
    """ A sensor support class that monitors the DS18B20's lux """
    def __init__(self, input_dev, testing=False):
        super(InputModule, self).__init__(input_dev, testing=testing, name=__name__)

        self.i2c_address = None
        self.i2c_bus = None
        self.resolution = None

        if not testing:
            self.initialize_input()

    def initialize_input(self):
        from smbus2 import SMBus

        self.i2c_address = int(str(self.input_dev.i2c_location), 16)
        self.resolution = self.input_dev.resolution
        self.i2c_bus = SMBus(self.input_dev.i2c_bus)
        self.power_down()
        self.set_sensitivity(sensitivity=self.input_dev.sensitivity)

    @property
    def lux(self):
        """ BH1750 luminosity in lux """
        if self._measurements is None:  # update if needed
            self.read()
        return self._measurements

    def get_measurement(self):
        """ Gets the BH1750's lux """
        self.return_dict = copy.deepcopy(measurements_dict)

        if self.resolution == 0:
            lux = self.measure_low_res()
        elif self.resolution == 1:
            lux = self.measure_high_res()
        elif self.resolution == 2:
            lux = self.measure_high_res2()
        else:
            return None

        self.value_set(0, lux)

        return self.return_dict

    def _set_mode(self, mode):
        self.mode = mode
        self.i2c_bus.write_byte(self.i2c_address, self.mode)

    def power_down(self):
        self._set_mode(POWER_DOWN)

    def power_on(self):
        self._set_mode(POWER_ON)

    def reset(self):
        self.power_on()  # It has to be powered on before resetting
        self._set_mode(RESET)

    def cont_low_res(self):
        self._set_mode(CONTINUOUS_LOW_RES_MODE)

    def cont_high_res(self):
        self._set_mode(CONTINUOUS_HIGH_RES_MODE_1)

    def cont_high_res2(self):
        self._set_mode(CONTINUOUS_HIGH_RES_MODE_2)

    def oneshot_low_res(self):
        self._set_mode(ONE_TIME_LOW_RES_MODE)

    def oneshot_high_res(self):
        self._set_mode(ONE_TIME_HIGH_RES_MODE_1)

    def oneshot_high_res2(self):
        self._set_mode(ONE_TIME_HIGH_RES_MODE_2)

    def set_sensitivity(self, sensitivity=69):
        """
        Set the sensor sensitivity.
        Valid values are 31 (lowest) to 254 (highest), default is 69.
        """
        if sensitivity < 31:
            self.mtreg = 31
        elif sensitivity > 254:
            self.mtreg = 254
        else:
            self.mtreg = sensitivity
        self.power_on()
        self._set_mode(0x40 | (self.mtreg >> 5))
        self._set_mode(0x60 | (self.mtreg & 0x1f))
        self.power_down()

    def get_result(self):
        """ Return current measurement result in lx. """
        data = self.i2c_bus.read_word_data(self.i2c_address, self.mode)
        count = data >> 8 | (data & 0xff) << 8
        mode2coeff = 2 if (self.mode & 0x03) == 0x01 else 1
        ratio = 1 / (1.2 * (self.mtreg / 69.0) * mode2coeff)
        return ratio * count

    def wait_for_result(self, additional=0):
        basetime = 0.018 if (self.mode & 0x03) == 0x03 else 0.128
        time.sleep(basetime * (self.mtreg / 69.0) + additional)

    def do_measurement(self, mode, additional_delay=0):
        """
        Perform complete measurement using command specified by parameter
        mode with additional delay specified in parameter additional_delay.
        Return output value in Lx.
        """
        self.reset()
        self._set_mode(mode)
        self.wait_for_result(additional=additional_delay)
        return self.get_result()

    def measure_low_res(self, additional_delay=0):
        return self.do_measurement(ONE_TIME_LOW_RES_MODE, additional_delay)

    def measure_high_res(self, additional_delay=0):
        return self.do_measurement(ONE_TIME_HIGH_RES_MODE_1, additional_delay)

    def measure_high_res2(self, additional_delay=0):
        return self.do_measurement(ONE_TIME_HIGH_RES_MODE_2, additional_delay)