ESP32要發出聲音,必須連接DAC晶片替它發出聲音,ESP32有了DAC之後,便可以播放MP3、WAV,聽網路廣播,甚至可以開發網路對講機。許多人常利用ESP32進行環境偵測或人體感應的偵測,如果偵測到變化,通常要發出警告聲,會接上一個蜂鳴器,藉由聲音的高低進行警告。但是蜂鳴器發出的聲音非常單調,而且無法發出真實的人聲或音樂聲。如果ESP32有了DAC晶片之後,便可以播放儲存在記憶卡中預先錄製好的真實聲音,甚至到Google抓取Text to Speech(TTS)的聲音,讓我們的專案更具有可聽性!於是我設計了這個DAC積木,讓大家可以利用拖拉積木的方式,很簡單就可以設計出具有音效功能的ESP32程式。因為這個積木有使用到額外的函式庫(ESP8266Audio),所以吉哥積木必須自己手動更新到20210529之後的版本,相關積木的安裝,請參閱「如何安裝吉哥積木」一文。
所謂的DAC(Digial to Analog Converter),能夠將數位的音頻訊號轉換成喇叭或是耳機的類比訊號。ESP32要能將MP3或是WAV,甚至是網路的音訊串流變成喇叭的類比訊號播放出來,便需要DAC這種解碼晶片。而ESP32和DAC溝通的界面是I2S(Integrated Interchip Sound)。I2S的界面是荷蘭飛利浦電子所發明,主要應用在各IC晶片之間處理音訊的匯流排,它通常需要三個接腳:
LRC(Left-Right Clock),主要用於傳送左右聲道的資料,也有稱為LRCK或是WS。
BCLK(Bit Clock),位元時脈,也有稱為SCK。
SD(Serial Data),序列資料線,也有稱為SDATA、SDIN、SDOUT、DIN等。
ESP32內部有二組I2S的週邊,可以接輸出裝置,例如DAC;也可以接輸入裝置,例如I2S的麥克風。I2S的三個接腳可以自行設定ESP32的三個數位腳位來連接I2S裝置。以DAC來說,常見可以連接ESP32的有,MAX98357A、PCM5102等,基本上,只要具有I2S界面的DAC晶片都可以和ESP32連接,並使用我所設計的積木。以下的程式範例都是以MAX98357A為例介紹,但是使用PCM5102也是可以的。請將買到的MAX98357A的排針及喇叭連接座先自行焊接好。
通常買來的MAX98357A需要自己把針腳焊好
自行把針腳焊好,黑色的基座是接喇叭使用
接下來將MAX98357A的LRC接到ESP32的IO27,BCLK接到IO17,SDATA(DIN)接到IO13(以上腳位可自行調整),GND接到GND,VCC接到VCC,其他二根針不用接。再準備一個喇叭,將喇叭的二條線連接到MAX98357A的黑色底座,用一字螺絲起子鎖緊。
我所設計的「I2S音訊模組DAC」積木,位在「吉哥積木」、「ESP32」、「模組」內,它可以設定腳位,播放網路電台聲音、播放GoogleTTS以及MP3,也可以指定將Google TTS的聲音儲存在SD卡或是SPIFFS裡。
程式範例的結果影片
連上WIFI後,設定MAX98357A的LRC腳位IO27,BCLK的腳位IO17,DATA(DIN)腳位IO13。
設定音量增益,預設是1.0,範圍從0.0到最大4.0,本範例設定為1.5。
接下來會去Google抓取TTS(Text to Speech)「WIFI已連線完成,現在播放ICRT」的聲音,語音設定為台灣,也可設定其他國家聲音。
注意,為了維持音訊裝置正常運作,在「重複執行」積木內部的最上方,必須放入「I2S音訊模組 持續維持音訊播放的運作」積木,才能持續播放聲音,如果沒有這個積木,聲音不會正常播放。
當TTS語音播放結束時會觸發「當TTS語音播放結束」事件,如果比對剛結束的語音內容和「WIFI已連線完成,現在播放ICRT」一致,那麼在Google TTS語音結束時,便會去播放網路電台ICRT的廣播節目,ICRT的網址為:http://live.leanstream.co/ICRTFM-MP3
連上WIFI後,設定MAX98357A的LRC腳位IO27,BCLK的腳位IO17,DATA(DIN)腳位IO13,音量增益請自行視需要設定。
注意,為了維持音訊裝置正常運作,在「重複執行」積木內部的最上方,必須放入「I2S音訊模組 持續維持音訊播放的運作」積木,才能持續播放聲音,如果沒有這個積木,聲音不會正常播放。
因為在播放音訊時,ESP正在處理音訊資料,所以如果有任何的其他偵測的動作,會使得播放音訊時不正常,或是聲音斷斷續續的,應該要在音訊模組沒有播放聲音的時候進行,因此要先用積木「I2S音訊模組 正在播放中?」先確定有沒有播放音訊。
如果沒有播放音訊,便可以開始偵測想要偵測的東西,例如光線值,並且判斷如果光線值小於500時,將「亮度:」、「,太暗了」,以及偵測到的亮度值結合成同一個字串,I2S音訊模組會去抓取Google TTS抓取這個字串的聲音來播放警告。
範例三的功能和範例二完全一樣,只不過在上個例子中,每一次亮度過低,便要連接一次Google下載同樣的聲音檔,其實有點沒有效率,而且如果WIFI中斷時,便完全抓不到Google的聲音了。如果能在連接WIFI時,便將聲音下載儲存下來,接下來就播放下載下來的聲音檔就可以了。ESP32內部把它的記憶體分了一些出來當使檔案系統,叫做SPIFFS,這個地方便是我們可以暫時存取檔案的地方。
連上WIFI後,設定MAX98357A的LRC腳位IO27,BCLK的腳位IO17,DATA(DIN)腳位IO13。
注意,為了維持音訊裝置正常運作,在「重複執行」積木內部的最上方,必須放入「I2S音訊模組 持續維持音訊播放的運作」積木,才能持續播放聲音,如果沒有這個積木,聲音不會正常播放。
去Google下載「亮度太暗了,請開燈」的聲音,儲存到SPIFFS,儲存到「/test/test.mp3」這個檔案裡。請注意,如果希望有路徑的話,要包含路徑和檔名。因為SPIFFS的空間有限,不建議在這裡儲存太多及太龐大的資料,如果有額外的SD記憶卡的話,也可以在這個積木選擇儲存到「SD記憶卡」。
因為在播放音訊時,ESP正在處理音訊資料,所以如果有任何的其他偵測的動作,會使得播放音訊時不正常,或是聲音斷斷續續的,應該要在音訊模組沒有播放聲音的時候進行,因此要先用積木「I2S音訊模組 正在播放中?」先確定有沒有播放音訊。
如果沒有播放音訊,便可以開始偵測想要偵測的東西,例如光線值,並且判斷如果光線值小於500時,I2S音訊模組直接從SPIFFS裡讀取之前儲存的MP3檔案「/test/test.mp3」來播放警告。
MP3音樂通常一首歌大約5MB左右,不太可能放在ESP32的SPIFFS裡面,如果有播放MP3音樂的需求,最好是額外購買一個microSD的記憶卡,並準備一個SPI界面的SD模組,記憶卡便可以儲存非常多的資料了。先在電腦中放置幾首MP3歌曲,請注意,路徑及檔名最好都不要是中文檔名。
如果手頭沒有這個模組,也可以使用microSD轉接卡,焊上七根排針,便可以和ESP32連接。
記憶卡是SPI界面,ESP32的SPI界面有固定的腳位,不能亂接,要接對ESP32才能讀取到這個記憶卡。
設定MAX98357A的LRC腳位IO27,BCLK的腳位IO17,DATA(DIN)腳位IO13,音量增益請自行調整。
注意,為了維持音訊裝置正常運作,在「重複執行」積木內部的最上方,必須放入「I2S音訊模組 持續維持音訊播放的運作」積木,才能持續播放聲音,如果沒有這個積木,聲音不會正常播放。
按下A鍵,會播放記憶卡中的「/01/001.mp3」這首歌曲。
按下B鍵,會播放記憶卡中的「/01/002.mp3」這首歌曲。
按下「A+B鍵」則會停止播放所有音樂。
當MP3檔案播放結束,可以觸發「當MP3檔案播放結束」的程式,並且可以依據播放的檔案名稱,設定相對應的播放結束時觸發的條件。
如果您沒有像範例四的讀卡模組,可以直接播放網路硬碟的MP3檔案嗎?網路硬碟中的檔案因為具有私密性,並且還要能提供串流的功能,因此不是所有的網路硬碟都能提供線上播放MP3的功能,例如Google Drive便不行。經過我的測試,Open Drive和DropBox都行,但是Open Drive的頻寬太小,ESP32播放MP3的時候,聲音會斷斷續續,並且在頻寬不夠時,I2S模組會產生刺耳的音頻,所以,最適合的方案便是使用DropBox的硬碟空間。但是DropBox提供的連結是https而不是http,因此我修正了原本ESP8266AUDIO的函式庫使它能接受https,要使用這個功能,吉哥積木必須更新到至少20220110之後的版本。
雖然DropBox可以讓ESP32直接播放MP3,但是在頻寬以及MP3的bit rate和ESP32的buffer的交互作用下,也不是所有檔案都能完美播放,幾秒鐘的MP3還可以不用顧慮這些,但是如果MP3是好幾分鐘的檔案,根據我的測試,把MP3格式修改成112K的位元率(bit rate)是比較能柔順播放的版本,所以在把MP3上傳到DropBox之前,先把長度較長的MP3改存成112kbps的格式,聲道模式為立體聲,播放時比較能有較好的音質。以下以Audacity為例,如何修改位元率以及立體聲:
選單依序點選「檔案」→「匯出」→「匯出為MP3之後出現對話框」,位元率模式點選「固定模式」,品質為「112kbps」,聲道模式為「立體聲」,設定完之後便可以存檔並將它傳送到DropBox。
將MP3檔案上傳到任一個資料夾都可以,點選檔案右側的「複製連結」便會將專屬這個檔案的超連結複製起來,這個就是讓ESP32能播放這個MP3的連結。
程式:
把DropBox取得的網址放入「I2S音訊模組 播放網路MP3檔案 URL」積木中的空間,這個積木便會去抓取DropBox的檔案串流直接播放音樂。
如果想處理播放音樂完畢的事件,必須使用「I2S音訊模組 當網路MP3播放結束」這個積木,但是這個積木是所有網路MP3播放結束都會觸發,如果還想控制到是哪一個MP3檔案播放結束(因為有可能會播放好幾首」,裡面必須要有「I2S音訊模組 如果網路MP3檔案URL是」,用這個積木可以更細微的控制到是哪一首MP3播放結束時會觸發的事件,所以可以依據播放的檔案連結的不同,設定相對應的播放結束時觸發的條件。