class MTSMBus(I2CBus): """ Multi-thread compatible SMBus bus. This is just a wrapper of SMBus, serializing I/O on the bus for use in multi-threaded context and adding _i2c_ variants of block transfers. """ def __init__(self, bus_id=1, **kwargs): """ :param int bus_id: the SMBus id (see Raspberry Pi documentation) :param kwargs: parameters transmitted to :py:class:`smbus.SMBus` initializer """ I2CBus.__init__(self, **kwargs) self._bus = SMBus(bus_id) # I/O serialization lock self._lock = threading.Lock() def read_byte(self, addr): with self._lock: return self._bus.read_byte(addr) def write_byte(self, addr, data): with self._lock: self._bus.write_byte(addr, data) def read_byte_data(self, addr, reg): with self._lock: return self._bus.read_byte_data(addr, reg) def write_byte_data(self, addr, reg, data): with self._lock: self._bus.write_byte_data(addr, reg, data) def read_word_data(self, addr, reg): with self._lock: return self._bus.read_word_data(addr, reg) def write_word_data(self, addr, reg, data): with self._lock: self._bus.write_word_data(addr, reg, data) def read_block_data(self, addr, reg): with self._lock: return self._bus.read_block_data(addr, reg) def write_block_data(self, addr, reg, data): with self._lock: self._bus.write_block_data(addr, reg, data) def read_i2c_block_data(self, addr, reg, count): with self._lock: return self._bus.read_i2c_block_data(addr, reg, count) def write_i2c_block_data(self, addr, reg, data): with self._lock: self._bus.write_i2c_block_data(addr, reg, data)
class LocalhostSMBusSlave(SMBusSlave): def __init__(self, bus, address): SMBusSlave.__init__(self, bus, address) self.bus = SMBus(bus) self.address = address #return: one byte hex string without '0x': '12' def get_byte(self, offset): # print "%s %s" % (datetime.datetime.utcnow().strftime("%H:%M:%S.%f")[:-4], sys._getframe().f_code.co_name) ret = self.bus.read_byte_data(self.address, offset) time.sleep(self.interval) data = hex(ret) return data[2:].zfill(2) #input: offset:str, data:int def set_byte(self, offset, data): # print "%s %s" % (datetime.datetime.utcnow().strftime("%H:%M:%S.%f")[:-4], sys._getframe().f_code.co_name) self.bus.write_byte_data(self.address, offset, data) time.sleep(self.interval) #return: two byte hex string without '0x': '1234' def get_word(self, offset): # print "%s %s" % (datetime.datetime.utcnow().strftime("%H:%M:%S.%f")[:-4], sys._getframe().f_code.co_name) ret = self.bus.read_word_data(self.address, offset) data = hex(ret) time.sleep(self.interval) return data[2:].zfill(4) def set_word(self, offset, data): # print "%s %s" % (datetime.datetime.utcnow().strftime("%H:%M:%S.%f")[:-4], sys._getframe().f_code.co_name) if sys.byteorder == "big": data = ((data & 0xff00) >> 8) + ((data & 0x00ff) << 8) self.bus.write_word_data(self.address, offset, data) time.sleep(self.interval) #return: hex string list per byte,without '0x' :['12', '0a'] def get_block(self, offset, length="32"): # print "%s %s" % (datetime.datetime.utcnow().strftime("%H:%M:%S.%f")[:-4], sys._getframe().f_code.co_name) ret = self.bus.read_block_data(self.address, offset) time.sleep(self.interval) hex_ret = [hex(i)[2:].zfill(2) for i in ret] return hex_ret def set_block(self, offset, data): # print "%s %s" % (datetime.datetime.utcnow().strftime("%H:%M:%S.%f")[:-4], sys._getframe().f_code.co_name) data_arr = [(data & 0x00ff), ((data & 0xff00) >> 8)] #self.bus.write_i2c_block_data(self.address, offset, data_arr) self.bus.write_block_data(self.address, offset, data_arr) time.sleep(self.interval)
class I2CDevice: def __init__(self, addr=None, addr_default=None, bus=BUS_NUMBER): if not addr: # try autodetect address, else use default if provided try: self.addr = int('0x{}'.format( findall("[0-9a-z]{2}(?!:)", check_output(['/usr/sbin/i2cdetect', '-y', str(BUS_NUMBER)]).decode())[0]), base=16) \ if exists('/usr/sbin/i2cdetect') else addr_default except: self.addr = addr_default else: self.addr = addr self.bus = SMBus(bus) # 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)
class LinuxI2cBus: """A Linux I²C device, which is itself an I²C bus. Should not be instantiated directly; use `LinuxI2c.find_devices` instead. This type mimics the `smbus.SMBus` read/write/close APIs. However, `open` does not take any parameters, and not all APIs are available. """ # note: this is not a liquidctl BaseBus, as that would cause # find_liquidctl_devices to try to directly instantiate it def __init__(self, i2c_dev): self._i2c_dev = i2c_dev self._smbus = None try: assert i2c_dev.name.startswith('i2c-') self._number = int(i2c_dev.name[4:]) except: raise ValueError(f'cannot infer bus number') def find_devices(self, drivers, **kwargs): """Probe drivers and find compatible devices in this bus.""" for drv in drivers: yield from drv.probe(self, **kwargs) def open(self): """Open the I²C bus.""" if not self._smbus: try: self._smbus = SMBus(self._number) except FileNotFoundError: if Path('/sys/class/i2c-dev').exists(): raise raise OSError('kernel module i2c-dev not loaded') from None def read_byte(self, address): """Read a single byte from a device.""" value = self._smbus.read_byte(address) _LOGGER.debug('read byte @ 0x%02x: 0x%02x', address, value) return value def read_byte_data(self, address, register): """Read a single byte from a designated register.""" value = self._smbus.read_byte_data(address, register) _LOGGER.debug('read byte data @ 0x%02x:0x%02x: 0x%02x', address, register, value) return value def read_word_data(self, address, register): """Read a single 2-byte word from a given register.""" value = self._smbus.read_word_data(address, register) _LOGGER.debug('read word data @ 0x%02x:0x%02x: 0x%04x', address, register, value) return value def read_block_data(self, address, register): """Read a block of up to 32 bytes from a given register.""" data = self._smbus.read_block_data(address, register) _LOGGER.debug('read block data @ 0x%02x:0x%02x: %r', address, register, LazyHexRepr(data)) return data def write_byte(self, address, value): """Write a single byte to a device.""" _LOGGER.debug('writing byte @ 0x%02x: 0x%02x', address, value) return self._smbus.write_byte(address, value) def write_byte_data(self, address, register, value): """Write a single byte to a designated register.""" _LOGGER.debug('writing byte data @ 0x%02x:0x%02x: 0x%02x', address, register, value) return self._smbus.write_byte_data(address, register, value) def write_word_data(self, address, register, value): """Write a single 2-byte word to a designated register.""" _LOGGER.debug('writing word data @ 0x%02x:0x%02x: 0x%04x', address, register, value) return self._smbus.write_word_data(address, register, value) def write_block_data(self, address, register, data): """Write a block of byte data to a given register.""" _LOGGER.debug('writing block data @ 0x%02x:0x%02x: %r', address, register, LazyHexRepr(data)) return self._smbus.write_block_data(address, register, data) def close(self): """Close the I²C connection.""" if self._smbus: self._smbus.close() self._smbus = None def load_eeprom(self, address): """Return EEPROM name and data in `address`, or None if N/A.""" # uses kernel facilities to avoid directly reading from the EEPROM # or managing its pages, also avoiding the need for unsafe=smbus dev = f'{self._number}-{address:04x}' try: name = self._i2c_dev.joinpath(dev, 'name').read_text().strip() eeprom = self._i2c_dev.joinpath(dev, 'eeprom').read_bytes() return LinuxEeprom(name, eeprom) except Exception as err: return None @property def name(self): return self._i2c_dev.name @property def description(self): return self._try_sysfs_read('name') @property def parent_vendor(self): return self._try_sysfs_read_hex('device/vendor') @property def parent_device(self): return self._try_sysfs_read_hex('device/device') @property def parent_subsystem_vendor(self): return self._try_sysfs_read_hex('device/subsystem_vendor') @property def parent_subsystem_device(self): return self._try_sysfs_read_hex('device/subsystem_device') @property def parent_driver(self): try: return Path( os.readlink(self._i2c_dev.joinpath('device/driver'))).name except FileNotFoundError: return None def __str__(self): if self.description: return f'{self.name}: {self.description}' return self.name def __repr__(self): def hexid(maybe): if maybe is not None: return f'{maybe:#06x}' return 'None' return f'{self.__class__.__name__}: name: {self.name!r}, ' \ f'description: {self.description!r}, ' \ f'parent_vendor: {hexid(self.parent_vendor)}, ' \ f'parent_device: {hexid(self.parent_device)}, ' \ f'parent_subsystem_vendor: {hexid(self.parent_subsystem_vendor)}, ' \ f'parent_subsystem_device: {hexid(self.parent_subsystem_device)}, ' \ f'parent_driver: {self.parent_driver!r}' def _try_sysfs_read(self, *sub, default=None): try: return self._i2c_dev.joinpath(*sub).read_text().rstrip() except FileNotFoundError: return default def _try_sysfs_read_hex(self, *sub, default=None): try: return int(self._i2c_dev.joinpath(*sub).read_text(), base=16) except FileNotFoundError: return default
# DroneBot Workshop 2019 # https://dronebotworkshop.com # https://raspberrypi.stackexchange.com/questions/8469/meaning-of-cmd-param-in-write-i2c-block-data # http://wiki.erazor-zone.de/wiki%3alinux%3apython%3asmbus%3adoc from smbus import SMBus import time from pdb import set_trace as st from sys import exit addr = 0x8 # bus address bus = SMBus(1) # indicates /dev/ic2-1 steerings = ['b', 'b', 't', 'b', 't', 't', 'b', 'b'] durations = [200, 134, 855, 565, 777, 254, 686, 741] i = 0 while i < len(steerings): steering = ord(steerings[i]) x_duration = "{:05}".format(durations[i]) duration = [ord(d) for d in x_duration] print("%s %i %i %s" % (steerings[i], steering, durations[i], duration)) bus.write_block_data(addr, steering, duration) time.sleep(0.95) i += 1 time.sleep(0.1)
bus = SMBus(1) # indicates /dev/ic2-1 """ while 1: nb = input(">>>> ") if int(nb) == 9: exit() msg= bus.read_i2c_block_data(addr, 7) st() """ while 1: print("combien de nombres a envoyer...") nb = input(">>>> ") msg = [x + 48 for x in list(range(int(nb)))] print(msg) bus.write_block_data(addr, 7, msg) if int(nb) == 9: break time.sleep(0.1) """ while 1: nb = input('>>>> ') lec = bus.read_byte(addr) print(type(lec)) print(lec) print("\n") if int(nb) == 9: break; """ # time.sleep(1)
if len(data) != expected_data: print( f"Input is {len(data)} ints long. Must be {expected_data} ({int(expected_data/4)} sets of 4)" ) else: vals = [] for i in range(int(expected_data / 4)): # Take sets of 4 integers and remove '0x' from hex() value hexState = hex(int(data[i * 4:(i + 1) * 4]))[2:] # Forward pad sets of 4 hex values with 0s while len(hexState) < 4: hexState = "0" + hexState print(f"state hex: {hexState}") vals.append(int(hexState[0:2], 16)) vals.append(int(hexState[2:4], 16)) print(f"vals: {vals}") bus.write_block_data(addr, 0x2, vals) time.sleep(1.0 / 1000.0) # response = "message passed to Teensy over I2C" # sock.sendall(response.encode('utf-8')) finally: print("closing socket") sock.close()
from smbus import SMBus addr = 0x8 # bus address bus = SMBus(0) # indicates /dev/ic2-0 numb = 1 while numb == 1: read = input("Read madthya write ah? "); if read == 0: #commands = input(">>>> ") #numbers = [int(i) for i in list(commands.split(" "))] num = [12,13,14] bus.write_block_data(addr,6,num) elif read == 1: n=3 a = [] for i in range(n): a.append(bus.read_byte_data(addr,200)) print(a) else: numb = 0
class LinuxI2cBus: """A Linux I²C device, which is itself an I²C bus. Should not be instantiated directly; use `LinuxI2c.find_devices` instead. This type mimics the `smbus.SMBus` read/write/close APIs. However, `open` does not take any parameters, and not all APIs are available. """ # note: this is not a liquidctl BaseBus, as that would cause # find_liquidctl_devices to try to directly instantiate it def __init__(self, i2c_dev): if not i2c_dev.name.startswith('i2c-'): raise ValueError('not a bus or unsupported adapter') self._i2c_dev = i2c_dev self._smbus = None self._number = int(i2c_dev.name[4:]) def find_devices(self, drivers, **kwargs): """Probe drivers and find compatible devices in this bus.""" for drv in drivers: yield from drv.probe(self, **kwargs) def open(self): """Open the I²C bus.""" if not self._smbus: try: self._smbus = SMBus(self._number) except FileNotFoundError: if Path('/sys/class/i2c-dev').exists(): raise raise OSError('kernel module i2c-dev not loaded') from None def read_byte(self, address): """Read a single byte from a device.""" value = self._smbus.read_byte(address) _LOGGER.debug('read byte @ 0x%02x:0x%02x', address, value) return value def read_byte_data(self, address, register): """Read a single byte from a designated register.""" value = self._smbus.read_byte_data(address, register) _LOGGER.debug('read byte data @ 0x%02x:0x%02x 0x%02x', address, register, value) return value def read_word_data(self, address, register): """Read a single 2-byte word from a given register.""" value = self._smbus.read_word_data(address, register) _LOGGER.debug('read word data @ 0x%02x:0x%02x 0x%02x', address, register, value) return value def read_block_data(self, address, register): """Read a block of up to 32 bytes from a given register.""" data = self._smbus.read_block_data(address, register) _LOGGER.debug('read block data @ 0x%02x:0x%02x: %r', address, register, LazyHexRepr(data)) return data def write_byte(self, address, value): """Write a single byte to a device.""" _LOGGER.debug('writing byte @ 0x%02x: 0x%02x', address, value) return self._smbus.write_byte(address, value) def write_byte_data(self, address, register, value): """Write a single byte to a designated register.""" _LOGGER.debug('writing byte data @ 0x%02x:0x%02x 0x%02x', address, register, value) return self._smbus.write_byte_data(address, register, value) def write_word_data(self, address, register, value): """Write a single 2-byte word to a designated register.""" _LOGGER.debug('writing word data @ 0x%02x:0x%02x 0x%02x', address, register, value) return self._smbus.write_word_data(address, register, value) def write_block_data(self, address, register, data): """Write a block of byte data to a given register.""" _LOGGER.debug('writing block data @ 0x%02x:0x%02x %r', address, register, LazyHexRepr(data)) return self._smbus.write_block_data(address, register, data) def close(self): """Close the I²C connection.""" if self._smbus: self._smbus.close() self._smbus = None def load_eeprom(self, address): """Return EEPROM name and data in `address`, or None if N/A.""" # uses kernel facilities to avoid directly reading from the EEPROM # or managing its pages, also avoiding the need for unsafe=smbus dev = f'{self._number}-{address:04x}' try: name = self._i2c_dev.joinpath(dev, 'name').read_text().strip() # work around a bug in the kernel by reading the ee1004 eeprom # in small enough chunks # related: #416 ("DDR4 support broken on Linux 5.16.3") # related: https://lore.kernel.org/lkml/[email protected]/ eeprom_path = self._i2c_dev.joinpath(dev, 'eeprom') eeprom_size = eeprom_path.stat().st_size _LOGGER.debug('path=%s, size=%s', eeprom_path, eeprom_size) with eeprom_path.open(mode='rb', buffering=0) as f: eeprom = bytearray() while len(eeprom) < eeprom_size: b = f.read(128) if not b: break eeprom.extend(b) return LinuxEeprom(name, eeprom) except FileNotFoundError: return None @property def name(self): return self._i2c_dev.name @property def description(self): return self._try_sysfs_read('name') @property def parent_vendor(self): return self._try_sysfs_read_hex('device/vendor') @property def parent_device(self): return self._try_sysfs_read_hex('device/device') @property def parent_subsystem_vendor(self): return self._try_sysfs_read_hex('device/subsystem_vendor') @property def parent_subsystem_device(self): return self._try_sysfs_read_hex('device/subsystem_device') @property def parent_driver(self): try: return Path(os.readlink(self._i2c_dev.joinpath('device/driver'))).name except FileNotFoundError: return None def __str__(self): if self.description: return f'{self.name}: {self.description}' return self.name def __repr__(self): def hexid(maybe): if maybe is not None: return f'{maybe:#06x}' return 'None' return f'{self.__class__.__name__}: name: {self.name!r}, description:' \ f' {self.description!r}, parent_vendor: {hexid(self.parent_vendor)},' \ f' parent_device: {hexid(self.parent_device)}, parent_subsystem_vendor:' \ f' {hexid(self.parent_subsystem_vendor)},' \ f' parent_subsystem_device: {hexid(self.parent_subsystem_device)},' \ f' parent_driver: {self.parent_driver!r}' def _try_sysfs_read(self, *sub, default=None): try: return self._i2c_dev.joinpath(*sub).read_text().rstrip() except FileNotFoundError: return default def _try_sysfs_read_hex(self, *sub, default=None): try: return int(self._i2c_dev.joinpath(*sub).read_text(), base=16) except FileNotFoundError: return default