Page 1 of 1

how can use i2c for external sensor

Posted: Tue Nov 21, 2017 9:32 am
by kishan patel
I want to use i2c for external sensor.
Can anyone tell me that which pin should i use.

and how can i read data from the external sensor.I have also mention my code as below.
I am trying to read device_id of external sensor.but i could not receive/communicate with it.


void i2c_master_init(void)
{
int i2c_master_port = I2C_MASTER_NUM;

i2c_config_t conf;
conf.mode = I2C_MODE_MASTER;
conf.sda_io_num = I2C_MASTER_SDA_IO;
conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
conf.scl_io_num = I2C_MASTER_SCL_IO;
conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
conf.master.clk_speed = I2C_MASTER_FREQ_HZ;

i2c_param_config(i2c_master_port, &conf);
i2c_driver_install(i2c_master_port, conf.mode,I2C_EXAMPLE_MASTER_RX_BUF_DISABLE,I2C_EXAMPLE_MASTER_TX_BUF_DISABLE, 0);
}

//i have used gpio25 as SDA and gpio26 as SCL.

esp_err_t i2c_master_read_data_kt(char* register_address, uint8_t* data_rd, size_t size)
{
if (size == 0) {
return ESP_OK;
}
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, ( SLAVE_ADDRESS << 1 ) | READ_BIT, ACK_CHECK_EN);
i2c_master_write_byte(cmd,0x00 ,ACK_CHECK_EN);
//i2c_master_write(cmd,0x00,size,ACK_CHECK_EN);
if (size > 1) {
i2c_master_read(cmd, data_rd, size - 1, ACK_VAL);
}
i2c_master_read_byte(cmd, data_rd + size - 1, NACK_VAL);
i2c_master_stop(cmd);
esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
return ret;

}

// i have put register-value(device_id address) directly as 0x00.

tell me steps to communicate with external sensor using i2c.

Re: how can use i2c for external sensor

Posted: Tue Nov 21, 2017 7:32 pm
by chegewara
On this diagram you are asking about Single byte read/ master. As you can see, before you can read from device you HAVE to send start + slave device address with write byte + register address you want to read. Since you want to read from device you need to send another start + slave address with byte read + stop.
  1. write address + register:
  2. i2c_cmd_handle_t cmd = i2c_cmd_link_create();
  3. start - i2c_master_start(cmd);
  4. write address - i2c_master_write_byte(cmd, ( SLAVE_ADDRESS << 1 ) | WRITE_BIT, ACK_CHECK_EN);
  5. i2c_master_write_byte(cmd,REGISTER ,ACK_CHECK_EN);
  6. i2c_master_stop(cmd);
  7. esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_RATE_MS);
  8. i2c_cmd_link_delete(cmd);
  • read data:
  • cmd = i2c_cmd_link_create();
  • i2c_master_start(cmd);
  • i2c_master_write_byte(cmd, ( SLAVE_ADDRESS << 1 ) | READ_BIT, ACK_CHECK_EN);
  • i2c_master_read_byte(cmd, data_rd + size - 1, NACK_VAL);
  • i2c_master_stop(cmd);
  • esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_RATE_MS);
  • i2c_cmd_link_delete(cmd);
Image

Re: how can use i2c for external sensor

Posted: Wed Nov 22, 2017 9:39 am
by kishan patel
thanks for reply.
i have worked same as u suggest.You can see my code to read single byte as below.

void i2c_read_data_byte_kt(char register_address,uint8_t* read_buffer)
{
i2c_cmd_handle_t cmd = i2c_cmd_link_create();

i2c_master_start(cmd);
i2c_master_write_byte(cmd,(SLAVE_ADDRESS << 1) | WRITE_BIT ,ACK_CHECK_EN);
i2c_master_write_byte(cmd,register_address,ACK_CHECK_EN);
i2c_master_stop(cmd);
i2c_master_cmd_begin(I2C_MASTER_NUM,cmd,1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);

cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (SLAVE_ADDRESS << 1) | I2C_MASTER_READ, true);
i2c_master_read_byte(cmd, read_buffer, NACK_VAL);
i2c_master_stop(cmd);
i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);

}


its working fine.

now,i want to write single byte.I have searched much about it.But i could not successful in that.Please,see my code to write single byte. and guide me.



void i2c_write_data_byte_kt(void)
{
uint8_t write_data = 0x08;

i2c_cmd_handle_t cmd = i2c_cmd_link_create();

i2c_master_start(cmd);
i2c_master_write_byte(cmd,(SLAVE_ADDRESS << 1) | WRITE_BIT ,ACK_CHECK_EN);
i2c_master_write_byte(cmd,0x2D,ACK_CHECK_EN);
// i2c_master_write_byte(cmd,0x80,ACK_CHECK_EN);
// i2c_master_write_byte(cmd,&write_data,ACK_CHECK_EN);
i2c_master_write(cmd,0x80,1,ACK_CHECK_EN);
i2c_master_stop(cmd);
i2c_master_cmd_begin(I2C_MASTER_NUM,cmd,1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);

/*
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (SLAVE_ADDRESS << 1) | I2C_MASTER_WRITE, true);
i2c_master_write(cmd,0x08,1,ACK_CHECK_EN);
i2c_master_stop(cmd);
i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
*/
}

I HAVE TRIED BY MANY CHANGES.SO,THERE ARE SOME COMMENTS.

Re: how can use i2c for external sensor

Posted: Wed Nov 22, 2017 5:45 pm
by chegewara
When you write to I2C all but last one byte need to be acknowledged. Since you are trying to write just one byte you need to send it with NACK_VAL:

Code: Select all

i2c_master_write(cmd,0x08,1,NACK_VAL);