ESP_ERR_TIMEOUT while write and read from I2C slave
Posted: Thu Apr 25, 2024 9:54 am
hello,
my setup is
esp32-c6
esp-idf 5.1.2
SHT30
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
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 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