ESP32 - ADS1115 Configure problem

temuko
Posts: 8
Joined: Sun Oct 15, 2023 10:55 am
Location: Europe, Spain

ESP32 - ADS1115 Configure problem

Postby temuko » Sun Aug 25, 2024 11:19 am

Hello everyone,

First of all, I'm a bit of a newbie when it comes to embedded programming. I'm working on my final degree project using an ESP32, and I'm having trouble configuring an external ADC (ADS1115).

According to the ADS1115 datasheet, I need to write 4 bytes to configure the register in the following order: START - ADDRESS/RW - 00000001 - 10000100 - 10000011 - STOP

I tested whether the ADS1115 is correctly connected using the i2c_master_probe function, and it seems to be working properly. However, the problem arises when I try to send all four bytes in the same transmit function. I get this error:

Code: Select all

D (326) i2c.common: bus clock source frequency: 80000000hz
Device found on I2C bus
E (334) i2c.master: s_i2c_synchronous_transaction(830): I2C transaction failed
I (341) gpio: GPIO[21]| InputEn: 1| OutputEn: 1| OpenDrain: 1| Pullup: 0| Pulldown: 0| Intr:0 
I (351) gpio: GPIO[22]| InputEn: 1| OutputEn: 1| OpenDrain: 1| Pullup: 0| Pulldown: 0| Intr:0 
E (360) i2c.master: i2c_master_transmit(1033): I2C transaction failed
ESP_ERROR_CHECK failed: esp_err_t 0x103 (ESP_ERR_INVALID_STATE) at 0x400d5768
0x400d5768: i2c_master_config at /home/xae/Projects/TFG_ECG/codes/ecg_b_i2c/main/main.c:121 (discriminator 1)

file: "./main/main.c" line 121
func: i2c_master_config
expression: i2c_master_transmit(i2c_handle, config_register_data, sizeof(config_register_data), -1)

abort() was called at PC 0x40085adf on core 0
0x40085adf: _esp_error_check_failed at /home/xae/esp/v5.2.2/esp-idf/components/esp_system/esp_err.c:50

Backtrace: 0x4008160e:0x3ffb4d00 0x40085ae9:0x3ffb4d20 0x4008b6bd:0x3ffb4d40 0x40085adf:0x3ffb4db0 0x400d5768:0x3ffb4de0 0x400d5886:0x3ffb4e10 0x400e6a2c:0x3ffb4e30 0x400865d9:0x3ffb4e60
0x4008160e: panic_abort at /home/xae/esp/v5.2.2/esp-idf/components/esp_system/panic.c:466
0x40085ae9: esp_system_abort at /home/xae/esp/v5.2.2/esp-idf/components/esp_system/port/esp_system_chip.c:93
0x4008b6bd: abort at /home/xae/esp/v5.2.2/esp-idf/components/newlib/abort.c:38
0x40085adf: _esp_error_check_failed at /home/xae/esp/v5.2.2/esp-idf/components/esp_system/esp_err.c:50
0x400d5768: i2c_master_config at /home/xae/Projects/TFG_ECG/codes/ecg_b_i2c/main/main.c:121 (discriminator 1)
0x400d5886: app_main at /home/xae/Projects/TFG_ECG/codes/ecg_b_i2c/main/main.c:332
0x400e6a2c: main_task at /home/xae/esp/v5.2.2/esp-idf/components/freertos/app_startup.c:208
0x400865d9: vPortTaskWrapper at /home/xae/esp/v5.2.2/esp-idf/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c:134
But if I send, for example, just the first two bytes, it works fine. I'm not sure what I'm doing wrong. I also tried splitting the transmission into two separate operations, but when I attempt to read in continuous mode, it seems like something isn't configured correctly. I believe it's because all the bytes need to be sent between the START and STOP conditions for the ESP32 to correctly communicate with the ADS1115.

Here’s the relevant portion of my code:

Code: Select all

void i2c_master_init(void)
{
    i2c_master_bus_config_t i2c_mst_config = {
        .clk_source = I2C_CLK_SRC_DEFAULT,
        .i2c_port = I2C_PORT_NUMB,
        .scl_io_num = I2C_MASTER_SCL_IO,
        .sda_io_num = I2C_MASTER_SDA_IO,
        .glitch_ignore_cnt = 7,
        .flags.enable_internal_pullup = false,
    };

    i2c_master_bus_handle_t bus_handle;
    ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_mst_config, &bus_handle));


    esp_err_t ret = i2c_master_probe(bus_handle, ADS1115_ADDRESS, -1);
    if (ret != ESP_OK) {
        printf("Device not found on I2C bus: %s\n", esp_err_to_name(ret));
    } else {
        printf("Device found on I2C bus\n");
    }


    i2c_device_config_t dev_cfg = {
        .dev_addr_length = I2C_ADDR_BIT_LEN_7,
        .device_address = ADS1115_ADDRESS,
        .scl_speed_hz = IC2_MASTER_FREQ_HZ,
    };
    ESP_ERROR_CHECK(i2c_master_bus_add_device(bus_handle, &dev_cfg, &i2c_handle));
}

void i2c_master_config(void)
{
    uint8_t config_register_data[] = {0x90, 0x01,0x84, 0x83}; 
    ESP_ERROR_CHECK(i2c_master_transmit(i2c_handle, config_register_data, sizeof(config_register_data), -1));


    // Apuntar al registro de conversión
    uint8_t conversion_register_pointer[] = {0x90, 0x00};
    ESP_ERROR_CHECK(i2c_master_transmit(i2c_handle, conversion_register_pointer, sizeof(conversion_register_pointer), -1));
    
}
I have 2.2 kOhm pull-up resistors installed on the PCB layout, and I haven’t found any issues with the PCB design. I'm using ESP-IDF 5.2.2 but also tried with 5.3.0

Any advice would be greatly appreciated.

Thanks!

MicroController
Posts: 1734
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: ESP32 - ADS1115 Configure problem

Postby MicroController » Sun Aug 25, 2024 5:58 pm

temuko wrote:
Sun Aug 25, 2024 11:19 am
According to the ADS1115 datasheet, I need to write 4 bytes to configure the register in the following order: START - ADDRESS/RW - 00000001 - 10000100 - 10000011 - STOP
Well, someone has to write the slave addres+R/W ;-)
Notice that the I2C "device", represented by i2c_handle in your code, contains the slave address. When reading from or writing to a "device" via the handle, the I2C driver uses the address from the "device", so you don't include the slave address in the data you pass to the driver.

So, to send 8 bits of "register pointer" + 16 bits of "register data" to the slave you have to pass three bytes to i2c_master_transmit.
Doing so may already solve your problem, because I believe the ADS1115 will accept only 16-bit data and respond with NACK to any extraneous bytes, which will make the driver return an error. (Or the ADS may already NACK the invalid "register pointer" value of 0x90 you sent.)

Another hint: Always remember that the ADS1115 uses big-endian byte order on the I2C bus :)

temuko
Posts: 8
Joined: Sun Oct 15, 2023 10:55 am
Location: Europe, Spain

Re: ESP32 - ADS1115 Configure problem

Postby temuko » Thu Aug 29, 2024 6:33 pm

It's still happening. I was able to send all the bytes, but it's still not properly configured.

Could it be because it doesn't wait for an ACK between each byte?

Code: Select all

uint8_t config_register_data[] = {0x01, 0x84, 0x83}; 
ESP_ERROR_CHECK(i2c_master_transmit(i2c_handle, config_register_data, sizeof(config_register_data), -1));
I will try with ESP-IDF 5.1.4 because I can manually write it

MicroController
Posts: 1734
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: ESP32 - ADS1115 Configure problem

Postby MicroController » Fri Aug 30, 2024 7:49 am

temuko wrote:
Thu Aug 29, 2024 6:33 pm
but it's still not properly configured.
What does that mean?
Could it be because it doesn't wait for an ACK between each byte?
Nope. The hardware takes care of that.

temuko
Posts: 8
Joined: Sun Oct 15, 2023 10:55 am
Location: Europe, Spain

Re: ESP32 - ADS1115 Configure problem

Postby temuko » Sun Sep 01, 2024 3:20 pm

MicroController wrote:
temuko wrote:
Thu Aug 29, 2024 6:33 pm
but it's still not properly configured.
What does that mean?
I have the alert/rdy pin connected to GPIO5 and tried to configure it on the ADS1115 to change the value to '1' after every conversion, but I did not see the pin status change. However, by using a delay corresponding to the configured SPS and reading the manual, I was finally able to get the readings using the driver as you suggested. For now, I'll continue this way and investigate later why I don't see the alert/rdy pin changing.
Thanks a lot!

MicroController
Posts: 1734
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: ESP32 - ADS1115 Configure problem

Postby MicroController » Sun Sep 01, 2024 4:16 pm

Glad you're making progress :)

As to the "RDY" signal, note that you have to also configure an upper and lower threshold value for the comparator. In fact, the "RDY" signal is only 'simulated', by setting the upper threshold < 0 and the lower threshold > 0, which causes the window comparator to assert an "alert" every time a new sample value is available because every possible sample value will always be deemed 'outside' the configured window.

Who is online

Users browsing this forum: No registered users and 156 guests