ESP32 IDF

ESP32 IDF I2C

임베디드 친구 2024. 11. 11. 09:50
반응형

I2C 프로토콜 개요

I2C(Inter-Integrated Circuit)는 단일 마스터와 여러 슬레이브 간 통신을 위한 직렬 통신 프로토콜입니다. I2C는 두 개의 와이어만 사용하여 데이터를 전송하는 방식으로, SCL(Serial Clock Line)과 SDA(Serial Data Line)으로 구성됩니다. 이 프로토콜은 간단한 배선으로 다수의 장치 간에 데이터를 송수신할 수 있기 때문에, 다양한 센서 및 디바이스와의 통신에서 많이 사용됩니다.

I2C의 주요 특징은 다음과 같습니다:

  • 다중 장치 연결: SCL과 SDA 두 개의 라인만으로 여러 장치를 연결할 수 있습니다.
  • 마스터-슬레이브 구조: 한 개의 마스터와 여러 개의 슬레이브로 구성됩니다. 마스터는 통신을 제어하며, 슬레이브는 마스터의 명령에 따라 동작합니다.
  • 클록 신호 기반: 마스터가 클록 신호(SCL)를 제공하여 모든 슬레이브가 같은 속도로 통신하게 합니다.

ESP32는 이러한 I2C 프로토콜을 지원하며, 다양한 센서나 디바이스와의 통신에 유용합니다. 이번 포스팅에서는 ESP32에서 I2C를 사용하여 센서 데이터를 읽는 방법에 대해 설명드리겠습니다.

ESP32에서 I2C 설정하기

ESP32에서 I2C 통신을 설정하려면, ESP-IDF 개발 환경을 사용하여 드라이버를 설정하고, SCL 및 SDA 핀을 정의해야 합니다. 아래에서는 VS Code 개발 환경에서 ESP32의 I2C 설정 방법과 예제를 보여드리겠습니다.

개발 환경 준비

이번 예제에서는 Visual Studio Code와 ESP-IDF 플러그인을 사용하여 개발을 진행합니다. ESP32 개발 환경이 이미 설치되어 있다고 가정하고, ESP-IDF 프로젝트를 생성하고 I2C 통신을 설정하는 과정을 설명하겠습니다.

  1. 프로젝트 생성: VS Code에서 새로운 ESP-IDF 프로젝트를 생성합니다. 이 프로젝트에서는 I2C 드라이버를 설정하여 센서 데이터를 읽는 프로그램을 작성합니다.
  2. 필요한 라이브러리 추가: I2C를 사용하기 위해 driver/i2c.h 헤더 파일을 포함해야 합니다. 이 파일은 I2C 드라이버 설정 및 데이터 전송에 필요한 함수들을 제공합니다.
#include "driver/i2c.h"
#include <stdio.h>

I2C 설정 코드 예제

다음은 ESP32에서 I2C를 설정하는 코드 예제입니다. SDA와 SCL 핀은 각각 GPIO 21과 GPIO 22로 설정합니다.

#define I2C_MASTER_SCL_IO           22    /*!< SCL 핀 번호 */
#define I2C_MASTER_SDA_IO           21    /*!< SDA 핀 번호 */
#define I2C_MASTER_FREQ_HZ          100000 /*!< I2C 클럭 주파수 */
#define I2C_MASTER_PORT_NUM         I2C_NUM_0 /*!< I2C 포트 번호 */
#define I2C_MASTER_TX_BUF_DISABLE   0     /*!< 전송 버퍼 비활성화 */
#define I2C_MASTER_RX_BUF_DISABLE   0     /*!< 수신 버퍼 비활성화 */

void i2c_master_init() {
    i2c_config_t i2c_config = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = I2C_MASTER_SDA_IO,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_io_num = I2C_MASTER_SCL_IO,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .master.clk_speed = I2C_MASTER_FREQ_HZ
    };
    i2c_param_config(I2C_MASTER_PORT_NUM, &i2c_config);
    i2c_driver_install(I2C_MASTER_PORT_NUM, i2c_config.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
}

위 코드는 I2C 마스터를 초기화하고 SDA 및 SCL 핀을 설정하는 코드입니다. GPIO 21과 22 핀을 SDA와 SCL로 설정하고, 클럭 속도를 100kHz로 설정하였습니다.

센서 데이터 읽기

이번에는 I2C를 이용해 실제로 센서 데이터를 읽는 예제를 보여드리겠습니다. 여기서는 보편적으로 사용되는 온도/습도 센서인 HTU21D를 사용하여 데이터를 읽어오는 코드를 작성합니다.

HTU21D 센서 데이터 읽기 코드

HTU21D 센서는 온도와 습도를 측정할 수 있는 센서로, I2C를 통해 데이터를 읽어올 수 있습니다. 다음 코드는 HTU21D 센서로부터 데이터를 읽는 방법을 보여줍니다.

#define HTU21D_SENSOR_ADDR 0x40 /*!< HTU21D I2C 주소 */
#define HTU21D_TEMP_MEASURE_NOHOLD_CMD 0xF3 /*!< 온도 측정 명령 */

esp_err_t htu21d_read_temperature(float *temperature) {
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (HTU21D_SENSOR_ADDR << 1) | I2C_MASTER_WRITE, true);
    i2c_master_write_byte(cmd, HTU21D_TEMP_MEASURE_NOHOLD_CMD, true);
    i2c_master_stop(cmd);
    esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_PORT_NUM, cmd, 1000 / portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);
    if (ret != ESP_OK) {
        return ret;
    }

    vTaskDelay(50 / portTICK_PERIOD_MS);

    uint8_t data[2];
    cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (HTU21D_SENSOR_ADDR << 1) | I2C_MASTER_READ, true);
    i2c_master_read(cmd, data, 2, I2C_MASTER_ACK);
    i2c_master_stop(cmd);
    ret = i2c_master_cmd_begin(I2C_MASTER_PORT_NUM, cmd, 1000 / portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);
    if (ret == ESP_OK) {
        uint16_t raw_temp = (data[0] << 8) | data[1];
        *temperature = -46.85 + 175.72 * ((float)raw_temp / 65536.0);
    }
    return ret;
}

위 코드는 HTU21D 센서로부터 온도 데이터를 읽는 예제입니다. 주요 단계는 다음과 같습니다:

  1. 측정 명령 전송: 센서에 온도 측정을 요청하는 명령을 전송합니다.
  2. 데이터 읽기: 측정 후 데이터를 읽어와서 온도를 계산합니다.
  3. 온도 계산: 센서에서 읽어온 값을 이용하여 실제 온도를 계산합니다.

main 함수에서의 동작

이제, main 함수에서 I2C 초기화 및 온도 데이터를 읽어오는 동작을 추가해보겠습니다.

void app_main() {
    // I2C 마스터 초기화
    i2c_master_init();

    // 온도 데이터 읽기
    float temperature;
    esp_err_t ret = htu21d_read_temperature(&temperature);
    if (ret == ESP_OK) {
        printf("Temperature: %.2f C\n", temperature);
    } else {
        printf("Failed to read temperature\n");
    }
}

위 코드에서는 I2C를 초기화한 후, HTU21D 센서로부터 온도 데이터를 읽어와 콘솔에 출력합니다. 만약 데이터 읽기에 실패하면 오류 메시지를 출력합니다.

결론

이번 포스팅에서는 ESP32와 I2C 프로토콜을 사용하여 HTU21D 센서로부터 데이터를 읽는 방법을 알아보았습니다. I2C는 여러 장치를 단일 마스터로 쉽게 연결할 수 있어 다양한 센서와의 통신에 매우 유용한 프로토콜입니다. ESP32에서 I2C를 설정하고 센서 데이터를 읽는 과정을 직접 따라해 보면서, I2C 통신에 대한 이해를 높이시길 바랍니다.

반응형

'ESP32 IDF' 카테고리의 다른 글

ESP32 IDF UART  (0) 2024.11.13
ESP32 IDF SPI  (0) 2024.11.12
ESP32 IDF DAC  (0) 2024.11.10
ESP32 IDF ADC  (0) 2024.11.09
ESP32 IDF PWM  (0) 2024.11.08