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
|
||||
<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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user