From babaa1db3f7e6d09448d4745772493d7aab7169e Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 23 Jul 2025 23:31:13 +1200 Subject: [PATCH] [i2c] Use ``i2c_master_probe`` to scan i2c bus (#9831) --- esphome/components/i2c/i2c_bus.h | 2 +- esphome/components/i2c/i2c_bus_arduino.cpp | 2 +- esphome/components/i2c/i2c_bus_esp_idf.cpp | 17 ++++++++++++++--- esphome/components/i2c/i2c_bus_esp_idf.h | 3 ++- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/esphome/components/i2c/i2c_bus.h b/esphome/components/i2c/i2c_bus.h index 5c1e15d814..da94aa940d 100644 --- a/esphome/components/i2c/i2c_bus.h +++ b/esphome/components/i2c/i2c_bus.h @@ -94,7 +94,7 @@ class I2CBus { protected: /// @brief Scans the I2C bus for devices. Devices presence is kept in an array of std::pair /// that contains the address and the corresponding bool presence flag. - void i2c_scan_() { + virtual void i2c_scan() { for (uint8_t address = 8; address < 120; address++) { auto err = writev(address, nullptr, 0); if (err == ERROR_OK) { diff --git a/esphome/components/i2c/i2c_bus_arduino.cpp b/esphome/components/i2c/i2c_bus_arduino.cpp index a85df0a4cd..1e84f122de 100644 --- a/esphome/components/i2c/i2c_bus_arduino.cpp +++ b/esphome/components/i2c/i2c_bus_arduino.cpp @@ -42,7 +42,7 @@ void ArduinoI2CBus::setup() { this->initialized_ = true; if (this->scan_) { ESP_LOGV(TAG, "Scanning bus for active devices"); - this->i2c_scan_(); + this->i2c_scan(); } } diff --git a/esphome/components/i2c/i2c_bus_esp_idf.cpp b/esphome/components/i2c/i2c_bus_esp_idf.cpp index c57d537bdb..141e6a670d 100644 --- a/esphome/components/i2c/i2c_bus_esp_idf.cpp +++ b/esphome/components/i2c/i2c_bus_esp_idf.cpp @@ -1,13 +1,13 @@ #ifdef USE_ESP_IDF #include "i2c_bus_esp_idf.h" +#include #include #include #include "esphome/core/application.h" #include "esphome/core/hal.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" -#include #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 3, 0) #define SOC_HP_I2C_NUM SOC_I2C_NUM @@ -78,7 +78,7 @@ void IDFI2CBus::setup() { if (this->scan_) { ESP_LOGV(TAG, "Scanning for devices"); - this->i2c_scan_(); + this->i2c_scan(); } #else #if SOC_HP_I2C_NUM > 1 @@ -125,7 +125,7 @@ void IDFI2CBus::setup() { initialized_ = true; if (this->scan_) { ESP_LOGV(TAG, "Scanning bus for active devices"); - this->i2c_scan_(); + this->i2c_scan(); } #endif } @@ -167,6 +167,17 @@ void IDFI2CBus::dump_config() { } } +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 2) +void IDFI2CBus::i2c_scan() { + for (uint8_t address = 8; address < 120; address++) { + auto err = i2c_master_probe(this->bus_, address, 20); + if (err == ESP_OK) { + this->scan_results_.emplace_back(address, true); + } + } +} +#endif + ErrorCode IDFI2CBus::readv(uint8_t address, ReadBuffer *buffers, size_t cnt) { // logging is only enabled with vv level, if warnings are shown the caller // should log them diff --git a/esphome/components/i2c/i2c_bus_esp_idf.h b/esphome/components/i2c/i2c_bus_esp_idf.h index 8d325de6bc..4e8f86fd0c 100644 --- a/esphome/components/i2c/i2c_bus_esp_idf.h +++ b/esphome/components/i2c/i2c_bus_esp_idf.h @@ -2,9 +2,9 @@ #ifdef USE_ESP_IDF +#include "esp_idf_version.h" #include "esphome/core/component.h" #include "i2c_bus.h" -#include "esp_idf_version.h" #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 2) #include #else @@ -46,6 +46,7 @@ class IDFI2CBus : public InternalI2CBus, public Component { #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 2) i2c_master_dev_handle_t dev_; i2c_master_bus_handle_t bus_; + void i2c_scan() override; #endif i2c_port_t port_; uint8_t sda_pin_;