From b23c131b6469c597bd109b29d5bde05313a6ea4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20de=20Assis=20Madruga=20Prestes?= <104784274+vinicius-de-assis@users.noreply.github.com> Date: Tue, 6 Aug 2024 13:01:53 -0300 Subject: [PATCH] feat(example): Add a I2C Simple example --- .../peripherals/i2c/i2c_simple/CMakeLists.txt | 6 ++ examples/peripherals/i2c/i2c_simple/README.md | 52 ++++++++++ .../i2c/i2c_simple/main/CMakeLists.txt | 2 + .../i2c/i2c_simple/main/Kconfig.projbuild | 21 +++++ .../i2c_simple/main/i2c_simple_example_main.c | 94 +++++++++++++++++++ 5 files changed, 175 insertions(+) create mode 100644 examples/peripherals/i2c/i2c_simple/CMakeLists.txt create mode 100644 examples/peripherals/i2c/i2c_simple/README.md create mode 100644 examples/peripherals/i2c/i2c_simple/main/CMakeLists.txt create mode 100644 examples/peripherals/i2c/i2c_simple/main/Kconfig.projbuild create mode 100644 examples/peripherals/i2c/i2c_simple/main/i2c_simple_example_main.c diff --git a/examples/peripherals/i2c/i2c_simple/CMakeLists.txt b/examples/peripherals/i2c/i2c_simple/CMakeLists.txt new file mode 100644 index 00000000000..ffb72b6825c --- /dev/null +++ b/examples/peripherals/i2c/i2c_simple/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(i2c-simple) diff --git a/examples/peripherals/i2c/i2c_simple/README.md b/examples/peripherals/i2c/i2c_simple/README.md new file mode 100644 index 00000000000..d9b062aa9da --- /dev/null +++ b/examples/peripherals/i2c/i2c_simple/README.md @@ -0,0 +1,52 @@ +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | + +# I2C Simple Example + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +## Overview + +This example demonstrates basic usage of I2C driver by reading and writing from a I2C connected sensor: + +If you have a new I2C application to go (for example, read the temperature data from external sensor with I2C interface), try this as a basic template, then add your own code. + +## How to use example + +### Hardware Required + +To run this example, you should have one ESP32, ESP32-S, ESP32-C or ESP32-H based development board as well as a MPU9250. MPU9250 is a inertial measurement unit, which contains a accelerometer, gyroscope as well as a magnetometer, for more information about it, you can read the [datasheet of the MPU9250 sensor](https://invensense.tdk.com/wp-content/uploads/2015/02/PS-MPU-9250A-01-v1.1.pdf). + +#### Pin Assignment: + +**Note:** The following pin assignments are used by default, you can change these in the `menuconfig` . + +| | SDA | SCL | +| ---------------- | -------------- | -------------- | +| ESP I2C Master | I2C_MASTER_SDA | I2C_MASTER_SCL | +| MPU9250 Sensor | SDA | SCL | + + +For the actual default value of `I2C_MASTER_SDA` and `I2C_MASTER_SCL` see `Example Configuration` in `menuconfig`. + +**Note:** There's no need to add an external pull-up resistors for SDA/SCL pin, because the driver will enable the internal pull-up resistors. + +### Build and Flash + +Enter `idf.py -p PORT flash monitor` to build, flash and monitor the project. + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects. + +## Example Output + +```bash +I (328) i2c-simple-example: I2C initialized successfully +I (338) i2c-simple-example: WHO_AM_I = 71 +I (338) i2c-simple-example: I2C de-initialized successfully +``` + +## Troubleshooting + +(For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you as soon as possible.) diff --git a/examples/peripherals/i2c/i2c_simple/main/CMakeLists.txt b/examples/peripherals/i2c/i2c_simple/main/CMakeLists.txt new file mode 100644 index 00000000000..01568354c1e --- /dev/null +++ b/examples/peripherals/i2c/i2c_simple/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "i2c_simple_example_main.c" + INCLUDE_DIRS ".") diff --git a/examples/peripherals/i2c/i2c_simple/main/Kconfig.projbuild b/examples/peripherals/i2c/i2c_simple/main/Kconfig.projbuild new file mode 100644 index 00000000000..6e8476a0476 --- /dev/null +++ b/examples/peripherals/i2c/i2c_simple/main/Kconfig.projbuild @@ -0,0 +1,21 @@ +menu "Example Configuration" + + orsource "$IDF_PATH/examples/common_components/env_caps/$IDF_TARGET/Kconfig.env_caps" + + config I2C_MASTER_SCL + int "SCL GPIO Num" + range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX + default 19 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 + default 2 + help + GPIO number for I2C Master clock line. + + config I2C_MASTER_SDA + int "SDA GPIO Num" + range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX + default 18 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 + default 1 + help + GPIO number for I2C Master data line. + +endmenu diff --git a/examples/peripherals/i2c/i2c_simple/main/i2c_simple_example_main.c b/examples/peripherals/i2c/i2c_simple/main/i2c_simple_example_main.c new file mode 100644 index 00000000000..a0ff5fa5743 --- /dev/null +++ b/examples/peripherals/i2c/i2c_simple/main/i2c_simple_example_main.c @@ -0,0 +1,94 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +/* i2c - Simple Example + + Simple I2C example that shows how to initialize I2C + as well as reading and writing from and to registers for a sensor connected over I2C. + + The sensor used in this example is a MPU9250 inertial measurement unit. +*/ +#include +#include "esp_log.h" +#include "driver/i2c.h" +#include + +static const char *TAG = "i2c-simple-example"; + +#define I2C_MASTER_SCL_IO CONFIG_I2C_MASTER_SCL /*!< GPIO number used for I2C master clock */ +#define I2C_MASTER_SDA_IO CONFIG_I2C_MASTER_SDA /*!< GPIO number used for I2C master data */ +#define I2C_MASTER_NUM I2C_NUM_0 /*!< I2C port number for master dev */ +#define I2C_MASTER_FREQ_HZ 400000 /*!< I2C master clock frequency */ +#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */ +#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */ +#define I2C_MASTER_TIMEOUT_MS 1000 + +#define MPU9250_SENSOR_ADDR 0x68 /*!< Address of the MPU9250 sensor */ +#define MPU9250_WHO_AM_I_REG_ADDR 0x75 /*!< Register addresses of the "who am I" register */ +#define MPU9250_PWR_MGMT_1_REG_ADDR 0x6B /*!< Register addresses of the power management register */ +#define MPU9250_RESET_BIT 7 + +/** + * @brief Read a sequence of bytes from a MPU9250 sensor registers + */ +static esp_err_t mpu9250_register_read(i2c_master_dev_handle_t dev_handle, uint8_t reg_addr, uint8_t *data, size_t len) +{ + return i2c_master_transmit_receive(dev_handle, ®_addr, 1, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS); +} + +/** + * @brief Write a byte to a MPU9250 sensor register + */ +static esp_err_t mpu9250_register_write_byte(i2c_master_dev_handle_t dev_handle, uint8_t reg_addr, uint8_t data) +{ + uint8_t write_buf[2] = {reg_addr, data}; + return i2c_master_transmit(dev_handle, write_buf, sizeof(write_buf), I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS); +} + +/** + * @brief i2c master initialization + */ +static esp_err_t i2c_master_init(i2c_master_bus_handle_t *bus_handle, i2c_master_dev_handle_t *dev_handle) +{ + i2c_master_bus_config_t bus_config = { + .i2c_port = I2C_MASTER_NUM, + .sda_io_num = I2C_MASTER_SDA_IO, + .scl_io_num = I2C_MASTER_SCL_IO, + .clk_source = I2C_CLK_SRC_DEFAULT, + .glitch_ignore_cnt = 7, + .enable_internal_pullup = true, + }; + + i2c_device_config_t dev_config = { + .dev_addr_length = I2C_ADDR_BIT_LEN_7, + .device_address = MPU9250_SENSOR_ADDR, + .scl_speed_hz = I2C_MASTER_FREQ_HZ, + }; + + ESP_ERROR_CHECK(i2c_new_master_bus(&bus_config, bus_handle)); + ESP_ERROR_CHECK(i2c_master_bus_add_device(*bus_handle, &dev_config, dev_handle)); + + return ESP_OK; +} + +void app_main(void) +{ + uint8_t data[2]; + i2c_master_bus_handle_t bus_handle; + i2c_master_dev_handle_t dev_handle; + ESP_ERROR_CHECK(i2c_master_init(&bus_handle, &dev_handle)); + ESP_LOGI(TAG, "I2C initialized successfully"); + + /* Read the MPU9250 WHO_AM_I register, on power up the register should have the value 0x71 */ + ESP_ERROR_CHECK(mpu9250_register_read(dev_handle, MPU9250_WHO_AM_I_REG_ADDR, data, 1)); + ESP_LOGI(TAG, "WHO_AM_I = %X", data[0]); + + /* Demonstrate writing by resetting the MPU9250 */ + ESP_ERROR_CHECK(mpu9250_register_write_byte(dev_handle, MPU9250_PWR_MGMT_1_REG_ADDR, 1 << MPU9250_RESET_BIT)); + + ESP_ERROR_CHECK(i2c_master_bus_rm_device(dev_handle)); + ESP_ERROR_CHECK(i2c_del_master_bus(bus_handle)); + ESP_LOGI(TAG, "I2C de-initialized successfully"); +}