I2C

The i2c component provides C++ wrappers built on ESP-IDF’s I2C drivers.

There are two driver families available:

  • the deprecated legacy driver

  • the new master/slave bus API available on ESP-IDF >= 5.4.0 and required on ESP-IDF v6.x and newer

Only one family can be selected at a time via Kconfig.

Primary API

When the new driver family is selected, espp::I2c remains the main public API. It preserves the familiar address-based helper methods for backwards compatibility while internally using ESP-IDF’s new master bus/device model.

That means existing code using methods such as probe_device(), read(), write(), write_read(), and read_at_register() can keep working when the new driver family is selected, without being rewritten around the raw ESP-IDF handles.

For code that wants explicit per-device ownership, espp::I2c also exposes add_device() which returns an I2cMasterDevice.

I2cMenu is available for the bus-compatible espp::I2c API and can be used to scan the bus, probe devices, and read/write registers interactively.

API Reference

Header File

Classes

class I2c : public espp::BaseComponent

I2C master bus wrapper with backwards-compatible helpers.

On ESP-IDF v6.x this class is backed by the new master bus/device API, but it keeps the familiar address-based helper methods for existing code. New code can create explicit per-device handles with add_device().

Example
    espp::I2c i2c({
        .port = I2C_NUM_0,
        .sda_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SDA_GPIO,
        .scl_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SCL_GPIO,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
    });

    std::vector<uint8_t> found_addresses;
    for (uint8_t address = 1; address < 128; address++) {
      if (i2c.probe_device(address)) {
        found_addresses.push_back(address);
      }
    }
    logger.info("Found devices at addresses: {::#02x}", found_addresses);

    static constexpr uint8_t device_address = CONFIG_EXAMPLE_I2C_DEVICE_ADDR;
    static constexpr uint8_t register_address = CONFIG_EXAMPLE_I2C_DEVICE_REG_ADDR;
    bool device_found = i2c.probe_device(device_address);
    if (device_found) {
      logger.info("Found device with address {:#02x}", device_address);
      std::vector<uint8_t> read_data(CONFIG_EXAMPLE_I2C_DEVICE_REG_SIZE, 0);
      bool success = i2c.read_at_register(device_address, register_address, read_data.data(),
                                          read_data.size());
      if (success) {
        logger.info("read data: {::#02x}", read_data);
      } else {
        logger.error("read failed");
      }
    } else {
      logger.error("Could not find device with address {:#02x}", device_address);
    }
Add a device
    auto device = i2c.add_device<uint8_t>(
        espp::I2c::DeviceConfig<uint8_t>{
            .device_address = CONFIG_EXAMPLE_I2C_DEVICE_ADDR,
            .timeout_ms = 50,
            .scl_speed_hz = CONFIG_EXAMPLE_I2C_CLOCK_SPEED_HZ,
            .log_level = espp::Logger::Verbosity::INFO,
        },
        ec);

Public Functions

inline explicit I2c(const Config &config)

Construct I2C driver

Parameters:

config – Configuration for I2C

inline ~I2c()

Destructor.

inline void set_log_level(Logger::Verbosity log_level)

Set the logger verbosity for the bus and cached compatibility devices.

Parameters:

log_level – The desired logger verbosity.

inline const Config &config() const

Get the active configuration.

Returns:

The active configuration.

inline void init(std::error_code &ec)

Initialize the I2C bus.

Parameters:

ec – Error code populated on failure.

inline void deinit(std::error_code &ec)

Deinitialize the I2C bus.

Parameters:

ec – Error code populated on failure.

inline bool initialized() const

Check whether the bus is initialized.

Returns:

True if the bus is initialized.

template<typename RegisterType = uint8_t>
inline std::shared_ptr<Device<RegisterType>> add_device(const DeviceConfig<RegisterType> &dev_config, std::error_code &ec)

Add an explicit I2C device to the bus.

Template Parameters:

RegisterType – Register address type for the device.

Parameters:
  • dev_config – Device configuration.

  • ec – Error code populated on failure.

Returns:

Shared pointer to the created device, or nullptr on failure.

inline bool write(const uint8_t dev_addr, const uint8_t *data, const size_t data_len)

Write data to an addressed I2C device.

inline bool write_vector(const uint8_t dev_addr, const std::vector<uint8_t> &data)

Write data to an addressed I2C device.

inline bool write_read(const uint8_t dev_addr, const uint8_t *write_data, const size_t write_size, uint8_t *read_data, size_t read_size)

Write to and then read from an addressed I2C device.

inline bool write_read_vector(const uint8_t dev_addr, const std::vector<uint8_t> &write_data, std::vector<uint8_t> &read_data)

Write to and then read from an addressed I2C device.

inline bool read_at_register(const uint8_t dev_addr, const uint8_t reg_addr, uint8_t *data, size_t data_len)

Read from a register on an addressed I2C device.

inline bool read_at_register_vector(const uint8_t dev_addr, const uint8_t reg_addr, std::vector<uint8_t> &data)

Read from a register on an addressed I2C device.

inline bool read(const uint8_t dev_addr, uint8_t *data, size_t data_len)

Read data from an addressed I2C device.

inline bool read_vector(const uint8_t dev_addr, std::vector<uint8_t> &data)

Read data from an addressed I2C device.

inline bool probe_device(const uint8_t dev_addr)

Probe an addressed I2C device.

inline const std::string &get_name() const

Get the name of the component

Note

This is the tag of the logger

Returns:

A const reference to the name of the component

inline void set_log_tag(const std::string_view &tag)

Set the tag for the logger

Parameters:

tag – The tag to use for the logger

inline espp::Logger::Verbosity get_log_level() const

Get the log level for the logger

Returns:

The verbosity level of the logger

inline void set_log_verbosity(espp::Logger::Verbosity level)

Set the log verbosity for the logger

See also

set_log_level

Note

This is a convenience method that calls set_log_level

Parameters:

level – The verbosity level to use for the logger

inline espp::Logger::Verbosity get_log_verbosity() const

Get the log verbosity for the logger

See also

get_log_level

Note

This is a convenience method that calls get_log_level

Returns:

The verbosity level of the logger

inline void set_log_rate_limit(std::chrono::duration<float> rate_limit)

Set the rate limit for the logger

Note

Only calls to the logger that have _rate_limit suffix will be rate limited

Parameters:

rate_limit – The rate limit to use for the logger

struct Config

Configuration for the I2C master bus.

Public Members

int isr_core_id = -1

Kept for compatibility; ignored by the new ESP-IDF API.

i2c_port_t port = I2C_NUM_0

I2C port.

gpio_num_t sda_io_num = GPIO_NUM_NC

SDA pin.

gpio_num_t scl_io_num = GPIO_NUM_NC

SCL pin.

gpio_pullup_t sda_pullup_en = GPIO_PULLUP_DISABLE

SDA pullup.

gpio_pullup_t scl_pullup_en = GPIO_PULLUP_DISABLE

SCL pullup.

uint32_t timeout_ms = 10

Default timeout in milliseconds.

uint32_t clk_speed = 400 * 1000

I2C clock speed in hertz.

bool auto_init = true

Automatically initialize I2C on construction.

Logger::Verbosity log_level = Logger::Verbosity::WARN

Verbosity of logger.

Header File

Classes

class I2cMenu

A CLI menu for interacting with an I2c bus.

This class provides a CLI menu for interacting with an I2c bus. It provides options for setting the log verbosity, scanning the bus for devices, probing for a device at a specific address, reading from a device, and writing to a device.

Example
    espp::I2c i2c({
        .port = I2C_NUM_0,
        .sda_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SDA_GPIO,
        .scl_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SCL_GPIO,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .clk_speed = CONFIG_EXAMPLE_I2C_CLOCK_SPEED_HZ,
        .log_level = espp::Logger::Verbosity::INFO,
    });
    auto root_menu = std::make_unique<cli::Menu>("main", "I2C Main Menu");
    espp::I2cMenu i2c_menu(i2c);
    root_menu->Insert(i2c_menu.get());
#if defined(CONFIG_ESPP_I2C_USE_NEW_API)
    std::error_code ec;
    auto device = i2c.add_device<uint8_t>(
        espp::I2c::DeviceConfig<uint8_t>{
            .device_address = CONFIG_EXAMPLE_I2C_DEVICE_ADDR,
            .timeout_ms = 50,
            .scl_speed_hz = CONFIG_EXAMPLE_I2C_CLOCK_SPEED_HZ,
            .log_level = espp::Logger::Verbosity::INFO,
        },
        ec);
    if (!device) {
      logger.error("Failed to add explicit I2C device: {}", ec.message());
    } else {
      espp::I2cMasterDeviceMenu<uint8_t> i2c_device_menu(device);
      root_menu->Insert(i2c_device_menu.get());
    }
#endif
    cli::Cli cli(std::move(root_menu));
    cli::SetColor();
    cli.ExitAction([](auto &out) { out << "Goodbye and thanks for all the fish.\n"; });
    espp::Cli input(cli);
    input.SetInputHistorySize(10);

    input.Start();

Public Functions

inline explicit I2cMenu(std::reference_wrapper<espp::I2c> i2c)

Construct a new I2cMenu object.

Parameters:

i2c – A reference to the I2c bus to interact with.

inline std::unique_ptr<cli::Menu> get(std::string_view name = "i2c", std::string_view description = "I2c menu")

Get the I2c menu.

Parameters:
  • name – The name of the menu.

  • description – The description of the menu.

Returns:

A unique pointer to the I2c menu that you can use to add to a CLI.

Explicit master/slave APIs

The component also exposes the explicit new-driver wrappers directly:

  • I2cMasterBus

  • I2cMasterDevice

  • I2cSlaveDevice

These classes mirror the ESP-IDF master/slave bus model more closely. The master helpers are synchronous/blocking wrappers around ESP-IDF’s new API.

I2cMasterMenu and I2cMasterDeviceMenu are also provided for interactive testing of explicit master buses and devices.

I2cSlaveDevice and I2cSlaveMenu are available for slave-side work. The slave wrapper follows ESP-IDF’s callback-driven model: read() returns the next complete master-write transaction buffered by the receive callback path, write() stages bytes for the next master read, and optional request / receive callbacks run in task context instead of the ISR callback itself.

If you need the exact transaction size, use the read() overload that returns the received length by reference. The original boolean-only read() API remains available for compatibility.

On ESP-IDF v5.5’s default slave driver, the receive callback does not expose the exact byte count. ESPP still supports buffered reads and receive callbacks in that configuration, but trailing unread bytes are zero-filled and the reported receive length matches the requested read size.

There is not yet a dedicated slave example.

API Reference

Header File

Classes

template<typename RegisterType = uint8_t>
class I2cMasterDevice : public espp::BaseComponent

I2C Master Device (C++ wrapper for ESP-IDF new I2C master API)

This class is a wrapper around the ESP-IDF I2C master device API. It provides thread-safe, modern C++ access to I2C master device operations.

Create a device
    // Create a device (using uint8_t as the size for its register addresses)
    auto dev = bus.add_device<uint8_t>(
        espp::I2cMasterDevice<uint8_t>::Config{
            .device_address = CONFIG_EXAMPLE_I2C_DEVICE_ADDR,
            .timeout_ms = 50,
            .scl_speed_hz = CONFIG_EXAMPLE_I2C_CLOCK_SPEED_HZ,
            .log_level = espp::Logger::Verbosity::DEBUG,
        },
        ec);
    if (!dev) {
      logger.error("[NEW API] Failed to add device: {}", ec.message());
      return;
    }
    logger.info("[NEW API] Created device with address {:#02x}", dev->get_device_address());
Read from a device
    static constexpr uint8_t device_address = CONFIG_EXAMPLE_I2C_DEVICE_ADDR;
    static constexpr uint8_t register_address = CONFIG_EXAMPLE_I2C_DEVICE_REG_ADDR;
    bool device_found = bus.probe(device_address, ec);
    if (device_found) {
      logger.info("Found device with address {:#02x}", device_address);
      std::vector<uint8_t> read_data(CONFIG_EXAMPLE_I2C_DEVICE_REG_SIZE, 0);
      bool success = dev->read_register(register_address, read_data, ec);
      if (success) {
        logger.info("read data: {::#02x}", read_data);
      } else {
        logger.error("read failed");
      }
    } else {
      logger.error("Could not find device with address {:#02x}", device_address);
    }

Usage:

  • Construct with a bus handle and config

  • Use read, write, write_read, and register-based access methods

  • Use probe() to check for device presence

  • All methods are thread-safe

Note

This class is intended for use with the new ESP-IDF I2C master API (>=5.4.0)

Public Functions

explicit I2cMasterDevice(i2c_master_bus_handle_t bus_handle, const Config &config)

Construct I2C Master Device.

Parameters:
  • bus_handle – I2C master bus handle

  • config – Configuration for the device

~I2cMasterDevice()

Destructor.

bool init(std::error_code &ec)

Initialize the device.

Parameters:

ec – Error code output

Returns:

True if successful

bool deinit(std::error_code &ec)

Deinitialize the device.

Parameters:

ec – Error code output

Returns:

True if successful

inline int get_timeout_ms() const

Get the configured timeout (ms)

inline void set_timeout_ms(int timeout_ms)

Set the timeout (ms)

inline uint16_t get_device_address() const

Get the device address.

Returns:

Device address (7-bit or 10-bit)

void set_device_address(uint16_t device_address, i2c_addr_bit_len_t addr_bit_len = I2C_ADDR_BIT_LEN_7)

Set the device address.

Parameters:
  • device_address – Device address (7-bit or 10-bit)

  • addr_bit_len – Address bit length (default is 7-bit)

bool probe(std::error_code &ec)

Probe for the device on the bus.

Parameters:

ec – Error code output

Returns:

True if device responds

bool probe(int32_t timeout_ms, std::error_code &ec)

Probe for the device with a custom timeout.

Parameters:
  • timeout_ms – Timeout in ms

  • ec – Error code output

Returns:

True if device responds

bool write(const uint8_t *data, size_t len, std::error_code &ec)

Write data to the device.

Parameters:
  • data – Pointer to data

  • len – Length of data

  • ec – Error code output

Returns:

True if successful

bool read(uint8_t *data, size_t len, std::error_code &ec)

Read data from the device.

Parameters:
  • data – Pointer to buffer

  • len – Length to read

  • ec – Error code output

Returns:

True if successful

bool write_read(const uint8_t *wdata, size_t wlen, uint8_t *rdata, size_t rlen, std::error_code &ec)

Write then read from the device.

Parameters:
  • wdata – Write data pointer

  • wlen – Write data length

  • rdata – Read buffer pointer

  • rlen – Read buffer length

  • ec – Error code output

Returns:

True if successful

bool write(const std::vector<uint8_t> &data, std::error_code &ec)

Write data to the device (vector overload)

Parameters:
  • data – Data vector

  • ec – Error code output

Returns:

True if successful

bool read(std::vector<uint8_t> &data, std::error_code &ec)

Read data from the device (vector overload)

Parameters:
  • data – Data vector (output)

  • ec – Error code output

Returns:

True if successful

bool write_read(const std::vector<uint8_t> &wdata, std::vector<uint8_t> &rdata, std::error_code &ec)

Write then read from the device (vector overload)

Parameters:
  • wdata – Write data vector

  • rdata – Read data vector (output)

  • ec – Error code output

Returns:

True if successful

bool write_register(RegisterType reg, const uint8_t *data, size_t len, std::error_code &ec)

Write to a register.

Parameters:
  • reg – Register address

  • data – Data pointer

  • len – Data length

  • ec – Error code output

Returns:

True if successful

bool write_register(RegisterType reg, const std::vector<uint8_t> &data, std::error_code &ec)

Write to a register (vector overload)

Parameters:
  • reg – Register address

  • data – Data vector

  • ec – Error code output

Returns:

True if successful

bool read_register(RegisterType reg, uint8_t *data, size_t len, std::error_code &ec)

Read from a register.

Parameters:
  • reg – Register address

  • data – Data pointer (output)

  • len – Data length

  • ec – Error code output

Returns:

True if successful

bool read_register(RegisterType reg, std::vector<uint8_t> &data, std::error_code &ec)

Read from a register (vector overload)

Parameters:
  • reg – Register address

  • data – Data vector (output)

  • ec – Error code output

Returns:

True if successful

inline const Config &config() const

Expose config for CLI menu.

Returns:

Reference to config

inline bool initialized() const

Check whether the device is initialized.

Returns:

True if initialized

inline const std::string &get_name() const

Get the name of the component

Note

This is the tag of the logger

Returns:

A const reference to the name of the component

inline void set_log_tag(const std::string_view &tag)

Set the tag for the logger

Parameters:

tag – The tag to use for the logger

inline espp::Logger::Verbosity get_log_level() const

Get the log level for the logger

Returns:

The verbosity level of the logger

inline void set_log_level(espp::Logger::Verbosity level)

Set the log level for the logger

Parameters:

level – The verbosity level to use for the logger

inline void set_log_verbosity(espp::Logger::Verbosity level)

Set the log verbosity for the logger

See also

set_log_level

Note

This is a convenience method that calls set_log_level

Parameters:

level – The verbosity level to use for the logger

inline espp::Logger::Verbosity get_log_verbosity() const

Get the log verbosity for the logger

See also

get_log_level

Note

This is a convenience method that calls get_log_level

Returns:

The verbosity level of the logger

inline void set_log_rate_limit(std::chrono::duration<float> rate_limit)

Set the rate limit for the logger

Note

Only calls to the logger that have _rate_limit suffix will be rate limited

Parameters:

rate_limit – The rate limit to use for the logger

struct Config

Configuration for I2C Master Device.

Public Members

uint16_t device_address = 0

I2C device address (7-bit or 10-bit)

int timeout_ms = 10

Timeout for I2C operations (ms)

i2c_addr_bit_len_t addr_bit_len = I2C_ADDR_BIT_LEN_7

Address bit length.

uint32_t scl_speed_hz = 400000

I2C clock speed in hertz.

bool auto_init = true

Automatically initialize on construction.

Logger::Verbosity log_level = Logger::Verbosity::WARN

Logger verbosity.

class I2cMasterBus : public espp::BaseComponent

I2C Master Bus (C++ wrapper for ESP-IDF new I2C master API)

This class is a wrapper around the ESP-IDF I2C master bus API. It provides thread-safe, modern C++ access to I2C master bus operations and device creation.

Construct
    logger.info("[NEW API] Starting I2C MasterBus/Device CLI example");
    using espp::I2cMasterBus;
    using espp::I2cMasterDevice;
    std::error_code ec;
    I2cMasterBus bus({
        .port = I2C_NUM_0,
        .sda_io_num = CONFIG_EXAMPLE_I2C_SDA_GPIO,
        .scl_io_num = CONFIG_EXAMPLE_I2C_SCL_GPIO,
        .clk_speed = CONFIG_EXAMPLE_I2C_CLOCK_SPEED_HZ,
        .log_level = espp::Logger::Verbosity::DEBUG,
    });
    if (!bus.init(ec)) {
      logger.error("[NEW API] Failed to init bus: {}", ec.message());
      return;
    }
Create a device
    // Create a device (using uint8_t as the size for its register addresses)
    auto dev = bus.add_device<uint8_t>(
        espp::I2cMasterDevice<uint8_t>::Config{
            .device_address = CONFIG_EXAMPLE_I2C_DEVICE_ADDR,
            .timeout_ms = 50,
            .scl_speed_hz = CONFIG_EXAMPLE_I2C_CLOCK_SPEED_HZ,
            .log_level = espp::Logger::Verbosity::DEBUG,
        },
        ec);
    if (!dev) {
      logger.error("[NEW API] Failed to add device: {}", ec.message());
      return;
    }
    logger.info("[NEW API] Created device with address {:#02x}", dev->get_device_address());
Probe for device(s)
    // NOTE: we turn off logging for this so we don't spam the console
    bus.set_log_level(espp::Logger::Verbosity::ERROR);
    std::vector<uint8_t> found_addresses;
    for (uint8_t address = 1; address < 128; address++) {
      static constexpr int timeout_ms = 50; // timeout for probing each address
      if (bus.probe(address, timeout_ms, ec)) {
        found_addresses.push_back(address);
      }
    }
    bus.set_log_level(espp::Logger::Verbosity::DEBUG);
    logger.info("Found devices at addresses: {::#02x}", found_addresses);

Usage:

Note

This class is intended for use with the new ESP-IDF I2C master API (>=5.4.0)

Public Functions

explicit I2cMasterBus(const Config &config)

Construct I2C Master Bus.

Parameters:

config – Configuration for the bus

~I2cMasterBus()

Destructor.

bool init(std::error_code &ec)

Initialize the bus.

Parameters:

ec – Error code output

Returns:

True if successful

bool deinit(std::error_code &ec)

Deinitialize the bus.

Parameters:

ec – Error code output

Returns:

True if successful

template<typename RegisterType>
inline std::shared_ptr<I2cMasterDevice<RegisterType>> add_device(const typename I2cMasterDevice<RegisterType>::Config &dev_config, std::error_code &ec)

Add a device to the bus.

Template Parameters:

RegisterType – Register address type

Parameters:
  • dev_config – Device configuration

  • ec – Error code output

Returns:

Shared pointer to the created device

bool probe(uint16_t device_address, std::error_code &ec)

Probe for a device on the bus.

Parameters:
  • device_address – I2C device address

  • ec – Error code output

Returns:

True if device responds

bool probe(uint16_t device_address, int32_t timeout_ms, std::error_code &ec)

Probe for a device with a custom timeout.

Parameters:
  • device_address – I2C device address

  • timeout_ms – Timeout in ms

  • ec – Error code output

Returns:

True if device responds

inline const std::string &get_name() const

Get the name of the component

Note

This is the tag of the logger

Returns:

A const reference to the name of the component

inline void set_log_tag(const std::string_view &tag)

Set the tag for the logger

Parameters:

tag – The tag to use for the logger

inline espp::Logger::Verbosity get_log_level() const

Get the log level for the logger

Returns:

The verbosity level of the logger

inline void set_log_level(espp::Logger::Verbosity level)

Set the log level for the logger

Parameters:

level – The verbosity level to use for the logger

inline void set_log_verbosity(espp::Logger::Verbosity level)

Set the log verbosity for the logger

See also

set_log_level

Note

This is a convenience method that calls set_log_level

Parameters:

level – The verbosity level to use for the logger

inline espp::Logger::Verbosity get_log_verbosity() const

Get the log verbosity for the logger

See also

get_log_level

Note

This is a convenience method that calls get_log_level

Returns:

The verbosity level of the logger

inline void set_log_rate_limit(std::chrono::duration<float> rate_limit)

Set the rate limit for the logger

Note

Only calls to the logger that have _rate_limit suffix will be rate limited

Parameters:

rate_limit – The rate limit to use for the logger

struct Config

Configuration for I2C Master Bus.

Public Members

int port = 0

I2C port number.

int sda_io_num = -1

SDA pin.

int scl_io_num = -1

SCL pin.

uint32_t clk_speed = 400000

I2C clock speed in hertz.

bool enable_internal_pullup = true

Enable internal pullups.

int intr_priority = 0

Interrupt priority.

Logger::Verbosity log_level = Logger::Verbosity::WARN

Logger verbosity.

Header File

Classes

class I2cMasterMenu

A CLI menu for interacting with an I2c master bus (new API).

This class provides a CLI menu for interacting with an I2c master bus using the new ESP-IDF I2C master API. It provides options for setting the log verbosity, scanning the bus for devices, probing for a device at a specific address, reading from a device, and writing to a device.

Example
    using espp::I2cMasterDeviceMenu;
    using espp::I2cMasterMenu;
    // Launch CLI menu for the new driver
    auto root_menu = std::make_unique<cli::Menu>("main", "I2C Main Menu");
    I2cMasterMenu i2c_menu(bus);
    I2cMasterDeviceMenu<uint8_t> i2c_device_menu(dev);
    root_menu->Insert(i2c_menu.get());
    root_menu->Insert(i2c_device_menu.get());
    cli::Cli cli(std::move(root_menu));
    cli::SetColor();
    cli.ExitAction([](auto &out) { out << "Goodbye and thanks for all the fish.\n"; });
    espp::Cli input(cli);
    input.SetInputHistorySize(10);
    input.Start();

Public Functions

inline explicit I2cMasterMenu(std::reference_wrapper<espp::I2cMasterBus> bus)

Construct a new I2cMasterMenu object.

Parameters:

bus – A reference to the I2cMasterBus to interact with.

inline std::unique_ptr<cli::Menu> get(std::string_view name = "i2c_master", std::string_view description = "I2c Master menu")

Get the I2c master menu.

Parameters:
  • name – The name of the menu.

  • description – The description of the menu.

Returns:

A unique pointer to the I2c menu that you can use to add to a CLI.

Header File

Classes

template<typename RegisterType = uint8_t>
class I2cMasterDeviceMenu

A CLI menu for interacting with a single I2c master device (new API).

This class provides a CLI menu for interacting with a single I2c master device using the new ESP-IDF I2C master API. It provides options for setting the log verbosity, probing the device, reading from a register, and writing to a register.

Example
    using espp::I2cMasterDeviceMenu;
    using espp::I2cMasterMenu;
    // Launch CLI menu for the new driver
    auto root_menu = std::make_unique<cli::Menu>("main", "I2C Main Menu");
    I2cMasterMenu i2c_menu(bus);
    I2cMasterDeviceMenu<uint8_t> i2c_device_menu(dev);
    root_menu->Insert(i2c_menu.get());
    root_menu->Insert(i2c_device_menu.get());
    cli::Cli cli(std::move(root_menu));
    cli::SetColor();
    cli.ExitAction([](auto &out) { out << "Goodbye and thanks for all the fish.\n"; });
    espp::Cli input(cli);
    input.SetInputHistorySize(10);
    input.Start();

Usage:

Note

This class is intended for use with the new ESP-IDF I2C master API (>=5.4.0)

Public Functions

inline explicit I2cMasterDeviceMenu(std::shared_ptr<espp::I2cMasterDevice<RegisterType>> device)

Construct a new I2cMasterDeviceMenu object.

Parameters:

device – A shared_ptr to the I2cMasterDevice to interact with.

inline std::unique_ptr<cli::Menu> get(std::string_view name = "i2c_device", std::string_view description = "I2c Device menu")

Get the I2c master device menu.

Parameters:
  • name – The name of the menu.

  • description – The description of the menu.

Returns:

A unique pointer to the I2c device menu that you can use to add to a CLI.

Header File

Macros

ESP_IDF_VERSION_VAL(major, minor, patch)
ESP_IDF_VERSION
ESPP_I2C_SLAVE_V2_API

Classes

class I2cSlaveDevice : public espp::BaseComponent

I2C slave device wrapper for ESP-IDF’s callback-driven slave API.

ESP-IDF’s slave driver is event/callback based: master writes arrive through receive callbacks, and master reads can trigger request callbacks when the slave transmit FIFO needs more data. This wrapper provides:

  • queued `read()` access to complete master-write transactions

  • blocking `write()` access for staging data back to the master

  • task-context request / receive callbacks so user code does not have to run inside the ISR callback context

When built against ESP-IDF v5.5’s default slave driver, the receive callback API does not expose the actual transaction length. In that configuration this wrapper buffers the requested receive length and zero-fills any trailing bytes the master did not write so `read()` and `on_receive` still behave consistently.

Usage:

  • Construct with a config, then call `init()`

  • Call `read()` to receive the next complete master-write transaction

  • Call `write()` to stage response bytes for the next master read

  • Register callbacks if you want task-context notifications

Note

No dedicated example exists yet.

Note

This class is intended for use with the new ESP-IDF I2C slave API (>=5.4.0)

Public Types

using RequestCallback = std::function<void()>

Callback for master read requests.

using ReceiveCallback = std::function<void(const uint8_t *data, size_t len)>

Callback for master writes.

Public Functions

explicit I2cSlaveDevice(const Config &config)

Construct I2C Slave Device.

Parameters:

config – Configuration for the device

~I2cSlaveDevice()

Destructor.

bool init(std::error_code &ec)

Initialize the device.

Parameters:

ec – Error code output

Returns:

True if successful

bool deinit(std::error_code &ec)

Deinitialize the device.

Parameters:

ec – Error code output

Returns:

True if successful

bool write(const uint8_t *data, size_t len, std::error_code &ec)

Write data to the master.

Parameters:
  • data – Pointer to data

  • len – Length of data

  • ec – Error code output

Returns:

True if successful

bool read(uint8_t *data, size_t len, size_t &received_len, std::error_code &ec)

Read data from the master.

Parameters:
  • data – Pointer to buffer

  • len – Maximum transaction length to read

  • received_len – Actual number of bytes received for the transaction

  • ec – Error code output

Returns:

True if a complete master-write transaction was received

bool read(uint8_t *data, size_t len, std::error_code &ec)

Read data from the master.

Parameters:
  • data – Pointer to buffer

  • len – Maximum transaction length to read

  • ec – Error code output

Returns:

True if a complete master-write transaction was received

bool register_callbacks(const Callbacks &callbacks, std::error_code &ec)

Register callbacks for slave events.

Parameters:
  • callbacksCallbacks to register

  • ec – Error code output

Returns:

True if successful

inline const Config &config() const

Expose config for CLI menu.

Returns:

Reference to config

inline const std::string &get_name() const

Get the name of the component

Note

This is the tag of the logger

Returns:

A const reference to the name of the component

inline void set_log_tag(const std::string_view &tag)

Set the tag for the logger

Parameters:

tag – The tag to use for the logger

inline espp::Logger::Verbosity get_log_level() const

Get the log level for the logger

Returns:

The verbosity level of the logger

inline void set_log_level(espp::Logger::Verbosity level)

Set the log level for the logger

Parameters:

level – The verbosity level to use for the logger

inline void set_log_verbosity(espp::Logger::Verbosity level)

Set the log verbosity for the logger

See also

set_log_level

Note

This is a convenience method that calls set_log_level

Parameters:

level – The verbosity level to use for the logger

inline espp::Logger::Verbosity get_log_verbosity() const

Get the log verbosity for the logger

See also

get_log_level

Note

This is a convenience method that calls get_log_level

Returns:

The verbosity level of the logger

inline void set_log_rate_limit(std::chrono::duration<float> rate_limit)

Set the rate limit for the logger

Note

Only calls to the logger that have _rate_limit suffix will be rate limited

Parameters:

rate_limit – The rate limit to use for the logger

struct Callbacks

Callbacks for I2C slave events.

Public Members

RequestCallback on_request = nullptr

Callback for data request from master.

ReceiveCallback on_receive = nullptr

Callback for data received from master.

struct Config

Configuration for I2C Slave Device.

Public Members

int port = 0

I2C port number.

int sda_io_num = -1

SDA pin.

int scl_io_num = -1

SCL pin.

uint16_t slave_address = 0

I2C slave address.

i2c_addr_bit_len_t addr_bit_len = I2C_ADDR_BIT_LEN_7

Address bit length.

int timeout_ms = 10

Read/write timeout in milliseconds.

uint32_t receive_buffer_depth = 256

Max bytes per received transaction.

uint32_t send_buffer_depth = 256

Depth of driver TX buffer.

size_t event_queue_depth = 8

Number of queued request/receive events.

bool enable_internal_pullup = true

Enable internal pullups.

int intr_priority = 0

Interrupt priority.

Logger::Verbosity log_level = Logger::Verbosity::WARN

Logger verbosity.

Header File

Classes

class I2cSlaveMenu

CLI menu for I2C Slave Device.

This class provides a command-line interface (CLI) menu for interacting with an I2C slave device using the new ESP-IDF I2C slave API.

Usage:

  • Construct with a shared pointer to an I2cSlaveDevice

  • Use get() to add I2C slave commands to a CLI menu

  • Supports reading queued master-write transactions and staging slave responses back to the master

Note

This class is intended for use with the new ESP-IDF I2C slave API (>=5.4.0)

Public Functions

inline explicit I2cSlaveMenu(std::shared_ptr<I2cSlaveDevice> device)

Construct I2C Slave Menu.

Parameters:

device – Shared pointer to the I2C slave device

inline std::unique_ptr<cli::Menu> get(std::string_view name = "i2c_slave", std::string_view description = "I2c Slave menu")

Get the I2c slave menu.

Parameters:
  • name – The name of the menu.

  • description – The description of the menu.

Returns:

A unique pointer to the I2c menu that you can use to add to a CLI.

Legacy API

The legacy ESP-IDF I2C driver is still available behind CONFIG_ESPP_I2C_USE_LEGACY_API for older environments, but it is deprecated and should not be used for new development.