miketeachman / micropython-esp32-i2s-examples

Usage and examples for I2S support on the ESP32 microcontroller
MIT License
156 stars 29 forks source link

[support] M5stick-c doesn't seem to work #6

Closed AutomationD closed 4 years ago

AutomationD commented 4 years ago

First of all, great kudos for such work, Mike!

I'm trying to make my m5stick-c, which is based on ESP32-PICO, and I'm getting no signal

I've merged your changes to the main branch of micropython and built it. Module inclusion, class instantiation works fine, but the wav file has only a header, and the signal is all zeroes.

I would appreciate if you or anyone could give me a hint where to look and troubleshoot. Thanks again!

Here's the latest iteration of the snippet (not that m5stick-c documentation doesn't provide any info on bck, and examples refer to I2S_PIN_NO_CHANGE

from machine import I2S
from machine import Pin

SAMPLE_BLOCK_SIZE = 4096
BITS_PER_SAMPLE = 16
BYTES_PER_SAMPLE = BITS_PER_SAMPLE // 8
SAMPLES_PER_SECOND = 16000
RECORD_TIME_IN_SECONDS = 8
DMA_LEN = 512

WAV_DATA_SIZE = RECORD_TIME_IN_SECONDS * SAMPLES_PER_SECOND * BYTES_PER_SAMPLE
wav_header = gen_wav_header(SAMPLES_PER_SECOND, BITS_PER_SAMPLE, 1, SAMPLES_PER_SECOND * RECORD_TIME_IN_SECONDS)

bck_pin = Pin(0)
ws_pin = Pin(0)
sdin_pin = Pin(34)

audio_in = I2S(I2S.NUM0, bck=bck_pin, ws=ws_pin, sdin=sdin_pin,
               standard=I2S.PHILIPS, mode=I2S.MASTER_RX,
               dataformat=I2S.B16,                                                         # Each sample will only take up 2bytes in DMA memory
               # NOTE: ONLY_RIGHT actually samples left channel.
               channelformat=I2S.ALL_RIGHT,                                               # Only sample single left channel (mono mic)
               samplerate=SAMPLES_PER_SECOND,
               dmacount=16,
               dmalen=DMA_LEN
               )

s = open('/mic_recording.wav', 'wb')
s.write(wav_header)

mic_samples = bytearray(SAMPLE_BLOCK_SIZE)

TOTAL_BYTES = RECORD_TIME_IN_SECONDS * SAMPLES_PER_SECOND * BYTES_PER_SAMPLE
bytes_written = 0

# Keep recording until enough samples are written
while bytes_written < TOTAL_BYTES:
    try:
        numread = 0
        numwrite = 0
        numread = audio_in.readinto(mic_samples, timeout=0)
        # If there were samples available in DMA, persist to flash
        if numread > 0:
            numwrite = s.write(mic_samples[:numread])
            bytes_written += numwrite
    except KeyboardInterrupt:
        break

s.close()
audio_in.deinit()

print('Done %d bytes written to flash' % bytes_written)

M5Stick-C specific Arduino Example One M5Stick-C specific Arduino Example Two

miketeachman commented 4 years ago

It might just be a typo in the code listing but the bck and ws signals show that they are attached to the same pin 0. Can you check that?

AutomationD commented 4 years ago

Hey, Mike, I've set it to 0, as there is simply no doc on which pin is this specific mic is attached, seems like there are only two pins documented (SCL/SDA), and two other pins are gnd and vcc: Datasheet

miketeachman commented 4 years ago

I just took a look at the SPM1423 microphone datasheet. It has a PDM interface and unfortunately will not work with the I2S micropython module which only supports microphones having the audio I2S interface of bck, ws, sdin.

This limitation is in the I2S micropython module implementation and not in the ESP32. The ESP32 I2S hardware peripheral supports PDM hardware . Take a look at section 12.4.7 I2S PDM in https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf.

The good news is that it is possible to modify the C code in machine_i2s.c to work with this microphone. The M5stack C code can be used as an example on how to do this.

Also, here is some information from Adafruit that discusses the different types of digital microphones: https://cdn-learn.adafruit.com/downloads/pdf/adafruit-pdm-microphone-breakout.pdf

AutomationD commented 4 years ago

Sigh I will have to look into that, then. My C is pretty basic, but I guess that would be a great chance to learn how to implement Arduino-based solutions as micropython modules :)

Btw, I tried adding I2S_PIN_NO_CHANGE into the pin config in machine_i2s.c, but it didn't seem enough

Thanks for checking, Mike!

UPD: Seems like this has been already implemented here or am I mistaken?

miketeachman commented 4 years ago

That's a good find, but I don't know if it will help to get the PDM feature supported on the ESP32. The CircuitPython PDM implementation is designed to run on the STM devices that are supported by CircuitPython. Unfortunately, Adafruit doesn't support any Espressif devices in CircuitPython.

My suggestion is to implement a new machine PDM class in MicroPython, using machine I2S and the M5stack C code as examples. Other PDM examples using the ESP-IDF might be found in the ESP32 forum or maybe an Arduino forum. To keep consistency with other machine classes, the C file name would likely be called machine_pdm.c.

Here is how I would approach this:

  1. copy machine_i2s.c to machine_pdm.c and integrate into the ESP32 build
  2. rework machine_pdm.c to support PDM devices, using the M5stack C implementation as a guide

It might be worthwhile to post on the MicroPython ESP32 forum to see if anyone has started to work on this feature.

miketeachman commented 4 years ago

This issue is not related to the I2S interface, so closing

valkyriesavage commented 2 years ago

@AutomationD : did you wind up finding or developing something that connects to the M5StickC's microphone? I am hoping to do some work with it soon, as well, and am still struggling to find anywhere that it's used in python.

AutomationD commented 2 years ago

@valkyriesavage I broke my M5StickC :-D But yeah, it would be nice...