I2C

The I2C class provides a simple interface to the I2C bus. It is a wrapper around the esp-idf I2C driver.

A helper I2cMenu is also provided which can be used to interactively test I2C buses - scanning the bus, probing devices, reading and writing to devices.

API Reference

Header File

Classes

class I2c : public espp::BaseComponent

I2C driver.

This class is a wrapper around the ESP-IDF I2C driver.

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,
    });

    // probe the bus for all addresses and store the ones that were found /
    // responded. NOTE: this will take a while to run, as it will probe all 128
    // possible addresses and the hard-coded timeout on the I2C (inside ESP-IDF)
    // is 1 second (I2C_CMD_ALIVE_INTERVAL_TICK within
    // esp-idf/components/driver/i2c/i2c.c).
    std::vector<uint8_t> found_addresses;
    for (uint8_t address = 0; address < 128; address++) {
      if (i2c.probe_device(address)) {
        found_addresses.push_back(address);
      }
    }
    // print out the addresses that were found
    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);
    }

Public Functions

inline explicit I2c(const Config &config)

Construct I2C driver

Parameters

config – Configuration for I2C

inline ~I2c()

Destructor.

inline void init(std::error_code &ec)

Initialize I2C driver.

inline void deinit(std::error_code &ec)

Deinitialize I2C driver.

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

Write data to I2C device

Parameters
  • dev_addr – I2C device address

  • data – Data to write

  • data_len – Length of data to write

Returns

True if successful

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

Write data to I2C device

Parameters
  • dev_addr – I2C device address

  • data – Data to write

Returns

True if successful

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 read data from I2C device

Parameters
  • dev_addr – I2C device address

  • write_data – Data to write

  • write_size – Length of data to write

  • read_data – Data to read

  • read_size – Length of data to read

Returns

True if successful

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

Write data to and read data from I2C device

Parameters
  • dev_addr – I2C device address

  • write_data – Data to write

  • read_data – Data to read

Returns

True if successful

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

Read data from I2C device at register

Parameters
  • dev_addr – I2C device address

  • reg_addr – Register address

  • data – Data to read

  • data_len – Length of data to read

Returns

True if successful

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

Read data from I2C device at register

Parameters
  • dev_addr – I2C device address

  • reg_addr – Register address

  • data – Data to read

Returns

True if successful

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

Read data from I2C device

Parameters
  • dev_addr – I2C device address

  • data – Data to read

  • data_len – Length of data to read

Returns

True if successful

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

Read data from I2C device

Parameters
  • dev_addr – I2C device address

  • data – Data to read

Returns

True if successful

inline bool probe_device(const uint8_t dev_addr)

Probe I2C device

This function sends a start condition, writes the device address, and then sends a stop condition. If the device acknowledges the address, then it is present on the bus.

Parameters

dev_addr – I2C device address

Returns

True if successful

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.

Public Members

int isr_core_id = -1

The core to install the I2C interrupt on. If -1, then the I2C interrupt is installed on the core that this constructor is called on. If 0 or 1, then the I2C interrupt is installed on the specified core.

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

I2C timeout in milliseconds.

uint32_t clk_speed = 400 * 1000

I2C clock speed in hertz.

bool auto_init = true

Automatically initialize I2C on construction.

espp::Logger::Verbosity log_level = espp::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,
    });
    // now make a menu for it
    espp::I2cMenu i2c_menu(i2c);
    cli::Cli cli(i2c_menu.get());
    cli::SetColor();
    cli.ExitAction([](auto &out) { out << "Goodbye and thanks for all the fish.\n"; });
    espp::Cli input(cli);
    input.SetInputHistorySize(10);

    input.Start(); // As this is in the primary thread, we hold here until cli
                   // is complete. This is a blocking call and will not return until
                   // the user enters the `exit` command.

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.