Go Down

Topic: New and Improved DFPlayer Mini Library!! (Read 23760 times) previous topic - next topic

stevestrong

Right, the order in which the files are added gives the file index in FAT.

stevestrong

#31
Jul 07, 2019, 11:33 am Last Edit: Jul 07, 2019, 11:50 am by stevestrong
I reworked (optimized) the lib, added some functions (stop, waitEndOfTrack, trackGetNr) and packed everything in only one header file, see attachment.

Dependency: Arduino Streaming (https://github.com/geneReeves/ArduinoStreaming/blob/master/Streaming.h)

Thee_Captain

Can this library be found in the Arduino IDE: Library Manager or must it be manually installed by downloading it from Github? Thanks for the help.
Throw a little karma my way. What goes around comes around.

Power_Broker

"The desire that guides me in all I do is the desire to harness the forces of nature to the service of mankind."
   - Nikola Tesla

Agatsuma

#34
Nov 27, 2019, 11:46 pm Last Edit: Nov 28, 2019, 12:07 am by Agatsuma
Strange thing. loop function do nothing. 0_o. Play works, but Loop do nothing. When run same code (simple begin and loop) everything works.

UPDATE. Strange, but it dont work in setup(), in loop() it works. 0_0

Power_Broker

Quite interesting indeed...

Can you post your code before and after working?
"The desire that guides me in all I do is the desire to harness the forces of nature to the service of mankind."
   - Nikola Tesla

Agatsuma

Now for some reason not Play nor Loop dont work. I have files from 0001.wav to 0005.wav in root and in mp3 folder. If I change library to DFRobot's and dont change anything else then sound plays. But with your library it wont.

Code: [Select]
#include <DFPlayerMini_Fast.h>

#include <MPU6050.h>

#include <SoftwareSerial.h>

#include "Wire.h"

#include "BladeHacking.h"

SoftwareSerial ss(4,5);

const int MPU_ADDR = 0x68;

int16_t accel_x, accel_y, accel_z, gyro_x, gyro_y, gyro_z, temp;
float averageGyroX,averageGyroY,averageGyroZ;

MPU6050 MyGyro(MPU_ADDR);
DFPlayerMini_Fast myDFPlayer;
BladeHacking bladeHack;



#define Idle 1
#define Swing 2
#define Hit 3
#define Opening 4
#define Closing 5

#define SWITCH_PIN 10

void setup() {       
 
  pinMode(10,INPUT_PULLUP);
 
  Serial.begin(9600);
  ss.begin(9600);

 
  pinMode(6, OUTPUT);
  digitalWrite(6, HIGH);

  //delay(2000);
 
  pinMode(8, OUTPUT);
  digitalWrite(BLADE_DATA_PIN, SIG_IDLE);
  bladeHack.send_sig( SIG_CMD_OFF );
  delay(1000);

 
 
  Wire.begin();
 
  MyGyro.initialize();
  MyGyro.setFullScaleGyroRange(MPU6050_GYRO_FS_2000);
  MyGyro.setFullScaleAccelRange(MPU6050_ACCEL_FS_4);
  MyGyro.setAccelerometerPowerOnDelay(3);
  MyGyro.setInterruptMode(true);
  MyGyro.setInterruptLatch(0);
  MyGyro.setIntMotionEnabled(true);
  MyGyro.setDHPFMode(1);
  MyGyro.setMotionDetectionThreshold(3);
  MyGyro.setMotionDetectionDuration(40);

  attachInterrupt(0,DetectedMotion, RISING);
 
 
  bool connectedToPlayer = false;
  while(!connectedToPlayer){
    connectedToPlayer = myDFPlayer.begin(ss);
  }
  Serial.println("Connected to player");
 
  myDFPlayer.volume(30);

  delay(100);
}


void DetectedMotion(){

  Serial.println("Detected motion. Detaching interrupt");
  detachInterrupt(0);
 
}

float getGlobalAccel(){

  MyGyro.getAcceleration(&accel_x,&accel_y,&accel_z);
  float ax = 1.0*(accel_x+1820)/8196;
  float ay = 1.0*(accel_y+4450)/8196;
  float az = 1.0*(accel_z+250)/8196;

  return abs(sqrt(ax*ax+ay*ay+az*az) - 1.0);
 
}

float getGlobalRot(){

  MyGyro.getRotation(&gyro_x,&gyro_y,&gyro_z);
  float gx = 1.0*(gyro_x+45)/16.4;
  float gy = 1.0*(gyro_y+55)/16.4;
  float gz = 1.0*(gyro_z+40)/16.4;

  return sqrt(gx*gx+gy*gy+gz*gz);
 
}

bool bladeOn = false;
bool isOpening = false;
bool isClosing = false;
bool isSwing = false;
bool isHit = false;
bool isLooping = false;
bool moving=false;


float minD=100000;
float maxD = 0;

float zeroMotionTimer=0;

float soundTimer=0;
float startMillis=0;

int playingSound = Idle;

void loop() {
 
  bladeHack.red_breath();
 
//  rot thres 350
//  accel thres 0.3-0.35

  if(digitalRead(SWITCH_PIN) == LOW && !bladeOn && playingSound != Opening)
  {
    //bladeOn=true;
    myDFPlayer.play(1);
    playingSound = Opening;
    soundTimer = 1826;
    startMillis = millis();
  }
 
  if(digitalRead(SWITCH_PIN) == HIGH && bladeOn)
  {
    bladeOn=false;
    myDFPlayer.play(2);
  }

  if(playingSound == Opening && millis()-startMillis > soundTimer){

    myDFPlayer.loop(3);
    playingSound = Idle;
    soundTimer = 300;
    startMillis = millis();
    bladeOn = true;
  }
 
  if(bladeOn)
  {
    float globalAcc = getGlobalAccel();
    //Serial.println(globalAcc);
    if(globalAcc>3.1 && playingSound != Hit){
      myDFPlayer.play(5);
      playingSound = Hit;
      soundTimer = 543;
      startMillis = millis();
    }
    else if(playingSound == Idle &&(getGlobalRot()>350 || globalAcc>0.33))
    {
      myDFPlayer.play(4);
      playingSound = Swing;
      soundTimer = 633;
      startMillis = millis();
    }
    else if(millis()-startMillis > soundTimer && playingSound != Idle)
    {
      myDFPlayer.loop(3);
      playingSound = Idle;
      soundTimer = 300;
      startMillis = millis();
    }
  }
}

Power_Broker

I went ahead an reformatted your code so that it is a little more organized. I tried to compile it, but I couldn't find the "BladeHacking.h" library anywhere in GitHub, so you'll have to do the compile-time testing:
Code: [Select]
#include <DFPlayerMini_Fast.h>
#include <MPU6050.h>
#include <SoftwareSerial.h>
#include "Wire.h"
#include "BladeHacking.h"


#define Idle 1
#define Swing 2
#define Hit 3
#define Opening 4
#define Closing 5
#define SWITCH_PIN 10


SoftwareSerial ss(4,5);
MPU6050 MyGyro(MPU_ADDR);
DFPlayerMini_Fast myDFPlayer;
BladeHacking bladeHack;


const int MPU_ADDR = 0x68;
int16_t accel_x, accel_y, accel_z, gyro_x, gyro_y, gyro_z, temp;
float averageGyroX,averageGyroY,averageGyroZ;

bool bladeOn = false;
bool isOpening = false;
bool isClosing = false;
bool isSwing = false;
bool isHit = false;
bool isLooping = false;
bool moving=false;

float minD=100000;
float maxD = 0;

float zeroMotionTimer=0;

float soundTimer=0;
float startMillis=0;

int playingSound = Idle;


void setup()
{
  pinMode(10,INPUT_PULLUP);
  pinMode(6, OUTPUT);
  digitalWrite(6, HIGH);
  pinMode(8, OUTPUT);
  digitalWrite(BLADE_DATA_PIN, SIG_IDLE);
  
  Serial.begin(9600);
  ss.begin(9600);
  Wire.begin();
  bladeHack.send_sig(SIG_CMD_OFF);
  delay(1000);
 
  MyGyro.initialize();
  MyGyro.setFullScaleGyroRange(MPU6050_GYRO_FS_2000);
  MyGyro.setFullScaleAccelRange(MPU6050_ACCEL_FS_4);
  MyGyro.setAccelerometerPowerOnDelay(3);
  MyGyro.setInterruptMode(true);
  MyGyro.setInterruptLatch(0);
  MyGyro.setIntMotionEnabled(true);
  MyGyro.setDHPFMode(1);
  MyGyro.setMotionDetectionThreshold(3);
  MyGyro.setMotionDetectionDuration(40);

  attachInterrupt(0, DetectedMotion, RISING);
  
  bool connectedToPlayer = myDFPlayer.begin(ss);
  while(!connectedToPlayer)
    connectedToPlayer = myDFPlayer.begin(ss);
  Serial.println("Connected to player");
 
  myDFPlayer.volume(30);
  delay(100);
}


void loop()
{
  bladeHack.red_breath();
 
//  rot thres 350
//  accel thres 0.3-0.35

  if(digitalRead(SWITCH_PIN) == LOW && !bladeOn && playingSound != Opening)
  {
    //bladeOn=true;
    myDFPlayer.play(1);
    playingSound = Opening;
    soundTimer = 1826;
    startMillis = millis();
  }
 
  if(digitalRead(SWITCH_PIN) == HIGH && bladeOn)
  {
    bladeOn=false;
    myDFPlayer.play(2);
  }

  if(playingSound == Opening && millis()-startMillis > soundTimer){

    myDFPlayer.loop(3);
    playingSound = Idle;
    soundTimer = 300;
    startMillis = millis();
    bladeOn = true;
  }
 
  if(bladeOn)
  {
    float globalAcc = getGlobalAccel();
    //Serial.println(globalAcc);
    if(globalAcc>3.1 && playingSound != Hit){
      myDFPlayer.play(5);
      playingSound = Hit;
      soundTimer = 543;
      startMillis = millis();
    }
    else if(playingSound == Idle &&(getGlobalRot()>350 || globalAcc>0.33))
    {
      myDFPlayer.play(4);
      playingSound = Swing;
      soundTimer = 633;
      startMillis = millis();
    }
    else if(millis()-startMillis > soundTimer && playingSound != Idle)
    {
      myDFPlayer.loop(3);
      playingSound = Idle;
      soundTimer = 300;
      startMillis = millis();
    }
  }
}


void DetectedMotion()
{
  Serial.println("Detected motion. Detaching interrupt");
  detachInterrupt(0);
}


float getGlobalAccel()
{
  MyGyro.getAcceleration(&accel_x,&accel_y,&accel_z);
  
  float ax = 1.0*(accel_x+1820)/8196;
  float ay = 1.0*(accel_y+4450)/8196;
  float az = 1.0*(accel_z+250)/8196;

  return abs(sqrt(ax*ax + ay*ay + az*az) - 1.0);
}


float getGlobalRot()
{
  MyGyro.getRotation(&gyro_x,&gyro_y,&gyro_z);
  
  float gx = 1.0*(gyro_x+45)/16.4;
  float gy = 1.0*(gyro_y+55)/16.4;
  float gz = 1.0*(gyro_z+40)/16.4;

  return sqrt(gx*gx + gy*gy + gz*gz);
}






As for the library, I've double checked everything and it all checks out. It might be an issue with how you've saved your files to the SD card. A couple of things to note:

1.) Filenames do not matter - the track numbers with respect to the library are based solely on the order in which the files were saved to the SD card
2.) The folder structure of the SD card matters. Tbh, I forget exactly how it's supposed to be structured (I think you need to save all of your MP3s to a folder named "mp3" in the root directory)


Can you post the exact contents of your SD card in a zip file?
"The desire that guides me in all I do is the desire to harness the forces of nature to the service of mankind."
   - Nikola Tesla

Agatsuma

I went ahead an reformatted your code so that it is a little more organized. I tried to compile it, but I couldn't find the "BladeHacking.h" library anywhere in GitHub, so you'll have to do the compile-time testing:
Code: [Select]
#include <DFPlayerMini_Fast.h>
#include <MPU6050.h>
#include <SoftwareSerial.h>
#include "Wire.h"
#include "BladeHacking.h"


#define Idle 1
#define Swing 2
#define Hit 3
#define Opening 4
#define Closing 5
#define SWITCH_PIN 10


SoftwareSerial ss(4,5);
MPU6050 MyGyro(MPU_ADDR);
DFPlayerMini_Fast myDFPlayer;
BladeHacking bladeHack;


const int MPU_ADDR = 0x68;
int16_t accel_x, accel_y, accel_z, gyro_x, gyro_y, gyro_z, temp;
float averageGyroX,averageGyroY,averageGyroZ;

bool bladeOn = false;
bool isOpening = false;
bool isClosing = false;
bool isSwing = false;
bool isHit = false;
bool isLooping = false;
bool moving=false;

float minD=100000;
float maxD = 0;

float zeroMotionTimer=0;

float soundTimer=0;
float startMillis=0;

int playingSound = Idle;


void setup()
{
  pinMode(10,INPUT_PULLUP);
  pinMode(6, OUTPUT);
  digitalWrite(6, HIGH);
  pinMode(8, OUTPUT);
  digitalWrite(BLADE_DATA_PIN, SIG_IDLE);
 
  Serial.begin(9600);
  ss.begin(9600);
  Wire.begin();
  bladeHack.send_sig(SIG_CMD_OFF);
  delay(1000);
 
  MyGyro.initialize();
  MyGyro.setFullScaleGyroRange(MPU6050_GYRO_FS_2000);
  MyGyro.setFullScaleAccelRange(MPU6050_ACCEL_FS_4);
  MyGyro.setAccelerometerPowerOnDelay(3);
  MyGyro.setInterruptMode(true);
  MyGyro.setInterruptLatch(0);
  MyGyro.setIntMotionEnabled(true);
  MyGyro.setDHPFMode(1);
  MyGyro.setMotionDetectionThreshold(3);
  MyGyro.setMotionDetectionDuration(40);

  attachInterrupt(0, DetectedMotion, RISING);
 
  bool connectedToPlayer = myDFPlayer.begin(ss);
  while(!connectedToPlayer)
    connectedToPlayer = myDFPlayer.begin(ss);
  Serial.println("Connected to player");
 
  myDFPlayer.volume(30);
  delay(100);
}


void loop()
{
  bladeHack.red_breath();
 
//  rot thres 350
//  accel thres 0.3-0.35

  if(digitalRead(SWITCH_PIN) == LOW && !bladeOn && playingSound != Opening)
  {
    //bladeOn=true;
    myDFPlayer.play(1);
    playingSound = Opening;
    soundTimer = 1826;
    startMillis = millis();
  }
 
  if(digitalRead(SWITCH_PIN) == HIGH && bladeOn)
  {
    bladeOn=false;
    myDFPlayer.play(2);
  }

  if(playingSound == Opening && millis()-startMillis > soundTimer){

    myDFPlayer.loop(3);
    playingSound = Idle;
    soundTimer = 300;
    startMillis = millis();
    bladeOn = true;
  }
 
  if(bladeOn)
  {
    float globalAcc = getGlobalAccel();
    //Serial.println(globalAcc);
    if(globalAcc>3.1 && playingSound != Hit){
      myDFPlayer.play(5);
      playingSound = Hit;
      soundTimer = 543;
      startMillis = millis();
    }
    else if(playingSound == Idle &&(getGlobalRot()>350 || globalAcc>0.33))
    {
      myDFPlayer.play(4);
      playingSound = Swing;
      soundTimer = 633;
      startMillis = millis();
    }
    else if(millis()-startMillis > soundTimer && playingSound != Idle)
    {
      myDFPlayer.loop(3);
      playingSound = Idle;
      soundTimer = 300;
      startMillis = millis();
    }
  }
}


void DetectedMotion()
{
  Serial.println("Detected motion. Detaching interrupt");
  detachInterrupt(0);
}


float getGlobalAccel()
{
  MyGyro.getAcceleration(&accel_x,&accel_y,&accel_z);
 
  float ax = 1.0*(accel_x+1820)/8196;
  float ay = 1.0*(accel_y+4450)/8196;
  float az = 1.0*(accel_z+250)/8196;

  return abs(sqrt(ax*ax + ay*ay + az*az) - 1.0);
}


float getGlobalRot()
{
  MyGyro.getRotation(&gyro_x,&gyro_y,&gyro_z);
 
  float gx = 1.0*(gyro_x+45)/16.4;
  float gy = 1.0*(gyro_y+55)/16.4;
  float gz = 1.0*(gyro_z+40)/16.4;

  return sqrt(gx*gx + gy*gy + gz*gz);
}






As for the library, I've double checked everything and it all checks out. It might be an issue with how you've saved your files to the SD card. A couple of things to note:

1.) Filenames do not matter - the track numbers with respect to the library are based solely on the order in which the files were saved to the SD card
2.) The folder structure of the SD card matters. Tbh, I forget exactly how it's supposed to be structured (I think you need to save all of your MP3s to a folder named "mp3" in the root directory)


Can you post the exact contents of your SD card in a zip file?
Blade hacking can be comented out with BladeHacking bladeHack; and all it method executions. It dont affect that situation. And problem is not that I cant play anything, but that I cant play anything using your library. Using DFRobot's library it plays like it should. I enden up using code to send commands directly, without any library.

stevestrong

You may try my header file posted here: https://forum.arduino.cc/index.php?topic=513128.msg4233655#msg4233655

Power_Broker

#40
Dec 06, 2019, 11:27 pm Last Edit: Dec 06, 2019, 11:31 pm by Power_Broker
I just want to point out that I tested the library as it stands today and it currently plays/loops file (etc) exactly as it should.

If anyone can't get their sketches to work in the future, please post:
- Your entire sketch
- Full wiring schematic (an additional set of pictures of your wiring is also a plus)
- File contents of your SD card
"The desire that guides me in all I do is the desire to harness the forces of nature to the service of mankind."
   - Nikola Tesla

Power_Broker

#41
Dec 07, 2019, 03:49 am Last Edit: Dec 07, 2019, 03:49 am by Power_Broker
***Update***

I did some work upgrading the library - now all DFPlayerMini commands and queries are supported by the library!

I literally just tagged the new release, so I expect the changes to be reflected in the IDE's libraries manager in a few hours. Either way, you can always get the latest version from the GitHub repo.

Here's the API listing for the library:
Code: [Select]
bool begin(Stream& stream);

void playNext();
void playPrevious();
void play(uint16_t trackNum);
void incVolume();
void decVolume();
void volume(uint8_t volume);
void EQSelect(uint8_t setting);
void loop(uint16_t trackNum);
void playbackSource(uint8_t source);
void standbyMode();
void normalMode();
void reset();
void resume();
void pause();
void playFolder(uint8_t folderNum, uint8_t trackNum);
void volumeAdjustSet(uint8_t gain);
void startRepeatPlay();
void stopRepeatPlay();
void playFromMP3Folder(uint16_t trackNum);
void repeatFolder(uint16_t folder);
void randomAll();
void startRepeat();
void stopRepeat();
void startDAC();
void stopDAC();
void sleep();
void wakeUp();

bool isPlaying();
int16_t currentVolume();
int16_t currentEQ();
int16_t currentMode();
int16_t currentVersion();
int16_t numUsbTracks();
int16_t numSdTracks();
int16_t numFlashTracks();
int16_t currentUsbTrack();
int16_t currentSdTrack();
int16_t currentFlashTrack();
int16_t numTracksInFolder(uint8_t folder);
int16_t numFolders();

void findChecksum(stack *_stack);
void sendData();
void flush();
int16_t query(uint8_t cmd, uint8_t msb=0, uint8_t lsb=0);
bool getStatus(uint8_t cmd);
bool parseFeedback();
bool timeout();

void printStack(stack _stack);



Please let me know if you have any problems or run into any bugs!


"The desire that guides me in all I do is the desire to harness the forces of nature to the service of mankind."
   - Nikola Tesla

Power_Broker

#42
Dec 07, 2019, 06:26 pm Last Edit: Dec 07, 2019, 06:26 pm by Power_Broker
Also, if you want to send custom packets or parse response packets (from the DFPlayer) if your sketch, you can use the following structs; sendStack and recStack:

Code: [Select]
struct stack {
 uint8_t start_byte;
 uint8_t version;
 uint8_t length;
 uint8_t commandValue;
 uint8_t feedbackValue;
 uint8_t paramMSB;
 uint8_t paramLSB;
 uint8_t checksumMSB;
 uint8_t checksumLSB;
 uint8_t end_byte;
 } sendStack, recStack;



Each member of the structs can be accessed directly in your sketch. Also, you can pass a stack struct pointer to
Code: [Select]
void findChecksum(stack *_stack);
 to automatically find and insert the correct checksum into your stack. To automatically send the contents of sendStack to the DFPlayer to make a command or query, simply call
Code: [Select]
void sendData();
. When parsing a response to the recStack struct, just call
Code: [Select]
bool parseFeedback();
 and the DFPlayer's response will automatically load into recStack. Your sketch can then access each member of recStack directly for processing.

To print the contents of any stack, call
Code: [Select]
void printStack(stack _stack);
"The desire that guides me in all I do is the desire to harness the forces of nature to the service of mankind."
   - Nikola Tesla

Go Up