Arduino 與 DFPlayer Mini MP3模組實作,進階篇
上一篇介紹了基本的DFPlayer Mini的操作,接下來我們就要更進一步,加上一些操作的控制,像是上一首/下一首,暫停/播放,還有音量的控制。如此一來,整個專題看起來就更完整,更專業囉!
如果你尚未使用過DFPlayer,強烈建議先看上一篇DFPlayer入門教學:
https://blog.jmaker.com.tw/arduino-dfplayer-mp3/
傑森創工獨家提供完整套件,歡迎選購!
https://www.jmaker.com.tw/products/dfplayer-mp3
再次提醒,這個範例是用DFPlayer Mini Mp3 by Makuna函式庫,一定要先行安裝才行哦!
接著我們就要接線了,這次多了3個按鈕和1個可變電阻,接線上自然複雜一些,但其實並不難的。
接線方式:
VCC => 5V (接到麵包板上方的紅線處,這樣可以方便所有零件都能使用這個5V)
GND => GND (接到麵包板上方的藍線處,這樣可以方便所有零件都能使用這個GND)
RX => Pin 10 (加1K電阻)
TX => Pin 11
SPK1,SPK2 => 分別接喇叭單體的兩條線,沒有序順限制
下一首按鈕 => Pin 5
播放/暫停按鈕 => Pin 6
上一首按鈕 => Pin 7
以上三個按鈕的另一腳 => GND (接到麵包板上方的藍線插孔即可)
可變電阻中間腳位 => A5
程式部份,基本上是由上一篇基本範例進行改寫,重複的部份請參考上一篇說明。
https://blog.jmaker.com.tw/arduino-dfplayer-mp3/
這次主要是新增音量鍵和三個按鈕。我們先看音量旋鈕,這是一個常見的可變電阻,我們透過旋轉的量,用map函式進行換算成0-30的音量質。
另外,我們還加了一個判斷,如果目前音量,不等於可變電阻設定的音量,才將音量設為新的值,不然就不用理會。
再來就是3個按鍵,主要是播放/暫停鍵比較麻煩,我們必須先判斷目前的播放狀態,是不是正在播放中,如果是,就進行暫停的動作;如果不是,就進行播放。
而這裡用的播放是start(),這個函式會自行判斷目前是不是有曲子播到一半被暫停,如果有,就會播著播,如果沒有,就把之前播完的那首,重頭播起。
另兩個按鈕,下一首,上一首就很簡單了,分別用prevTrack()和nextTrack()就搞定了。
這個專題雖然接的線不少,但其實並不難,大家試看看吧!
/*
* 本範程式為Arduino結合DFPlayer MP3範例程式,加上播放控制,由傑森創工提供
*
*
* 請先安裝DFPlayer Mini Mp3 by Makuna函式庫,可由Arduino IDE裡的「程式管理員」進行安裝
* 建議先看上一篇DFPlayer入門教學:
* https://blog.jmaker.com.tw/arduino-dfplayer-mp3/
*
* 粉絲團:https://www.facebook.com/jasonshow
* 傑森創工購物網:https://www.jmaker.com.tw/
* 傑森創工部落格:https://blog.jmaker.com.tw/
*/
// SD卡上的MP3檔案,必須放在mp3這個目錄,並取名0開頭的4個數字,如:0001.mp3、0002.mp3
// sd:/mp3/0001.mp3
// sd:/mp3/0002.mp3
const int Next_BUTTON_PIN = 5; // 下一首按鍵的接腳
const int PlayPause_BUTTON_PIN = 6; // 播放/暫停 按鍵的接腳
const int Prev_BUTTON_PIN = 7; // 上一首按鍵的接腳
int sensorPin = A5; //音量控制類比輸入的PIN腳
int sensorValue = 0; // 類比輸入得到的數值
int volume = 0; //目前音量
#include <DFMiniMp3.h>
//使用軟體Serial
#include <SoftwareSerial.h>
SoftwareSerial mySerial(11, 10); // RX, TX
// 宣告 notify class
//
class Mp3Notify;
// 定義類型,其中第一個參數為決定用硬體Serial或軟體Serail
//
typedef DFMiniMp3<SoftwareSerial, Mp3Notify> DfMp3; //如果用UNO板就用軟體Serail
//typedef DFMiniMp3<HardwareSerial, Mp3Notify> DfMp3; //如果用Mega板就用硬體Serail
// 建立mp3物件
//
DfMp3 dfmp3(mySerial);
DfMp3_Status playOrPause; // 建立播放狀態物件
// 實作notification的類別,可以在不同的事件中,寫入想要進行的動作
// 若沒有特別要進行的處理,這裡不用修改
class Mp3Notify
{
public:
static void PrintlnSourceAction(DfMp3_PlaySources source, const char* action)
{
if (source & DfMp3_PlaySources_Sd)
{
Serial.print("SD Card, ");
}
if (source & DfMp3_PlaySources_Usb)
{
Serial.print("USB Disk, ");
}
if (source & DfMp3_PlaySources_Flash)
{
Serial.print("Flash, ");
}
Serial.println(action);
}
static void OnError([[maybe_unused]] DfMp3& mp3, uint16_t errorCode)
{
// 錯誤訊息
Serial.println();
Serial.print("Com Error ");
Serial.println(errorCode);
}
static void OnPlayFinished([[maybe_unused]] DfMp3& mp3, [[maybe_unused]] DfMp3_PlaySources source, uint16_t track)
{
Serial.print("Play finished for #");
Serial.println(track);
}
static void OnPlaySourceOnline([[maybe_unused]] DfMp3& mp3, DfMp3_PlaySources source)
{
PrintlnSourceAction(source, "online");
}
static void OnPlaySourceInserted([[maybe_unused]] DfMp3& mp3, DfMp3_PlaySources source)
{
PrintlnSourceAction(source, "inserted");
}
static void OnPlaySourceRemoved([[maybe_unused]] DfMp3& mp3, DfMp3_PlaySources source)
{
PrintlnSourceAction(source, "removed");
}
};
void setup()
{
Serial.begin(9600); //啟用監控視窗
Serial.println("initializing...");
pinMode(Next_BUTTON_PIN, INPUT_PULLUP); //設定按鈕的接腳為輸入
pinMode(PlayPause_BUTTON_PIN, INPUT_PULLUP);
pinMode(Prev_BUTTON_PIN, INPUT_PULLUP);
dfmp3.begin(); //開始使用DFPlayer模組
//重置DFPlayer模組,會聽到"波"一聲
dfmp3.reset();
//音量控制,0~30
uint16_t volume = dfmp3.getVolume();
Serial.print("volume ");
Serial.println(volume);
dfmp3.setVolume(24);
//取得所有MP3檔的總數
uint16_t count = dfmp3.getTotalTrackCount(DfMp3_PlaySource_Sd);
Serial.print("files ");
Serial.println(count);
Serial.println("Play Mp3...");
// 播放MP3,參數就是第N首。如要播第一首MP3,參數就是1
dfmp3.playMp3FolderTrack(1);
}
void loop()
{
//音量控制,旋轉可變電阻,讀取類比值後,換算成音量,然後進行設定
sensorValue = analogRead(sensorPin); //讀取類比輸入的值會得到0~1023
sensorValue = map(sensorValue,0,1023,0,30); //將0~1023轉化成0~30音量
if(volume != sensorValue){ //如果目前音量,不等於可變電阻設定的音量,就將音量設為新的值
dfmp3.setVolume(sensorValue);
volume = sensorValue;
Serial.println(volume); //從監控視窗看到音量值
}
//判斷 播放/暫停 的狀態,如果正在播放,按了鈕就表示要暫停,除此之外,就接著播放
if(digitalRead(PlayPause_BUTTON_PIN) == LOW){ // 如果按了鍵
Serial.println("click Play/Pause...");
playOrPause = dfmp3.getStatus(); //取得播放狀態
if(playOrPause.state == DfMp3_StatusState_Playing ){ //判斷目前是不是播放中
dfmp3.pause(); //暫停
delay(500); //delay半秒,以免操作者按住不放會一直重複操作
}else{
dfmp3.start(); //接著播放
delay(500);
}
}
//按下上一首按鍵的處理
if(digitalRead(Prev_BUTTON_PIN) == LOW){ //如果按鍵按了
dfmp3.prevTrack();
delay(500);
}
//按下下一首按鍵的處理
if(digitalRead(Next_BUTTON_PIN) == LOW){ //如果按鍵按了
dfmp3.nextTrack();
delay(500);
}
}