Use this forum to chat about hardware specific topics for the ESP8266 (peripherals, memory, clocks, JTAG, programming)

User avatar
By corey
#95291 Hello,
I am using an ESP-12F and the ESP8266_RTOS_SDK to read the Temperature/Humidity from an Si7020-a20 connected via I2C. SDA is pin 2, SCL is pin 14 on this particular setup. I am using the release/3.4 branch from https://github.com/espressif/ESP8266_RTOS_SDK and Xtensa v8.4.0 toolchain for 64-bit Linux (Fedora) to build the project and upload it.

I would like to mention that I am able to use the Arduino framework with its Wire.h library to interact with the Si7020-a20 without issue and get accurate temperature and humidity readings, so I would think that the wiring is correct.

I have an oscilloscope on the way tomorrow so that I can try to debug this issue, but I thought someone might have an idea of what is going on before then.

I have posted the full code below. I am using this datasheet (https://www.digikey.com/en/htmldatashee ... sheet.html), referring to the instructions on page 21 for "No Hold Master Mode", I have also tried the "Hold Master Mode" with no luck.

Here is the error that I am getting:
Code: Select allmake -j$(cat /proc/cpuinfo | grep processor | wc -l) flash monitor
Toolchain path: /.../.espressif/tools/xtensa-lx106-elf/esp-2020r3-49-gd5524c1-8.4.0/xtensa-lx106-elf/bin/xtensa-lx106-elf-gcc
Toolchain version: esp-2020r3-49-gd5524c1
Compiler version: 8.4.0
Python requirements from /.../ESP8266_RTOS_SDK/requirements.txt are satisfied.
App "device-a-frame" version: 9252808-dirty
CC build/main/main.o
AR build/main/libmain.a
Generating esp8266.project.ld
LD build/device-a-frame.elf
esptool.py v2.4.0
Flashing binaries to serial port /dev/ttyUSB0 (app at offset 0x10000)...
esptool.py v2.4.0
Connecting........_____....._____.
Chip is ESP8266EX
Features: WiFi
MAC: 58:bf:25:cb:8f:48
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Compressed 10432 bytes to 7022...
Wrote 10432 bytes (7022 compressed) at 0x00000000 in 0.6 seconds (effective 134.4 kbit/s)...
Hash of data verified.
Compressed 137664 bytes to 86060...
Wrote 137664 bytes (86060 compressed) at 0x00010000 in 7.6 seconds (effective 145.3 kbit/s)...
Hash of data verified.
Compressed 3072 bytes to 83...
Wrote 3072 bytes (83 compressed) at 0x00008000 in 0.0 seconds (effective 2051.8 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...
MONITOR
/.../ESP8266_RTOS_SDK/tools/idf_monitor.py:322: DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.
  if StrictVersion(serial.VERSION) < StrictVersion('3.3.0'):
--- idf_monitor on /dev/ttyUSB0 74880 ---
--- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---

 ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x40100000, len 7040, room 16
tail 0
chksum 0xe2
load 0x3ffe8408, len 24, room 8
tail 0
chksum 0x6b
load 0x3ffe8420, len 3324, room 8
tail 4
chksum 0x43
csum 0x43
I (45) boot: ESP-IDF v3.4-39-g23a225a5 2nd stage bootloader
I (45) boot: compile time 16:16:50
I (45) qio_mode: Enabling default flash chip QIO
I (53) boot: SPI Speed      : 40MHz
I (60) boot: SPI Mode       : QIO
I (66) boot: SPI Flash Size : 2MB
I (72) boot: Partition Table:
I (77) boot: ## Label            Usage          Type ST Offset   Length
I (89) boot:  0 nvs              WiFi data        01 02 00009000 00006000
I (100) boot:  1 phy_init         RF data          01 01 0000f000 00001000
I (112) boot:  2 factory          factory app      00 00 00010000 000f0000
I (123) boot: End of partition table
I (130) esp_image: segment 0: paddr=0x00010010 vaddr=0x40210010 size=0x16f74 ( 94068) map
0x40210010: _stext at ??:?

I (175) esp_image: segment 1: paddr=0x00026f8c vaddr=0x40226f84 size=0x06048 ( 24648) map
I (184) esp_image: segment 2: paddr=0x0002cfdc vaddr=0x3ffe8000 size=0x003dc (   988) load
I (186) esp_image: segment 3: paddr=0x0002d3c0 vaddr=0x40100000 size=0x00080 (   128) load
I (200) esp_image: segment 4: paddr=0x0002d448 vaddr=0x40100080 size=0x0454c ( 17740) load
I (219) boot: Loaded app from partition at offset 0x10000
D (228) phy_init: loading PHY init data from application binary
D (244) nvs: nvs_open_from_partition backup_mac 0
D (247) nvs: nvs_get_str_or_blob backup_mac_data
D (250) nvs: nvs_close 1
D (252) system_api: Load MAC from NVS error=0
D (254) reset_reason: RTC reset 2 wakeup 0 store 0, reason is 2
D (261) wdt: Enable task watch dog panic, panic time parameter is 11
D (271) wdt: task watch dog trigger time parameter is 15
I (278) gpio: GPIO[2]| InputEn: 0| OutputEn: 1| OpenDrain: 1| Pullup: 1| Pulldown: 0| Intr:0
I (292) gpio: GPIO[14]| InputEn: 0| OutputEn: 1| OpenDrain: 1| Pullup: 1| Pulldown: 0| Intr:0
ESP_ERROR_CHECK failed: esp_err_t 0xffffffff (ESP_FAIL) at 0x402117e8
0x402117e8: _esp_error_check_failed at /.../ESP8266_RTOS_SDK/components/freertos/port/esp8266/panic.c:206

file: "main.c" line 37
func: app_main
expression: i2c_master_cmd_begin(I2C_MASTER_ADDRESS, cmd, 1000 / portTICK_RATE_MS)
abort() was called at PC 0x402117eb on core 0
0x402117eb: _esp_error_check_failed at /.../ESP8266_RTOS_SDK/components/freertos/port/esp8266/panic.c:207

Guru Meditation Error: Core  0 panic'ed (StoreProhibited). Exception was unhandled.
Core 0 register dump:
PC      : 0x402139f6  PS      : 0x00000030  A0      : 0x402139f4  A1      : 0x3ffea0e0 
0x402139f6: abort at /.../ESP8266_RTOS_SDK/components/newlib/src/syscall.c:69 (discriminator 1)

0x402139f4: abort at /.../ESP8266_RTOS_SDK/components/newlib/src/syscall.c:69 (discriminator 1)

A2      : 0x00000000  A3      : 0xffffffdb  A4      : 0x00000001  A5      : 0x00000001 
A6      : 0x00000000  A7      : 0x40228de8  A8      : 0x3ffea0f0  A9      : 0x00000004 
A10     : 0x00000000  A11     : 0x00000020  A12     : 0x3ffeb2d4  A13     : 0x00000000 
A14     : 0x00000000  A15     : 0x00000000  SAR     : 0x0000001e  EXCCAUSE: 0x0000001d 

Backtrace: 0x402139f6:0x3ffea0e0 0x402117ee:0x3ffea0f0 0x402135a1:0x3ffea100 0x40210b13:0x3ffea130
0x402139f6: abort at /.../ESP8266_RTOS_SDK/components/newlib/src/syscall.c:69 (discriminator 1)

0x402117ee: _esp_error_check_failed at ??:?

0x402135a1: app_main at /.../device-a-frame/main/main.c:38 (discriminator 2)


Here is the full code that I am using:
Code: Select all#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "driver/i2c.h"

#define I2C_MASTER_ADDRESS I2C_NUM_0

void app_main()
{
    i2c_config_t conf = {};
    conf.mode = I2C_MODE_MASTER;
    conf.sda_io_num = 2;
    conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
    conf.scl_io_num = 14;
    conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
    conf.clk_stretch_tick = 300; // Not 100% sure about this value
   
    ESP_ERROR_CHECK(i2c_driver_install(I2C_MASTER_ADDRESS, conf.mode)); // Install the Driver
    ESP_ERROR_CHECK(i2c_param_config(I2C_MASTER_ADDRESS, &conf)); // Setup the Configuration


    uint8_t data[2];

    i2c_cmd_handle_t cmd = i2c_cmd_link_create(); // Create the link
    i2c_master_start(cmd); // Issue Start Command
    i2c_master_write_byte(cmd, 0x40 << 1 | I2C_MASTER_WRITE, true); // Slave Address + Write bit + Check ACK
    i2c_master_write_byte(cmd, 0xF3, true); // Measure Command
    i2c_master_start(cmd); // Repeated Start
    i2c_master_write_byte(cmd, 0x40 << 1 | I2C_MASTER_READ, true); // Slave Address + Read bit + Check ACK
    i2c_master_start(cmd); // Repeated Start
    i2c_master_write_byte(cmd, 0x40 << 1 | I2C_MASTER_READ, true); // Slave Address + Read bit + Check ACK
    // How do we account for "Device will NACK the slave address byte until conversion is complete." here???
    i2c_master_read_byte(cmd, &data[0], I2C_MASTER_ACK); // Read MS byte and send ACK
    i2c_master_read_byte(cmd, &data[1], I2C_MASTER_LAST_NACK); // Read LS Byte and send NACK
    i2c_master_stop(cmd); // Issue Stop Command
    ESP_ERROR_CHECK(i2c_master_cmd_begin(I2C_MASTER_ADDRESS, cmd, 1000 / portTICK_RATE_MS)); // Not 100% sure about the 1000 / portTick_RATE_MS
    i2c_cmd_link_delete(cmd); // Delete the Link
    i2c_driver_delete(I2C_MASTER_ADDRESS); // Delete the Driver

    printf("data[0]: %d, data[1]: %d\n", data[0], data[1]); // data[0]: <int>, data[1]: <int>

    int temperature = (((175.72 * (data[0] << 8 | data[1])) / 65536) - 46.85) * 1.8 + 32; // Convert to degrees fahrenheit
    printf("Temperature reading: %d\n", temperature); // Temperature reading: <int>

}



I am not sure how to account for the "Clock stretch during measurement" in the "Hold Master Mode" or the "Device will NACK the slave address byte until conversion is complete." in the "No Hold Master Mode".

Any help would be greatly appreciated.
User avatar
By eriksl
#95294 I am not surprised there. The Espressif I2C implementation is really, let's say, suboptimal. Two major things they don't get right:
- not ever checking errors or invalid states
- set/reset SDA and SCL at the same time. You're not supposed to do that, but often you get away with it. But a proper implementation should first set/reset SDA, then wait a while (depending on the clock speed, which you can't even control in the Espressif implementation) and only then set SCL, wait a while, reset SCL, wait a while and then clock the next SDA bit. The SCL line is often directly connected to a bit bitshifter clock in the device, which will yield unpredictable results in this case.