-
-
Notifications
You must be signed in to change notification settings - Fork 7
Description
(this is a summary of an earlier discussion by e-mail, better to archive the essence here)
The NANO 33 BLE is an processor using MBED toolchain.
Problem
The MS5611 cannot be seen on the I2C bus
- not with the isConnected() call
- not by I2C scanners
This prevents to check if the device is connected in the device.begin() call during the setup of the project.
Note that the device will work as it should if one ignores the return value of begin().
Analysis
The isConnected() call and I2C scanners just put addresses on the I2C bus and expect an ACK when a device recognizes its address. The MS5611 does this well on AVR and ESP but not on MBED.
Note that on the internet there were similar an related problems mentioned without a solution.
(many tests and mails later a possible cause is found in the endTransmission() code of MBED
....Arduino15\packages\arduino\hardware\mbed_nano\2.7.2\libraries\Wire\Wire.cpp
uint8_t arduino::MbedI2C::endTransmission(bool stopBit) {
#ifndef TARGET_PORTENTA_H7
if (usedTxBuffer == 0) {
// we are scanning, return 0 if the addresed device responds with an ACK
char buf[1];
int ret = master->read(_address, buf, 1, !stopBit);
return ret;
}
#endif
if (master->write(_address, (const char *) txBuffer, usedTxBuffer, !stopBit) == 0) return 0;
return 2;
}
If there are no bytes in the transmitBuffer the MBED returns the value of read()
If there are bytes in the transmitBuffer the MBED returns the value of write()
Other endTransmission() implementations known - AVR / ESP - always use the write()
even if the transmitBuffer is empty (usedTxBuffer == 0)
The rationale why MBED does this differently is unknown.
Patch / workaround
The library is patched so if an NANO 33 BLE is addressed it adds an write(0) in the isConnected() code (0.3.5)
https://github.com/RobTillaart/MS5611/blob/master/MS5611.cpp
bool MS5611::isConnected()
{
_wire->beginTransmission(_address);
#ifdef ARDUINO_ARCH_NRF52840
// needed for NANO 33 BLE
_wire->write(0); // <<< extra byte forces code to select the write path in endTransmission()
#endif
return (_wire->endTransmission() == 0);
}
This forces the write path in endTransmission() and the device returns the ACK expected.
WARNING: Although this works it is not a solution as it is unknown how devices in general will react on this extra byte,
Thoughts about a solution
The patch above is a workaround that is not the right solution so more investigations / discussions are needed to solve this.
- why does MBED use a master->read() when the buffer is empty?
- what does the master->read() return ? is that correct? (apparently not)
- can the endTransmission() function be simplified to always using write()?
a test shows this works well for the MS5611 but unknown if this causes any problems with other devices.
A generic solution could be that the Wire library is extended with a call, which returns if the address exist on the I2C bus.
- bool exist(address)