i2s compatibility

All ESP32 boards running MicroPython.
Target audience: MicroPython users with an ESP32 board.
vitocosmic
Posts: 3
Joined: Thu Jan 24, 2019 10:15 pm

i2s compatibility

Post by vitocosmic » Thu Jan 31, 2019 7:47 pm

it is posible to use i2s protocol to communicate a mic to esp32 board? i'm working with a heltec esp32 wifi lora, datasheet of esp32 shows that is posible to use i2s but in micropython there are not module for achieve this, if someone knows other way of doing this please let me know

User avatar
Mike Teachman
Posts: 155
Joined: Mon Jun 13, 2016 3:19 pm
Location: Victoria, BC, Canada

Re: i2s compatibility

Post by Mike Teachman » Fri Feb 01, 2019 3:39 pm

I'm not aware of a uPy I2S module for the ESP32. For a project that requires an I2S microphone I ended up writing a uPy module that uses the I2S interface in the ESP-IDF. I'll be finishing that work in a couple of days, then submitting a pull request to the main uPy repo. A few things left to do, like rebase my github branch with uPy V1.10, test, and provide some example usage code.

If you are comfortable to make your own ESP32 build you will be able to pull in this work and have a uPy I2S module to try out.

the work-in-progress is on this github branch:
https://github.com/miketeachman/micropy ... /esp32-i2s

For I2S receive, I'm testing with the Adafruit I2S MEMS microphone breakout... the python interface looks like this

Code: Select all

from machine import I2S

audio_mic=I2S(I2S.NUM0,bck=bck_mic_pin,ws=ws_mic_pin,sdin=sdin_mic_pin,mode=I2S.MASTER_RX,
samplerate=SAMPLES_PER_SECOND, dataformat=I2S.B32,
channelformat=I2S.RIGHT_LEFT,standard=I2S.PHILIPS,
dmacount=64,dmalen=128)

samples = bytearray(SAMPLE_BLOCK_SIZE)

numread = audio_mic.readinto(samples)
I'll post again when the pull request is done

User avatar
mattyt
Posts: 410
Joined: Mon Jan 23, 2017 6:39 am

Re: i2s compatibility

Post by mattyt » Fri Feb 01, 2019 11:34 pm

Hey Mike, that'd be great - the lack of an I2S module is one of the large holes in the ESP32 port. I'll be sure to take a look!

vitocosmic
Posts: 3
Joined: Thu Jan 24, 2019 10:15 pm

Re: i2s compatibility

Post by vitocosmic » Sun Feb 03, 2019 11:47 pm

thanks a lot! that's the same mic I'm using. i want to introduce myself into this subject, do you know any documentation on adding modules to upy? i mean i know how to achieve this but i want to acquire a deeper knowledge to integrate other drivers in the future to the platform, i found a document made by Radomir Dopieralski and is my only source beside forums and github discussions

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: i2s compatibility

Post by dhylands » Mon Feb 04, 2019 2:05 am

I put together an example over here: https://github.com/dhylands/micropython ... /c_sample3
It's a little dated (about a year old) but has most of the elements.

User avatar
Mike Teachman
Posts: 155
Joined: Mon Jun 13, 2016 3:19 pm
Location: Victoria, BC, Canada

Re: i2s compatibility

Post by Mike Teachman » Wed Feb 06, 2019 8:18 pm

update: PR for I2S support is submitted:
https://github.com/micropython/micropython/pull/4471

usage guide and examples describing how to use this new I2S class:
https://github.com/miketeachman/micropy ... s-examples

It would be great if a few enthusiasts could try out this PR and report back.

feedback welcome !

OutoftheBOTS_
Posts: 847
Joined: Mon Nov 20, 2017 10:18 am

Re: i2s compatibility

Post by OutoftheBOTS_ » Wed Feb 06, 2019 8:59 pm

Lobo port has had some I2S stuff for a while. I did play with it a bit back when it was first released.

He had a couple of nice features like using the I2S to feed the DAC via DMA to pay a WAV file with a simple amp and speaker, this is the amp that I used https://www.ebay.com/sch/i.html?_from=R ... =1&_sop=15

He also had the ability to do the opposite and record to a buffer sampling from the ADC via I2S
I used https://www.ebay.com/itm/MAX9814-Electr ... 3877416550 and it worked well.

User avatar
Mike Teachman
Posts: 155
Joined: Mon Jun 13, 2016 3:19 pm
Location: Victoria, BC, Canada

Re: i2s compatibility

Post by Mike Teachman » Wed Feb 06, 2019 9:46 pm

Thanks for mentioning this work and listing those devices - I'll have to order some and try them out.

The PR I submitted addresses a gap in the functionality of the LoBo port. It is missing a core I2S piece, which is about interfacing to external I2S hardware devices via the ESP32 pins, using the I2S protocol. It would be great if Loboris could integrate this PR, or some derivative, into his port. I already do this on my local LoBo build - it's a clean integration. Then, we'd have I2S protocol support on his amazing port.

The LoBo port uses some of the I2S capabilities to bring very powerful enhancements to the existing machine.ADC and machine.DAC classes. By levering the DMA capabilities of I2S, the DAC and ADC hardware on the ESP32 can "run in the background" - it's an excellent addition to the ADC and DAC classes. This work would be a welcome addition to the mainline of uPy.

Dogostyle
Posts: 3
Joined: Fri Feb 08, 2019 4:33 pm

Re: i2s compatibility

Post by Dogostyle » Fri Feb 08, 2019 4:58 pm

Mike Teachman wrote:
Wed Feb 06, 2019 8:18 pm
update: PR for I2S support is submitted:
https://github.com/micropython/micropython/pull/4471

usage guide and examples describing how to use this new I2S class:
https://github.com/miketeachman/micropy ... s-examples

It would be great if a few enthusiasts could try out this PR and report back.

feedback welcome !
I tested your SD example using the same mic, and it works perfect !!. Thanks a lot for your effort, along with @vitocosmic, we had a lot of trouble trying to make it work.
I have some questions though, why you decimate or prune your samples before saving into the SD?. And, how can I achieve full resolution (18bits) from the mic (https://cdn-shop.adafruit.com/product-f ... asheet.PDF)?

User avatar
Mike Teachman
Posts: 155
Joined: Mon Jun 13, 2016 3:19 pm
Location: Victoria, BC, Canada

Re: i2s compatibility

Post by Mike Teachman » Sun Feb 10, 2019 4:12 am

thanks for trying it out. Really glad to know it works on someone else's build !

For the pruning part, I reduced the sample size to 16 bits to reduce the time to copy the samples to the SDCard (which should help to support a higher sampling rate), and to reduce the space used on the SDCard. In my application I will be continuously recording audio to SDCard for 8 hours or more.

To use 32 bit samples (to get all 18 bits of resolution), the prune() function might be changed to something like this:

Code: Select all

def prune(samples_out, samples_in):
    for i in range(SAMPLE_BLOCK_SIZE // 8):
        samples_out[4*i] = samples_in[8*i]
        samples_out[4*i + 1] = samples_in[8*i + 1]    
        samples_out[4*i + 2] = samples_in[8*i + 2]
        samples_out[4*i + 3] = samples_in[8*i + 3]    
and the definitions at the top:

Code: Select all

SDCARD_SECTOR_SIZE = 512 # bytes
SAMPLE_BLOCK_SIZE = SDCARD_SECTOR_SIZE * 2
BYTES_PER_SAMPLE = 4
SAMPLES_PER_SECOND = 16000
BITS_PER_SAMPLE = 32
That will pick out the 32bit samples from the left channel. There is likely a more efficient way to implement this operation. Perhaps an implementation based on the ustruct module? Making my python code efficient is still a work-in-progress.

Post Reply