I've been reading values from a BME280 continuously for the last week over I2C without any glitches, but yesterday when I wanted to implement the MCP23017 I/O expander I discovered an error in my code that prevented it from ever calling i2c_master_stop() at the end of the command sequence.
So, I fixed that but in doing so the entire i2C communication broke down and i2c_master_cmd_begin() now always returns ESP_ERR_TIMEOUT.
I've compared my code with how the IED I2C example does things and I see no difference in how commands are built. Apart from potentially OR:ing error codes together, am I building the command wrong in some way? I2CCommandLink is a scoped-based resource that is implicitly cast to a i2c_cmd_handle_t when needed.
Code: Select all
I2CCommandLink link(*this);
// Set R/W bit to 0 for write.
uint8_t write_address = address << 1;
// Set R/W bit to 1 for read.
uint8_t read_address = (address << 1) | 0x1;
// Generate start condition
auto res = i2c_master_start(link);
// Write the slave write address followed by the register address.
res |= i2c_master_write_byte(link, write_address, true);
res |= i2c_master_write_byte(link, slave_register, true);
// Generate another start condition
res = i2c_master_start(link);
// Write the read address, then read the desired amount,
// ending the read with a NACK (0) to signal the slave to stop sending data.
res |= i2c_master_write_byte(link, read_address, true);
res |= i2c_master_read(link, data.data(), data.size(), 0);
// Complete the read with a stop condition.
res |= i2c_master_stop(link); // Removing this line makes things work?!?!?!!?!?
res |= i2c_master_cmd_begin(port, link, Task::to_tick(timeout));