Page 1 of 1

I2C not reading properly

Posted: Fri Sep 07, 2018 8:06 pm
by embedded_systems
I'm trying to communicate with a Si8901 I2C ADC IC.

From the documentation, this is the I2C protocol:
Screen Shot 2018-09-07 at 1.05.25 PM.png
Screen Shot 2018-09-07 at 1.05.25 PM.png (59.55 KiB) Viewed 2845 times
Here is my code:

Code: Select all

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


#define ACK_CHECK_EN   0x1
#define ACK_CHECK_DIS  0x0              /*!< I2C master will not check ack from slave */
#define I2C_MASTER_NUM I2C_NUM_0   /*!< I2C port number for master dev */
#define I2C_MASTER_TX_BUF_DISABLE   0   /*!< I2C master do not need buffer */
#define I2C_MASTER_RX_BUF_DISABLE   0   /*!< I2C master do not need buffer */
#define WRITE_BIT  I2C_MASTER_WRITE /*!< I2C master write */
#define READ_BIT   I2C_MASTER_READ  /*!< I2C master read */
#define ACK_VAL    0x0         /*!< I2C ack value */
#define NACK_VAL   0x1         /*!< I2C nack value */

#define ADC_ADDRESS 0xF0
#define command 0xC3

i2c_cmd_handle_t i2c_cmd_handler;


void print_i2c_error_(int ret){
	if (ret != ESP_OK) {
		switch(ret){
			case ESP_FAIL: 
				printf("ESP_FAIL\n");
				break;
			case ESP_ERR_INVALID_ARG: 
				printf("ESP_ERR_INVALID_ARG\n");
				break;
			case ESP_ERR_INVALID_STATE: 
				printf("ESP_ERR_INVALID_STATE\n");
				break;
			case ESP_ERR_TIMEOUT: 
				printf("ESP_ERR_TIMEOUT\n");
				break;
			case ESP_OK: 
				printf("ESP_OK\n");
				break;
			default:
				printf("I2C Failed with code %d\n", ret);
		}
	}else{
		printf("Read Passed\n");
	}
}

uint8_t i2c_adc_read(){

    uint8_t ADC_VALUE_1 = 0;
    uint8_t ADC_VALUE_2 = 0x00;
    uint8_t ADC_VALUE_3 = 0x00;

    int ret = 0;

    printf("v___________________CNFG_0___________________v\n");
    i2c_cmd_handler = i2c_cmd_link_create();
	i2c_master_start(i2c_cmd_handler);
	i2c_master_write_byte(i2c_cmd_handler, ADC_ADDRESS | WRITE_BIT, ACK_CHECK_EN);
	i2c_master_write_byte(i2c_cmd_handler, command, ACK_CHECK_EN);
	i2c_master_stop(i2c_cmd_handler);
    ret = i2c_master_cmd_begin(I2C_MASTER_NUM, i2c_cmd_handler, 100 / portTICK_RATE_MS);
    print_i2c_error_(ret);
    i2c_cmd_link_delete(i2c_cmd_handler);
    printf("^___________________CNFG_0___________________^\n");


    printf("v___________________Read_____________________v\n");
    i2c_cmd_handler = i2c_cmd_link_create();
	i2c_master_start(i2c_cmd_handler);
	i2c_master_write_byte(i2c_cmd_handler, ADC_ADDRESS | READ_BIT, ACK_CHECK_EN);
	i2c_master_read_byte(i2c_cmd_handler, &ADC_VALUE_1, ACK_VAL);
	i2c_master_read_byte(i2c_cmd_handler, &ADC_VALUE_2, ACK_VAL);
	i2c_master_read_byte(i2c_cmd_handler, &ADC_VALUE_3, ACK_VAL);
	i2c_master_stop(i2c_cmd_handler);
	ret = i2c_master_cmd_begin(I2C_MASTER_NUM, i2c_cmd_handler, 100 / portTICK_RATE_MS);
    print_i2c_error_(ret);
	i2c_cmd_link_delete(i2c_cmd_handler);
    
    printf("ADC_VALUE_1: %02x\n", ADC_VALUE_1);
    printf("ADC_VALUE_2: %02x\n", ADC_VALUE_2);
    printf("ADC_VALUE_3: %02x\n", ADC_VALUE_3);
    printf("^___________________Read_____________________^\n");
    return 0;
}

void app_main(void)
{

	i2c_config_t conf;
	conf.mode = I2C_MODE_MASTER;
	conf.sda_io_num = 5;
	conf.scl_io_num = 17;
	conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
	conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
	conf.master.clk_speed = 100000;
	ESP_ERROR_CHECK(i2c_param_config(I2C_MASTER_NUM, &conf));
	ESP_ERROR_CHECK(i2c_driver_install(I2C_MASTER_NUM, I2C_MODE_MASTER, 0, 0, 0));

    while(1){
        printf("read\n");
        i2c_adc_read();
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}
The output I get is:

Code: Select all

read
v___________________CNFG_0___________________v
Read Passed
^___________________CNFG_0___________________^
v___________________Read_____________________v
ESP_ERR_TIMEOUT
ADC_VALUE_1: c3
ADC_VALUE_2: 86
ADC_VALUE_3: 60
^___________________Read_____________________^
readv___________________CNFG_0___________________v
Read Passed
^___________________CNFG_0___________________^
v___________________Read_____________________v
ESP_ERR_TIMEOUT
ADC_VALUE_1: c3
ADC_VALUE_2: 60
ADC_VALUE_3: 60
^___________________Read_____________________^
The value of ADC_VALUE_1 is correct, 0xC3. The value us ADC_VALUE_2 and ADC_VALUE_3 is wrong. After the first iteration or reads, the values are alway different. With every read, I get the ESP_ERR_TIMEOUT error. I used a saleae logic analyzer to get a closer look at what is happening. Below I have those screen shots.
Screen Shot 2018-09-07 at 2.01.28 PM.png
Screen Shot 2018-09-07 at 2.01.28 PM.png (85.54 KiB) Viewed 2845 times
The protocol should be
Master Start
Master write address 0xF0 with write bit and ACK
Master write config byte with ACK (Config byte is 0xC3)
Master Stop
Master Start
Master write address 0xF0 with read bit and ACK
Slave Start
Master Read with ACK
Master Read with ACK
Master Read with ACK
Master Stop

I'm not sure what the issue is. The third i2c_master_read_byte looks different on the logic analyzer than the other i2c_master_read_byte reads on the first iteration.