XIAO DFPlayer: replace demo loop with serial command console (play/pause/stop/next/vol/loop/folder/eq/reset/status)
This commit is contained in:
@@ -1,80 +1,210 @@
|
|||||||
/***************************************************
|
/***************************************************
|
||||||
DFPlayer - A Mini MP3 Player For Arduino
|
DFPlayer Mini - serial console control (Seeed XIAO nRF52840)
|
||||||
<https://www.dfrobot.com/product-1121.html>
|
|
||||||
|
|
||||||
***************************************************
|
Hardware Serial1 link to the DFPlayer Mini:
|
||||||
This example shows the basic function of library for DFPlayer.
|
XIAO D7 (RX) <- DFPlayer TX (add a divider/level shifter if the
|
||||||
|
DFPlayer runs at 5V - nRF52 is not 5V tolerant)
|
||||||
|
XIAO D6 (TX) -> 1k -> DFPlayer RX
|
||||||
|
common ground; feed DFPlayer VCC from 5V with a >=470uF cap at the module.
|
||||||
|
|
||||||
Created 2016-12-07
|
Open the Serial Monitor at 115200 baud, line ending = Newline, and type
|
||||||
By [Angelo qiao](Angelo.qiao@dfrobot.com)
|
commands (see "help"). Based on the DFRobot DFPlayerMini example (LGPL).
|
||||||
|
|
||||||
GNU Lesser General Public License.
|
|
||||||
See <http://www.gnu.org/licenses/> for details.
|
|
||||||
All above must be included in any redistribution
|
|
||||||
****************************************************/
|
|
||||||
|
|
||||||
/***********Notice and Trouble shooting***************
|
|
||||||
1.Connection and Diagram can be found here
|
|
||||||
<https://www.dfrobot.com/wiki/index.php/DFPlayer_Mini_SKU:DFR0299#Connection_Diagram>
|
|
||||||
2.This code is tested on Arduino Uno, Leonardo, Mega boards.
|
|
||||||
****************************************************/
|
****************************************************/
|
||||||
|
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include "DFRobotDFPlayerMini.h"
|
#include "DFRobotDFPlayerMini.h"
|
||||||
|
|
||||||
//#if (defined(ARDUINO_Seeed_XIAO_nRF52840_Sense))
|
#include <Adafruit_TinyUSB.h> // for Serial (USB CDC)
|
||||||
#include <Adafruit_TinyUSB.h> // for Serial
|
|
||||||
|
|
||||||
#define FPSerial Serial1 // D7 <- DFPlayer TX, D6 -> DFPlayer RX
|
#define FPSerial Serial1 // D7 <- DFPlayer TX, D6 -> DFPlayer RX
|
||||||
// #elif (defined(ARDUINO_AVR_UNO) || defined(ESP8266)) // Using a soft serial port
|
|
||||||
// #include <SoftwareSerial.h>
|
|
||||||
// SoftwareSerial softSerial(/*rx =*/4, /*tx =*/5);
|
|
||||||
// #define FPSerial softSerial
|
|
||||||
// #else
|
|
||||||
// #define FPSerial Serial1
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
DFRobotDFPlayerMini myDFPlayer;
|
DFRobotDFPlayerMini myDFPlayer;
|
||||||
|
|
||||||
|
int currentVolume = 20; // shadow of the DFPlayer volume (0..30)
|
||||||
|
bool dfOnline = false;
|
||||||
|
|
||||||
|
char cmdBuf[64];
|
||||||
|
uint8_t cmdLen = 0;
|
||||||
|
|
||||||
void printDetail(uint8_t type, int value);
|
void printDetail(uint8_t type, int value);
|
||||||
|
void printHelp();
|
||||||
|
void printStatus();
|
||||||
|
void handleLine(char *line);
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
// Open serial communications and wait for port to open:
|
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
uint32_t t0 = millis();
|
uint32_t t0 = millis();
|
||||||
while (!Serial && millis() - t0 < 3000) {
|
while (!Serial && millis() - t0 < 3000) delay(10); // headless-safe
|
||||||
delay(10); // for nrf52840 with native usb
|
|
||||||
Serial.println(F("Initializing serial..."));
|
|
||||||
}
|
|
||||||
|
|
||||||
FPSerial.begin(9600);
|
FPSerial.begin(9600);
|
||||||
delay(1500); // let the DFPlayer boot
|
delay(1500); // let the DFPlayer boot
|
||||||
|
|
||||||
if (!myDFPlayer.begin(FPSerial, /*isACK=*/true, /*doReset=*/true)) {
|
dfOnline = myDFPlayer.begin(FPSerial, /*isACK=*/true, /*doReset=*/true);
|
||||||
Serial.println(F("DFPlayer not responding - check wiring / power / SD"));
|
if (dfOnline) {
|
||||||
delay(5000);
|
Serial.println(F("DFPlayer online."));
|
||||||
Serial.println(F("DFPlayer not responding - check wiring / power / SD"));
|
} else {
|
||||||
// fall through instead of hanging, so you can still debug
|
Serial.println(F("WARNING: DFPlayer did not answer begin() - check wiring / power / SD."));
|
||||||
|
Serial.println(F("Commands are still sent; status feedback may be missing."));
|
||||||
}
|
}
|
||||||
myDFPlayer.volume(20);
|
|
||||||
|
myDFPlayer.volume(currentVolume);
|
||||||
delay(50);
|
delay(50);
|
||||||
myDFPlayer.play(1);
|
myDFPlayer.play(1); // play the first track on boot (optional)
|
||||||
|
|
||||||
|
printHelp();
|
||||||
|
Serial.print(F("> "));
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop()
|
void loop()
|
||||||
{
|
{
|
||||||
static unsigned long timer = millis();
|
// ---- read a line from the USB serial console ----
|
||||||
|
while (Serial.available()) {
|
||||||
if (millis() - timer > 3000) {
|
char c = (char)Serial.read();
|
||||||
timer = millis();
|
if (c == '\n' || c == '\r') {
|
||||||
myDFPlayer.next(); //Play next mp3 every 3 second.
|
if (cmdLen) {
|
||||||
|
cmdBuf[cmdLen] = '\0';
|
||||||
|
handleLine(cmdBuf);
|
||||||
|
cmdLen = 0;
|
||||||
|
Serial.print(F("> "));
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (cmdLen < sizeof(cmdBuf) - 1) {
|
||||||
|
cmdBuf[cmdLen++] = c;
|
||||||
|
} else {
|
||||||
|
cmdLen = 0; // overrun - drop the line
|
||||||
|
Serial.println(F("\n(input too long)"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---- surface DFPlayer events / errors ----
|
||||||
if (myDFPlayer.available()) {
|
if (myDFPlayer.available()) {
|
||||||
printDetail(myDFPlayer.readType(), myDFPlayer.read()); //Print the detail message from DFPlayer to handle different errors and states.
|
printDetail(myDFPlayer.readType(), myDFPlayer.read());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void strlwr_(char *s) { for (; *s; ++s) *s = tolower((unsigned char)*s); }
|
||||||
|
|
||||||
|
void handleLine(char *line)
|
||||||
|
{
|
||||||
|
strlwr_(line);
|
||||||
|
char *cmd = strtok(line, " \t");
|
||||||
|
char *arg1 = strtok(NULL, " \t");
|
||||||
|
char *arg2 = strtok(NULL, " \t");
|
||||||
|
if (!cmd) return;
|
||||||
|
int n1 = arg1 ? atoi(arg1) : -1;
|
||||||
|
|
||||||
|
if (!strcmp(cmd, "help") || !strcmp(cmd, "?")) {
|
||||||
|
printHelp();
|
||||||
|
}
|
||||||
|
else if (!strcmp(cmd, "status") || !strcmp(cmd, "stat")) {
|
||||||
|
printStatus();
|
||||||
|
}
|
||||||
|
else if (!strcmp(cmd, "play")) {
|
||||||
|
if (n1 > 0) { myDFPlayer.play(n1); Serial.print(F("play track ")); Serial.println(n1); }
|
||||||
|
else { myDFPlayer.start(); Serial.println(F("play / resume")); }
|
||||||
|
}
|
||||||
|
else if (!strcmp(cmd, "pause")) {
|
||||||
|
myDFPlayer.pause(); Serial.println(F("paused"));
|
||||||
|
}
|
||||||
|
else if (!strcmp(cmd, "resume") || !strcmp(cmd, "start")) {
|
||||||
|
myDFPlayer.start(); Serial.println(F("resumed"));
|
||||||
|
}
|
||||||
|
else if (!strcmp(cmd, "stop")) {
|
||||||
|
myDFPlayer.stop(); Serial.println(F("stopped"));
|
||||||
|
}
|
||||||
|
else if (!strcmp(cmd, "next")) {
|
||||||
|
myDFPlayer.next(); Serial.println(F("next"));
|
||||||
|
}
|
||||||
|
else if (!strcmp(cmd, "prev") || !strcmp(cmd, "previous")) {
|
||||||
|
myDFPlayer.previous(); Serial.println(F("previous"));
|
||||||
|
}
|
||||||
|
else if (!strcmp(cmd, "vol") || !strcmp(cmd, "volume") || !strcmp(cmd, "v")) {
|
||||||
|
if (arg1 && (!strcmp(arg1, "up") || !strcmp(arg1, "+"))) currentVolume = min(30, currentVolume + 1);
|
||||||
|
else if (arg1 && (!strcmp(arg1, "down") || !strcmp(arg1, "-"))) currentVolume = max(0, currentVolume - 1);
|
||||||
|
else if (n1 >= 0) currentVolume = constrain(n1, 0, 30);
|
||||||
|
myDFPlayer.volume(currentVolume);
|
||||||
|
Serial.print(F("volume = ")); Serial.println(currentVolume);
|
||||||
|
}
|
||||||
|
else if (!strcmp(cmd, "+")) {
|
||||||
|
currentVolume = min(30, currentVolume + 1);
|
||||||
|
myDFPlayer.volume(currentVolume);
|
||||||
|
Serial.print(F("volume = ")); Serial.println(currentVolume);
|
||||||
|
}
|
||||||
|
else if (!strcmp(cmd, "-")) {
|
||||||
|
currentVolume = max(0, currentVolume - 1);
|
||||||
|
myDFPlayer.volume(currentVolume);
|
||||||
|
Serial.print(F("volume = ")); Serial.println(currentVolume);
|
||||||
|
}
|
||||||
|
else if (!strcmp(cmd, "loop")) {
|
||||||
|
if (n1 > 0) { myDFPlayer.loop(n1); Serial.print(F("loop track ")); Serial.println(n1); }
|
||||||
|
else Serial.println(F("usage: loop <track>"));
|
||||||
|
}
|
||||||
|
else if (!strcmp(cmd, "folder")) {
|
||||||
|
if (arg1 && arg2) {
|
||||||
|
myDFPlayer.playFolder(atoi(arg1), atoi(arg2));
|
||||||
|
Serial.print(F("folder ")); Serial.print(atoi(arg1));
|
||||||
|
Serial.print(F(" file ")); Serial.println(atoi(arg2));
|
||||||
|
} else {
|
||||||
|
Serial.println(F("usage: folder <folder#> <file#>"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!strcmp(cmd, "eq")) {
|
||||||
|
int eq = -1;
|
||||||
|
if (arg1 && !strcmp(arg1, "normal")) eq = DFPLAYER_EQ_NORMAL;
|
||||||
|
else if (arg1 && !strcmp(arg1, "pop")) eq = DFPLAYER_EQ_POP;
|
||||||
|
else if (arg1 && !strcmp(arg1, "rock")) eq = DFPLAYER_EQ_ROCK;
|
||||||
|
else if (arg1 && !strcmp(arg1, "jazz")) eq = DFPLAYER_EQ_JAZZ;
|
||||||
|
else if (arg1 && !strcmp(arg1, "classic")) eq = DFPLAYER_EQ_CLASSIC;
|
||||||
|
else if (arg1 && !strcmp(arg1, "bass")) eq = DFPLAYER_EQ_BASS;
|
||||||
|
if (eq >= 0) { myDFPlayer.EQ(eq); Serial.print(F("eq ")); Serial.println(arg1); }
|
||||||
|
else Serial.println(F("usage: eq normal|pop|rock|jazz|classic|bass"));
|
||||||
|
}
|
||||||
|
else if (!strcmp(cmd, "reset")) {
|
||||||
|
myDFPlayer.reset();
|
||||||
|
Serial.println(F("reset - waiting ~2s"));
|
||||||
|
delay(2000);
|
||||||
|
myDFPlayer.volume(currentVolume);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Serial.print(F("unknown command: ")); Serial.println(cmd);
|
||||||
|
Serial.println(F("type 'help'"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printHelp()
|
||||||
|
{
|
||||||
|
Serial.println(F("--- DFPlayer console --------------------------------------"));
|
||||||
|
Serial.println(F(" play [n] play track n, or resume if no number"));
|
||||||
|
Serial.println(F(" pause pause playback"));
|
||||||
|
Serial.println(F(" resume resume playback"));
|
||||||
|
Serial.println(F(" stop stop playback"));
|
||||||
|
Serial.println(F(" next / prev skip track"));
|
||||||
|
Serial.println(F(" vol [n|up|down] set volume 0..30 (no arg = show)"));
|
||||||
|
Serial.println(F(" + / - volume up / down by 1"));
|
||||||
|
Serial.println(F(" loop [n] play track n on repeat"));
|
||||||
|
Serial.println(F(" folder <f> <n> play /ff/nnn.mp3"));
|
||||||
|
Serial.println(F(" eq <name> normal|pop|rock|jazz|classic|bass"));
|
||||||
|
Serial.println(F(" reset re-init the DFPlayer"));
|
||||||
|
Serial.println(F(" status state / volume / file counts"));
|
||||||
|
Serial.println(F(" help this list"));
|
||||||
|
Serial.println(F("----------------------------------------------------------"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void printStatus()
|
||||||
|
{
|
||||||
|
Serial.print(F("begin() ok : ")); Serial.println(dfOnline ? F("yes") : F("no"));
|
||||||
|
Serial.print(F("volume (shadow) : ")); Serial.println(currentVolume);
|
||||||
|
Serial.print(F("volume (device) : ")); Serial.println(myDFPlayer.readVolume());
|
||||||
|
Serial.print(F("state : ")); Serial.println(myDFPlayer.readState());
|
||||||
|
Serial.print(F("files on card : ")); Serial.println(myDFPlayer.readFileCounts());
|
||||||
|
Serial.print(F("current file : ")); Serial.println(myDFPlayer.readCurrentFileNumber());
|
||||||
|
}
|
||||||
|
|
||||||
void printDetail(uint8_t type, int value){
|
void printDetail(uint8_t type, int value){
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case TimeOut:
|
case TimeOut:
|
||||||
@@ -134,5 +264,4 @@ void printDetail(uint8_t type, int value){
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user