Skip to content

ESP32-C3-WROOM-02 i2S and i2C bus errors #7648

@Parkview785

Description

@Parkview785

Board

ESP32-C3-WROOM-02

Device Description

The module is mounted on a custom PCB, along with 3 i2C sensors, a OLED display and a i2S based SPH0645 microphone. All GPIO are being used.

Hardware Configuration

i2C pins: SDA=1; SCL=0
i2S pins: SCK=3; WS=21; SD=20

i2C devices
QMC5883L compass
LTR-553ALS light sensor
LSM6DSL 6-DoF acc/gyro
SSD1306

i2S device:
SPH0645 MEMS Microphone

Version

v2.0.6

IDE Name

PlatformIO Core: 6.1.5, Home: 3.4.3

Operating System

Ubuntu

Flash frequency

40MHz

PSRAM enabled

no

Upload speed

921600

Description

initializing a i2C bus and device before the i2s_set_pin function is called will cause the buses to stop working (i2C bus has to time out before code will continue). i2S bus doesn't seem to return proper data.

I would expect there would be no dependency on the order of initialization.

Sketch

//////////////////////////////////////////////////////////
/*
   Minimal code for a ESP32-C3-WROOM-02 based i2S SPH0645 MEMS microphone and a i2C SSD1306 OLED display mounted on a custom PCB.

   If I remark out the i2C code, the i2S code seems to work ok. If I remark out the i2S code, then the display works ok.
   In fact, I have 3 other i2C based sensors: QMC5883, LTR-553 and a LSM6DSL all working ok with the OLED display and WiFi.
   Only when I turn on the i2S and any one i2C based item, does i2C stall (stops working and times out after some seconds)
   when the "i2s_set_pin" function is called.

   Resolution:
   Place the i2S init code BEFORE any i2C init code, then both i2S and i2C work ok.

   i2C pins:  SDA=1; SCL=0
   i2S pins:  SCK=3; WS=21; SD=20

   Notes:
    * Red LED blinks at the end of a loop
    * Yellow LED lights up near the end of the code Setup
    * Blue LED lights up depending on the sound level
    * Green PWR LED lights up when power is applied
*/
/////////////////////////////////////////////////////////////////

#include <Arduino.h>
#include <driver/i2s.h>
#include "SSD1306Wire.h"

// i2C GPIO pin assignments:
#define i2C_SDA 1
#define i2C_SCL 0
// i2S Microphone GPIO assignments
#define I2S_SCK_RX 3
#define I2S_WS_RX 21
#define I2S_SD_RX 20
#define I2S_PORT_RX I2S_NUM_0

#define ledXpin 7       // for USB LED String PCB
#define ledYpin 6       // for USB LED String PCB
#define ledSNDpin 4     // for USB LED String PCB
#define ledChannelX 1   // X LED
#define ledChannelY 2   // Y LED
#define ledChannelSND 4 // SND LED
#define ledPWMFreq 500  // Frequency specified in Hz
#define resolution 8
#define SAMPLE_BUFFER_SIZE 512
#define SAMPLE_RATE 16000
#define SAMPLE_BITS 32
#define DMA_BANKS 4
#define DMA_BANK_SIZE 1024
esp_err_t i2Serr;

SSD1306Wire display(0x3c, i2C_SDA, i2C_SCL); // ADDRESS, SDA, SCL

TaskHandle_t i2sReadTaskHandler = NULL;

const i2s_config_t i2s_config_rx = {
    .mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX),
    .sample_rate = SAMPLE_RATE,
    .bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
    .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT, // SPH0645 is wired for Rightside, but need to call for LEFT
    .communication_format = I2S_COMM_FORMAT_STAND_I2S,
    .intr_alloc_flags = i2s_comm_format_t(I2S_COMM_FORMAT_STAND_I2S),
    .dma_buf_count = DMA_BANKS,
    .dma_buf_len = DMA_BANK_SIZE,
    .use_apll = false,
    .tx_desc_auto_clear = false,
    .fixed_mclk = 0};

const i2s_pin_config_t pin_config_rx = {
    .bck_io_num = I2S_SCK_RX,
    .ws_io_num = I2S_WS_RX,
    .data_out_num = I2S_PIN_NO_CHANGE,
    .data_in_num = I2S_SD_RX};

void i2s_RX_init()
{
  i2Serr = i2s_driver_install(I2S_PORT_RX, &i2s_config_rx, 0, NULL);
  if (i2Serr != ESP_OK)
  {
    // Serial.printf("Failed installing i2S driver: %d\n", i2Serr);
    while (true)
      ;
  }
  display.drawString(2, 12, "This does work");
  display.display(); // now the display times out with no updated text

  i2Serr = i2s_set_pin(I2S_PORT_RX, &pin_config_rx);
  if (i2Serr != ESP_OK)
  {
    // Serial.printf("Failed setting i2S pin: %d\n", i2Serr);
    while (true)
      ;
  }
  display.drawString(2, 24, "This doesn't work");
  display.display(); // now the display times out with no updated text
}

void i2s_reader_task(void *parameter)
{
  while (1)
  {
    uint8_t dutyCycle = 0;
    int32_t samples[DMA_BANK_SIZE];
    size_t num_bytes_read = 0;
    i2s_read(I2S_PORT_RX, &samples, DMA_BANK_SIZE, &num_bytes_read, portMAX_DELAY); // read microphone data into buffer
    int samples_read = num_bytes_read / 8;
    if (samples_read > 0)
    {
      // Do something with the audio 'samples'...
      float mean = 0;
      for (int i = 0; i < samples_read; ++i)
      {
        mean += (samples[i] >> 14);
      }
      mean /= samples_read;

      float maxsample = -1e8, minsample = 1e8;
      for (int i = 0; i < samples_read; ++i)
      {
        minsample = min(minsample, samples[i] - mean);
        maxsample = max(maxsample, samples[i] - mean);
      }

      float result = (maxsample - minsample) / 100000000;
      // light up the SND LED - make it fluctuate depending on sound level. could be a funct
      if (result > 32)
      {
        dutyCycle = 255;
      }
      else if (result > 16)
      {
        dutyCycle = 255;
      }
      else if (result > 8)
      {
        dutyCycle = 180;
      }
      else if (result > 4)
      {
        dutyCycle = 100;
      }
      else if (result > 2)
      {
        dutyCycle = 64;
      }
      else
        dutyCycle = 0;
      ledcWrite(ledChannelSND, dutyCycle); // adjust the Blue SND LED brightness level
      display.drawString(2, 36, "this doesn't work");
      display.display(); // now the display times out with no updated text
    }
    // end of loop - flash LEDX to show it's all working ok
    ledcWrite(ledChannelX, 100); // adjust LED brightness level
    vTaskDelay(100);
    ledcWrite(ledChannelX, 0); // adjust LED brightness level
    vTaskDelay(100);
  }
}

void setup()
{
  // setup LED's for visual feedback
  ledcSetup(ledChannelX, ledPWMFreq, resolution);
  ledcSetup(ledChannelY, ledPWMFreq, resolution);
  ledcSetup(ledChannelSND, ledPWMFreq, resolution);
  ledcAttachPin(ledXpin, ledChannelX);
  ledcAttachPin(ledYpin, ledChannelY);
  ledcAttachPin(ledSNDpin, ledChannelSND);
  ledcWrite(ledChannelX, 0);
  ledcWrite(ledChannelY, 0);
  ledcWrite(ledChannelSND, 0);
  // setup SSD1306 OLED screen works and text displays ok
  Wire.begin(i2C_SDA, i2C_SCL); // not needed as OLED display init does this too, just listing it to show completness
  display.init();
  display.setFont(ArialMT_Plain_10);
  display.drawString(2, 0, "Test code");
  display.drawHorizontalLine(1, 11, 127);
  display.display();
  // setup i2S
  ledcWrite(ledChannelX, 100);
  vTaskDelay(500);
  i2s_RX_init();
  vTaskDelay(100);
  ledcWrite(ledChannelY, 100);
  xTaskCreatePinnedToCore(i2s_reader_task, "i2s_reader_task", 10000, NULL, 1, &i2sReadTaskHandler, 0);
}

void loop()
{
} // not used, as we are using Tasks

Debug Message

Note: LED's are being used for debugging purposes and have no impact on the actual issue

As I don't have access to the serial port, I don't have any error messages being presented.  I use the LEDs to note a long many second timeout (with no more data being written to the i2C display) when a i2C bus is used after the i2S bus has been initalized after the i2C bas was initialzed first.

Other Steps to Reproduce

  1. init i2C first.
  2. use i2C to display text - all ok;
  3. Run the i2S initialization. "this does work" is displayed on the screen. "This doesn't work" is not displayed on the screen and no further i2C bus communications work, with a many second pause in code runtime (while the i2C bus times out?). i2S bus doesn't seem to work either.

Steps to make the code work:
A) call the i2S bus initialization first, before the i2C bus init (ie: Wire.begin()) is called. Both i2C and i2S function as expected.

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