XIAO DFPlayer: replace demo loop with serial command console (play/pause/stop/next/vol/loop/folder/eq/reset/status)

This commit is contained in:
zyphlar
2026-09-10 00:27:19 -07:00
parent 16dee110af
commit 8629ba2d22
+176 -47
View File
@@ -1,80 +1,210 @@
/***************************************************
DFPlayer - A Mini MP3 Player For Arduino
<https://www.dfrobot.com/product-1121.html>
***************************************************
This example shows the basic function of library for DFPlayer.
Created 2016-12-07
By [Angelo qiao](Angelo.qiao@dfrobot.com)
GNU Lesser General Public License.
See <http://www.gnu.org/licenses/> for details.
All above must be included in any redistribution
****************************************************/
DFPlayer Mini - serial console control (Seeed XIAO nRF52840)
/***********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.
Hardware Serial1 link to the DFPlayer Mini:
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.
Open the Serial Monitor at 115200 baud, line ending = Newline, and type
commands (see "help"). Based on the DFRobot DFPlayerMini example (LGPL).
****************************************************/
#include "Arduino.h"
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include "DFRobotDFPlayerMini.h"
//#if (defined(ARDUINO_Seeed_XIAO_nRF52840_Sense))
#include <Adafruit_TinyUSB.h> // for Serial
#include <Adafruit_TinyUSB.h> // for Serial (USB CDC)
#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;
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 printHelp();
void printStatus();
void handleLine(char *line);
void setup()
{
// Open serial communications and wait for port to open:
Serial.begin(115200);
uint32_t t0 = millis();
while (!Serial && millis() - t0 < 3000) {
delay(10); // for nrf52840 with native usb
Serial.println(F("Initializing serial..."));
}
while (!Serial && millis() - t0 < 3000) delay(10); // headless-safe
FPSerial.begin(9600);
delay(1500); // let the DFPlayer boot
delay(1500); // let the DFPlayer boot
if (!myDFPlayer.begin(FPSerial, /*isACK=*/true, /*doReset=*/true)) {
Serial.println(F("DFPlayer not responding - check wiring / power / SD"));
delay(5000);
Serial.println(F("DFPlayer not responding - check wiring / power / SD"));
// fall through instead of hanging, so you can still debug
dfOnline = myDFPlayer.begin(FPSerial, /*isACK=*/true, /*doReset=*/true);
if (dfOnline) {
Serial.println(F("DFPlayer online."));
} else {
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);
myDFPlayer.play(1);
myDFPlayer.play(1); // play the first track on boot (optional)
printHelp();
Serial.print(F("> "));
}
void loop()
{
static unsigned long timer = millis();
if (millis() - timer > 3000) {
timer = millis();
myDFPlayer.next(); //Play next mp3 every 3 second.
// ---- read a line from the USB serial console ----
while (Serial.available()) {
char c = (char)Serial.read();
if (c == '\n' || c == '\r') {
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()) {
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){
switch (type) {
case TimeOut:
@@ -134,5 +264,4 @@ void printDetail(uint8_t type, int value){
default:
break;
}
}