def read_from_rpi_to_esp32(): try: # change 1 of SMBus(1) to bus number on your RPI smbus = SMBus(1) # prepare the data packed = None with Packer() as packer: packer.write(register) packer.end() packed = packer.read() raw_list = None smbus.write_bytes(register, bytearray(packed)) time.sleep(0.3) # wait i2c process the request raw_list = list( smbus.read_bytes(register, 5) ) # the read_bytes contains the data format: first, length, data, crc8, end bytes print(raw_list) # let's clean received data unpacked = None with Unpacker as unpacker: unpacker.write(raw_list) unpacked = unpacker.read() return unpacked except Exception as e: print("ERROR: {}".format(e))
def __init__(self, bus=DEFAULT_BUS, addr=DEFAULT_ADDR): self._bus = bus self._address = addr self._smbus = SMBus(bus) self._debug = False self._short_timeout = 0.6 self._long_timeout = 1.4
def write_from_rpi_to_esp32(): try: # change 1 of SMBus(1) to bus number on your RPI smbus = SMBus(1) # prepare the data packed = None with Packer() as packer: packer.write(register) packer.write(value) packer.end() packed = packer.read() smbus.write_bytes(register, bytearray(packed)) except Exception as e: print("ERROR: {}".format(e))
def read_from_rpi_to_esp32(): try: # prepare the data packed = None with Packer() as packer: packer.write(value) packer.end() packed = packer.read() print("in packer") # change 1 of SMBus(1) to bus number on your RPI raw_list = None with SMBus(1) as smbus: smbus.write_bytes(slave_address, bytearray(packed)) #how would the slave know whether to write or receive? time.sleep(0.3) # wait i2c process the request raw_list = list(smbus.read_bytes(slave_address, 5)) # the read_bytes contains the data format: first, length, data, crc8, end bytes rawList = smbus.read_byte(slave_address) #print(rawList) print(raw_list) print("in smbus") # let's clean received data unpacked = None with Unpacker() as unpacker: print("unpacker 1") unpacker.write(raw_list) print("unpacker 2") unpacked = unpacker.read() print("in unpacker") return unpacked except Exception as e: print("ERROR: {}".format(e))
def __init__(self, bus=DEFAULT_BUS, addr=None, moduletype=""): """ @brief create instance of AtlasI2c class @param int => bus i2c bus number @param int/hexa => device i2c address @param string => device module type """ if None is addr or ( addr not in self.ADDR_EZO_HEXA and addr not in self.ADDR_EZO_DECIMAL and addr not in self.ADDR_OEM_HEXA and addr not in self.ADDR_OEM_DECIMAL ): raise Exception( "You have to give a value to addr argument \ take a look on AtlasI2c.ADDR_EZO_HEXA, \ AtlasI2c.ADDR_EZO_DECIMAL, \ AtlasI2c.ADDR_OEM_HEXA \ and AtlasI2c.ADDR_OEM_DECIMAL" ) if moduletype not in self.ALLOWED_MODULES_TYPES: raise Exception( "sorry i can just interact \ with EC or PH moduletype" ) # private properties self._debug = False self._bus_number = bus self._address = addr self._name = moduletype.upper() self._module = moduletype.upper() self._short_timeout = self.SHORT_TIMEOUT self._long_timeout = self.LONG_TIMEOUT self._smbus = SMBus(self._bus_number)
def bus(): try: return SMBus(1) except FileNotFoundError: logger.warning('failed to init SMBus')
class _AtlasOEMI2c: ALLOWED_MODULES_TYPES = { "EC", "PH", } """@brief Array key=>value for each EZO sensors i2c hexa addresses """ ADDR_EZO_HEXA = { 0x61, # DO 0x62, # ORP 0x63, # PH 0x64, # EC } """@brief Array value of each EZO sensors i2c decimal addresses """ ADDR_EZO_DECIMAL = { 97, # DO 98, # ORP 99, # PH 100, # EC } """@brief Array key=>value for each EZO sensors name i2c hexa addresses """ ADDR_EZO_TXT_TO_HEXA = { "DO": 0x61, "ORP": 0x62, "PH": 0x63, "EC": 0x64, } """@brief Array key=>value for each EZO sensors i2c hexa to decimal addresses """ ADDR_EZO_HEXA_TO_DECIMAL = { 0x61: 97, # DO 0x62: 98, # ORP 0x63: 99, # PH 0x64: 100, # EC } """@brief Array key=>value for each OEM sensors i2c hexa addresses """ ADDR_OEM_HEXA = { 0x64, # EC 0x65, # PH 0x66, # ORP 0x67, # DO } """@brief Array value of each OEM sensors decimal addresses """ ADDR_OEM_DECIMAL = { 100, # EC 101, # PH 102, # ORP 103, # DO } """@brief Array key=>value for each OEM sensors name i2c hexa addresses """ ADDR_OEM_TXT_TO_HEXA = { "EC": 0x64, "PH": 0x65, "ORP": 0x66, "DO": 0x67, } """@brief Array key=>value for each OEM sensors i2c hexa to decimal addresses """ ADDR_OEM_HEXA_TO_DECIMAL = { 0x64: 100, # DO 0x65: 101, # ORP 0x66: 102, # PH 0x67: 103, # EC } ONE_BYTE_READ = 0x01 TWO_BYTE_READ = 0x02 THREE_BYTE_READ = 0x03 FOUR_BYTE_READ = 0x04 OEM_EC_REGISTERS = { "device_type": 0x00, "device_firmware": 0x01, "device_addr_lock": 0x02, "device_addr": 0x03, "device_intr": 0x04, "device_led": 0x05, "device_sleep": 0x06, "device_new_reading": 0x07, "device_probe_type_msb": 0x08, # 0x08 - 0x09 2 registers "device_probe_type_lsb": 0x09, # 0x08 - 0x09 2 registers "device_calibration_value_msb": 0x0A, # 0x0A - 0x0D 4 registers "device_calibration_value_high": 0x0B, # 0x0A - 0x0D 4 registers "device_calibration_value_low": 0x0C, # 0x0A - 0x0D 4 registers "device_calibration_value_lsb": 0x0D, # 0x0A - 0x0D 4 registers "device_calibration_request": 0x0E, "device_calibration_confirm": 0x0F, "device_temperature_comp_msb": 0x10, # 0x10 - 0x13 4 registers "device_temperature_comp_high": 0x11, # 0x10 - 0x13 4 registers "device_temperature_comp_low": 0x12, # 0x10 - 0x13 4 registers "device_temperature_comp_lsb": 0x13, # 0x10 - 0x13 4 registers "device_temperature_confirm_msb": 0x14, # 0x14 - 0x17 4 registers "device_temperature_confirm_high": 0x15, # 0x14 - 0x17 4 registers "device_temperature_confirm_low": 0x16, # 0x14 - 0x17 4 registers "device_temperature_confirm_lsb": 0x17, # 0x14 - 0x17 4 registers "device_ec_msb": 0x18, # 0x18 - 0x1B 4 registers "device_ec_high": 0x19, # 0x18 - 0x1B 4 registers "device_ec_low": 0x20, # 0x18 - 0x1B 4 registers "device_ec_lsb": 0x21, # 0x18 - 0x1B 4 registers "device_tds_msb": 0x1C, # 0x1C - 0x1F 3 registers "device_tds_high": 0x1D, # 0x1C - 0x1F 3 registers "device_tds_low": 0x1E, # 0x1C - 0x1F 3 registers "device_tds_lsb": 0x1F, # 0x1C - 0x1F 3 registers "device_salinity_msb": 0x20, # 0x20 - 0x23 4 registers "device_salinity_high": 0x21, # 0x20 - 0x23 4 registers "device_salinity_low": 0x22, # 0x20 - 0x23 4 registers "device_salinity_lsb": 0x23, # 0x20 - 0x23 4 registers } OEM_PH_REGISTERS = { "device_type": 0x00, "device_firmware": 0x01, "device_addr_lock": 0x02, "device_addr": 0x03, "device_intr": 0x04, "device_led": 0x05, "device_sleep": 0x06, "device_new_reading": 0x07, "device_calibration_msb": 0x08, # 0x08 - 0x0B 4 registers "device_calibration_high": 0x09, # 0x08 - 0x0B 4 registers "device_calibration_low": 0x0A, # 0x08 - 0x0B 4 registers "device_calibration_lsb": 0x0B, # 0x08 - 0x0B 4 registers "device_calibration_request": 0x0C, "device_calibration_confirm": 0x0D, "device_temperature_comp_msb": 0x0E, # 0x0E - 0x11 4 registers "device_temperature_comp_high": 0x0F, # 0x0E - 0x11 4 registers "device_temperature_comp_low": 0x10, # 0x0E - 0x11 4 registers "device_temperature_comp_lsb": 0x11, # 0x0E - 0x11 4 registers "device_temperature_confirm_msb": 0x12, # 0x12 - 0x15 4 registers "device_temperature_confirm_high": 0x13, # 0x12 - 0x15 4 registers "device_temperature_confirm_low": 0x14, # 0x12 - 0x15 4 registers "device_temperature_confirm_lsb": 0x15, # 0x12 - 0x15 4 registers "device_ph_msb": 0x16, # 0x16 - 0x19 4 registers "device_ph_high": 0x17, # 0x16 - 0x19 4 registers "device_ph_low": 0x18, # 0x16 - 0x19 4 registers "device_ph_lsb": 0x19, # 0x16 - 0x19 4 registers } # the default bus for I2C on the newer Raspberry Pis, # certain older boards use bus 0 DEFAULT_BUS = 1 # the timeout needed to query readings and calibrations LONG_TIMEOUT = 1.5 # timeout for regular commands SHORT_TIMEOUT = 0.3 LONG_TIMEOUT_COMMANDS = ("R", "CAL") SLEEP_COMMANDS = ("SLEEP",) @property def debug(self): return self._debug @debug.setter def debug(self, d): self._debug = d @property def mysmbus(self): return self._smbus @property def bus_number(self): return self._bus_number @bus_number.setter def bus_number(self, bus_number): self._bus_number = bus_number @property def address(self): return self._address @address.setter def address(self, address): self._address = address @property def short_timeout(self): return self._short_timeout @short_timeout.setter def short_timeout(self, timeout): self._short_timeout = timeout @property def long_timeout(self): return self._long_timeout @long_timeout.setter def long_timeout(self, timeout): self._long_timeout = timeout @property def name(self): return self._name @name.setter def name(self, name): self._name = name @property def moduletype(self): return self._module @moduletype.setter def moduletype(self, m): self._module = m.upper() def __init__(self, bus=DEFAULT_BUS, addr=None, moduletype=""): """ @brief create instance of AtlasI2c class @param int => bus i2c bus number @param int/hexa => device i2c address @param string => device module type """ if None is addr or ( addr not in self.ADDR_EZO_HEXA and addr not in self.ADDR_EZO_DECIMAL and addr not in self.ADDR_OEM_HEXA and addr not in self.ADDR_OEM_DECIMAL ): raise Exception( "You have to give a value to addr argument \ take a look on AtlasI2c.ADDR_EZO_HEXA, \ AtlasI2c.ADDR_EZO_DECIMAL, \ AtlasI2c.ADDR_OEM_HEXA \ and AtlasI2c.ADDR_OEM_DECIMAL" ) if moduletype not in self.ALLOWED_MODULES_TYPES: raise Exception( "sorry i can just interact \ with EC or PH moduletype" ) # private properties self._debug = False self._bus_number = bus self._address = addr self._name = moduletype.upper() self._module = moduletype.upper() self._short_timeout = self.SHORT_TIMEOUT self._long_timeout = self.LONG_TIMEOUT self._smbus = SMBus(self._bus_number) def read(self, register, num_of_bytes=1): """ @brief """ if num_of_bytes > 1: raw = self._smbus.read_i2c_block_data(self._address, register, num_of_bytes) else: raw = self._smbus.read_byte_data(self._address, register) if self._debug: print("Read: %s registers start from: %s" % (num_of_bytes, hex(register))) print("Raw response from i2c: ", raw) return raw def _prepare_values_to_write_block(self, v): """ @brief from AdafruitPureIO smbus class the write_block_data(self, addr, cmd, vals) need specific data organisation to work: >> `Write a block of data to the specified cmd register of the device. The amount of data to write should be the first byte inside the vals string/bytearray and that count of bytes of data to write should follow it.` """ b = bytearray(len(v) + 1) b[0] = len(v) i = 1 for elm in v: b[i] = hex(elm) i += 1 return b def write(self, register, v): """ @brief """ if("int" != type(v).__name__ and len(v) > 1 and ("bytearray" == type(v).__name__ or "bytes" == type(v).__name__) ): # v = self._prepare_values_to_write_block(v) # self._smbus.write_block_data(self._address, register, v) self.mysmbus.write_i2c_block_data(self._address, register, v) elif "int" == type(v).__name__: self.mysmbus.write_byte_data(self._address, register, v) else: # "str" == type(v).__name__: raise Exception("cannot write this in smbus/i2c: ", v) if self._debug: print("Write %s on register: %s" % (v, hex(register))) def list_i2c_devices(self): """ @brief save the current address so we can restore it after """ with I2C(self._bus_number) as i2c: scan = i2c.scan() if self._debug: print("I2c devices found: ", scan) return scan def print_all_registers_values(self): if "EC" == self._module: registers = self.OEM_EC_REGISTERS elif "PH" == self._module: registers = self.OEM_PH_REGISTERS for reg in range(0, len(registers)): print("Register: %s, Value: %s" % (hex(reg), self.read(reg)))
class WaterPumpDriver: DEFAULT_BUS = 1 DEFAULT_ADDR = 0x01 """@brief I2C Registers Array key=>value for each i2c register you can read """ I2C_REGISTERS = { "TYPE": 0x00, # i2c Read Only "FIRMWARE": 0x01, # i2c Read Only "UUID": 0x02, # i2c Read Only "I2C_ADDRESS": 0x03, # i2c Read / Write "LED_ACTIVATION": 0x04, # i2c Read / Write "WATER_PUMP_STATE": 0x05, # i2c Read / Write "PUMP_1_STATE": 0x06, # i2c Read / Write "PUMP_2_STATE": 0x07, # i2c Read / Write "PUMP_3_STATE": 0x08, # i2c Read / Write "PUMP_4_STATE": 0x09, # i2c Read / Write "ALL": 0x20, # i2c Read } """@brief Ordering Pumps Registers Array key=>value pump number to i2c register converter """ PUMP_REGISTERS = { 0: I2C_REGISTERS["WATER_PUMP_STATE"], 1: I2C_REGISTERS["PUMP_1_STATE"], 2: I2C_REGISTERS["PUMP_2_STATE"], 3: I2C_REGISTERS["PUMP_3_STATE"], 4: I2C_REGISTERS["PUMP_4_STATE"], } """@brief I2C Devices Array key=>value for each i2c device type you can read on the bus """ I2C_DEVICES_TYPE = 1 """@brief I2C command Array key=>value for each command can be send through bus """ I2C_COMMANDS = {"OFF": 0x00, "ON": 0x01} def __init__(self, bus=DEFAULT_BUS, addr=DEFAULT_ADDR): self._bus = bus self._address = addr self._smbus = SMBus(bus) self._debug = False self._short_timeout = 0.6 self._long_timeout = 1.4 @property def bus(self): return self._bus @property def address(self): return self._address @property def short_timeout(self): return self._short_timeout @property def long_timeout(self): return self._long_timeout @property def debug(self): return self._debug @short_timeout.setter def short_timeout(self, t): self._short_timeout = t @long_timeout.setter def long_timeout(self, t): self._long_timeout = t @debug.setter def debug(self, d): self._debug = d def __enter__(self): """Context manager enter function.""" # Just return this object so it can be used in a with statement, like # # do stuff! return self def __exit__(self, exc_type, exc_val, exc_tb): """Context manager exit function, ensures resources are cleaned up.""" self._smbus.close() return False # Don't suppress exceptions. def __del__(self): """Clean up any resources instance.""" self._smbus.close() def _device_is_water_pump(self): try: device_type = None try: with Packer() as packer: # packer.debug = True # first write => the register address we want read/write packer.write(self.I2C_REGISTERS["TYPE"]) packer.end() self._smbus.write_bytes(self._address, bytearray(packer.read())) except Exception as e: print("ERROR: on packer, {}".format(e)) try: sleep(self._short_timeout) raw = self._smbus.read_bytes( self._address, 5) # read 5 bytes from slave due to data format if self._debug: print("Raw data from i2c: ", raw) except Exception as e: print("ERROR: on smbus, {}".format(e)) try: with Unpacker() as unpacker: # unpacker.debug = True unpacker.write(raw) device_type = unpacker.read()[ 0] # type data is the first field of list except Exception as e: print("ERROR: on unpack, {}".format(e)) return device_type == self.I2C_DEVICES_TYPE except Exception as e: print("ERROR: on device type check {}".format(e)) def read(self, register: int, num_of_bytes: int = 5): """ @brief read data from i2c bus @param register > int i2c register to read @param num_of_byte > int number of bytes to read started from the register by default num_of_bytes = 5 because the data format from ESP32 i2c slave is 5 length more information on Packer() and Unpacker() classes @return list """ # if not self._device_is_water_pump(): # raise Exception("Current device type is not a water pump") # else: try: unpacked = None try: with Packer() as packer: packer.write(register) packer.end() packed = packer.read() if self._debug: print("packed: ", packed) self._smbus.write_bytes(self._address, bytearray(packed)) except Exception as e: print("ERROR: on packer, {}".format(e)) try: sleep(self._short_timeout) # let the bus process first write raw = self._smbus.read_bytes(self._address, num_of_bytes) if self._debug: print("Raw data from i2c: ", raw) except Exception as e: print("ERROR: on smbus, {}".format(e)) try: with Unpacker() as unpacker: unpacker.write(list(raw)) unpacked = unpacker.read() except Exception as e: print("ERROR: on unpacker, {}".format(e)) if self._debug: print("Read: %s registers start from: %s" % (num_of_bytes, hex(register))) print("Get values: ", unpacked) return unpacked except Exception as e: print("ERROR: on read, {}".format(e)) def write(self, register: int, value=None): """ @brief write data through i2c bus @param register > int/byte i2c register to read @param value > int/list to be write through i2c """ # if not self._device_is_water_pump(): # raise Exception("Current device type is not a water pump") # else: try: with Packer() as packer: # first write => the register address we want read/write packer.write(register) # if value == None we just write register we want read into the i2c bus and then read the value if None is not value: if int is not type(value) and list is type(value): for elm in value: packer.write(elm) elif int is type(value): packer.write(value) else: raise Exception("cannot format this kind of data: ", value) packer.end() # finish data formatting packed = packer.read() except Exception as e: print("ERROR: {0}, cannot use packer yo prepare data".format(e)) try: self._smbus.write_bytes(self._address, bytearray(packed)) except Exception as e: print( "ERROR: {0}, when write data on i2c: ".format(e), packed, ) if self._debug: print("Write %s on register: %s" % (value, hex(register))) def list_i2c_devices(self): """ @brief list all i2c device on the current bus @return list of addresses """ try: with I2C(self._bus) as i2c: scan = i2c.scan() if self._debug: print("I2c devices found: ", scan) return scan except Exception as e: print("ERROR: Exception occured during get i2c devices list", e) def print_all_registers_values(self): """ @brief print all i2c register value on the cli """ try: for reg in range(0, len(self.I2C_REGISTERS)): print("Register: %s, Value: %s" % (hex(reg), self.read(reg))) except Exception as e: print("ERROR: Exception occured during get all registers values", e) # ----- getters ----- # def get_all(self): """ @brief get the device type @return dict all i2c registers values """ try: # 13 registers to read from the i2c slave to get all values # add 4 bytes to add data format _all = self.read(self.I2C_REGISTERS["ALL"], 17) if self._debug: print("ask for all registers: %s" % _all) return _all except Exception as e: print("ERROR: Exception occured during get type", e) def get_type(self): """ @brief get the device type @return int 1=>water pump """ try: _type = self.read(self.I2C_REGISTERS["TYPE"])[0] if self._debug: print("ask for type: %s" % _type) return _type except Exception as e: print("ERROR: Exception occured during get type", e) def get_firmware(self): """ @brief get the device type @return int 2=>firmware rev 2 """ try: firmware = self.read(self.I2C_REGISTERS["FIRMWARE"])[0] if self._debug: print("ask for firmware: %s" % firmware) return firmware except Exception as e: print("ERROR: Exception occured during get firmware", e) def get_uuid(self): """ @brief get the device uuid @return 8 bytes 5241224745987163 => device uuid """ try: # ask for 12 bytes because uuid is 8 bytes long + 4 bytes for data formatting uuid = "".join(map(str, self.read(self.I2C_REGISTERS["UUID"], 12))) if self._debug: print("ask for uuid: %s" % uuid) return uuid except Exception as e: print("ERROR: Exception occured during get uuid", e) def get_i2c_address(self): """ @brief get the device i2c address @return int 100=>address 100 = 0x64 """ try: add = self.read(self.I2C_REGISTERS["I2C_ADDRESS"])[0] if self._debug: print("ask for add: %s" % add) return add except Exception as e: print("ERROR: Exception occured during get address", e) def get_led_status(self): """ @brief get the device leds status @return int 0=>LEDs OFF / 1=>LEDs ON """ try: led_status = self.read(self.I2C_REGISTERS["LED_ACTIVATION"])[0] if self._debug: print("ask for led status: %s" % led_status) return led_status except Exception as e: print("ERROR: Exception occured during get LEDs status", e) def get_pump_status(self, pump_register: int): """ @brief get the pump status @param int pump register to ask @return int 0=>pump OFF / 1=>pump ON """ try: status = self.read(pump_register)[0] if self._debug: print("ask for pump: %s status: %s" % (pump_register, status)) return status except Exception as e: print("ERROR: Exception occured during get pump status", e) # ----- setters ----- # def set_i2c_address(self, addr: int): """ @brief set water pump i2c address @param int addr => new address """ try: self.write(self.I2C_REGISTERS["I2C_ADDRESS"], addr) except Exception as e: print("ERROR: Exception occured during set i2c address", e) def set_led_status(self, status: int): """ @brief set water pump LEDs activation @param int status => new status 0=>OFF / 1=>ON """ try: self.write(self.I2C_REGISTERS["LED_ACTIVATION"], status) except Exception as e: print("ERROR: Exception occured during set LEDs status", e) def set_pump_command(self, pump_register: int, command: int): """ @brief set command pump @param int pump_register to set @param int command 0=>pump OFF / 1=>pump ON """ try: self.write(pump_register, command) if self._debug: print("Pump: %s, Command passed: %s" % (pump_register, command)) except Exception as e: print("ERROR: Exception occured during set pump command", e)
from Adafruit_PureIO.smbus import SMBus import struct import time from utils import bytes_to_str HEART_ADDR = 0x09 bus = SMBus(1) estimated_value = 127 errors = [] n = 0 bus.write_bytes(HEART_ADDR, b'\x7f\x00') time.sleep(.1) for n in range(2**32): raw_data = bus.read_bytes(HEART_ADDR, 2) val = struct.unpack('h', raw_data)[0] s = bytes_to_str(raw_data[0], raw_data[1]) print(s + " | " + str(val) + " | " + str(estimated_value) + " [ " + str(len(errors)) + " / " + str(n) + " ]" + str(errors)) if estimated_value != val: errors.append(estimated_value) estimated_value += 1 if estimated_value == 1024: estimated_value = 0 # data = bus.read_word_data(HEART_ADDR, 1) # input('press a key') time.sleep(.03) # timing here is super sensitive