Esempio n. 1
0
class Motors:
    def __init__(self, motorsList):
        self.motors = motorsList
        self.motorCount = 0
        self.bus = SMBus(1)

    def start_motor(self):
        if self.motorCount < self.motors.count:
            self.bus.write_byte(self.motors[self.motorCount], 0x01)

    def add_counter(self):
        if self.motorCount < len(self.motors) - 1:
            self.motorCount += 1
        else:
            self.motorCount = 0

    def read_motor_info(self):
        b = self.bus.read_byte(self.motors[self.motorCount])
        return b

    def set_status_counter(self):
        self.bus.write_byte(self.motors[self.motorCount], 0x02)

    def set_status_sensor(self):
        self.bus.write_byte(self.motors[self.motorCount], 0x03)

    def set_status_reset(self):
        self.bus.write_byte(self.motors[self.motorCount], 0x09)

    def get_actual_status(self):
        b = self.bus.read_byte(self.motors[self.motorCount])
        return b
Esempio n. 2
0
def scan(bus_num, start=0x03, end=0x78):
    try:
        bus = SMBus(bus_num)
    except PermissionError:
        print("Permission error!")
        sys.exit()

    print("I2C bus       : " + str(bus_num))
    print("Start address : " + hex(start))
    print("End address   : " + hex(end) + "\n")

    for i in range(start, end):
        val = 1
        try:
            bus.read_byte(i)
        except OSError as e:
            val = e.args[0]
        finally:
            if val != 5:  # No device
                if val == 1:
                    res = "Available"
                elif val == 16:
                    res = "Busy"
                elif val == 110:
                    res = "Timeout"
                else:
                    res = "Error code: " + str(val)
                print(hex(i) + " -> " + res)
Esempio n. 3
0
def i2cdetect(bus_num):
    b = SMBus(bus_num)
    devs = []
    for a in range(0xff):
        try:
            b.read_byte(a)
            devs.append(hex(a))
        except IOError:
            pass
    return devs
Esempio n. 4
0
def scan() -> List[str]:
    devices = []
    try:
        bus = SMBus(1)  # 1 indicates /dev/i2c-1
        for device in range(128):
            try:
                bus.read_byte(device)
                devices.append(hex(device))
            except:
                pass
    except FileNotFoundError as e:
        print("WARNING: I2C seems not to be activated")
    return devices
Esempio n. 5
0
class Si7021Sensor:
    def __init__(self):
        self._bus = SMBus(1)
        self._address = 0x40

    def __del__(self):
        self._bus.close()

    def _send_command(self, command_code):
        self._bus.write_byte(self._address, command_code)
        time.sleep(0.3)

    def _read_data(self):
        data0 = self._bus.read_byte(self._address)
        data1 = self._bus.read_byte(self._address)
        time.sleep(0.3)
        return data0, data1

    def humidity(self):
        """
        :return: relative humidity in percent.
        """
        self._send_command(0xF5)
        data0, data1 = self._read_data()
        humidity = ((data0 * 256 + data1) * 125 / 65536.0) - 6
        return humidity

    def temperature(self):
        """
        :return: temperature in celsius degrees.
        """
        self._send_command(0xF3)
        data0, data1 = self._read_data()
        cels_temp = ((data0 * 256 + data1) * 175.72 / 65536.0) - 46.85
        return cels_temp
class i2c_device:
	def __init__(self, addr, port=I2CBUS):
		self.addr = addr
		self.bus = SMBus(port)

	# Write a single command
	def write_cmd(self, cmd):
		self.bus.write_byte(self.addr, cmd)
		sleep(0.0001)

	# Write a command and argument
	def write_cmd_arg(self, cmd, data):
		self.bus.write_byte_data(self.addr, cmd, data)
		sleep(0.0001)

	# Write a block of data
	def write_block_data(self, cmd, data):
		self.bus.write_block_data(self.addr, cmd, data)
		sleep(0.0001)

	# Read a single byte
	def read(self):
		return self.bus.read_byte(self.addr)

	# Read
	def read_data(self, cmd):
		return self.bus.read_byte_data(self.addr, cmd)

	# Read a block of data
	def read_block_data(self, cmd):
		return self.bus.read_block_data(self.addr, cmd)
Esempio n. 7
0
def start_RFID():
    global current_rfid
    global prev_rfid
    bus = SMBus(0)
    time.sleep(1)
    ok = True
    id = ""
    while True:

        try:
            gled.value = False
            print("reading...")
            start = time.time()
            b = bus.read_byte(0x41)

            id += chr(b)
            print("read", chr(b))
            if (len(id)) % 2 == 1:
                gled.value = True
            else:
                gled.value = False

            if ok == False and len(id) == 15 or len(id) == 16:
                rfid = id[-8:]
                id = ""
                ok = True
                lock.acquire()
                current_rfid = rfid
                lock.release()
                gled.value = True
                time.sleep(3)
                print("RFID Scanned: ", rfid, id)
            elif len(id) == 16:
                rfid = id[-8:]
                lock.acquire()
                current_rfid = rfid
                lock.release()
                id = ""
                ok = True
                gled.value = True
                time.sleep(3)
                print("RFID Scanned: ", rfid)

        except Exception as e:
            print(e)
            end = time.time()
            #print(end-start)
            if (end - start > 2):
                print("resetting prev_rfid")
                lock.acquire()
                prev_rfid = ""
                current_rfid = ""
                lock.release()
            ok = False
            continue
Esempio n. 8
0
def scan_i2c_bus():
        bus = SMBus(1)
        L = []
        for i in range(3,127):
                try:
                        b = bus.read_byte(i)
                        L.append(i)
                except IOError:
                        continue

        bus.close()
        return L
Esempio n. 9
0
def main(argv):
    print("Hello world!")

    bus = SMBus(1)

    for i in range(0, 128, 16):
        vals = []
        for j in range(0, 16):
            res = True
            try:
                k = i + j
                if (k >= 0x30 and k <= 0x37) or (k >= 0x50 and k <= 0x5f):
                    bus.read_byte(i + j)
                else:
                    bus.write_byte(i + j, 0)
            except Exception as e:
                res = False
            if res:
                vals.append("{}: {:3}".format(j, i + j))
            else:
                vals.append("{}: ---".format(j))
        print("{:3}".format(i), ", ".join(vals))
Esempio n. 10
0
class VCNL4010:
    """Vishay VCNL4010 proximity and ambient light sensor."""
    def __init__(self):
        self._device = SMBus(1)
        self.led_current = 20
        self.frequency = FREQUENCY_390K625
        self.write(_VCNL4010_INTCONTROL, 0x08)

    def read(self, address):
        # Read an 8-bit unsigned value from the specified 8-bit address.
        with SMBus(1) as self._device:
            read = self._device.read_byte_data(_VCNL4010_I2CADDR_DEFAULT,
                                               address)
        return read

    def write(self, address, val):
        # Write an 8-bit unsigned value to the specified 8-bit address.
        with SMBus(1) as self._device:
            self._device.write_byte_data(_VCNL4010_I2CADDR_DEFAULT, address,
                                         val)

    def read_16(self, address):
        with SMBus(1) as self._device:
            read_block = self._device.read_i2c_block_data(
                _VCNL4010_I2CADDR_DEFAULT, address, 2)
        return (read_block[0] << 8) | read_block[1]

    def read_byte(self, address):
        with SMBus(1) as self._device:
            read = self._device.read_byte(address)

    @property
    def proximity(self):
        """The detected proximity of an object in front of the sensor.  This
        is a unit-less unsigned 16-bit value (0-65535) INVERSELY proportional
        to the distance of an object in front of the sensor (up to a max of
        ~200mm).  For example a value of 10 is an object farther away than a
        value of 1000.  Note there is no conversion from this value to absolute
        distance possible, you can only make relative comparisons.
        """
        # Clear interrupt.
        status = self.read(_VCNL4010_INTSTAT)
        status &= ~0x80
        self.write(_VCNL4010_INTSTAT, status)
        # Grab a proximity measurement.
        self.write(_VCNL4010_COMMAND, _VCNL4010_MEASUREPROXIMITY)
        # Wait for result, then read and return the 16-bit value.
        while True:
            result = self.read(_VCNL4010_COMMAND)
            if result & _VCNL4010_PROXIMITYREADY:
                return self.read(_VCNL4010_PROXIMITYDATA)
def main():

    # Initialize I2C (SMBus)
    bus = SMBus(1)
    arduino_addr = 0x7f

    arduino_status = -1

    while arduino_status < 255:

        try:
            print("Requesting status: ", end='')
            arduino_status = bus.read_byte(arduino_addr)
            #print(type(bus.read_byte(arduino_addr)))
        except OSError:
            print("OSError: Failed to read from specified peripheral")

        print("status:", arduino_status)
        sleep(.05)  # Take a picture
Esempio n. 12
0
class WiiController:
    def __init__(self, delay=0.05):
        self.delay = delay
        if rpi.RPI_REVISION == 1:
            i2c_bus = 0
        elif rpi.RPI_REVISION == 2:
            i2c_bus = 1
        elif rpi.RPI_REVISION == 3:
            i2c_bus = 1
        else:
            raise OSError("Unable to determine Raspberry Pi revision.")
        self.bus = SMBus(i2c_bus)
        self.bus.write_byte_data(0x52, 0x40, 0x00)
        time.sleep(0.1)

    @cached(TTLCache(maxsize=1, ttl=0.0166))
    def read(self):
        self.bus.write_byte(0x52, 0x00)
        time.sleep(self.delay)
        return [(0x17 + (0x17 ^ self.bus.read_byte(0x52))) % 256
                for _ in range(6)]
Esempio n. 13
0
class PCF8754:
    def __init__(self, address, busnum=1):
        self._address = address
        self._i2c = SMBus(busnum)
        self._access_error = False

    def set_out(self, output):
        try:
            self._i2c.write_byte(self._address, (~output & 0xFF))
            self._access_error = False

        except OSError:
            if not self._access_error:
                self._access_error = True
                log.warning('I2C device at address ' +
                            str(hex(self._address)) +
                            ' could not be accessed.')
                # print('I2C device at address ' + str(hex(self._address)) + ' could not be accessed.')

        return self._access_error

    def get_out(self):
        try:
            value = ~self._i2c.read_byte(self._address) & 0xFF
            self._access_error = False

        except OSError:
            if not self._access_error:
                self._access_error = True
                log.warning('I2C device at address ' +
                            str(hex(self._address)) +
                            ' could not be accessed.')
                # print('I2C device at address ' + str(hex(self._address)) + ' could not be accessed.')
            value = 0x00

        return value, self._access_error
Esempio n. 14
0
#_READ_USER1 = const(0xE7)
#_USER1_VAL = const(0x3A)


#with SMBus(1) as bus:
#    # Write a byte to address 80, offset 0
#    print("immabus")
#    bus.write_byte_data(HTU21D_ADDR, 0, resetbin)
    
# Open i2c bus 1 and read one byte from address 80, offset 0
bus = SMBus(1)

#b = bus.read_byte_data(40, 0)
#print(b)
#bus.close()

for device in range(254):
      try:
         bus.read_byte(device)
         print(hex(device))
      except: # exception if read_byte fails
         pass


#b = bus.write_byte_data(64, 1)
#bus.write_byte_data(80, 0, data)
#print(b)
#bus.close()

Esempio n. 15
0
from utils import bytes_to_str

addr = 0x9  # bus address
bus = SMBus(1)  # indicates /dev/ic2-1

bus.write_byte(addr, 0)
bus.write_byte(addr, 0)

time.sleep(.1)
estimated_value = 1

while True:
    # data = bus.read_word_data(addr,0)
    data = bus.read_i2c_block_data(addr, 1, 2)

    b1 = bus.read_byte(addr)
    b2 = bus.read_byte(addr)

    # val = struct.unpack('h', b1 + b2)[0]
    val = b2 + (b1 << 8)
    s = bytes_to_str(b1, b2)

    print(s + " | " + str(val) + " | " + str(estimated_value))
    assert (estimated_value == val)
    estimated_value += 1
    # data = bus.read_i2c_block_data(addr, 0, 1)
    time.sleep(.01)

# bus.write_byte(addr, 0x1) # switch it on
# input("Press return to exit")
# bus.write_byte(addr, 0x0) # switch it on
import time
from smbus2 import SMBus

address = 0x48
A0 = 0x40
A1 = 0x41
A2 = 0x42
A3 = 0x43

bus = SMBus(1)

while True:
    bus.write_byte(address, A0)
    value = bus.read_byte(address)
    if (value < 3):
        print("- No Pressure")
    elif (value < 50):
        print("- Light Touch")
    elif (value < 125):
        print("- Light Squeeze")
    elif (value < 200):
        print("- Meduim Squeeze")
    else:
        print("- Big Squeeze")
    time.sleep(1)
Esempio n. 17
0
def adcReadInit(bus, i2c_addr, slave_addr, adc_ch):
    '''Reads data from ADC.
    \nbus -> SMBus object
    \ni2c_addr -> hex adress of i2c connection (i.e. 0x12)
    \nslave_addr -> configuration of A0-A2 in string form (i.e. '010')
    \nadc_ch -> channel where adc is connected (0-3)'''

    addr_byte = '0b1001' + slave_addr + '1'
    addr_byte = int(addr_byte, 2)
    control_byte = adc_ch

    bus.write_byte(i2c_addr, addr_byte)
    bus.write_byte(i2c_addr, control_byte)


def getSample(bus, i2c_addr):
    return bus.read_byte(i2c_addr)


bus = SMBus(1)
adcReadInit(bus, 0X48, '000', 0)
samples = []

s = timer()
i = 0
while timer() - s < 1:
    sample = bus.read_byte(0x48)
    i += 1
    #print("Input level: %s" % sample)

print(i)
Esempio n. 18
0
def I2C_setup(i2c_bus, i2c_address, i2c_channel_setup):
    address = 0x70 + i2c_address % 10
    bus = SMBus(i2c_bus)
    bus.write_byte(address, i2c_channel_setup)
    time.sleep(0.1)
    print("TCA9548A I2C channel status:{}".format(bin(bus.read_byte(address))))
Esempio n. 19
0
from smbus2 import SMBus

bus = SMBus(1)

ADDRESS = 0x19

bus.write_byte(ADDRESS, 0xaa)
b = bus.read_byte(ADDRESS)
assert b == 0xaa

print("Read byte and write byte OK")

b = bus.read_byte_data(ADDRESS, 1)
assert b == 0xaa

print("Read byte data@1 OK")

bus.write_byte_data(ADDRESS, 4, 0x44)
b = bus.read_byte_data(ADDRESS, 1)
assert b == 0x44
print("Write byte data@4 OK")

bus.write_byte_data(ADDRESS, 5, 0x55)
b = bus.read_byte_data(ADDRESS, 2)
assert b == 0x55
print("Write byte data@5 OK")

bus.write_byte_data(ADDRESS, 6, 0x66)
b = bus.read_byte_data(ADDRESS, 3)
assert b == 0x66
print("Write byte data@6 OK")
Esempio n. 20
0
class PilotSensors(object):
    # _rss_feed_src = './habrahabr.xml'
    # _rss_refrash_int = 60 # in seconds
    _rss_refrash_int = 300  # in seconds
    _alarms = PilotAlarms()
    _alarm_proc = None
    _alarm_in_reproduction = Value(c_bool, False)

    _photores_approx_arr = []
    _photores_DEV_ADDR = 0x48
    _adc_channels = {
        'AIN0': 0b1000000,  # 0x40 (photo-resistor)
        'AIN1': 0b1000001,  # 0x41 (not connected)
        'AIN2': 0b1000010,  # 0x42 (not connected)
        'AIN3': 0b1000011,  # 0x43 (not connected)
    }
    _dac_channel = 0b1000000  # 0x40

    _therm_sensors_base_dir = '/sys/devices/w1_bus_master1'
    _therm_sensor_ids = [
        '000001ac0d2d',  # Indoor sensor ID
        '000001ac5f3a'
    ]  # Outdoor sensor ID

    def __init__(self):
        if os.name == 'nt':
            self._devel = True
        else:
            self._devel = False
            self._bus = SMBus(1)  # 1 for RPi model B rev.2

        # Starting photoresistor process
        self._photores_proc_enable = Value(c_bool, True)
        self._photores_proc_val = Value(c_int, 0xFF)
        self._photores_proc = Process(target=self.lightProc,
                                      args=(self._photores_proc_enable,
                                            self._photores_proc_val, 20))
        self._photores_proc.start()

        # Starting RSS feed reader process
        self._rss_proc_enable = Value(c_bool, True)
        self._rss_proc_feed_src = MpArray(c_char, bytearray(255))
        self._rss_proc_feed_src.value = 'https://news.yandex.ru/index.rss'.encode(
            'cp1251')
        self._rss_proc_val = MpArray(c_char, bytearray(255))
        self._rss_proc = Process(
            target=self.rssProc,
            args=(self._rss_proc_enable, self._rss_proc_feed_src,
                  self._rss_proc_val, self._rss_refrash_int))
        self._rss_proc.start()

        # Starting DS18B20 thermosensors process
        self._therm_proc_enable = Value(c_bool, True)
        init_temps = [float(-99) for _ in range(len(self._therm_sensor_ids))]
        self._therm_proc_val = MpArray(c_double, init_temps)
        self._therm_proc = Process(target=self.thermProc,
                                   args=(self._therm_proc_enable,
                                         self._therm_proc_val, 60))
        self._therm_proc.start()

    def stopSensors(self):
        """
        The method of stopping all processes of sensors
        :return:
        """
        print('Stop sensors...')
        if self._alarm_proc is not None and self._alarm_proc.pid is not None and self._alarm_proc.is_alive(
        ):
            self._alarm_proc.terminate()
        self._photores_proc_enable.value = False
        self._photores_proc.join()
        self._rss_proc.terminate()
        self._therm_proc_enable.value = False
        self._therm_proc.join()

    def alarm(self, atype='click'):
        """
        Method for starting process of sound reproduction
        :param atype: Sets type of sound to play
        :return:
        """
        atype = atype.lower() if type(atype) == str else 'click'
        if self._alarm_proc is not None and self._alarm_proc.pid is not None and self._alarm_proc.is_alive(
        ):
            self._alarm_proc.terminate()
        if atype == 'click':
            self._alarm_proc = Process(target=self._alarms.click,
                                       args=(self._alarm_in_reproduction, ))
        elif atype == 'config_accept':
            self._alarm_proc = Process(target=self._alarms.configAccept,
                                       args=(self._alarm_in_reproduction, ))
        elif atype == 'config_fail':
            self._alarm_proc = Process(target=self._alarms.configFail,
                                       args=(self._alarm_in_reproduction, ))
        elif atype == 'alarm1':
            self._alarm_proc = Process(target=self._alarms.clockAlarm,
                                       args=(self._alarm_in_reproduction, 1))
        elif atype == 'alarm2':
            self._alarm_proc = Process(target=self._alarms.clockAlarm,
                                       args=(self._alarm_in_reproduction, 2))
        if self._alarm_proc.pid is None:
            self._alarm_proc.start()

    def alarmInReproduction(self):
        """
        Method for get current state of sound reproduction flag
        :return: Current state of sound reproduction
        """
        return self._alarm_in_reproduction.value

    def getLight(self):
        """
        Method of obtaining the current value of light intensity
        :return: Integer value in range from 0 to 255
        """
        return self._photores_proc_val.value

    def lightProc(self, proc_enable, proc_val, approx_length=20):
        """
        Code of the logic for reading the ADC data to determine the light intensity
        :param proc_enable: Continued polling cycle flag
        :param proc_val: The communication variable with the main process for returning the value read from the ADC
        :param approx_length: Parameter specifying the number of values for obtaining the mean value of illumination in a time interval
        :return:
        """
        while proc_enable.value:
            if self._devel:
                proc_val.value = 255
            else:
                self._bus.write_byte(self._photores_DEV_ADDR,
                                     self._adc_channels['AIN0'])
                self._photores_approx_arr.append(
                    self._bus.read_byte(self._photores_DEV_ADDR))
                alen = len(self._photores_approx_arr)
                approx_val = sum(self._photores_approx_arr) / alen
                if alen > approx_length:
                    self._photores_approx_arr = self._photores_approx_arr[
                        alen - approx_length:]
                proc_val.value = 255 - int(approx_val)
            time.sleep(0.1)

    def getRSSFeedSource(self):
        """
        Method for get current value of RSS feed source variable
        :return: RSS feed URL
        """
        return self._rss_proc_feed_src.value.decode('cp1251')

    def setRSSFeedSource(self, url):
        """
        Method to set current value of RSS feed source variable
        :param url: RSS feed URL
        :return:
        """
        self._rss_proc_feed_src.value = url.encode(
            'cp1251') if type(url) is str else self._rss_proc_feed_src.value

    def getLastFeed(self):
        """
        The method of obtaining the last title name of a record from RSS feed
        :return: Last title name of a RSS feed
        """
        return self._rss_proc_val.value.decode('iso8859-5')

    def rssProc(self,
                proc_enable,
                rss_proc_feed_src,
                proc_val,
                get_inerval=300):
        """
        Code of the logic for reading data from RSS feed channel
        :param proc_enable: Continued polling cycle flag
        :param rss_proc_feed_src: The communication variable with the main process for get/set the value RSS-channel source URL
        :param proc_val: The communication variable with the main process for returning the value read RSS-channel
        :param get_inerval: Sets the polling time interval
        :return:
        """
        time.sleep(5)  # Starting delay for accepting configuration
        interval = 0
        replace_map = [('«', '"'), ('»', '"'), ('–', '-'), ('—', '-')]
        while proc_enable.value:
            if interval == 0:
                feed = feedparser.parse(
                    rss_proc_feed_src.value.decode('cp1251'))
                feed_len = len(feed['entries'])
                if feed_len > 0:
                    last_rec_title = str(feed['entries'][0]['title']).replace(
                        '«', '"')
                    for rep in replace_map:
                        last_rec_title = last_rec_title.replace(rep[0], rep[1])
                    proc_val.value = bytes(last_rec_title[:255],
                                           encoding='iso8859-5',
                                           errors='replace')
                else:
                    proc_val.value = bytes(
                        'А новостей на сегодня больше нет... или накрылся интернет :-(',
                        encoding='iso8859-5',
                        errors='replace')
            interval = interval + 1 if interval <= get_inerval else 0
            time.sleep(1)

    def getTherms(self):
        """
        The method of obtaining the list of values containing data from thermal sensors
        :return: list of float values temperature
        """
        return [t for t in self._therm_proc_val]

    def thermProc(self, proc_enable, proc_val, get_interval=60):
        """
        Code of the logic for obtaining data from thermal sensors
        :param proc_enable: Continued polling cycle flag
        :param proc_val: The communication variable with the main process for returning the value obtained from thermal sensors
        :param get_interval: Sets the polling time interval
        :return:
        """
        interval = 0
        s_paths = [
            self._therm_sensors_base_dir + '/28-' + sid + '/w1_slave'
            for sid in self._therm_sensor_ids
        ]
        while proc_enable.value:
            if interval == 0:
                for i, sensor in enumerate(s_paths):
                    if os.path.exists(sensor):
                        try:
                            with open(sensor, "r") as t_file:
                                tdata = t_file.readlines()
                                if tdata[0].strip()[-4:].strip() == "YES":
                                    proc_val[i] = float(
                                        tdata[1].split('=')[1]) / 1000
                        except IOError:
                            pass
            interval = interval + 1 if interval <= get_interval else 0
            time.sleep(1)
Esempio n. 21
0
class Pca9546a():
    def __init__(self, address):
        """Init smbus channel and Pca9546 driver on specified address."""
        try:
            self.i2c_bus = SMBus(I2C_CHANNEL)
            self.i2c_address = address  # whatever we see on RPi
            if self.read_config_register() is None:
                raise ValueError
        except ValueError:
            log.error("Pca9546 ERROR: No device found on address {}!".format(
                hex(address)))
            self.i2c_bus = None
        except:
            log.error(
                "Bus on channel {} is not available. Error raised by Pca9546.".
                format(I2C_CHANNEL))
            log.info("Available busses are listed as /dev/i2c*")
            self.i2c_bus = None

    def __del__(self):
        """Driver destructor."""
        self.i2c_bus = None

    def read_config_register(self):
        try:
            return self.i2c_bus.read_byte(self.i2c_address)
        except Exception as e:
            log.error(
                f"An exception occured when trying to read config register: {e}"
            )
            return None

    def select_channel(self, val=None, ch0=0, ch1=0, ch2=0, ch3=0):
        """
        Set internal register to desired combination of channels.
        """

        if type(val) is not int:
            log.error(f"Input value must be an integer!")
            return False

        if val < 0 or val > 15:
            log.error(
                f"Specified channel configuration must be between 0000 (0 dec) and 1111 (15 dec)"
            )
            return False

        if ch0 < 0 or ch0 > 1:
            log.error(f"Channel 0 must be set to either 0 or 1")
            return False

        if ch1 < 0 or ch1 > 1:
            log.error(f"Channel 1 must be set to either 0 or 1")
            return False

        if ch2 < 0 or ch2 > 1:
            log.error(f"Channel 2 must be set to either 0 or 1")
            return False

        if ch3 < 0 or ch3 > 1:
            log.error(f"Channel 3 must be set to either 0 or 1")
            return False

        if val is None:
            val = ch0 | (ch1 << 1) | (ch2 << 2) | (ch3 << 3)
        try:
            self.i2c_bus.write_byte(self.i2c_address, val)
            return True
        except Exception as e:
            log.error(
                f"An exception occured when trying to write config register: {e}"
            )
            return False
Esempio n. 22
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)
Esempio n. 23
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)
class i2c_device:
    # Bit masks.
    bit0 = 0x01
    bit1 = 0x02
    bit2 = 0x04
    bit3 = 0x08
    bit4 = 0x10
    bit5 = 0x20
    bit6 = 0x40
    bit7 = 0x80

    def __init__(self, address=None, bus=None):
        self.address = address  # "address" is the device address on the i2c bus.
        self.bus = bus
        self.DEBUG = 0
        if self.bus == None:
            self.bus = DEFAULT_I2C_BUS
            # "bus" is the Raspberry Pi external i2c bus, where the MCP23017 is connected.
            # This may vary accross different Raspberry Pi models.  0 is used by the
            # original Raspbery Pi model B (256 MB memory, 26-pin GPIO connector).
            # 1 is used by recent Raspberry Pi devices.
        self.device = SMBus(self.bus)
        return

    def bus_reset(self):
        '''Caution:  bus reset is a general call operation.  It
is not device-specific.  All devices on the bus are affected.
In systems with multiple i2c busses, only one bus (the bus associated
with this device) is reset.'''
        self.device.write_byte(0, 6)
        return

    def wbyte_only(self, value):
        # Write a single byte to device, without any register address.
        self.device.write_byte(self.address, value)

    def rbyte_only(self):
        # Read a single byte from device, without any register address.
        return self.device.read_byte(self.address)

    def wbyte(self, reg, value):
        # Write a single byte <value> to register <reg>.
        if self.DEBUG >= 32:
            sys.stdout.write(
                '  write  x{:02X} to chip x{:02X} register {}\n'.format(
                    value, self.address, reg))
            sys.flush()
        self.device.write_byte_data(self.address, reg, value)
        return

    def rbyte(self, reg):
        # Read one byte from register <reg>.
        return self.device.read_byte_data(self.address, reg)

    def wword(self, reg, value):
        '''Write the integer <value> (two bytes) to register <reg>.'''
        if byte_swap:
            value = ((value & 0xff) << 8) | ((value >> 8) & 0xff)
        self.device.write_word_data(self.address, reg, value)
        return

    def rword(self, reg):
        value = self.device.read_word_data(self.address, reg)
        if byte_swap:
            value = ((value & 0xff) << 8) | ((value >> 8) & 0xff)
        return value
Esempio n. 25
0
from smbus2 import SMBus
import time
bus = SMBus(0)
time.sleep(1)

while True:
    counter = 0
    id = ""
    ok = True
    while len(id) < 8:
    #while True:
        try:
            start = time.time()
            print("reading...")
            b = bus.read_byte(0x41)
            end = time.time()
            print(end-start)
            print("read", chr(b))
            if end-start > 1:
                print("set ok to true")
                ok = True
            if ok:
                id += chr(b)
            
        except Exception as e:
            print(e)
            ok = False
            id=""
            continue
    
    #print("resetting counter")
Esempio n. 26
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__(input_dev,
                                          testing=testing,
                                          name=__name__)

        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.sht2x = SMBus(self.input_dev.i2c_bus)

    def get_measurement(self):
        """ Gets the humidity and temperature """
        if not self.sht2x:
            self.logger.error("Input not set up")
            return

        self.return_dict = copy.deepcopy(measurements_dict)

        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):
                    self.value_set(0, temperature)

                if self.is_enabled(1):
                    self.value_set(1, humidity)

                if self.is_enabled(2) and self.is_enabled(
                        0) and self.is_enabled(1):
                    self.value_set(
                        2,
                        calculate_dewpoint(self.value_get(0),
                                           self.value_get(1)))

                if self.is_enabled(3) and self.is_enabled(
                        0) and self.is_enabled(1):
                    self.value_set(
                        3,
                        calculate_vapor_pressure_deficit(
                            self.value_get(0), self.value_get(1)))

                return self.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)
Esempio n. 27
0
class EPS(Device):
    BUS_NAME = '/dev/i2c-1'
    ADDRESS = 0x57

    def __init__(self):
        super().__init__("EPS")
        self.bus = SMBus()

    def is_open(self) -> bool:
        return self.bus.fd is not None

    def write_i2c_block_response(self, register: EPSRegister,
                                 data) -> bytes or None:
        if type(register) != EPSRegister:
            return

        self.write_i2c_block_data(register, data)
        return self.read_byte()

    def write_byte_response(self, register: EPSRegister,
                            value) -> bytes or None:
        if type(register) != EPSRegister:
            return

        self.write_byte_data(register, value)
        return self.read_byte()

    def read_byte_data(self, register: EPSRegister) -> bytes or None:
        if type(register) != EPSRegister:
            return

        self.bus.open(self.BUS_NAME)
        next_byte = self.bus.read_byte_data(self.ADDRESS, register.value)
        self.bus.close()
        return next_byte

    def read_byte(self) -> bytes or None:
        self.bus.open(self.BUS_NAME)
        next_byte = self.bus.read_byte(self.ADDRESS)
        self.bus.close()
        return next_byte

    def write_i2c_block_data(self, register: EPSRegister, data):
        if type(register) != EPSRegister:
            return

        self.bus.open(self.BUS_NAME)
        self.bus.write_i2c_block_data(self.ADDRESS, register.value, data)
        self.bus.close()

    def write_byte_data(self, register: EPSRegister, value):
        if type(register) != EPSRegister:
            return

        self.bus.open(self.BUS_NAME)
        self.bus.write_byte_data(self.ADDRESS, register.value, value)
        self.bus.close()

    def functional(self):
        raise NotImplementedError

    def reset(self):
        raise NotImplementedError

    def disable(self):
        raise NotImplementedError

    def enable(self):
        raise NotImplementedError
Esempio n. 28
0
class I2CBus(AbstractBus):
    """Initialize the I2C hardware driver and represent as bus object."""

    type = BusType.I2C
    frequency = 100000

    def start(self):
        """  """
        # Todo: Improve error handling.
        try:
            if self.platform_info.vendor == self.platform_info.MICROPYTHON.Vanilla:
                from machine import I2C
                self.adapter = I2C(self.number,
                                   sda=Pin(int(self.pins['sda'][1:])),
                                   scl=Pin(int(self.pins['scl'][1:])),
                                   freq=self.frequency)

            elif self.platform_info.vendor == self.platform_info.MICROPYTHON.Pycom:
                from machine import I2C
                self.adapter = I2C(self.number,
                                   mode=I2C.MASTER,
                                   pins=(self.pins['sda'], self.pins['scl']),
                                   baudrate=self.frequency)

            elif self.platform_info.vendor == self.platform_info.MICROPYTHON.Odroid:
                from smbus2 import SMBus
                self.adapter = SMBus(self.number)

            elif self.platform_info.vendor == self.platform_info.MICROPYTHON.RaspberryPi:
                import board
                import busio

                def i2c_add_bus(busnum, scl, sda):
                    """
                    Register more I2C buses with Adafruit Blinka.

                    Make Adafruit Blinka learn another I2C bus.
                    Please make sure you define it within /boot/config.txt like::

                    dtoverlay=i2c-gpio,bus=3,i2c_gpio_delay_us=1,i2c_gpio_sda=26,i2c_gpio_scl=20
                    """

                    # Uncache this module, otherwise monkeypatching will fail on subsequent calls.
                    import sys
                    try:
                        del sys.modules['microcontroller.pin']
                    except:
                        pass

                    # Monkeypatch "board.pin.i2cPorts".
                    i2c_port = (busnum, scl, sda)
                    if i2c_port not in board.pin.i2cPorts:
                        board.pin.i2cPorts += (i2c_port, )

                pin_scl = self.pins['scl']
                pin_sda = self.pins['sda']

                # When I2C port pins are defined as Integers, register them first.
                if isinstance(pin_scl, int):
                    i2c_add_bus(self.number, pin_scl, pin_sda)
                    SCL = board.pin.Pin(pin_scl)
                    SDA = board.pin.Pin(pin_sda)

                # When I2C port pins are defined as Strings and start with "board.",
                # they are probably already Pin aliases of Adafruit Blinka.
                elif isinstance(pin_scl, str) and pin_scl.startswith('board.'):
                    SCL = eval(pin_scl)
                    SDA = eval(pin_sda)

                self.adapter = busio.I2C(SCL, SDA)

            else:
                raise NotImplementedError(
                    'I2C bus is not implemented on this platform')

            self.just_started = True

            if not self.platform_info.vendor == self.platform_info.MICROPYTHON.Odroid:
                self.scan_devices()

            if self.platform_info.vendor == self.platform_info.MICROPYTHON.Odroid:

                self.devices = self.scan_devices_smbus2()
                log.info("Scan I2C bus via smbus2 for devices...")
                log.info("Found {} I2C devices: {}.".format(
                    len(self.devices), self.devices))

            self.ready = True

        except Exception as ex:
            #log.exc(ex, 'I2C hardware driver failed')
            raise

    def scan_devices(self):
        log.info('Scan I2C with id={} bus for devices...'.format(self.number))
        self.devices = self.adapter.scan()
        # i2c.readfrom(0x76, 5)
        log.info("Found {} I2C devices: {}".format(len(self.devices),
                                                   self.devices))

    def scan_devices_smbus2(self, start=0x03, end=0x78):
        try:
            list = []
            for i in range(start, end):
                val = 1
                try:
                    self.adapter.read_byte(i)
                except OSError as e:
                    val = e.args[0]
                finally:
                    if val != 5:  # No device
                        if val == 1:
                            res = "Available"
                        elif val == 16:
                            res = "Busy"
                        elif val == 110:
                            res = "Timeout"
                        else:
                            res = "Error code: " + str(val)
                        # print(hex(i) + " -> " + res)
                        if res == 'Available':
                            # print(i)
                            list.append(i)
            return list

        except Exception as exp:
            log.exc(exp, 'scan smbus2 failed')

    def power_on(self):
        """
        Turn on the I2C peripheral after power off.
        """

        # Don't reinitialize device if power on just occurred through initial driver setup.
        if self.just_started:
            self.just_started = False
            return

        # uPy doesn't have deinit so it doesn't need init
        if self.platform_info.vendor == self.platform_info.MICROPYTHON.Pycom:
            from machine import I2C
            self.adapter.init(mode=I2C.MASTER, baudrate=self.frequency)

    def power_off(self):
        """
        Turn off the I2C peripheral.

        https://docs.pycom.io/firmwareapi/pycom/machine/i2c.html
        """
        log.info('Turning off I2C bus {}'.format(self.name))
        if self.platform_info.vendor == self.platform_info.MICROPYTHON.Pycom:
            self.adapter.deinit()
Esempio n. 29
0
    user_input = 1
    payload = 0
    response = 0
    other_response = 0
    bomba2 = 7

    bus = SMBus(1)
    wiringpi.wiringPiSetup()
    wiringpi.pinMode(bomba2, wiringpi.OUTPUT)

    while (user_input != 0):
        user_input = int(input('Qual ação deseja realizar? '))

        bus.write_byte(slave_addr, user_input)
        sleep(0.2)
        response = bus.read_byte(slave_addr)

        print(INPUT[user_input], response)

        if (user_input == 9):
            if (response == 10):
                payload = 3

                bus.write_byte(slave_addr, payload)
                sleep(1)
                other_response = bus.read_byte(slave_addr)

                while (other_response1 < 20):
                    i = 0
                    while i < 20:
                        bus.write_byte(slave_addr, payload)
Esempio n. 30
0
class UpbeatLabs_MCP39F521(object):
    """Class for communicating with an MCP39F521 device like Dr. Wattson using the 
    python smbus library."""
    class Error_code(Enum):
        SUCCESS = 0
        ERROR_INCORRECT_HEADER = 1
        ERROR_CHECKSUM_FAIL = 2
        ERROR_UNEXPECTED_RESPONSE = 3
        ERROR_INSUFFICIENT_ARRAY_SIZE = 4
        ERROR_CHECKSUM_MISMATCH = 5
        ERROR_SET_VALUE_MISMATCH = 6
        ERROR_VALUE_OUT_OF_BOUNDS = 7

    class Event_config(Enum):
        EVENT_OVERCUR_TST = 0
        EVENT_OVERPOW_TST = 1
        EVENT_VSAG_TST = 2
        EVENT_VSUR_TST = 3
        EVENT_OVERCUR_LA = 4
        EVENT_OVERPOW_LA = 5
        EVENT_VSAG_LA = 6
        EVENT_VSUR_LA = 7
        EVENT_VSAG_CL = 8
        EVENT_VSUR_CL = 9
        EVENT_OVERPOW_CL = 10
        EVENT_OVERCUR_CL = 11
        EVENT_MANUAL = 14
        EVENT_VSAG_PIN = 16
        EVENT_VSURGE_PIN = 17
        EVENT_OVERCUR_PIN = 18
        EVENT_OVERPOW_PIN = 19

    class System_status(Enum):
        SYSTEM_VSAG = 0
        SYSTEM_VSURGE = 1
        SYSTEM_OVERCUR = 2
        SYSTEM_OVERPOW = 3
        SYSTEM_SIGN_PA = 4
        SYSTEM_SIGN_PR = 5
        SYSTEM_EVENT = 10

    class calibration_config(Enum):
        CALIBRATION_CONFIG_4A = 0
        CALIBRATION_CONFIG_10A = 1  # 30 ohm burden resistor x2
        CALIBRATION_CONFIG_15A = 2  # 20 ohm burden resistor x2

    class __Response_code(Enum):
        RESPONSE_ACK = 0x06
        RESPONSE_NAK = 0x15
        RESPONSE_CSFAIL = 0x51

    class __Command_code(Enum):
        COMMAND_REGISTER_READ_N_BYTES = 0x4e
        COMMAND_REGISTER_WRITE_N_BYTES = 0x4d
        COMMAND_SET_ADDRESS_POINTER = 0x41
        COMMAND_SAVE_TO_FLASH = 0x53
        COMMAND_PAGE_READ_EEPROM = 0x42
        COMMAND_PAGE_WRITE_EEPROM = 0x50
        COMMAND_BULK_ERASE_EEPROM = 0x4f
        COMMAND_AUTO_CALIBRATE_GAIN = 0x5a
        COMMAND_AUTO_CALIBRATE_REACTIVE_GAIN = 0x7a
        COMMAND_AUTO_CALIBRATE_FREQUENCY = 0x76

    ## There is a bug in current MCP39F511/521 where energy accumulation
    ## values are off if the energy accumulation interval is
    ## anything but 2. This applies the workaround for that problem.
    ## To be removed for chips that have the issue fixed.
    ## XXX : TODO

    def __init__(self, address=MCP39F521_I2CADDR, busnum=DEFAULT_BUSNUM):
        """Create an instance of the MCP39F521 device at the specified address on the
           specified I2C bus number."""
        self._address = address
        self._bus = SMBus(busnum)
        self._logger = logging.getLogger(
            'DrWattson.UpbeatLabs_MCP39F521.Bus.{0}.Address.{1:#0X}'.format(
                busnum, address))
        self._energy_accum_correction_factor = 1
        (retVal, enabled) = self.isEnergyAccumulationEnabled()
        if (retVal == self.Error_code.SUCCESS.value and enabled):
            (retVal,
             accumIntervalReg) = self.readAccumulationIntervalRegister()
            self._energy_accum_correction_factor = (accumIntervalReg - 2)

    ## Get energy related data from the module
    ##
    ## Parameters:
    ## UpbeatLabs_MCP39F521_Data (output) - Metering data
    ##

    def readEnergyData(self):
        (retVal, buf) = self.__registerReadNBytes(0x00, 0x02, 28)
        data = UpbeatLabs_MCP39F521_Data()

        if (retVal == self.Error_code.SUCCESS.value):
            data.systemStatus = (buf[3] << 8 | buf[2])
            data.systemVersion = (buf[5] << 8 | buf[4])
            data.voltageRMS = (buf[7] << 8 | buf[6]) / 10.0
            data.lineFrequency = (buf[9] << 8 | buf[8]) / 1000.0
            data.analogInputVoltage = (buf[11] << 8 | buf[10]) / 1023.0 * 3.3

            pfRaw = buf[13] << 8 | buf[12]
            f = ((pfRaw & 0x8000) >> 15) * -1.0

            for ch in range(14, 3, -1):
                f += ((pfRaw & (1 << ch)) >> ch) * 1.0 / (1 << (15 - ch))

            data.powerFactor = f

            data.currentRMS = (buf[17] << 24 | buf[16] << 16 | buf[15] << 8
                               | buf[14]) / 10000.0
            data.activePower = (buf[21] << 24 | buf[20] << 16 | buf[19] << 8
                                | buf[18]) / 100.0
            data.reactivePower = (buf[25] << 24 | buf[24] << 16 | buf[23] << 8
                                  | buf[22]) / 100.0
            data.apparentPower = (buf[29] << 24 | buf[28] << 16 | buf[27] << 8
                                  | buf[26]) / 100.0

        return (retVal, data)

    ## Get energy accumulator data from the module
    ##
    ## Parameters:
    ## UpbeatLabs_MCP39F521_AccumData (output) - accumulator data for energy
    ## Notes:
    ## On Arduino cannot read more than 32 bytes on I2C
    ## Let's just stick to that limit!
    ## Splitting out activeEnergyImport, activeEnergyExport and
    ## reactiveEnergyImport, reactiveEnergyExport into two calls
    ## as the total is 32+3 = 35 bytes otherwise.

    def readEnergyAccumData(self):
        (retVal, buf) = self.__registerReadNBytes(0x00, 0x1e, 16)
        data = UpbeatLabs_MCP39F521_AccumData()

        if (retVal == self.Error_code.SUCCESS.value):
            if (self._energy_accum_correction_factor == -1):
                data.activeEnergyImport = (
                    ((buf[9]) << 56 | (buf[8]) << 48 | (buf[7]) << 40 |
                     (buf[6]) << 32 | (buf[5]) << 24 | (buf[4]) << 16 |
                     (buf[3]) << 8 | buf[2]) / 2) / 1000.0
                data.activeEnergyExport = (
                    ((buf[17]) << 56 | (buf[16]) << 48 | (buf[15]) << 40 |
                     (buf[14]) << 32 | (buf[13]) << 24 | (buf[12]) << 16 |
                     (buf[11]) << 8 | buf[10]) / 2) / 1000.0
            else:
                data.activeEnergyImport = (
                    ((buf[9]) << 56 | (buf[8]) << 48 | (buf[7]) << 40 |
                     (buf[6]) << 32 | (buf[5]) << 24 | (buf[4]) << 16 |
                     (buf[3]) << 8 | buf[2]) *
                    (1 << self._energy_accum_correction_factor)) / 1000.0
                data.activeEnergyExport = (
                    ((buf[17]) << 56 | (buf[16]) << 48 | (buf[15]) << 40 |
                     (buf[14]) << 32 | (buf[13]) << 24 | (buf[12]) << 16 |
                     (buf[11]) << 8 | buf[10]) *
                    (1 << self._energy_accum_correction_factor)) / 1000.0

        time.sleep(0.05)
        (retVal, buf) = self.__registerReadNBytes(0x00, 0x2e, 16)

        if (retVal == self.Error_code.SUCCESS.value):
            if (self._energy_accum_correction_factor == -1):
                data.reactiveEnergyImport = (
                    ((buf[9]) << 56 | (buf[8]) << 48 | (buf[7]) << 40 |
                     (buf[6]) << 32 | (buf[5]) << 24 | (buf[4]) << 16 |
                     (buf[3]) << 8 | buf[2]) / 2) / 1000.0
                data.reactiveEnergyExport = (
                    ((buf[17]) << 56 | (buf[16]) << 48 | (buf[15]) << 40 |
                     (buf[14]) << 32 | (buf[13]) << 24 | (buf[12]) << 16 |
                     (buf[11]) << 8 | buf[10]) / 2) / 1000.0
            else:
                data.reactiveEnergyImport = (
                    ((buf[9]) << 56 | (buf[8]) << 48 | (buf[7]) << 40 |
                     (buf[6]) << 32 | (buf[5]) << 24 | (buf[4]) << 16 |
                     (buf[3]) << 8 | buf[2]) *
                    (1 << self._energy_accum_correction_factor)) / 1000.0
                data.reactiveEnergyExport = (
                    ((buf[17]) << 56 | (buf[16]) << 48 | (buf[15]) << 40 |
                     (buf[14]) << 32 | (buf[13]) << 24 | (buf[12]) << 16 |
                     (buf[11]) << 8 | buf[10]) *
                    (1 << self._energy_accum_correction_factor)) / 1000.0

        return (retVal, data)

    # Event control methods

    ## Reads the event configuration and returns the 32-bit bit map.
    ## Use the event_config enum to read bits of interest, without
    ## worrying about the bit position and structure of the
    ## event config register
    ##
    ## For example, bitRead(eventConfigRegisterValue, EVENT_VSAG_PIN)
    ## to see if event notification for VSAG events is turned on

    def readEventConfigRegister(self):
        (retVal, buf) = self.__registerReadNBytes(0x00, 0x7e, 4)
        configRegister = 0
        if (retVal == self.Error_code.SUCCESS.value):
            configRegister = buf[5] << 24 | buf[4] << 16 | buf[3] << 8 | buf[2]

        return (retVal, configRegister)

    ## Set the event configuration register to the appropriate value
    ##
    ## First, read the existing register value. Then, set (or clear) appropriate
    ## bits using the event_config enum for assitance. Lastly, set the
    ## new value back in the register.
    ##
    ## For example, bitSet(eventConfigRegisterValue, EVENT_VSAG_PIN)
    ## to turn on the event notification for VSAG events
    ## or bitClear(eventConfigRegisterValue, EVENT_VSAG_PIN)

    def setEventConfigurationRegister(self, value):
        byteArray = []
        byteArray.append(value & 0xFF)
        byteArray.append((value >> 8) & 0xFF)
        byteArray.append((value >> 16) & 0xFF)
        byteArray.append((value >> 24) & 0xFF)

        retVal = self.__registerWriteNBytes(0x00, 0x7e, 4, byteArray)
        if (retVal != self.Error_code.SUCCESS.value):
            return retVal

        (retVal, readArray) = self.__registerReadNBytes(0x00, 0x7e, 4)

        if (retVal == self.Error_code.SUCCESS.value):
            readValue = readArray[5] << 24 | readArray[4] << 16 | readArray[
                3] << 8 | readArray[2]

        if (readValue != value):
            return self.Error_code.ERROR_SET_VALUE_MISMATCH.value

        return self.Error_code.SUCCESS.value

    ## Read the event flag limits that have been set for the various events.
    ## For example, the voltage sag limit sets the voltage value below which
    ## the VSAG event is triggered
    ##
    ## See UpbeatLabs_MCP39F521_EventFlagLimits for more information about
    ## various limits

    def readEventFlagLimitRegisters(self):
        (retVal, buf) = self.__registerReadNBytes(0x00, 0xA0, 12)
        data = UpbeatLabs_MCP39F521_EventFlagLimits()

        if (retVal == self.Error_code.SUCCESS.value):
            data.voltageSagLimit = (buf[3] << 8 | buf[2])
            data.voltageSurgeLimit = (buf[5] << 8 | buf[4])
            data.overCurrentLimit = (buf[9] << 24 | buf[8] << 16 | buf[7] << 8
                                     | buf[6])
            data.overPowerLimit = (buf[13] << 24 | buf[12] << 16 | buf[11] << 8
                                   | buf[10])

        return (retVal, data)

    ## Write the event flag limits for the various events.
    ## For example, the voltage sag limit sets the voltage value below which
    ## the VSAG event is triggered
    ##
    ## See UpbeatLabs_MCP39F521_EventFlagLimits for more information about
    ## various limits

    def writeEventFlagLimitRegisters(self, input):
        byteArray = []
        byteArray.append(input.voltageSagLimit & 0xFF)
        byteArray.append((input.voltageSagLimit >> 8) & 0xFF)

        byteArray.append(input.voltageSurgeLimit & 0xFF)
        byteArray.append((input.voltageSurgeLimit >> 8) & 0xFF)

        byteArray.append(input.overCurrentLimit & 0xFF)
        byteArray.append((input.overCurrentLimit >> 8) & 0xFF)
        byteArray.append((input.overCurrentLimit >> 16) & 0xFF)
        byteArray.append((input.overCurrentLimit >> 24) & 0xFF)

        byteArray.append(input.overPowerLimit & 0xFF)
        byteArray.append((input.overPowerLimit >> 8) & 0xFF)
        byteArray.append((input.overPowerLimit >> 16) & 0xFF)
        byteArray.append((input.overPowerLimit >> 24) & 0xFF)

        retVal = self.__registerWriteNBytes(0x00, 0xA0, 12, byteArray)

        if (retVal != self.Error_code.SUCCESS.value):
            return retVal

        (retVal, eventFlagLimitsData) = self.readEventFlagLimitRegisters()
        if (retVal == self.Error_code.SUCCESS.value):
            ## Verify read values with input values
            if (eventFlagLimitsData.voltageSagLimit != input.voltageSagLimit
                    or eventFlagLimitsData.voltageSurgeLimit !=
                    input.voltageSurgeLimit
                    or eventFlagLimitsData.overCurrentLimit !=
                    input.overCurrentLimit
                    or eventFlagLimitsData.overPowerLimit !=
                    input.overPowerLimit):
                return self.Error_code.ERROR_SET_VALUE_MISMATCH.value

        return retVal

    # EEPROM methods

    ## Bulk erase all pages of the EEPROM memory

    def bulkEraseEEPROM(self):
        return self.__issueAckNackCommand(
            self.__Command_code.COMMAND_BULK_ERASE_EEPROM.value)

    def pageReadEEPROM(self, pageNum):
        """Implementation of pageReadEEPROM """
        data = [
            0xa5, 0x05, self.__Command_code.COMMAND_PAGE_READ_EEPROM.value,
            pageNum
        ]
        checksum = 0
        for x in data:
            checksum += x
        data.append(checksum % 256)

        write = i2c_msg.write(self._address, data)
        self._bus.i2c_rdwr(write)

        time.sleep(0.05)

        ##
        ## Read the specified length of data - ACK, Num Bytes, EEPROM Page Data, Checksum
        ## -> 1 + 1 + 16 + 1 = 19 bytes of data
        ##
        read = i2c_msg.read(self._address, 19)
        self._bus.i2c_rdwr(read)

        buf = []
        buf.extend(read)

        return (self.__checkHeaderAndChecksum(16, buf), buf[2:-1])

    def pageWriteEEPROM(self, pageNum, byteArray):
        """Implementation of pageWriteEEPROM """
        if (len(byteArray) != 16):
            return self.Error_code.ERROR_INSUFFICIENT_ARRAY_SIZE.value

        data = [
            0xa5, 21, self.__Command_code.COMMAND_PAGE_WRITE_EEPROM.value,
            pageNum
        ]

        # Data here...
        data.extend(byteArray)

        checksum = 0
        for x in data:
            checksum += x
        data.append(checksum % 256)

        write = i2c_msg.write(self._address, data)
        self._bus.i2c_rdwr(write)

        time.sleep(0.05)

        header = self._bus.read_byte(self._address)
        self._logger.debug(header)

        return self.__checkHeader(header)

    # Energy Accumulation methods

    ## This method is used to turn on/off energy accumulation.
    ## When it is turned on, the data read from the module
    ## in UpbeatLabs_MCP39F521_AccumData represents the
    ## accumulated energy data over the no load threshold
    ## (defaults to 1w). Therefore any energy over 1w
    ## gets accumulated over time.

    ## There is a bug in current MCP39F511/521 where energy accumulation
    ## values are off if the energy accumulation interval is
    ## anything but 2. This applies the workaround for that problem.
    ## To be removed for chips that have the issue fixed.

    def enableEnergyAccumulation(self, enable):
        ## First, note the accumulation interval. If it is anything
        ## other than the default (2), note the correction
        ## factor that has to be applied to the energy
        ## accumulation.
        (retVal, accumIntervalReg) = self.readAccumulationIntervalRegister()

        self._energy_accum_correction_factor = (accumIntervalReg - 2)

        byteArray = [enable, 0]

        ## write register
        retVal = self.__registerWriteNBytes(0x00, 0xDC, 2, byteArray)

        return retVal

    def isEnergyAccumulationEnabled(self):
        (retVal, readArray) = self.__registerReadNBytes(0x00, 0xDC, 5)
        enabled = False
        if (retVal == self.Error_code.SUCCESS.value):
            enabled = readArray[2]

        return (retVal, enabled)

    # <----   End Energy Accumulation methods

    # START --- WARNING!!! WARNING!!! WARNING!!!
    # Advanced methods for calibration, etc
    # WARNING!!!! Use with extreme caution! These can render your Dr. Wattson
    # uncalibrated. Only use if you know what you are doing!

    ## Read the contents of the calibration registers
    ## Results returned in UpbeatLabs_MCP39F521_CalibrationData object

    def readCalibrationRegisters(self):
        (retVal, buf) = self.__registerReadNBytes(0x00, 0x5e, 28)
        data = UpbeatLabs_MCP39F521_CalibrationData()

        if (retVal == self.Error_code.SUCCESS.value):
            data.calibrationRegisterDelimiter = (buf[3] << 8 | buf[2])
            data.gainCurrentRMS = (buf[5] << 8 | buf[4])
            data.gainVoltageRMS = (buf[7] << 8 | buf[6])
            data.gainActivePower = (buf[9] << 8 | buf[8])
            data.gainReactivePower = (buf[11] << 8 | buf[10])
            data.offsetCurrentRMS = (buf[15] << 24 | buf[14] << 16
                                     | buf[13] << 8 | buf[12])
            data.offsetActivePower = (buf[19] << 24 | buf[18] << 16
                                      | buf[17] << 8 | buf[16])
            data.offsetReactivePower = (buf[23] << 24 | buf[22] << 16
                                        | buf[21] << 8 | buf[20])
            data.dcOffsetCurrent = (buf[25] << 8 | buf[24])
            data.phaseCompensation = (buf[27] << 8 | buf[26])
            data.apparentPowerDivisor = (buf[29] << 8 | buf[28])

        return (retVal, data)

    ## This method writes the current, voltage, active power and reactive power gains directly to
    ## the MCP39F521 registers. Use this if you know what the appropriate gains are to be for
    ## your particular metering range and design. Typically, these are not to be changed unless
    ## you are performing your own calibration, and even so, it is better to use the
    ## auto-calibration methods instead. This is one big gun to shoot yourself, be warned!

    def writeGains(self, gainCurrentRMS, gainVoltageRMS, gainActivePower,
                   gainReactivePower):

        byteArray = []
        byteArray.append(gainCurrentRMS & 0xFF)
        byteArray.append((gainCurrentRMS >> 8) & 0xFF)

        byteArray.append(gainVoltageRMS & 0xFF)
        byteArray.append((gainVoltageRMS >> 8) & 0xFF)

        byteArray.append(gainActivePower & 0xFF)
        byteArray.append((gainActivePower >> 8) & 0xFF)

        byteArray.append(gainReactivePower & 0xFF)
        byteArray.append((gainReactivePower >> 8) & 0xFF)

        retVal = self.__registerWriteNBytes(0x00, 0x60, 8, byteArray)

        return retVal

    ## Read the system config register, which is a 32-bit bit map.
    ## The system config register is used to set setting like
    ## PGA gains for current and voltage channels, etc
    ## You will typically not be changing these unless you are
    ## performing a calibration.

    def readSystemConfigRegister(self):
        (retVal, buf) = self.__registerReadNBytes(0x00, 0x7a, 4)
        value = 0
        if (retVal == self.Error_code.SUCCESS.value):
            value = buf[5] << 24 | buf[4] << 16 | buf[3] << 8 | buf[2]
        return (retVal, value)

    ## Set the system config register, which is a 32-bit bit map.
    ## The system config register is used to set setting like
    ## PGA gains for current and voltage channels, etc
    ## You will typically not be changing these unless you are
    ## performing a calibration. Do not use unless you know what
    ## you are doing! This is one big gun to shoot yourself, be warned!

    def setSystemConfigurationRegister(self, value):
        retVal = 0
        byteArray = [0] * 4
        byteArray[0] = value & 0xFF
        byteArray[1] = (value >> 8) & 0xFF
        byteArray[2] = (value >> 16) & 0xFF
        byteArray[3] = (value >> 24) & 0xFF
        # print byteArray

        retVal = self.__registerWriteNBytes(0x00, 0x7a, 4, byteArray)
        if (retVal != self.Error_code.SUCCESS.value):
            return retVal

        time.sleep(0.05)

        (retVal, readArray) = self.__registerReadNBytes(0x00, 0x7a, 4)
        readValue = ((readArray[5]) << 24 | (readArray[4]) << 16 |
                     (readArray[3]) << 8 | readArray[2])

        if (readValue != value):
            return self.Error_code.ERROR_SET_VALUE_MISMATCH.value
        return self.Error_code.SUCCESS.value

    ## Read the accumlation interval register, which represents N in 2^N
    ## number of line cycles to be used for a single computation.
    ## You will not be modifying this unless you are performing a
    ## calibration.

    def readAccumulationIntervalRegister(self):
        (retVal, buf) = self.__registerReadNBytes(0x00, 0x9e, 2)
        value = 0
        if (retVal == self.Error_code.SUCCESS.value):
            value = buf[3] << 8 | buf[2]
        return (retVal, value)

    ## Set the accumlation interval register, which represents N in 2^N
    ## number of line cycles to be used for a single computation.
    ## You will not be modifying this unless you are performing a
    ## calibration. Use with caution!!

    def setAccumulationIntervalRegister(self, value):
        retVal = 0
        byteArray = [0] * 2
        byteArray[0] = value & 0xFF
        byteArray[1] = (value >> 8) & 0xFF

        retVal = self.__registerWriteNBytes(0x00, 0x9e, 2, byteArray)
        if (retVal != self.Error_code.SUCCESS.value):
            return retVal

        time.sleep(0.05)

        (retVal, readArray) = self.__registerReadNBytes(0x00, 0x9e, 2)
        readValue = ((readArray[3]) << 8 | readArray[2])

        if (readValue != value):
            return self.Error_code.ERROR_SET_VALUE_MISMATCH.value
        return self.Error_code.SUCCESS.value

    ## Read the design config registers into the UpbeatLabs_MCP39F521_DesignConfigData struct.
    ## See class for more details. These are used to set the appropriate calibration values for
    ## calibrating your module.

    def readDesignConfigurationRegisters(self):
        (retVal, buf) = self.__registerReadNBytes(0x00, 0x82, 20)
        data = UpbeatLabs_MCP39F521_DesignConfigData()

        if (retVal == self.Error_code.SUCCESS.value):
            data.rangeVoltage = buf[2]
            data.rangeCurrent = buf[3]
            data.rangePower = buf[4]
            data.rangeUnimplemented = buf[5]
            data.calibrationCurrent = (buf[9] << 24 | buf[8] << 16
                                       | buf[7] << 8 | buf[6])
            data.calibrationVoltage = ((buf[11] << 8) | buf[10])
            data.calibrationPowerActive = (buf[15] << 24 | buf[14] << 16
                                           | buf[13] << 8 | buf[12])
            data.calibrationPowerReactive = (buf[19] << 24 | buf[18] << 16
                                             | buf[17] << 8 | buf[16])
            data.lineFrequencyRef = ((buf[21] << 8) | buf[20])

        return (retVal, data)

    ## Write the design config registers. See UpbeatLabs_MCP39F521_DesignConfigData
    ## struct for more details. These are used to set the appropriate calibration values for
    ## calibrating your module. Use this method only if you know what you are doing!
    ## This is one big gun to shoot yourself, be warned!

    def writeDesignConfigRegisters(self, data):
        byteArray = [] * 20
        ## range
        byteArray[0] = data.rangeVoltage
        byteArray[1] = data.rangeCurrent
        byteArray[2] = data.rangePower
        byteArray[3] = data.rangeUnimplemented

        ## calibration current
        byteArray[4] = data.calibrationCurrent & 0xFF
        byteArray[5] = (data.calibrationCurrent >> 8) & 0xFF
        byteArray[6] = (data.calibrationCurrent >> 16) & 0xFF
        byteArray[7] = (data.calibrationCurrent >> 24) & 0xFF

        ## calibration voltage
        byteArray[8] = data.calibrationVoltage & 0xFF
        byteArray[9] = (data.calibrationVoltage >> 8) & 0xFF

        ## calibration power active
        byteArray[10] = data.calibrationPowerActive & 0xFF
        byteArray[11] = (data.calibrationPowerActive >> 8) & 0xFF
        byteArray[12] = (data.calibrationPowerActive >> 16) & 0xFF
        byteArray[13] = (data.calibrationPowerActive >> 24) & 0xFF

        ## calibration power reactive
        byteArray[14] = data.calibrationPowerReactive & 0xFF
        byteArray[15] = (data.calibrationPowerReactive >> 8) & 0xFF
        byteArray[16] = (data.calibrationPowerReactive >> 16) & 0xFF
        byteArray[17] = (data.calibrationPowerReactive >> 24) & 0xFF

        ## line frequency ref
        byteArray[18] = data.lineFrequencyRef & 0xFF
        byteArray[19] = (data.lineFrequencyRef >> 8) & 0xFF

        retVal = self.__registerWriteNBytes(0x00, 0x82, 20, byteArray)
        if (retVal != self.Error_code.SUCCESS.value):
            return retVal

        time.sleep(0.05)

        ## Read the values to verify write

        (retVal, designConfigData) = self.readDesignConfigurationRegisters()

        if (retVal != self.Error_code.SUCCESS.value):
            return retVal

        ## Verify read values with input values
        if (designConfigData.rangeVoltage != data.rangeVoltage
                or designConfigData.rangeCurrent != data.rangeCurrent
                or designConfigData.rangePower != data.rangePower or
                designConfigData.calibrationCurrent != data.calibrationCurrent
                or
                designConfigData.calibrationVoltage != data.calibrationVoltage
                or designConfigData.calibrationPowerActive !=
                data.calibrationPowerActive
                or designConfigData.calibrationPowerReactive !=
                data.calibrationPowerReactive
                or designConfigData.lineFrequencyRef != data.lineFrequencyRef):
            return self.Error_code.ERROR_SET_VALUE_MISMATCH.value

        return self.Error_code.SUCCESS.value

    ## Write the phase compensation register. This will not be required unless
    ## you are manually writing calibration values yourself. Use with caution!

    def writePhaseCompensation(self, phaseCompensation):

        byteArray = [] * 2
        ## Calibrating phase
        byteArray[0] = phaseCompensation
        byteArray[1] = 0

        retVal = self.__registerWriteNBytes(0x00, 0x76, 2, byteArray)

        return retVal

    ## Read and set the ambient reference temperature when
    ## calibrating. This is used during calibration as one
    ## of the steps. Use with caution!

    def readAndSetTemperature(self):
        (retVal, byteArray) = __registerReadNBytes(0x00, 0x0a, 2)

        if (retVal != self.Error_code.SUCCESS.value):
            return retVal

        bytesWrite = [] * 2
        bytesWrite[0] = byteArray[2]
        bytesWrite[1] = byteArray[3]

        retVal = self.__registerWriteNBytes(0x00, 0xcc, 2, bytesWrite)

        return retVal

    ## Invoke the "autoCalibrate Gain" command. Prior to this,
    ## other requisite steps need to be taken like setting
    ## the design config registers with the appropriate
    ## calibration values. Use only if you know what you are
    ## doing! This is one big gun to shoot yourself, be warned!

    def autoCalibrateGain(self):
        return self.__issueAckNackCommand(
            self.__Command_code.COMMAND_AUTO_CALIBRATE_GAIN.value)

    ## Invoke the "autoCalibrate Reactive Gain" command. Prior to this,
    ## other requisite steps need to be taken like setting
    ## the design config registers with the appropriate
    ## calibration values, and auto calibrating gain.
    ## Use only if you know what you are doing!
    ## This is one big gun to shoot yourself, be warned!

    def autoCalibrateReactiveGain(self):
        return self.__issueAckNackCommand(
            self.__Command_code.COMMAND_AUTO_CALIBRATE_REACTIVE_GAIN.value)

    ## Invoke the "autoCalibrate Line Frequency" command. Prior to this,
    ## other requisite calibration steps need to be taken like setting
    ## the appropriate design config registers.
    ## Use only if you know what you are doing!
    ## This is one big gun to shoot yourself, be warned!

    def autoCalibrateFrequency(self):
        return self.__issueAckNackCommand(
            self.__Command_code.COMMAND_AUTO_CALIBRATE_FREQUENCY.value)

    ## This method is used to calibrate the phase compensation
    ## when calibrating the module, as one of the steps during
    ## system calibration. Use only if you know what you are doing!
    ## This is one big gun to shoot yourself, be warned!

    def calibratePhase(self, pfExp):
        (retVal, byteArray) = self.__registerReadNBytes(0x00, 0x0c, 2)

        if (retVal != self.Error_code.SUCCESS.value):
            return retVal

        pfRaw = buf[13] << 8 | buf[12]
        f = ((pfRaw & 0x8000) >> 15) * -1.0

        for ch in range(14, 3, -1):
            f += ((pfRaw & (1 << ch)) >> ch) * 1.0 / (1 << (15 - ch))

        pfMeasured = f

        angleMeasured = acos(pfMeasured)
        angleExp = acos(pfExp)
        angleMeasuredDeg = angleMeasured * 180.0 / 3.14159
        angleExpDeg = angleExp * 180.0 / 3.14159

        phi = (angleMeasuredDeg - angleExpDeg) * 40.0

        (retVal, byteArray) = self.__registerReadNBytes(0x00, 0x76, 2)

        if (retVal != self.Error_code.SUCCESS.value):
            return retVal

        # phase compensation is stored as an 8-bit 2's complement number
        # (in a 16 bit register)
        pcRaw = byteArray[2]
        if pcRaw > 127:
            pcRaw = pcRaw - 256
        phaseComp = pcRaw

        phaseCompNew = phaseComp + phi

        # New value has to be between 127 and -128 and has to be converted
        # back to an 8 bit integer for transmission
        if (phaseCompNew > 127 or phaseCompNew < -128):
            retVal = self.Error_code.ERROR_VALUE_OUT_OF_BOUNDS.value
        else:
            ## Calibrating phase
            bytes = [0] * 2
            # converting back to 8 bit unsigned integer representation of
            # two's complement value
            bytes[0] = phaseCompNew if (phaseCompNew >= 0) else (256 +
                                                                 phaseCompNew)
            bytes[1] = 0

            retVal = self.__registerWriteNBytes(0x00, 0x76, 2, bytes)

        return retVal

    ## This method saves the contents of all calibration
    ## and configuration registers to flash. Use with caution!

    def saveToFlash(self):
        return self.__issueAckNackCommand(
            self.__Command_code.COMMAND_SAVE_TO_FLASH.value)

    # This will revert the MCP39F521 to its factory settings and
    # remove any calibration data. Use with extreme caution!!!!

    def factoryReset(self):
        byteArray = [0] * 2
        byteArray[0] = 0xa5
        byteArray[1] = 0xa5

        retVal = self.__registerWriteNBytes(0x00, 0x5e, 2, byteArray)

        if (retVal != self.Error_code.SUCCESS.value):
            return retVal

        retVal = self.saveToFlash()

        return retVal

    ## This method will reset the calibration values to Dr. Wattson

    def resetCalibration(self,
                         cc=calibration_config.CALIBRATION_CONFIG_4A.value):
        global calibConfig
        retVal = self.Error_code.SUCCESS.value

        retVal = self.setSystemConfigurationRegister(
            calibConfig[cc].systemConfig)  # Channel 1 Gain 4, Channel 0 Gain 1
        if (retVal != self.Error_code.SUCCESS.value):
            return retVal

        retVal = self.setAccumulationIntervalRegister(
            calibConfig[cc].accumInt)  # Accumulation interval 5
        if (retVal != self.Error_code.SUCCESS.value):
            return retVal

        ## We need to apply correction factor where accumulation interval is not 2;
        if (calibConfig[cc].accumInt > 2):
            self._energy_accum_correction_factor = (calibConfig[cc].accumInt -
                                                    2)

        retVal = self.writeDesignConfigRegisters(
            calibConfig[cc].designConfigData)
        if (retVal != self.Error_code.SUCCESS.value):
            return retVal

        retVal = self.writeGains(calibConfig[cc].gainCurrentRMS,
                                 calibConfig[cc].gainVoltageRMS,
                                 calibConfig[cc].gainActivePower,
                                 calibConfig[cc].gainReactivePower)
        if (retVal != self.Error_code.SUCCESS.value):
            return retVal

        retVal = self.writePhaseCompensation(calibConfig[cc].phaseCompensation)
        if (retVal != self.Error_code.SUCCESS.value):
            return retVal

        retVal = self.saveToFlash()
        if (retVal != self.Error_code.SUCCESS.value):
            return retVal

        return self.Error_code.SUCCESS.value

    # END --- WARNING!!! WARNING!!! WARNING!!!

    ## Bit manipulation convenience methods

    # Check to see if the kth bit is set in value n
    # (where k starts with 0 for the least significant bit
    def bitRead(self, n, k):
        return n & (1 << k)

    # Set the kth bit in value n
    # (where k starts with 0 for the least significant bit
    def bitSet(self, n, k):
        return n | (1 << k)

    # Clear the kth bit in value n
    # (where k starts with 0 for the least significant bit
    def bitClear(self, n, k):
        return n ^ (1 << k)

    ## Private methods ---

    ## Read the contents of the registers starting with the starting address,
    ## up to the number of bytes specified.

    def __registerReadNBytes(self, addressHigh, addressLow, numBytesToRead):
        """Implementation of RegisterReadNBytes """
        data = [
            0xa5, 0x08, self.__Command_code.COMMAND_SET_ADDRESS_POINTER.value,
            addressHigh, addressLow,
            self.__Command_code.COMMAND_REGISTER_READ_N_BYTES.value,
            numBytesToRead
        ]
        checksum = 0
        for x in data:
            checksum += x
        # Add checksum at the end
        data.append(checksum % 256)

        write = i2c_msg.write(self._address, data)
        self._bus.i2c_rdwr(write)

        time.sleep(0.05)

        read = i2c_msg.read(self._address, numBytesToRead + 3)
        self._bus.i2c_rdwr(read)

        buf = []
        buf.extend(read)
        # print buf

        return (self.__checkHeaderAndChecksum(numBytesToRead, buf), buf)

    ## Write to the registers, starting from the starting address the number of bytes
    ## specified in the byteArray

    def __registerWriteNBytes(self, addressHigh, addressLow, numBytes,
                              byteArray):
        """Implementation of registerWriteNBytes """
        data = [
            0xa5, numBytes + 8,
            self.__Command_code.COMMAND_SET_ADDRESS_POINTER.value, addressHigh,
            addressLow,
            self.__Command_code.COMMAND_REGISTER_WRITE_N_BYTES.value, numBytes
        ]
        ## data here
        data.extend(byteArray)
        # print data

        ## compute and fill checksum as last element
        checksum = 0
        for x in data:
            checksum += x
        data.append(checksum % 256)

        write = i2c_msg.write(self._address, data)
        self._bus.i2c_rdwr(write)

        time.sleep(0.05)

        header = self._bus.read_byte(self._address)
        self._logger.debug(header)

        return self.__checkHeader(header)

    ## Some commands are issued and just return an ACK (or NAK)
    ## This method factors out those types of commands
    ## and takes in as argument the specified command to issue.

    def __issueAckNackCommand(self, command):
        """Implementation of issueAckNackCommand """
        # header, numBytes, command
        data = [0xa5, 0x04, command]
        checksum = 0
        for x in data:
            checksum += x
        # Add checksum at the end
        data.append(checksum % 256)

        write = i2c_msg.write(self._address, data)
        self._bus.i2c_rdwr(write)

        time.sleep(0.05)

        ## Read the ack
        header = self._bus.read_byte(self._address)
        self._logger.debug(header)

        return self.__checkHeader(header)

    ## Convenience method to check the header and the checksum for the returned data.
    ## If all is good, this method should return SUCCESS

    def __checkHeaderAndChecksum(self, numBytesToRead, byteArray):
        """Implementation of checkHeaderAndChecksum """
        checksumTotal = 0
        header = byteArray[0]
        dataLen = byteArray[1]
        checksum = byteArray[numBytesToRead + 3 - 1]

        for i in range(0, numBytesToRead + 3 - 1):
            checksumTotal += byteArray[i]

        calculatedChecksum = checksumTotal % 256
        error = self.Error_code.SUCCESS.value

        error = self.__checkHeader(header)

        if (calculatedChecksum != checksum):
            error = self.Error_code.ERROR_CHECKSUM_MISMATCH.value

        return error

    ## Convenience method to check the header of the response.
    ## If all is good, this will return SUCCESS

    def __checkHeader(self, header):
        """Implementation of checkHeader """
        error = self.Error_code.SUCCESS.value
        if (header != self.__Response_code.RESPONSE_ACK.value):
            error = self.Error_code.ERROR_INCORRECT_HEADER.value

        if (header == self.__Response_code.RESPONSE_CSFAIL.value):
            error = self.Error_code.ERROR_CHECKSUM_FAIL.value

        return error
Esempio n. 31
0
class Device(object):
    """Class for communicating with an I2C device using the smbus library.
    Allows reading and writing 8-bit, 16-bit, and byte array values to registers
    on the device."""
    def __init__(self, address, busnum):
        """Create an instance of the I2C device at the specified address on the
        specified I2C bus number."""
        self._address = address
        self._bus = SMBus(busnum)

    def writeRaw8(self, value):
        """Write an 8-bit value on the bus (without register)."""
        value = value & 0xFF
        self._bus.write_byte(self._address, value)

    def write8(self, register, value):
        """Write an 8-bit value to the specified register."""
        value = value & 0xFF
        self._bus.write_byte_data(self._address, register, value)

    def write16(self, register, value):
        """Write a 16-bit value to the specified register."""
        value = value & 0xFFFF
        self._bus.write_word_data(self._address, register, value)

    def writeList(self, register, data):
        """Write bytes to the specified register."""
        self._bus.write_i2c_block_data(self._address, register, data)

    def readList(self, register, length):
        """Read a length number of bytes from the specified register.  Results
        will be returned as a bytearray."""
        results = self._bus.read_i2c_block_data(self._address, register,
                                                length)
        return results

    def readRaw8(self):
        """Read an 8-bit value on the bus (without register)."""
        result = self._bus.read_byte(self._address) & 0xFF
        return result

    def readU8(self, register):
        """Read an unsigned byte from the specified register."""
        result = self._bus.read_byte_data(self._address, register) & 0xFF
        return result

    def readS8(self, register):
        """Read a signed byte from the specified register."""
        result = self.readU8(register)
        if result > 127:
            result -= 256
        return result

    def readU16(self, register, little_endian=True):
        """Read an unsigned 16-bit value from the specified register, with the
        specified endianness (default little endian, or least significant byte
        first)."""
        result = self._bus.read_word_data(self._address, register) & 0xFFFF
        # Swap bytes if using big endian because read_word_data assumes little
        # endian on ARM (little endian) systems.
        if not little_endian:
            result = ((result << 8) & 0xFF00) + (result >> 8)
        return result

    def readS16(self, register, little_endian=True):
        """Read a signed 16-bit value from the specified register, with the
        specified endianness (default little endian, or least significant byte
        first)."""
        result = self.readU16(register, little_endian)
        if result > 32767:
            result -= 65536
        return result

    def readU16LE(self, register):
        """Read an unsigned 16-bit value from the specified register, in little
        endian byte order."""
        return self.readU16(register, little_endian=True)

    def readU16BE(self, register):
        """Read an unsigned 16-bit value from the specified register, in big
        endian byte order."""
        return self.readU16(register, little_endian=False)

    def readS16LE(self, register):
        """Read a signed 16-bit value from the specified register, in little
        endian byte order."""
        return self.readS16(register, little_endian=True)

    def readS16BE(self, register):
        """Read a signed 16-bit value from the specified register, in big
        endian byte order."""
        return self.readS16(register, little_endian=False)