From 3a1339cb714abe559d69a5a3fbbac26c1e7fc849 Mon Sep 17 00:00:00 2001 From: Drew Fustini Date: Mon, 22 Oct 2018 20:27:16 +0000 Subject: [PATCH 1/4] Fix I2C init error on BeagleBone Black This init method verifies that a device exists at the given address. It was writing a zero byte value to the bus. This triggered a bug in the Linux kernel I2C bus OMAP2 driver for the BeagleBone. The driver returns an invalid write error when msg->len is 0: https://github.com/beagleboard/linux/blob/4.14/drivers/i2c/busses/i2c-omap.c#L665 The solution is to write the value 'x' instead of ''. Refer to Adafruit_Blinka PR #42 for more information: https://github.com/adafruit/Adafruit_Blinka/pull/42#issuecomment-431948703 --- adafruit_bus_device/i2c_device.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/adafruit_bus_device/i2c_device.py b/adafruit_bus_device/i2c_device.py index bbf6f24..dffdd52 100644 --- a/adafruit_bus_device/i2c_device.py +++ b/adafruit_bus_device/i2c_device.py @@ -57,11 +57,11 @@ class I2CDevice: device.write(bytes_read) """ def __init__(self, i2c, device_address): - # Verify that a device with that address exists. + # write non-zero byte value to verify device exists at address while not i2c.try_lock(): pass try: - i2c.writeto(device_address, b'') + i2c.writeto(device_address, b'x') except OSError: raise ValueError("No I2C device at address: %x" % device_address) finally: From 796e0a1e357a609c4984cc827620b9b37ba28744 Mon Sep 17 00:00:00 2001 From: Drew Fustini Date: Mon, 29 Oct 2018 18:57:09 +0000 Subject: [PATCH 2/4] modify i2c init to fix issue on BeagleBone instead of writing a zero byte, try to read a byte from an address if you get an OSError it means the device is not there this fixes issue for BealgeBone Black in Adafruit_Blinka https://github.com/adafruit/Adafruit_Blinka/pull/42 --- adafruit_bus_device/i2c_device.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/adafruit_bus_device/i2c_device.py b/adafruit_bus_device/i2c_device.py index dffdd52..c2213a9 100644 --- a/adafruit_bus_device/i2c_device.py +++ b/adafruit_bus_device/i2c_device.py @@ -57,11 +57,15 @@ class I2CDevice: device.write(bytes_read) """ def __init__(self, i2c, device_address): - # write non-zero byte value to verify device exists at address + """ + Try to read a byte from an address, + if you get an OSError it means the device is not there + """ while not i2c.try_lock(): pass try: - i2c.writeto(device_address, b'x') + result = bytearray(2) + i2c.readfrom_into(device_address, result) except OSError: raise ValueError("No I2C device at address: %x" % device_address) finally: From 793537e64bffcb005dda8de0f11f62bc72763b42 Mon Sep 17 00:00:00 2001 From: Drew Fustini Date: Mon, 29 Oct 2018 19:38:46 +0000 Subject: [PATCH 3/4] change the i2c init to just read 1 byte it is not needed to read more than 1 byte just to verify that the i2c device is present --- adafruit_bus_device/i2c_device.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_bus_device/i2c_device.py b/adafruit_bus_device/i2c_device.py index c2213a9..1310769 100644 --- a/adafruit_bus_device/i2c_device.py +++ b/adafruit_bus_device/i2c_device.py @@ -64,7 +64,7 @@ def __init__(self, i2c, device_address): while not i2c.try_lock(): pass try: - result = bytearray(2) + result = bytearray(1) i2c.readfrom_into(device_address, result) except OSError: raise ValueError("No I2C device at address: %x" % device_address) From aea9d07e8f60d79d5e5043a48b6b4f50e35dfc31 Mon Sep 17 00:00:00 2001 From: Drew Fustini Date: Mon, 19 Nov 2018 19:15:48 +0000 Subject: [PATCH 4/4] Attempt to write then fall back to read for i2c detect This approach was suggested by ladyada in Adafruit_CircuitPython_BusDevice PR #22: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice/pull/22#issuecomment-435209002 > ok tested with a plethora of sensors and the VEML6075 hates this > so turns out you actually need something like.... def __init__(self, i2c, device_address): """ Try to read a byte from an address, if you get an OSError it means the device is not there """ while not i2c.try_lock(): pass try: i2c.writeto(device_address, b'') except OSError: # some OS's dont like writing an empty bytesting... # Retry by reading a byte try: result = bytearray(1) i2c.readfrom_into(device_address, result) except OSError: raise ValueError("No I2C device at address: %x" % device_address) finally: i2c.unlock() self.i2c = i2c self.device_address = device_address --- adafruit_bus_device/i2c_device.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/adafruit_bus_device/i2c_device.py b/adafruit_bus_device/i2c_device.py index 1310769..5dea936 100644 --- a/adafruit_bus_device/i2c_device.py +++ b/adafruit_bus_device/i2c_device.py @@ -56,6 +56,7 @@ class I2CDevice: with device: device.write(bytes_read) """ + def __init__(self, i2c, device_address): """ Try to read a byte from an address, @@ -64,10 +65,15 @@ def __init__(self, i2c, device_address): while not i2c.try_lock(): pass try: - result = bytearray(1) - i2c.readfrom_into(device_address, result) + i2c.writeto(device_address, b'') except OSError: - raise ValueError("No I2C device at address: %x" % device_address) + # some OS's dont like writing an empty bytesting... + # Retry by reading a byte + try: + result = bytearray(1) + i2c.readfrom_into(device_address, result) + except OSError: + raise ValueError("No I2C device at address: %x" % device_address) finally: i2c.unlock()