M5StickC running i2s microphone with i2c ToF Hat with Arduino code



  • Hi M5StickC community,

    I love my new M5StickC with my ToF Hat. I would to use the built-in i2S microphone and the i2c ToF Hat simultaneously. I tried combining the 2 examples provided in the Arduino library. The ToF distance shows up on the display (but very slow response time), but the audio doesn't show up.

    May I have some help getting these two working together?

    Thanks

    Here's the code below:

    #include <M5StickC.h>
    #include <driver/i2s.h>
    #include <Wire.h>
    #include <VL53L0X.h>

    #define PIN_CLK 0
    #define PIN_DATA 34
    #define READ_LEN (2 * 256)
    #define GAIN_FACTOR 3
    uint8_t BUFFER[READ_LEN] = {0};

    uint16_t oldy[160];
    int16_t *adcBuffer = NULL;
    VL53L0X sensor;
    TFT_eSprite img = TFT_eSprite(&M5.Lcd);
    uint16_t sensorDistance;

    void i2sInit()
    {
    i2s_config_t i2s_config = {
    .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM),
    .sample_rate = 44100,
    .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, // is fixed at 12bit, stereo, MSB
    .channel_format = I2S_CHANNEL_FMT_ALL_RIGHT,
    .communication_format = I2S_COMM_FORMAT_I2S,
    .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
    .dma_buf_count = 2,
    .dma_buf_len = 128,
    };

    i2s_pin_config_t pin_config;
    pin_config.bck_io_num = I2S_PIN_NO_CHANGE;
    pin_config.ws_io_num = PIN_CLK;
    pin_config.data_out_num = I2S_PIN_NO_CHANGE;
    pin_config.data_in_num = PIN_DATA;

    i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
    i2s_set_pin(I2S_NUM_0, &pin_config);
    i2s_set_clk(I2S_NUM_0, 44100, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_MONO);
    }

    void mic_record_task (void* arg)
    {
    size_t bytesread;
    while(1){
    i2s_read(I2S_NUM_0,(char*) BUFFER, READ_LEN, &bytesread, (100 / portTICK_RATE_MS));
    adcBuffer = (int16_t *)BUFFER;
    //sensorDistance = sensor.readRangeContinuousMillimeters();
    //Serial.print(sensorDistance);
    //if (sensor.timeoutOccurred()) { Serial.print(" TIMEOUT"); }
    //Serial.println();
    showSignal();
    vTaskDelay(100 / portTICK_RATE_MS);
    }
    }

    void setup() {
    Serial.begin(115200);
    Wire.begin(0, 26, 100000);
    M5.begin();
    M5.Lcd.setRotation(3);
    M5.Lcd.fillScreen(WHITE);
    M5.Lcd.setTextColor(BLACK, WHITE);
    M5.Lcd.println("mic test");

    img.createSprite(70, 35);
    img.fillSprite(BLACK);
    img.setTextColor(WHITE);
    img.setTextSize(2);

    sensor.setTimeout(500);
    if (!sensor.init()) {
    img.setCursor(10, 10);
    img.print("Failed");
    img.pushSprite(0, 0);
    Serial.println("Failed to detect and initialize sensor!");
    while (1) {}
    }
    // Start continuous back-to-back mode (take readings as
    // fast as possible). To use continuous timed mode
    // instead, provide a desired inter-measurement period in
    // ms (e.g. sensor.startContinuous(100)).
    sensor.startContinuous();

    i2sInit();
    xTaskCreate(mic_record_task, "mic_record_task", 2048, NULL, 1, NULL);
    }

    void showSignal(){
    img.fillSprite(BLACK);
    img.setCursor(10, 10);
    img.print(sensorDistance);
    img.pushSprite(0, 0);
    int y;
    for (int n = 0; n < 160; n++){
    y = adcBuffer[n] * GAIN_FACTOR;
    y = map(y, INT16_MIN, INT16_MAX, 10, 70);
    M5.Lcd.drawPixel(n, oldy[n],WHITE);
    M5.Lcd.drawPixel(n,y,BLACK);
    oldy[n] = y;
    }
    }

    void loop() {
    printf("loop cycling\n");
    vTaskDelay(1000 / portTICK_RATE_MS); // otherwise the main task wastes half of the cpu cycles
    }