[第七課] DFPlayer開聲試啼 (UART)
當你開始踏上路途,路就會自己展現。"As you start to walk on the way, the way appears." ~Rumi嗯,嵌入式系統的設計,必須學會『勇於嘗試,發揮各組件的特色。』;就像只會用高檔的食材稱不上大廚,而能將一般當季時令的食材,用到淋漓盡致的必定是名廚。這就是說:通常,Maker不會去開發系統裡的每一項關鍵組件;而是基於系統的需求,去想辦法找到合用的組件,設法將其進行完美的連接。
就是因為這樣的系統需求太過陽春,而「可以選曲」、「可以控制播放與暫停」與「可以設定音量大小與模式」,這些才是ACCP的基本需求,『怎麼做到?』就是下一步。
所幸, DFPlayer Mini 有提供一組UART介面(Rx,Tx),來接受主控端下達預設的各項命令,與回應的訊息。使用上,和先前其他模組 RTC 、 OLED 大致相同,先引入該程序與並在 setup() 開啟連接:
#include "DFRobotDFPlayerMini.h"/* MP3Player via UART*/DFRobotDFPlayerMini myDFPlayer;......
while(!Serial1);bool tt = myDFPlayer.begin(Serial1);delay(1000);if (!tt) { //Use softwareSerial to communicate with mp3.sl3 = "-MP3/SD failed..";ss = "System is some fault...";digitalWrite(LED_R, LOW);} else {sl3 = "-MP3/SD is ready..";delay(1000);myDFPlayer.setTimeOut(1000); // 設定通訊逾時為500msmyDFPlayer.volume(vol); //Set volume value. From 0 to 30myDFPlayer.outputDevice(DFPLAYER_DEVICE_SD);myDFPlayer.EQ(DFPLAYER_EQ_NORMAL); //myDFPlayer.playFolder(1, 1);}
在連接完成後,開始進行初值的設定。 在這裡 myDFPlayer.playFolder(1, 1) 就是順利連接上時,聽到的第一次音樂播放;播放在Folder 01 裡的 001xxx.mp3 。往後,在ACCP系統裡90%都只會使用這個命令。是不是很直覺的控制方式,但要注意的如果下的指令是有要收回應訊息,必須至少等ㄧ秒 delay(1000) 再去收訊息。更詳盡的說明,請參考其 Wiki 。
說到這,可以下課了吧!?當然可以啊!......
但,就看你有沒有當名廚的決心?如果有,那請再看下去!
解決了,可以用主控來指揮 DFPlayer Mini 來播放。但是,下了指令卻沒有聽到任何聲音,怎麼辦?還有,當歌曲播完時,主控能知道嗎?
其實, DFPlayer Mini 提供的範例,並沒有詳盡的控制流程說明;在其播放音樂的期間,你不去詢問,是沒有辦法知道目前的狀況;而只有在播放完畢時,才會有訊息丟出來。
另外,我們自己編的MP3檔名的編號,和放進SD卡內時 DFPlayer Mini 索引的FAT檔案編號是不一致的;也就是說在Folder 01 裡的 001xxx.mp3 ,並不是它所認知的編號#1。
『怎麼解決?』就是精進的下一步。在 <setPlayer.ino> ,是加料對 DFPlayer Mini 的設定與狀況檢知:
- setEQ 是在每次有新的X-DISC播放時,依其設定調整EQ的模式。
- smartVol 是可以根據現在的時間,適當調整一開始時的音量大小。
- chkState 是主動詢問播放器目前的狀態:0 :NO_TRACK; 1 :PLAYING; 2 :PAUSE; 3 :STOP; -1 :NACK;
myDFPlayer.playFolder(numFolder, numTrack);delay(1000);
if (chkState() > 0) {
f_nowPlaying = true;
ss = "play all folder.."; draw(TRK, 0x01);
sysDelay = 2000;
} else { //no such track;
f_nowPlaying = false;
ss = "Can't play.."; draw(NG_ERR, 0x03);
sysDelay = 500;
}
case NOP: {lowPowerHandler();digitalWrite(LED_R, HIGH);digitalWrite(LED_B, HIGH);rfOff();if (myDFPlayer.available()) {delay(100);uint8_t type = myDFPlayer.readType();int vv = myDFPlayer.read();
switch (type) {case DFPlayerPlayFinished: {f_nowPlaying = false;st = FW_VERSION;ss="Ready to scan..[B:" + String(battLife) + "%]";draw(SCAN, 0xFF);sysDelay = 500;break;}default: {break;}}}......
就是在發現播放器播完曲子,回應 DFPlayerPlayFinished 訊息時,讓系統回復 f_nowPlaying = false 到正常的狀態。
當然,在想要精進的這段過程,相信更能體會『柳暗花明又一村』的喜悅了。
留言
張貼留言