Skip to content

Wire i2cread returned error 263 with periodic polling #8056

Closed
@dizcza

Description

@dizcza

Board

Frogboard

Device Description

A regular Frogboard.

Hardware Configuration

SDA: 21
SCL: 22

Version

v2.0.4

IDE Name

Arduino IDE

Operating System

Ubuntu 22.04

Flash frequency

Default

PSRAM enabled

no

Upload speed

921600

Description

Polling an I2C sensor (Sensirion SDP810-125) at 1000 Hz

  • works with arduino-esp32 v2.0.3 but
  • doesn't work with v2.0.4 and so on (same story with the latest v2.0.7)

Could be related to #7209 --> It's not a library- or sensor-specific issue.

I mean, it's the Wire issue - one of the most used components of ESP32 arduino.


I have no problems whatsoever running a corresponding code with ESP-IDF v5.1 & master branch with the same I2C clock speed and timer interrupt (it works even at higher sampling rates: up to 1900 Hz, the sensor limit).

Sketch

Install https://github.com/UT2UH/SDP3x-Arduino.

#include "SDPSampler.h"

SDP8XX sensor = SDP8XX(Address5);
SDPSampler *sampler;

void setup() {
  Serial.begin(115200);
  Wire.begin(21, 22, (uint32_t) 400000);
  sampler = new SDPSampler(sensor);
  assert(sampler->begin());
  Serial.println("started");
}

void loop() {
  
}

SDPSampler.cpp:

#include <math.h>
#include <unistd.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_log.h"
#include "esp_timer.h"
#include "esp_task_wdt.h"
#include "esp_ota_ops.h"

#include "SDPSampler.h"

#define RECORD_READ_SENSOR_PRIORITY  (configMAX_PRIORITIES - 1)



static void sdprecord_read_sensor_task(void*);


static TaskHandle_t m_task_read_handle = NULL;
static const char *TAG = "sdprecord";



void ARDUINO_ISR_ATTR onTimer()
{
    static uint32_t timer_counter = 0;
    xTaskNotifyFromISR(m_task_read_handle, timer_counter++, eSetValueWithOverwrite, NULL);
}



static void sdprecord_read_sensor_task(void* args) {
    SDPSampler* sdp_sampler = (SDPSampler*) args;
    int64_t rtc_counter = 0;

    esp_task_wdt_add(NULL);
    sdp_sampler->startTimer();

    // Skip the first sample.
    // The first sample period is less than expected.
    ulTaskNotifyTake(pdTRUE, portMAX_DELAY);

	while (1) {
	    esp_task_wdt_reset();
	    ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
        sdp_sampler->readSensor();
	}
}


bool SDPSampler::ready() {
    return uxQueueMessagesWaiting(xQueueRecords) >= SPECTROGRAM_WINDOW_SIZE;
}


const int16_t* SDPSampler::getCapturedAudioBuffer() {
    if (!ready()) {
        return NULL;
    }
    for (int i = 0; i < SPECTROGRAM_WINDOW_SIZE; i++) {
        xQueueReceive(xQueueRecords, &raw_buffer[i], portMAX_DELAY);
    }
    return raw_buffer;
}


bool SDPSampler::readSensor() {
    int16_t dp_raw = 0;
    if (m_sensor.readMeasurement(&dp_raw, NULL, NULL)) {
        xQueueSend(xQueueRecords, &dp_raw, 0);
        return true;
    }
    return false;
}


/**
 * Better to call this function from the core
 * on which the sampler is running.
*/
void SDPSampler::startTimer()
{
    m_timer = timerBegin(0, 80, true);
    timerAttachInterrupt(m_timer, &onTimer, true);

    // Set alarm to call onTimer function every second (value in microseconds).
    // Repeat the alarm (third parameter)
    timerAlarmWrite(m_timer, 1000, true);

    // Start an alarm
    timerAlarmEnable(m_timer);
}

bool SDPSampler::begin() {
    // Always stop SDP before running again
    if (!m_sensor.stopContinuous()) {
        log_e("SDPSensor::stopContinuous failed");
    }
    delay(20);
    if (!m_sensor.startContinuous(false)) {
        log_e("SDPSensor::startContinuous failed");
        return false;
    }
    delay(20);
    xTaskCreatePinnedToCore(sdprecord_read_sensor_task, "sdp_read", 4096, this, RECORD_READ_SENSOR_PRIORITY, &m_task_read_handle, APP_CPU_NUM);
    return true;
}

void SDPSampler::stop() {
    m_sensor.stopContinuous();
    if (m_timer) {
        timerStop(m_timer);
        m_timer = NULL;
    }
    if (m_task_read_handle) {
        esp_task_wdt_delete(m_task_read_handle);
        vTaskDelete(m_task_read_handle);
        m_task_read_handle = NULL;
    }
}

SDPSampler::SDPSampler(SDPSensor& sensor) : m_sensor(sensor)
{
    m_sensor.begin();
    xQueueRecords = xQueueCreate(5000, sizeof(int16_t));
    assert(xQueueRecords != NULL);
}

SDPSampler.h:

#pragma once

#include <Arduino.h>
#include "SDPSensors.h"

#define SPECTROGRAM_WINDOW_SIZE 256


class SDPSampler {
    private:
        SDPSensor& m_sensor;
        hw_timer_t* m_timer;
        QueueHandle_t xQueueRecords;
        int16_t raw_buffer[SPECTROGRAM_WINDOW_SIZE];

    public:
        SDPSampler(SDPSensor& sensor);
        bool begin();
        void stop();
        void startTimer();
        bool readSensor();
        const int16_t* getCapturedAudioBuffer();
        bool ready();
};

Debug Message

[ 12174][E][Wire.cpp:392] requestFrom(): i2cRead returned Error 263
[ 13178][E][Wire.cpp:392] requestFrom(): i2cRead returned Error 263

Expected: no errors.

Other Steps to Reproduce

No response

I have checked existing issues, online documentation and the Troubleshooting Guide

  • I confirm I have checked existing issues, online documentation and Troubleshooting guide.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions