13static const char *
const TAG =
"i2c.arduino";
19 static uint8_t next_bus_num = 0;
20 if (next_bus_num == 0) {
23 wire_ =
new TwoWire(next_bus_num);
26#elif defined(USE_ESP8266)
27 wire_ =
new TwoWire();
28#elif defined(USE_RP2040)
29 static bool first =
true;
38 this->set_pins_and_clock_();
42 ESP_LOGV(TAG,
"Scanning i2c bus for active devices...");
47void ArduinoI2CBus::set_pins_and_clock_() {
59#elif defined(USE_ESP8266)
62#elif defined(USE_RP2040)
71 ESP_LOGCONFIG(TAG,
"I2C Bus:");
72 ESP_LOGCONFIG(TAG,
" SDA Pin: GPIO%u", this->
sda_pin_);
73 ESP_LOGCONFIG(TAG,
" SCL Pin: GPIO%u", this->
scl_pin_);
74 ESP_LOGCONFIG(TAG,
" Frequency: %u Hz", this->
frequency_);
77 ESP_LOGCONFIG(TAG,
" Timeout: %u ms", this->
timeout_ / 1000);
78#elif defined(USE_ESP8266)
79 ESP_LOGCONFIG(TAG,
" Timeout: %u us", this->
timeout_);
80#elif defined(USE_RP2040)
81 ESP_LOGCONFIG(TAG,
" Timeout: %u ms", this->
timeout_ / 1000);
84 switch (this->recovery_result_) {
86 ESP_LOGCONFIG(TAG,
" Recovery: bus successfully recovered");
89 ESP_LOGCONFIG(TAG,
" Recovery: failed, SCL is held low on the bus");
92 ESP_LOGCONFIG(TAG,
" Recovery: failed, SDA is held low on the bus");
96 ESP_LOGI(TAG,
"Results from i2c bus scan:");
98 ESP_LOGI(TAG,
"Found no i2c devices!");
102 ESP_LOGI(TAG,
"Found i2c device at address 0x%02X", s.first);
104 ESP_LOGE(TAG,
"Unknown error at address 0x%02X", s.first);
112#if defined(USE_ESP8266)
113 this->set_pins_and_clock_();
119 ESP_LOGVV(TAG,
"i2c bus not initialized!");
122 size_t to_request = 0;
123 for (
size_t i = 0; i < cnt; i++)
124 to_request += buffers[i].
len;
125 size_t ret =
wire_->requestFrom((
int)
address, (
int) to_request, 1);
126 if (ret != to_request) {
127 ESP_LOGVV(TAG,
"RX %u from %02X failed with error %u", to_request,
address, ret);
131 for (
size_t i = 0; i < cnt; i++) {
132 const auto &buf = buffers[i];
133 for (
size_t j = 0; j < buf.len; j++)
137#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
139 std::string debug_hex;
141 for (
size_t i = 0; i < cnt; i++) {
142 const auto &buf = buffers[i];
143 for (
size_t j = 0; j < buf.len; j++) {
144 snprintf(debug_buf,
sizeof(debug_buf),
"%02X", buf.data[j]);
145 debug_hex += debug_buf;
148 ESP_LOGVV(TAG,
"0x%02X RX %s",
address, debug_hex.c_str());
154#if defined(USE_ESP8266)
155 this->set_pins_and_clock_();
161 ESP_LOGVV(TAG,
"i2c bus not initialized!");
165#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
167 std::string debug_hex;
169 for (
size_t i = 0; i < cnt; i++) {
170 const auto &buf = buffers[i];
171 for (
size_t j = 0; j < buf.len; j++) {
172 snprintf(debug_buf,
sizeof(debug_buf),
"%02X", buf.data[j]);
173 debug_hex += debug_buf;
176 ESP_LOGVV(TAG,
"0x%02X TX %s",
address, debug_hex.c_str());
181 for (
size_t i = 0; i < cnt; i++) {
182 const auto &buf = buffers[i];
185 size_t ret =
wire_->write(buf.data, buf.len);
187 if (ret != buf.len) {
188 ESP_LOGVV(TAG,
"TX failed at %u", written);
198 ESP_LOGVV(TAG,
"TX failed: buffer not large enough");
202 ESP_LOGVV(TAG,
"TX failed: not acknowledged: %d",
status);
205 ESP_LOGVV(TAG,
"TX failed: timeout");
209 ESP_LOGVV(TAG,
"TX failed: unknown error %u",
status);
217void ArduinoI2CBus::recover_() {
218 ESP_LOGI(TAG,
"Performing I2C bus recovery");
224 const auto half_period_usec = 1000000 / 100000 / 2;
234 ESP_LOGE(TAG,
"Recovery failed: SCL is held LOW on the I2C bus");
252 for (
auto i = 0; i < 9; i++) {
271 while (wait-- && digitalRead(
scl_pin_) == LOW) {
276 ESP_LOGE(TAG,
"Recovery failed: SCL is held LOW during clock pulse cycle");
291 ESP_LOGE(TAG,
"Recovery failed: SDA is held LOW after clock pulse cycle");
void feed_wdt(uint32_t time=0)
void dump_config() override
ErrorCode writev(uint8_t address, WriteBuffer *buffers, size_t cnt, bool stop) override
ErrorCode readv(uint8_t address, ReadBuffer *buffers, size_t cnt) override
bool scan_
Should we scan ? Can be set in the yaml.
std::vector< std::pair< uint8_t, bool > > scan_results_
array containing scan results
void i2c_scan_()
Scans the I2C bus for devices.
ErrorCode
Error codes returned by I2CBus and I2CDevice methods.
@ ERROR_OK
No error found during execution of method.
@ ERROR_TIMEOUT
timeout while waiting to receive bytes
@ ERROR_NOT_ACKNOWLEDGED
I2C bus acknowledgment not received.
@ ERROR_NOT_INITIALIZED
call method to a not initialized bus
@ ERROR_UNKNOWN
miscellaneous I2C error during execution
@ RECOVERY_FAILED_SDA_LOW
@ RECOVERY_FAILED_SCL_LOW
Providing packet encoding functions for exchanging data with a remote host.
void IRAM_ATTR HOT delayMicroseconds(uint32_t us)
Application App
Global storage of Application pointer - only one Application can exist.
the ReadBuffer structure stores a pointer to a read buffer and its length
uint8_t * data
pointer to the read buffer
the WriteBuffer structure stores a pointer to a write buffer and its length