I2C polling and ACK/NACK checked in next command
Posted: Tue May 07, 2019 12:39 pm
Dear all,
I am struggling with I2C bus and reading measurement from SHT30 sensor.
I am able to read serial number and status register therefore i2c driver, i2c bus and sensor should be working.
But for measurement readout in polling mode I need to create special sequence to "poll" if measurement is ready or not.
I create this sequence exactly according SHT30 specification and example source code.
Here is my readout code snippet:
1. My first question is following:
Why ACK/NACK checking are sent in next command cycle?
See this picture for better view. Position of cursor shows ACK checking. This checking is sent after first 1ms delay in code. 2. My second question is, if there is something wrong in my code, because it is not working at all.
Is there any way how to make polling functional?
How to force I2C driver to send ACK/NACK checking in one command stream?
Thank you for your help.
I am struggling with I2C bus and reading measurement from SHT30 sensor.
I am able to read serial number and status register therefore i2c driver, i2c bus and sensor should be working.
But for measurement readout in polling mode I need to create special sequence to "poll" if measurement is ready or not.
I create this sequence exactly according SHT30 specification and example source code.
Here is my readout code snippet:
Code: Select all
static esp_err_t sh2_start_measurement_with_polling_ht_sensor(void)
{
uint8_t data_rd[6];
esp_err_t err_return;
memset(data_rd, 0, 6);
uint16_t temperature_readout = 0;
uint16_t humidity_readout = 0;
i2c_port_t i2c_port_num = I2C_MASTER_NUM;
//change default I2C timeout to higher value (workaround)
i2c_set_timeout(i2c_port_num, I2C_MASTER_TOUT_CNUM);
//create new i2c link for i2c commands
i2c_cmd_handle_t i2c_command_handle = i2c_cmd_link_create();
//queue start bit
if ( sh2_handle_i2C_error_return ( i2c_master_start(i2c_command_handle)) != ESP_OK ) return ESP_FAIL;
//queue address with ACK checking
i2c_master_write_byte(i2c_command_handle, (HT_SENSOR_I2C_7B_ADDRESS << 1) | I2C_WRITE_BIT, ACK_CHECK_EN);
//queue command with ACK checking
i2c_master_write_byte(i2c_command_handle, (CMD_MEAS_POLLING_M >> 8), ACK_CHECK_EN);
//queue command with ACK checking
i2c_master_write_byte(i2c_command_handle, (CMD_MEAS_POLLING_M & 0xff), ACK_CHECK_EN);
//begin i2c command
i2c_master_cmd_begin(i2c_port_num, i2c_command_handle, I2C_READ_WAIT_MS / portTICK_RATE_MS);
//delete link to release i2c resources
i2c_cmd_link_delete(i2c_command_handle);
vTaskDelay(1 / portTICK_PERIOD_MS);
//poll command with reading device address until ACK appears (this means that measurement has been finished)
uint8_t reading_tries = MAX_SHT_POLLING_TRIES;
while(reading_tries--)
{
//change default I2C timeout to higher value (workaround)
i2c_set_timeout(i2c_port_num, I2C_MASTER_TOUT_CNUM);
//create new i2c link for i2c commands
i2c_command_handle = i2c_cmd_link_create();
//queue start bit
i2c_master_start(i2c_command_handle);
//queue address with ACK checking
i2c_master_write_byte(i2c_command_handle, (HT_SENSOR_I2C_7B_ADDRESS << 1) | I2C_READ_BIT, ACK_CHECK_EN) ;
//begin i2c command
err_return = i2c_master_cmd_begin(i2c_port_num, i2c_command_handle, I2C_READ_WAIT_MS / portTICK_RATE_MS);
//delete link to release i2c resources
i2c_cmd_link_delete(i2c_command_handle);
if ( err_return == ESP_OK ) break;
//wait little bit and cycle reading again
vTaskDelay(1 / portTICK_PERIOD_MS);
}
//if no error then finish reading of temperature and humidity raw values and CRCs
if (reading_tries > 0)
{
//change default I2C timeout to higher value (workaround)
i2c_set_timeout(i2c_port_num, I2C_MASTER_TOUT_CNUM);
//create new i2c link for i2c commands
i2c_command_handle = i2c_cmd_link_create();
//queue data read command with ACK checking
i2c_master_read(i2c_command_handle, data_rd, 6, I2C_MASTER_LAST_NACK );
//queue stop bit
i2c_master_stop(i2c_command_handle);
//begin i2c command
err_return = i2c_master_cmd_begin(i2c_port_num, i2c_command_handle, I2C_READ_WAIT_MS / portTICK_RATE_MS);
//delete link to release i2c resources
i2c_cmd_link_delete(i2c_command_handle);
//verify CRC of received TEMPERATURE data - it is feature of SHT30
err_return = sh2_check_crc(data_rd, 2, data_rd + 2); //check CRC of first 2 bytes
if (err_return != ESP_OK)
{
device_data.ht_sensor_data.i2c_bus_errors_return = I2C_ERROR_CRC;
return ESP_FAIL;
}
temperature_readout = (data_rd[0] << 24) | (data_rd[1] << 16); //copy data of temperature readout
device_data.ht_sensor_data.sensor_temperature = temperature_readout;
//verify CRC of received HUMIDITY data - it is feature of SHT30
err_return = sh2_check_crc(data_rd + 3, 2, data_rd + 5); //check CRC of first 2 bytes
if (err_return != ESP_OK)
{
device_data.ht_sensor_data.i2c_bus_errors_return = I2C_ERROR_CRC;
return ESP_FAIL;
}
humidity_readout = (data_rd[3] << 8) | (data_rd[4] ); //copy data of humidity readout
device_data.ht_sensor_data.sensor_humidity = humidity_readout;
return ESP_OK;
}
else
{
//there was problem while trying to read SHT sensor
device_data.ht_sensor_data.i2c_bus_errors_return = I2C_ERROR_FATAL;
return ESP_FAIL;
}
}
Why ACK/NACK checking are sent in next command cycle?
See this picture for better view. Position of cursor shows ACK checking. This checking is sent after first 1ms delay in code. 2. My second question is, if there is something wrong in my code, because it is not working at all.
Is there any way how to make polling functional?
How to force I2C driver to send ACK/NACK checking in one command stream?
Thank you for your help.