ESP_ERR_TIMEOUT while write and read from I2C slave

rotematari
Posts: 4
Joined: Tue Mar 26, 2024 3:36 pm

ESP_ERR_TIMEOUT while write and read from I2C slave

Postby rotematari » Thu Apr 25, 2024 9:54 am

hello,

my setup is
esp32-c6
esp-idf 5.1.2
SHT30

Code: Select all

#include <stdio.h>
#include "driver/i2c.h"
#include "esp_log.h"

#define LOG_TAG "SHT30_APP"

#define I2C_MASTER_SCL_IO 19     /*!< GPIO number used for I2C master clock yellow in sht30 */
#define I2C_MASTER_SDA_IO 18     /*!< GPIO number used for I2C master data white in sht30 */
#define I2C_MASTER_NUM I2C_NUM_0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */

#define I2C_MASTER_FREQ_HZ 20000    /*!< 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_WRITE 0x0
#define I2C_MASTER_READ 0x1
#define ACK 0
#define NACK 1
#define I2C_PORT_NUM I2C_NUM_0
#define I2C_MASTER_TIMEOUT_MS 1000
#define I2C_SLAVE_ADDRESS 0x44


// SHT30 Command Codes for Single Shot Data Acquisition Mode
#define SHT30_CMD_READ_HIGHREP_STRETCH 0x2C06 /*!< Command to read with high repeatability and clock stretching enabled */
#define SHT30_CMD_READ_MEDREP_STRETCH 0x2C0D  /*!< Command to read with medium repeatability and clock stretching enabled */
#define SHT30_CMD_READ_LOWREP_STRETCH 0x2C10  /*!< Command to read with low repeatability and clock stretching enabled */

#define SHT30_CMD_READ_HIGHREP 0x2400 /*!< Command to read with high repeatability without clock stretching */
#define SHT30_CMD_READ_MEDREP 0x240B  /*!< Command to read with medium repeatability without clock stretching */
#define SHT30_CMD_READ_LOWREP 0x2416  /*!< Command to read with low repeatability without clock stretching */

// Additional Commands
#define SHT30_CMD_SOFT_RESET 0x30A2 /*!< Soft reset command */
#define SHT30_READ_PERIODIC 0XE000  /*read periodic data sampling*/

/**
 * @brief i2c master initialization
 */
static esp_err_t i2c_master_init(void)
{
    int i2c_master_port = I2C_NUM_0;
    i2c_config_t conf = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = I2C_MASTER_SDA_IO, // select SDA GPIO specific to your project
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_io_num = I2C_MASTER_SCL_IO, // select SCL GPIO specific to your project
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .master.clk_speed = I2C_MASTER_FREQ_HZ, // select frequency specific to your project
        .clk_flags = 0,                         // optional; you can use I2C_SCLK_SRC_FLAG_* flags to choose i2c source clock here
    };

    i2c_param_config(i2c_master_port, &conf);

    return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
}

esp_err_t sht30_send_command(i2c_port_t i2c_num, uint16_t cmd)
{
    // Create I2C link
    i2c_set_timeout(i2c_num, I2C_MASTER_TIMEOUT_MS);
    i2c_cmd_handle_t cmd_handle = i2c_cmd_link_create();
    i2c_master_start(cmd_handle);
    i2c_master_write_byte(cmd_handle, (I2C_SLAVE_ADDRESS << 1) | I2C_MASTER_WRITE, ACK);
    i2c_master_write_byte(cmd_handle, cmd >> 8, ACK);   // Send MSB of the command
    i2c_master_write_byte(cmd_handle, cmd & 0xFF, ACK); // Send LSB of the command
    i2c_master_stop(cmd_handle);
    esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd_handle, pdMS_TO_TICKS(1000));
    i2c_cmd_link_delete(cmd_handle);
    return ret;
}

esp_err_t sht30_read_data(i2c_port_t i2c_num, uint8_t *data, size_t size)
{
    if (size < 6)
    {
        // We expect at least 6 bytes, for two values and two CRCs
        return ESP_ERR_INVALID_SIZE;
    }
    i2c_cmd_handle_t cmd_handle = i2c_cmd_link_create();
    i2c_master_start(cmd_handle);
    i2c_master_write_byte(cmd_handle, (I2C_SLAVE_ADDRESS << 1) | I2C_MASTER_READ, ACK);
    i2c_master_read(cmd_handle, data, size - 1, ACK);
    i2c_master_read_byte(cmd_handle, data + size - 1, ACK); // Last byte followed by NACK
    i2c_master_stop(cmd_handle);
    esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd_handle, pdMS_TO_TICKS(1000));
    i2c_cmd_link_delete(cmd_handle);
    return ret;
}

// Usage example
void app_main(void)
{
    uint8_t sensorData[6];
    esp_err_t err;

    // Initialize I2C master interface
    esp_err_t ret;
    ret = i2c_master_init();
    if (ret != ESP_OK)
    {
        ESP_LOGE(LOG_TAG, "I2C initialization failed");
    }

    ESP_LOGI(LOG_TAG, "I2C initialized successfully");
    while (1)
    {
        // Send the command to the sensor
        err = sht30_send_command(I2C_PORT_NUM, SHT30_CMD_READ_HIGHREP);
        if (err != ESP_OK)
        {
            ESP_LOGE(LOG_TAG, "send command failed");
            ESP_LOGE(LOG_TAG, "send Return value: %s", esp_err_to_name(err));
        }

        // Read the sensor data
        err = sht30_read_data(I2C_PORT_NUM, sensorData, sizeof(sensorData));

        if (err == ESP_OK)
        {
            // Convert the sensor data to human-readable form
            int temp = (sensorData[0] << 8) + sensorData[1];
            int humidity = (sensorData[3] << 8) + sensorData[4];

            float temperature = -45 + (175 * ((float)temp / 65535));
            float relative_humidity = 100 * ((float)humidity / 65535);

            // Log to console
            ESP_LOGI(LOG_TAG, "Temperature: %.2f °C, Humidity: %.2f %%", temperature, relative_humidity);

            // Print to the serial monitor
            printf("Current Temperature: %.2f °C, Humidity: %.2f %%\n", temperature, relative_humidity);
        }
        else
        {
            ESP_LOGE(LOG_TAG, "Failed to read data");
            printf("Error reading data from SHT30 sensor\n");
        }
    }
}
I get ESP_ERR_TIMEOUT
I did some digging and saw that it is a common problem
but couldn't find a solution
did some managed to find a solution other than working with arduino code ?
or maybe can I work with wire.h ?

best regards

Who is online

Users browsing this forum: benrank, Gaston1980, ok-home and 52 guests