espressif / arduino-esp32

Arduino core for the ESP32
GNU Lesser General Public License v2.1
13.42k stars 7.37k forks source link

[I2C] TI HDC2080 temp/humidity sensor not working over ESP32 I2C interface #2597

Closed pwntr closed 5 years ago

pwntr commented 5 years ago

Hardware:

Board: ESP32 dev module, home brew PCB Core Installation version: tested 1.0.1 and 1.0.2 rc1. < 1.0.0 works IDE name: Arduino IDE and PlatformIO Flash Frequency: 40Mhz PSRAM enabled: no Upload Speed: 115200 Computer OS: Windows 10, Max OS X 10.13, Ubuntu 18.04

Description:

Using current versions of the esp core (> 1.0.0) results in bogus sensor data returned/interpreted for the HDC2080 from TI. Other sensors (Bosch BME280, BME680, both on their own breakout board externally) work fine on the same board (attached via SDA and SCL breakout pins) and with the current cores.

All things being equal (hardware, OS, libraries, IDEs), using an old core from January 2018 (relevant I2C files attached, exact version number hard to determine...?), the HDC2080 and the other sensors work as expected. Only the cores > 1.0.0 break functionality for the HDC2080 (after @stickbreaker changes were merged?).

Old I2C core files that I suspect to be relevant: oldcore_jan2018.zip

Cross-checking with the same sketches and libraries on an Arduino Nano clone, all three sensors work right away, (attaching the SDA and SCL pins on my board to A4 and A5 on the Nano to use it as a slave breakout board of sorts). Here are the relevant sections of the pcb (sensor and pullups in the upper left, SDA and SCL breakout pins lower right.): pcb_layout_snapshot

I tested various pullup resistors on SDA and SCL (2.7k, 6.7k, 10k), all with the same result: old core works fine, newer core returns bogus data from HDC2080.

Sketch:

HDC2080 Arduino library: HDC2080.zip


#include <HDC2080.h>
#define ADDR 0x40

HDC2080 sensor(ADDR);

float temperature = 0, humidity = 0;

void setup() {

  Serial.begin(115200);

  // Initialize I2C communication
  sensor.begin();

  // Begin with a device reset
  sensor.reset();

  // Configure Measurements
  sensor.setMeasurementMode(TEMP_AND_HUMID);  // Set measurements to temperature and humidity
  sensor.setRate(ONE_HZ);                     // Set measurement frequency to 1 Hz
  sensor.setTempRes(FOURTEEN_BIT);
  sensor.setHumidRes(FOURTEEN_BIT);

  //begin measuring
  sensor.triggerMeasurement();
}

void loop() {

  Serial.print("Temperature (C): "); Serial.print(sensor.readTemp());
  Serial.print("\t\tHumidity (%): "); Serial.println(sensor.readHumidity());

  // Wait 1 second for the next reading
  delay(1000);

}

I ordered a logic analyzer to further submerge myself into the I2C rabbit hole. Currently I can't make any sense out of this behavior. Please let me know how I can help with the investigation.

This issue seems related based on the symptoms: #2408

Thanks a ton for your help :)!

Debug Messages:

Arduino Nano with ESP32 home brew pcb attached OR ESP32 home brew board standalone with the old core release (working fine after the first reading, desired target output basically):

Temperature (C): -40.00     Humidity (%): 40.17
Temperature (C): 25.33      Humidity (%): 40.17
Temperature (C): 25.36      Humidity (%): 40.14
Temperature (C): 25.36      Humidity (%): 40.13
...

ESP32 home brew board with core v. 1.0.1 stable (verbose):

[V][esp32-hal-i2c.c:1483] i2cInit(): num=0 sda=21 scl=22 freq=0
[V][esp32-hal-i2c.c:1677] i2cSetFrequency(): freq=100000Hz
[V][esp32-hal-i2c.c:1692] i2cSetFrequency(): cpu Freq=240Mhz, i2c Freq=100000Hz
[V][esp32-hal-i2c.c:1698] i2cSetFrequency(): Fifo delta=1
Temperature (C): -39.35     Humidity (%): 3.52
Temperature (C): 102.46     Humidity (%): 93.75
Temperature (C): 102.46     Humidity (%): 93.75
Temperature (C): 102.46     Humidity (%): 93.75
...

ESP32 home brew board with core v. 1.0.2 dev (verbose, #define ENABLE_I2C_DEBUG_BUFFER in enabled in esp32-hal-i2c.c):

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1100
load:0x40078000,len:10312
load:0x40080400,len:6460
entry 0x400806a4
[V][esp32-hal-i2c.c:1483] i2cInit(): num=0 sda=21 scl=22 freq=0
[V][esp32-hal-i2c.c:1677] i2cSetFrequency(): freq=100000Hz
[V][esp32-hal-i2c.c:1692] i2cSetFrequency(): cpu Freq=240Mhz, i2c Freq=100000Hz
[V][esp32-hal-i2c.c:1698] i2cSetFrequency(): Fifo delta=1
Temperature (C): -39.35     Humidity (%): 3.52
Temperature (C): -40.00     Humidity (%): 3.52
Temperature (C): -40.00     Humidity (%): 3.52
Temperature (C): -40.00     Humidity (%): 3.52
...
stickbreaker commented 5 years ago

@pwntr There is an error in your library. I just glanced through it, and found one error in the readReg() function. I went through the library and did some modifications for style and error checking, try this version and see If your readings change.

Chuck.

HDC2080.zip


uint8_t HDC2080::readReg(uint8_t reg)
{
    openReg(reg);
    uint8_t reading;                    // holds byte of read data
    Wire.requestFrom(_addr, 1);         // Request 1 byte from open register
    Wire.endTransmission();             // Relinquish bus control

    if (1 <= Wire.available())
    {
        reading = (Wire.read());            // Read byte
    }

    return reading;
}

the Wire.endTransmission() is bogus and the error checking if() is questionable. This is what I changed it to.


uint8_t HDC2080::readReg(uint8_t reg)
{
    openReg(reg);
    uint8_t reading;                    // holds byte of read data
    Wire.requestFrom(_addr, 1);         // Request 1 byte from open register
    if (Wire.lastError() != I2C_ERROR_OK){
        log_e("Request from failed reg=%d, err=%d(%s)",reg,Wire.lastError(),Wire.getErrorText(Wire.lastError()));
        reading = 0;
    }
    else {
        reading = Wire.read();
    }

    return reading;
}
pwntr commented 5 years ago

@stickbreaker thank you SO much for the quick and thorough help with this! It works flawlessly, with 1.0.1 and 1.0.2 rc1. You, sir, deserve a 🥇.

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1100
load:0x40078000,len:10312
load:0x40080400,len:6460
entry 0x400806a4
[V][esp32-hal-i2c.c:1483] i2cInit(): num=0 sda=21 scl=22 freq=0
[V][esp32-hal-i2c.c:1677] i2cSetFrequency(): freq=100000Hz
[V][esp32-hal-i2c.c:1692] i2cSetFrequency(): cpu Freq=240Mhz, i2c Freq=100000Hz
[V][esp32-hal-i2c.c:1698] i2cSetFrequency(): Fifo delta=1
Temperature (C): -40.00     Humidity (%): 38.49
Temperature (C): 27.37      Humidity (%): 38.49
Temperature (C): 27.35      Humidity (%): 38.53
Temperature (C): 27.32      Humidity (%): 38.54
Temperature (C): 27.29      Humidity (%): 38.51

For anyone interested, the revised lib that contains the changes can now be found right here.