ESP-IDF: How to scan I2C devices

The following function allows you to scan I2C devices on a ESP-IDF I2C bus. The result will be printed on the configured console.

#include <driver/i2c.h>

void scan_i2c(i2c_port_t port) {
    printf("Scanning I2C bus on port %d...\n", port);
    
    int devices_found = 0;
    esp_err_t ret;
    
    for (uint8_t address = 1; address < 127; address++) {
        i2c_cmd_handle_t cmd = i2c_cmd_link_create();
        i2c_master_start(cmd);
        i2c_master_write_byte(cmd, (address << 1) | I2C_MASTER_WRITE, true);
        i2c_master_stop(cmd);
        
        ret = i2c_master_cmd_begin(port, cmd, 50 / portTICK_PERIOD_MS);
        i2c_cmd_link_delete(cmd);
        
        if (ret == ESP_OK) {
            printf("I2C device found at address 0x%02X\n", address);
            devices_found++;
        } else if (ret != ESP_FAIL) { /* Slave has not ACKd the transfer*/
            printf("Error at address 0x%02X, error: %s\n", address, esp_err_to_name(ret));
        }
        
        // Small delay between scans
        vTaskDelay(5 / portTICK_PERIOD_MS);
    }
    
    if (devices_found == 0) {
        printf("No I2C devices found\n");
    } else {
        printf("Scan complete, %d device(s) found\n", devices_found);
    }
}

Prerequisites

You need to initialize the I2C bus before calling this function. Here is an example of how to do that:

#include <driver/i2c.h>

constexpr int Pin_I2C_SCL = 14;
constexpr int Pin_I2C_SDA = 13;

extern "C" void app_main()
{
    // Setup I2C port 0 on the GPIOs
    i2c_config_t conf = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = Pin_I2C_SDA,
        .scl_io_num = Pin_I2C_SCL,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .master = {
            .clk_speed = 400000
        },
    };
    i2c_param_config(I2C_NUM_0, &conf);
    i2c_driver_install(I2C_NUM_0, conf.mode, 0, 0, 0);

    while(true) {
      scan_i2c(I2C_NUM_0);
      vTaskDelay(500 / portTICK_PERIOD_MS);
    }
}

Example output

Scanning I2C bus on port 0...
I2C device found at address 0x70
Scan complete, 1 device(s) found