Forum >DFPLayer reset and non repeat
DFPLayer reset and non repeat

I have a project where I am displaying the verses of a song on a TFT display while playing the song using the DFPlayer module. I'm using a Nano Every and a Adafruit 3.5" TFT display. I copied the logic for the DFPlayer from a example I found on YouTube, it does not use the DFPlayer library but sends the commands via SoftwareSerial. Everything works except 2 things I would like to add.
I only want to play the song once then stop until I reset the Nano. Looking in the play() function it does use the repeat play command, execute_CMD(0x11,0,1);. I tried commenting it out and changing the parameters but it either doesn't play the song or continues to repeat,
I also want to reset the player when I reset the Nano, I used the command execute_CMD(0x0C, 0, 1); in setup, but that also doesn't seem to work.
Here is my sketch
John
I only want to play the song once then stop until I reset the Nano. Looking in the play() function it does use the repeat play command, execute_CMD(0x11,0,1);. I tried commenting it out and changing the parameters but it either doesn't play the song or continues to repeat,
I also want to reset the player when I reset the Nano, I used the command execute_CMD(0x0C, 0, 1); in setup, but that also doesn't seem to work.
Here is my sketch
Code: Select all
Thanks for the help// mp3 player with TFT display // Cycles through circles, and verses sync'd with song // With Bit map image at end // added DFPlayer #include <SPI.h> #include "Adafruit_GFX.h" #include "Adafruit_HX8357.h" #include <SD.h> #include <SPI.h> // for mp3 player #include <SoftwareSerial.h> SoftwareSerial mySerial(3, 4); # define Start_Byte 0x7E # define Version_Byte 0xFF # define Command_Length 0x06 # define End_Byte 0xEF # define Acknowledge 0x00 //Returns info with command 0x41 [0x01: info, 0x00: no info] boolean isPlaying = false; # define ACTIVATED LOW // These are 'flexible' lines that can be changed #define TFT_CS 7 #define TFT_DC 9 #define TFT_RST 8 // RST can be set to -1 if you tie it to Arduino's reset #define SD_CS 10 // Color definitions #define BLACK 0x0000 #define BLUE 0x001F #define RED 0xF800 #define GREEN 0x07E0 #define CYAN 0x07FF #define MAGENTA 0xF81F #define YELLOW 0xFFE0 #define WHITE 0xFFFF #define MAX_BMP 10 // bmp file num #define FILENAME_LEN 20 //Max filename length File bmpfile; // Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC Adafruit_HX8357 tft = Adafruit_HX8357(TFT_CS, TFT_DC, TFT_RST); char *verse[] = {"zero", "one", "two", "three", "four"}; byte verseNumber = 1; const unsigned long verseChange = 2000; unsigned long markTime = millis(); unsigned long currentTime; long int test = 0; char *color[] = {BLACK, BLUE, RED, GREEN, CYAN, MAGENTA, YELLOW, WHITE}; byte colorNumber; int unsigned long verseDly[20]; int verseDlyIndx; void setup() { Serial.begin(9600); mySerial.begin (9600); delay(1000); // reset player execute_CMD(0x0C, 0, 1); delay(500); // start song play(); isPlaying = true; tft.begin(); tft.fillScreen(BLACK); //clears screen, sets to Black tft.setRotation(3); // rotates screen 90' for landscape mode tft.setTextSize(2); // delays between verses verseDlyIndx = 1; verseDly[1] = 23000; verseDly[2] = 27000; verseDly[3] = 37000; verseDly[4] = 28000; verseDly[5] = 27000; verseDly[6] = 15000; verseDly[7] = 11000; verseDly[8] = 32000; verseDly[9] = 32000; verseDly[10] = 1000; Serial.print("Initializing SD card..."); if (!SD.begin(SD_CS)) { Serial.println("failed!"); } else Serial.println("OK!"); //bmpDraw("sunrise2.bmp", 0, 0); } // end setup void loop() { // cycle through verses currentTime = millis(); //Serial.print("verseNumber ="); //Serial.print("\t"); //Serial.println(verse[verseNumber]); // fill screen with circles if(verseNumber == 1){ circles(); } // Verse delays if (((currentTime - markTime) > verseDly[verseDlyIndx]) && verseNumber <= 9) { verseNumber ++; verseDlyIndx ++; Serial.print(verseNumber); Serial.print("\t"); Serial.println(verseDlyIndx); switch (verseNumber) { case 1: tft.fillScreen(BLACK); //clears screen, sets to Black; circles(); markTime = millis(); break; case 2: tft.fillScreen(BLACK); //clears screen, sets to Black tft.setTextColor(BLUE); // Print verse 2 tft.setCursor(10, 70); tft.print("Every day is so wonderful"); tft.setCursor(10, 100); tft.print("Then suddenly it's hard to breathe"); tft.setCursor(10, 130); tft.print("Now and then I get insecure"); tft.setCursor(10, 160); tft.print("From all the pain"); tft.setCursor(10, 190); tft.print("I'm so ashamed"); markTime = millis(); break; case 3: tft.fillScreen(BLUE); //clears screen, sets to Black tft.setTextColor(WHITE); // Print verse 3 tft.setCursor(10, 70); tft.print("I am beautiful no matter what they say"); tft.setCursor(10, 100); tft.print("Words can't bring me down"); tft.setCursor(10, 130); tft.print("I am beautiful in every single way"); tft.setCursor(10, 160); tft.print("Yes, words can't bring me down, oh no"); tft.setCursor(10, 190); tft.print("So don't you bring me down today"); markTime = millis(); break; case 4: tft.fillScreen(RED); //clears screen, sets to Black tft.setTextColor(WHITE); // Print verse 4 tft.setCursor(10, 70); tft.print("To all your friends you're delirious"); tft.setCursor(10, 100); tft.print("So consumed in all your doom"); tft.setCursor(10, 130); tft.print("Trying hard to fill the emptiness"); tft.setCursor(10, 160); tft.print("The pieces gone, left the puzzle undone"); tft.setCursor(10, 190); tft.print("Is that the way it is?"); markTime = millis(); break; case 5: tft.fillScreen(GREEN); //clears screen, sets to Black tft.setTextColor(BLACK); // Print verse 5 tft.setCursor(10, 50); tft.print("You are so beautiful"); tft.setCursor(60, 70); tft.print("no matter what they say"); tft.setCursor(10, 100); tft.print("Words can't bring you down, oh no"); tft.setCursor(10, 130); tft.print("you are so beautiful"); tft.setCursor(60, 150); tft.print("in every single way"); tft.setCursor(10, 180); tft.print("Yes, words can't bring you down, oh no"); tft.setCursor(10, 210); tft.print("So don't you bring me down today"); markTime = millis(); break; case 6: tft.fillScreen(MAGENTA); //clears screen, sets to Black tft.setTextColor(BLACK); // Print verse 6 tft.setCursor(10, 70); tft.print("No matter what we do"); tft.setCursor(10, 100); tft.print("(No matter what we do)"); tft.setCursor(10, 130); tft.print("No matter what we say"); tft.setCursor(10, 160); tft.print("(No matter what we say)"); tft.setCursor(10, 190); tft.print("We're the song inside the tune (Yeah)"); tft.setCursor(10, 220); tft.print("Full of beautiful mistakes"); markTime = millis(); break; case 7: tft.fillScreen(CYAN); //clears screen, sets to Black tft.setTextColor(BLACK); // Print verse 7 tft.setCursor(10, 70); tft.print("And everywhere we go"); tft.setCursor(10, 100); tft.print("(And everywhere we go)"); tft.setCursor(10, 130); tft.print("The sun will always shine"); tft.setCursor(10, 160); tft.print("(The sun will always, always shine)"); tft.setCursor(10, 190); tft.print("And tomorrow we might wake up"); tft.setCursor(60, 210); tft.print("on the other side"); markTime = millis(); break; case 8: tft.fillScreen(YELLOW); //clears screen, sets to Black tft.setTextColor(BLACK); // Print verse 8 tft.setCursor(10, 50); tft.print("'cause we are beautiful"); tft.setCursor(60, 70); tft.print("no matter what they say"); tft.setCursor(10, 100); tft.print("Yes, words won't bring us down, no, no"); tft.setCursor(10, 130); tft.print("We are beautiful in every single way"); tft.setCursor(10, 160); tft.print("Yes, words won't bring us down, no, no"); tft.setCursor(10, 190); tft.print("So don't you bring me down today"); markTime = millis(); break; case 9: tft.fillScreen(WHITE); //clears screen, sets to Black tft.setTextColor(BLUE); // Print verse 9 tft.setCursor(10, 70); tft.print("Ooh-oh-oh,yeah"); tft.setCursor(10, 100); tft.print("Don't you bring me down today"); tft.setCursor(10, 130); tft.print("Yeah, ooh"); tft.setCursor(10, 160); tft.print("Don't you bring me down today"); tft.setCursor(10, 190); tft.print("Ooh,today"); markTime = millis(); break; case 10: Serial.println("case 10"); // print smilely sunrise bmpDraw("sunrise2.bmp", 0, 0); //markTime = millis(); break; default: tft.fillScreen(BLACK); //clears screen, sets to Black } // end switch } // end ((currentTime - markTime)) } // end loop void circles() { tft.fillCircle(random(0,480), random(0,320), random(10, 40), color[random(1, 8)]); delay(250); } // end void circles #define BUFFPIXEL 20 void bmpDraw(char *filename, uint8_t x, uint16_t y) { File bmpFile; int bmpWidth, bmpHeight; // W+H in pixels uint8_t bmpDepth; // Bit depth (currently must be 24) uint32_t bmpImageoffset; // Start of image data in file uint32_t rowSize; // Not always = bmpWidth; may have padding uint8_t sdbuffer[3*BUFFPIXEL]; // pixel buffer (R+G+B per pixel) uint8_t buffidx = sizeof(sdbuffer); // Current position in sdbuffer boolean goodBmp = false; // Set to true on valid header parse boolean flip = true; // BMP is stored bottom-to-top int w, h, row, col; uint8_t r, g, b; uint32_t pos = 0, startTime = millis(); if((x >= tft.width()) || (y >= tft.height())) return; Serial.println(); Serial.print(F("Loading image '")); Serial.print(filename); Serial.println('\''); // Open requested file on SD card if ((bmpFile = SD.open(filename)) == NULL) { Serial.print(F("File not found")); return; } // Parse BMP header if(read16(bmpFile) == 0x4D42) { // BMP signature Serial.print(F("File size: ")); Serial.println(read32(bmpFile)); (void)read32(bmpFile); // Read & ignore creator bytes bmpImageoffset = read32(bmpFile); // Start of image data Serial.print(F("Image Offset: ")); Serial.println(bmpImageoffset, DEC); // Read DIB header Serial.print(F("Header size: ")); Serial.println(read32(bmpFile)); bmpWidth = read32(bmpFile); bmpHeight = read32(bmpFile); if(read16(bmpFile) == 1) { // # planes -- must be '1' bmpDepth = read16(bmpFile); // bits per pixel Serial.print(F("Bit Depth: ")); Serial.println(bmpDepth); if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed goodBmp = true; // Supported BMP format -- proceed! Serial.print(F("Image size: ")); Serial.print(bmpWidth); Serial.print('x'); Serial.println(bmpHeight); // BMP rows are padded (if needed) to 4-byte boundary rowSize = (bmpWidth * 3 + 3) & ~3; // If bmpHeight is negative, image is in top-down order. // This is not canon but has been observed in the wild. if(bmpHeight < 0) { bmpHeight = -bmpHeight; flip = false; } // Crop area to be loaded w = bmpWidth; h = bmpHeight; if((x+w-1) >= tft.width()) w = tft.width() - x; if((y+h-1) >= tft.height()) h = tft.height() - y; // Set TFT address window to clipped image bounds tft.startWrite(); // Start TFT transaction tft.setAddrWindow(x, y, w, h); for (row=0; row<h; row++) { // For each scanline... // Seek to start of scan line. It might seem labor- // intensive to be doing this on every line, but this // method covers a lot of gritty details like cropping // and scanline padding. Also, the seek only takes // place if the file position actually needs to change // (avoids a lot of cluster math in SD library). if(flip) // Bitmap is stored bottom-to-top order (normal BMP) pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize; else // Bitmap is stored top-to-bottom pos = bmpImageoffset + row * rowSize; if(bmpFile.position() != pos) { // Need seek? tft.endWrite(); // End TFT transaction bmpFile.seek(pos); buffidx = sizeof(sdbuffer); // Force buffer reload tft.startWrite(); // Start new TFT transaction } for (col=0; col<w; col++) { // For each pixel... // Time to read more pixel data? if (buffidx >= sizeof(sdbuffer)) { // Indeed tft.endWrite(); // End TFT transaction bmpFile.read(sdbuffer, sizeof(sdbuffer)); buffidx = 0; // Set index to beginning tft.startWrite(); // Start new TFT transaction } // Convert pixel from BMP to TFT format, push to display b = sdbuffer[buffidx++]; g = sdbuffer[buffidx++]; r = sdbuffer[buffidx++]; tft.pushColor(tft.color565(r,g,b)); } // end pixel } // end scanline tft.endWrite(); // End last TFT transaction Serial.print(F("Loaded in ")); Serial.print(millis() - startTime); Serial.println(" ms"); } // end goodBmp } } bmpFile.close(); if(!goodBmp) Serial.println(F("BMP format not recognized.")); } // These read 16- and 32-bit types from the SD card file. // BMP data is stored little-endian, Arduino is little-endian too. // May need to reverse subscript order if porting elsewhere. uint16_t read16(File &f) { uint16_t result; ((uint8_t *)&result)[0] = f.read(); // LSB ((uint8_t *)&result)[1] = f.read(); // MSB return result; } uint32_t read32(File &f) { uint32_t result; ((uint8_t *)&result)[0] = f.read(); // LSB ((uint8_t *)&result)[1] = f.read(); ((uint8_t *)&result)[2] = f.read(); ((uint8_t *)&result)[3] = f.read(); // MSB return result; } void playFirst() { execute_CMD(0x3F, 0, 0); delay(500); setVolume(20); delay(500); execute_CMD(0x11,0,1); delay(500); }// end playFirst void setVolume(int volume) { execute_CMD(0x06, 0, volume); // Set the volume (0x00~0x30) delay(2000); } void execute_CMD(byte CMD, byte Par1, byte Par2) // Excecute the command and parameters { // Calculate the checksum (2 bytes) word checksum = -(Version_Byte + Command_Length + CMD + Acknowledge + Par1 + Par2); // Build the command line byte Command_line[10] = { Start_Byte, Version_Byte, Command_Length, CMD, Acknowledge, Par1, Par2, highByte(checksum), lowByte(checksum), End_Byte}; //Send the command line to the module for (byte k=0; k<10; k++) { mySerial.write( Command_line[k]); } } void play() { execute_CMD(0x3F, 0, 0); delay(500); setVolume(5); delay(500); execute_CMD(0x11,0,1); delay(500); }
John