Possible to "fake" I2S output using PDM? #14225
Replies: 2 comments 3 replies
-
Have you looked at using the non-blocking mode to implement buzzers and beepers? You can create short wav files and send them to the I2S peripheral using the non-blocking mode. There is no need to block. See examples here. |
Beta Was this translation helpful? Give feedback.
-
@echo-lalia
The beep.wav file used in this example is 5338 bytes in length. I used a Lolin D32 Pro development board which has an ESP32 WROVER module. Hopefully the ESP32-S3 has a similar response. Would 7.7ms be perceived as a fast enough response for a user? import os
import time
import micropython
from machine import I2S
from machine import Pin
from machine import SDCard
sd = SDCard(slot=2, sck=18, mosi=23, miso=19, cs=4)
os.mount(sd, "/sd")
# ======= I2S CONFIGURATION =======
SCK_PIN = 33
WS_PIN =25
SD_PIN = 32
I2S_ID = 1
BUFFER_LENGTH_IN_BYTES = 10000
# ======= I2S CONFIGURATION =======
# ======= AUDIO CONFIGURATION =======
WAV_FILE = "beep.wav"
WAV_SAMPLE_SIZE_IN_BITS = 16
FORMAT = I2S.MONO
SAMPLE_RATE_IN_HZ = 11025
# ======= AUDIO CONFIGURATION =======
def i2s_callback(arg):
print("cb")
scope_sync = Pin(21, Pin.OUT, value=0)
audio_out = I2S(
I2S_ID,
sck=Pin(SCK_PIN),
ws=Pin(WS_PIN),
sd=Pin(SD_PIN),
mode=I2S.TX,
bits=WAV_SAMPLE_SIZE_IN_BITS,
format=FORMAT,
rate=SAMPLE_RATE_IN_HZ,
ibuf=BUFFER_LENGTH_IN_BYTES,
)
audio_out.irq(i2s_callback)
wav = open("/sd/{}".format(WAV_FILE), "rb")
_ = wav.seek(44) # advance to first byte of Data section in WAV file
# allocate sample array buffer
wav_samples = bytearray(10000)
wav_samples_mv = memoryview(wav_samples)
# time delay to allow internal Tx buffer to be emptied by DMA
time.sleep(1)
# preload samples into application buffer
num_read = wav.readinto(wav_samples_mv)
print('num_read', num_read)
# toggle IO. This simulates a pushbutton or some trigger in the application program
scope_sync.value(1)
_ = audio_out.write(wav_samples_mv[:num_read])
scope_sync.value(0)
print('done') Here is an oscilloscope capture showing the signals SCK, WS, SD, DIO sync (top to bottom). The delay from DIO going high to the first audio sample on the I2S bus is about 7.7ms. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
I have a funny question, and I'm curious to hear your thoughts!
Im developing a software for a M5Stack Cardputer, which is an Esp32-s3 device, with an I2S speaker built into it. The I2S speaker is really nice for playing back samples and high quality generated signals. However, I'd also like to use it just like a "beeper".
I made a little module for generating a simple square wave to a chosen frequency, and sending it to the I2S output. However, it feels kinda janky and imperfect. It also blocks my code, and it certainly feels needlessly complex for such a simple task. I've used simple buzzers in MicroPython before, and I really like the way they're easy to work with, and they work really well for short, loud tones, for UI feedback.
I'm curious if anyone knows whether or not it's possible to abuse the I2S peripheral a bit, and treat it more like a simple buzzer for this purpose, by generating 2 PWM signals to imitate the clock and word select, and then using a 3rd PWM signal to imitate a data signal flipping from 0x00-0xff.
If course, I'll probably just try it out once I'm back at my PC. But if anyone's tried it before, or sees some issues with my logic here, I'd appreciate your input before I waste my time (or, idk, blow up my speaker 😅)
Beta Was this translation helpful? Give feedback.
All reactions