I am maintaining a MAX30102 I2C sensor driver.
I am not aware of any best practices, so I took inspiration from I2C drivers here and there, and the library (as of today) basically requires the user to create a SoftI2C instance, which will then be used to communicate with the target sensor.
When the class gets instantiated, it performs a check for ensuring that the target sensor is connected to the I2C bus:
Code: Select all
try:
self._i2c.readfrom(self._address, 1)
except OSError as error:
if error.errno == uerrno.ENODEV:
raise RuntimeError("Sensor not found on I2C bus.")
else:
raise RuntimeError(f"Error while reading from I2C bus: OSError code {error.errno}")
Assuming that I2C pins are correct, consider the following snippet:
Code: Select all
i2c = SoftI2C(sda=Pin(22), scl=Pin(21), freq=400000)
# i2c.scan()
sensor = MAX30102(i2c=i2c)
- When using an ESP32-based board, the result is that `OSError: [Errno 19] ENODEV` is raised when the board gets a soft reset (Ctrl-D on REPL prompt). Instead, if the board is hard reset, it works as expected.
- When using a RP2 board, the result is that `OSError: [Errno 19] ENODEV` is always raised.
So, what am I missing? Is a I2C.scan() required before using the I2C bus? And why is a hard reset solving the problem with ESP32-based boards?
I may solve the problem by using a I2C.scan() call within the initial checks (when the class gets instantiated), but I'd like to understand why.
Thank you in advance for your help!