ADS1115 with espress-idf and esp32

casmeiron
Posts: 4
Joined: Thu Dec 07, 2017 7:39 pm

ADS1115 with espress-idf and esp32

Postby casmeiron » Thu Dec 07, 2017 7:54 pm

Hi guys, this is my first post, so I'm sorry if any guide rules are being broken, I will learn fast how to respect them.

I'm tryin' to read sensor data from channel AIN0 of ADS1115 using my esp32 where AIN0 is connected with 5V of a power source and the ADS is grounded to this source.

I found the i2c a bit complex (maybe I didnt understand it correctly), I hope you guys could help me.

I'm using I2C_NUM_0 (as a guess, but tried I2C_NUM_1 too) and after using I2C Scanner, I see the ADS sensor is present at address 0x48.

The pins are correct, I've doubled checked it.

So after installing using the follow code:

Code: Select all

#define SDA_PIN 21
#define SCL_PIN 22
#define SENSOR_ADDRESS	0x48
#define ACK_VAL                            0x0              /*!< I2C ack value */
#define AIN0_CHANNEL		0x4000
#define WRITE_BIT                          I2C_MASTER_WRITE /*!< I2C master write */
#define READ_BIT                           I2C_MASTER_READ  /*!< I2C master read */

void install() {
    if(!ic2DriverInstalled) {
		ESP_LOGI(tag, "Installing...");
        i2c_config_t conf;
        conf.mode = I2C_MODE_MASTER;
        conf.sda_io_num = SDA_PIN;
        conf.scl_io_num = SCL_PIN;
        conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
        conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
        conf.master.clk_speed = 100000;
        i2c_param_config(I2C_PORT, &conf);
	    i2c_driver_install(I2C_PORT, I2C_MODE_MASTER, 0, 0, 0);
        ic2DriverInstalled = true;
		ESP_LOGI(tag, "Installed!");
    }
}
First question: Do I have to use GPIO_PULLUP_ENABLE for this sensor? (SDA AND SCL)
When to use and when not to use ACK wasn't understood by me too.

Ok, after installing I run the code to retrieve sensor data. It's something like this:

Code: Select all

esp_err_t read_sensor(uint8_t* data) {
    int ret;
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, SENSOR_ADDRESS << 1 | WRITE_BIT, ACK_VAL);
    i2c_master_write_byte(cmd, AIN0_CHANNEL, ACK_VAL);
    i2c_master_stop(cmd);
    ret = i2c_master_cmd_begin(I2C_PORT, cmd, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);
    ESP_LOGD(tag, "RET X1: %d", ret);

    if (ret != ESP_OK) {
        return ret;
    }

    vTaskDelay(30 / portTICK_RATE_MS);
    cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, SENSOR_ADDRESS << 1 | READ_BIT, ACK_CHECK_EN);
    i2c_master_read_byte(cmd, data, ACK_VAL);
    i2c_master_stop(cmd);
    ret = i2c_master_cmd_begin(I2C_PORT, cmd, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);

    ESP_LOGD(tag, "RET X2: %d", ret);
    
    return ret;
}
I'm using the i2c example code (from esp-idf github) but modified a little bit with the values that I THINK are correct, like I just get one value from sensor not two [well I think] (like the example, humidity and temperature).

The first RET print is 0 the second is 263, but I don't have a clue what I'm doing, really. :oops:
Is this the correct flow?
1) Write to I2C the address that I want to communicate
2) Write to I2C the address/channel of the sensor that I want to read
3) Read from I2C (in the address that I first used [SENSOR ADDRESS]) the stored value

I really appreciate any help guys. ;)

God Bless.

compact_banner
Posts: 1
Joined: Wed Jun 06, 2018 12:52 am

Re: ADS1115 with espress-idf and esp32

Postby compact_banner » Sat Sep 07, 2019 4:09 pm

I know this is a 2 year old thread, but it's still one of the top results on Google for "esp idf ads1115", so figured it was worth putting down what I know. I just got my own ADS1115 working with my ESP-32 by following the datasheet, which is available here: http://www.ti.com/lit/ds/symlink/ads1114.pdf.
Do I have to use GPIO_PULLUP_ENABLE for this sensor? (SDA AND SCL)
That's answered directly in the datasheet (yes, you do):
Pullup resistors are required on both the SDA and SCL lines because I2C bus drivers are open drain.
When to use and when not to use ACK wasn't understood by me too.
I'm not experienced enough to know if there's a general answer for this, but I think the answer is "use it when the datasheet tells you to". It looks like the ADS1115 will let you read a single byte of a 2-byte register by leaving the first byte unacknowledged. It's a worthwhile distinction to pay attention to whether it's the slave acknowledging a communication from the master or vice versa. In the first case the sensor is telling your ESP-32 "I got your message", whereas in the second case your ESP-32 is asking the sensor to acknowledge when the sensor receives a message from the ESP-32.
The first RET print is 0 the second is 263
So far as I'm aware, the returned value should always be 0 unless there's an error of some sort.

Other than that, it looks like you're on the right track. Once you successfully read the two bytes into your data variable it will contain the raw reading (two's complement mV after gain). To get a usable value out of that, convert the reading to a signed integer, undo the effect of the gain, and you should have an actual voltage reading. Here's what I'm using:

Code: Select all

    // Convert the two u_int8_t sensor reading into a single u_int16_t
    u_int16_t raw_measurement = (sensor_data_h << 8 | sensor_data_l);

    // Convert the unsigned u_int16_t into a signed integer
    int raw_measurement_as_signed_int = (0x8000 & raw_measurement ? (int)(0x7FFF & raw_measurement) - 0x8000 : raw_measurement);

    // Undo the effect of the gain
    float millivolts_before_gain = raw_measurement_as_signed_int * 0.1875;

    // Convert to volts
    float voltage = millivolts_before_gain / 1000;

A1k1shay
Posts: 2
Joined: Thu Jan 14, 2021 7:26 am

Re: ADS1115 with espress-idf and esp32

Postby A1k1shay » Thu Jan 14, 2021 9:56 am

ESP_FAIL error from below code. Can anyone please help?
  1. [#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
  2. #define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
  3. #define ACK_CHECK_EN 0x1            /*!< I2C master will check ack from slave*/
  4. #define ACK_CHECK_DIS 0x0           /*!< I2C master will not check ack from slave */
  5. #define ACK_VAL 0x0                 /*!< I2C ack value */
  6. #define NACK_VAL 0x1               /*!< I2C nack value */
  7.  
  8. //static const char *TAG = "cmd_i2ctools";
  9.  
  10. static gpio_num_t i2c_gpio_sda = 21;
  11. static gpio_num_t i2c_gpio_scl = 22;
  12. static uint32_t i2c_frequency = 1000;
  13. static i2c_port_t i2c_port = I2C_NUM_0;
  14. uint8_t datah;
  15. uint8_t datal;
  16. esp_err_t i2c_ret;
  17. uint8_t config_reg_val1 = 0b00001110;
  18. uint8_t config_reg_val2 = 0b00000011;
  19.  
  20. void app_main ()
  21. {
  22.  
  23.   i2c_config_t conf = {
  24.       .mode = I2C_MODE_MASTER,
  25.       .sda_io_num = i2c_gpio_sda,
  26.       .sda_pullup_en = GPIO_PULLUP_ENABLE,
  27.       .scl_io_num = i2c_gpio_scl,
  28.       .scl_pullup_en = GPIO_PULLUP_ENABLE,
  29.       .master.clk_speed = i2c_frequency
  30.   };
  31.   i2c_param_config(i2c_port, &conf);
  32.   i2c_driver_install(i2c_port, I2C_MODE_MASTER, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
  33.   i2c_cmd_handle_t cmd = i2c_cmd_link_create ();
  34.   i2c_master_start(cmd);
  35.   i2c_master_write_byte(cmd, 0b1001000|I2C_MASTER_WRITE, 1); //address pin connected to ground
  36.   i2c_master_write_byte(cmd, 0b00000001, 1); // config register
  37.   i2c_master_write(cmd, config_reg_val1, 8, 1);
  38.   i2c_master_write(cmd, config_reg_val2 , 8, 1);
  39.   i2c_master_stop(cmd);
  40.   i2c_ret = i2c_master_cmd_begin(i2c_port, cmd, 10000/portTICK_RATE_MS);
  41.   i2c_cmd_link_delete(cmd);
  42.  
  43.   if (i2c_ret == ESP_OK)
  44.   {
  45.     printf("I2C Write OK\n");
  46.   }
  47.   if (i2c_ret == ESP_FAIL)
  48.   {
  49.     printf("I2C_fail\n");
  50.   }
  51.   if (i2c_ret == ESP_ERR_INVALID_ARG)
  52.   {
  53.     printf("wrong parameter\n");
  54.   }
  55.   if (i2c_ret == ESP_ERR_INVALID_STATE)
  56.   {
  57.     printf("driver_error\n");
  58.   }
  59.   if (i2c_ret == ESP_ERR_TIMEOUT)
  60.   {
  61.     printf("timeout\n");
  62.   }
  63.  
  64.   i2c_driver_delete(i2c_port);
  65. }

chegewara
Posts: 2378
Joined: Wed Jun 14, 2017 9:00 pm

Re: ADS1115 with espress-idf and esp32

Postby chegewara » Thu Jan 14, 2021 4:32 pm

I dont know which idf version you are using, but some time ago 1 more value has been added to "i2c_config_t" struct which is causing issue when i am trying arduino as component, because is not initilized. But this is issue with C++, in your case it may be something else (worth to try). I think its that value:
https://github.com/espressif/esp-idf/bl ... _i2c.c#L94

dhruvag2000
Posts: 1
Joined: Fri Mar 05, 2021 1:14 pm

Re: ADS1115 with espress-idf and esp32

Postby dhruvag2000 » Fri Mar 05, 2021 1:20 pm

Hey, I finally got the ADS1115 working using this https://pastebin.com/0fU89YTb code here.
You probably want to know the connections, so they are as follows:
ADS | ESP32
1. V_DD --> V_in
2. GND --> GND
3. SCL --> D22
4. SDA --> D21
5. Your analog input in A0
No other pins need any connections in my experience uptil now.
Hope this helps anyone facing these issues, as this is the only thread I found after googling for solutions

venugopala
Posts: 2
Joined: Mon Nov 22, 2021 11:56 am

Re: ADS1115 with espress-idf and esp32

Postby venugopala » Mon Nov 22, 2021 12:47 pm

I can able to read ADC channel A0,using this example code https://pastebin.com/0fU89YTb.
I want to read all 4 ADC channel please share the knowledge about this.
Am tried to read all 4 channel, based on my configuration it is not able to get all 4 ADC channel data.
this is my configuration:
for (size_t i = 0; i < DEV_COUNT; i++)
{
ESP_ERROR_CHECK(ads111x_init_desc(&devices, ADS111X_ADDR_GND, I2C_PORT, SDA_GPIO, SCL_GPIO));
ESP_ERROR_CHECK(ads111x_set_mode(&devices, ADS111X_MODE_CONTINUOUS)); // Continuous conversion mode
ESP_ERROR_CHECK(ads111x_set_data_rate(&devices, ADS111X_DATA_RATE_32)); // 32 samples per second
ESP_ERROR_CHECK(ads111x_set_input_mux(&devices, ADS111X_MUX_0_GND)); // positive = AIN0, negative = GND
ESP_ERROR_CHECK(ads111x_set_input_mux(&devices, ADS111X_MUX_1_GND)); // positive = AIN1, negative = GND
ESP_ERROR_CHECK(ads111x_set_input_mux(&devices, ADS111X_MUX_2_GND)); // positive = AIN2, negative = GND
ESP_ERROR_CHECK(ads111x_set_input_mux(&devices, ADS111X_MUX_3_GND)); // positive = AIN0, negative = GND
ESP_ERROR_CHECK(ads111x_set_gain(&devices, GAIN));
}

while (1)
{
for (size_t i = 0; i < DEV_COUNT; i++)
measure(i);

vTaskDelay(pdMS_TO_TICKS(500));
}

Who is online

Users browsing this forum: atx823, brushlow18, Google [Bot] and 224 guests