DFPlayer and Ardunio Jawdrino

Ok I have a working version of Jawdrino (as seen on YouTube but so old not I dont get a response) This is great project and I have successfully incorporated a DFPlayer to play .mp3 files. Im using a Arduino Nano.
This all works great however I have been unable to get the DFPlayer to wait to finish a track before playing the next. The basic code I am using to control the DFPlayer has a timer that I have not been able to program around to make this work properly. Looking over and trying several commands have not worked.


/***********************************************************
08-14-2016 Mike North This is a little proof of concept 
to make a servo move in sync with audio.
http://buttonbanger.com/?page_id=137
04-23-2023 DFriedl Incorporate DFRobot DFPlayer - A Mini MP3 Player For Arduino
https://wiki.dfrobot.com/DFPlayer_Mini_SKU_DFR0299#Connection_Diagram
Overall intent is a prop to play .mp3 files while moving a skull jaw
*******************/
#include "SoftRcPulseOut.h"

#include "SoftwareSerial.h"//from MP3mini
#include "DFRobotDFPlayerMini.h" //from MP3mini

#define TEST_PIN 5 //pin 5 set to ground will kick off the servo sweep test
int audio_value = 0;
long lastMsg = 0;
long sleepWindow = 300000; //if 5 minutes go by with no signal, then put the servos to bed
SoftRcPulseOut servo;
volatile boolean servosEnabled = false;
volatile boolean ledsOn = true;
volatile unsigned long currentTime = 0;
volatile unsigned long lastLEDtime = 0;
unsigned long resetWait = 120000; //servos sleep if not changed within this time frame (120 secs)
int SPin3=A2;
int SVal3;

SoftwareSerial mySoftwareSerial(10, 11); // RX, TX  //from MP3mini
DFRobotDFPlayerMini myDFPlayer; //from MP3mini


void setup()
{
mySoftwareSerial.begin(9600);
  
  if (!myDFPlayer.begin(mySoftwareSerial)) {while(true); //Use softwareSerial to communicate with mp3
  }

	set_minmax();
	pinMode(TEST_PIN,INPUT);  //pin 5 will be 
	digitalWrite(TEST_PIN,HIGH); //assign pull-up resistor

  myDFPlayer.volume(27);  //Set volume value. From 0 to 30  //from MP3mini
  myDFPlayer.play(1);  //Play the first mp3  //from MP3mini

//Serial.begin (9600);  
} 


void loop()
{
///////////////////////////////////////////////////////////////////
//replace this timed play to one that waits for track to complete and advances to next
//also add 5sec delay before playing next track
//how to do this? Want to bypass timer and allow track to complete then play next.



  static unsigned long timer = millis(); //from MP3mini
  
  if (millis() - timer > 32000) //from MP3mini
  {
    timer = millis(); //from MP3mini
    myDFPlayer.next();  //Play next mp3 every 10 seconds. //from MP3mini
  }
//////////////////////////////////////////////////////////////////////
SVal3=analogRead (SPin3);    
Serial.println(SVal3);

  servo_test();
  audio_updates(); //read sample from audio input and apply average to buffer
  if(servosEnabled) 
  {
	action(); //servos are handled in the action loop
	SoftRcPulseOut::refresh();
	if((millis() - lastMsg) > sleepWindow)
	  detach_servos();
  }
} 
void attach_servos()
{   // attach the pin to the servo object
    servo.attach(2);
    servosEnabled = true;
}
void detach_servos()
{   // detach the servo objects
    servo.detach();
    servosEnabled = false;
}
void servo_test()
{
	if(digitalRead(TEST_PIN) == HIGH) return;
	attach_servos();
	SoftRcPulseOut::refresh();
	for(int i = 0; i < 360;i++)
	{
		if(i < 180)
			audio_value = i;
		else
			audio_value = 359 - i;
		action();
		for(int i = 0; i < 10; i++)
		{
		   delay(1); 
		   SoftRcPulseOut::refresh();
		}
	}
	detach_servos();
}
void audio_updates()
{
	audio_value = 0;
	if(analogRead(A0) < 341) audio_value += 60;
	if(analogRead(A1) < 341) audio_value += 60;
	if(analogRead(A2) < 341) audio_value += 60;

	if(audio_value > 0) 
	{
		lastMsg = millis(); //save the time stamp from when we last had some action
		if(!servosEnabled)attach_servos();
	}
}
void action() { 
  if (!servosEnabled) attach_servos();
  servo.write(audio_value);
  SoftRcPulseOut::refresh();
} 
void set_minmax()
{
	//set the first parameter in the following functions to a number between 0 and 180.
	//I used 92 and 72 in my tests to give about 20 degrees of motion.
	//You may swap the large and small numbers to reverse direction.
	//Just play with them, upload the code, then ground pin 11 to run the sweep test.
	// Be sure to only play with these numbers while the jaw linkage is disconnected,
	//  otherwise, you risk hitting mechanical limits and damaging your linkage or servo!
	servo.setMinimumPulse(map(48,0,180,512,2400));
	servo.setMaximumPulse(map(80,0,180,512,2400));
}


To learn how to post your code and include images, you could start with reading How to get the best out of this forum, which explains all that and more.

You didn't mention which DFPlayer you're using, but if it's a Mini, it has a BUSY pin. You might want to ponder what use you could make of that.

1 Like

Ahh yes. Your correct..a re-read was needed.
Yes Im using a DFPlayer mini.
...and yes I did make some attempts using the BUSY pin but my inexperience with this held me back.
The code should now be listed.

Sooo. I was able to find a sketch with help from "markd833" for using the BUSY port on the DFPlayerMini. Thanks again for this help.
At this point I have carefully tried to copy and paste the content of the BUSY sketch I now have into the "jawduino" sketch. While I dont see any errors the servo will not move however the MP3 files play correctly.

Below is my latest attempt at getting this going. The only thing Im trying to do here is to remove the timed MP3 play time so it will play various file times to completion with a set delay between each track.

Any help appreciated.

///  Test3 combining jawduino and  DFPlayerMini BUSY sketches

#include "SoftRcPulseOut.h"
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"


int audio_value = 0;
long lastMsg = 0;
long sleepWindow = 300000; //if 5 minutes go by with no signal, then put the servos to bed
SoftRcPulseOut servo;
volatile boolean servosEnabled = false;
volatile boolean ledsOn = true;
volatile unsigned long currentTime = 0;
volatile unsigned long lastLEDtime = 0;
unsigned long resetWait = 120000; //servos sleep if not changed within this time frame (120 secs)
int SPin3=A2;
int SVal3;
SoftwareSerial mySoftwareSerial(10, 11); // RX, TX
DFRobotDFPlayerMini myDFPlayer;
#define BUSY_PIN 8
int busyState = 0;
int prevBusyState = 0;

void setup()
{
  mySoftwareSerial.begin(9600);
 
  
  if (!myDFPlayer.begin(mySoftwareSerial)) { while(true); //Use softwareSerial to communicate with mp3.
   //set_minmax();

    
    {
      delay(0); // Code to compatible with ESP8266 watch dog.
    }
  }

  myDFPlayer.volume(18);  //Set volume value. From 0 to 30
  delay(500);
  myDFPlayer.next();

  // assume we need a delay to give the player time to start playing the initial track
  delay( 1000 );

  // initialise the BUSY states
  busyState = digitalRead( BUSY_PIN );
  prevBusyState = busyState;
}



void loop()
{
  // copy the state of the BUSY pin onto the UNO built-in LED
  busyState = digitalRead( BUSY_PIN );
 

  // has the player BUSY pin changed state?
  if ( busyState != prevBusyState ) {
    // state change - has the player stopped playing?
    if ( busyState == HIGH ) 
    {
      // stopped playing so wait xx seconds and then start the next track
      delay( 5000 );
      myDFPlayer.next();  
    }
    prevBusyState = busyState;
  }
  // reduce the delay between checks of the BUSY pin
  delay( 1000 );
SVal3=analogRead (SPin3);    
Serial.println(SVal3);

  //servo_test();
  audio_updates(); //read sample from audio input and apply average to buffer
  if(servosEnabled) 
  {
	action(); //servos are handled in the action loop
	SoftRcPulseOut::refresh();
	if((millis() - lastMsg) > sleepWindow)
	  detach_servos();
 }
} 
void attach_servos()
{   // attach the pin to the servo object
    servo.attach(2);
    servosEnabled = true;
}
void detach_servos()
{   // detach the servo objects
    servo.detach();
    servosEnabled = false;
}
//void servo_test()
//{
	//if(digitalRead(TEST_PIN) == HIGH) return;
	//attach_servos();
	//SoftRcPulseOut::refresh();
	//for(int i = 0; i < 360;i++)
	//{
		//if(i < 180)
			//audio_value = i;
		//else
			//audio_value = 359 - i;
		//action();
		//for(int i = 0; i < 10; i++)
		//{
		  // delay(1); 
		  // SoftRcPulseOut::refresh();
		//}
	//}
	//detach_servos();
//}
void audio_updates()
{
	audio_value = 0;
	if(analogRead(A0) < 341) audio_value += 60;
	if(analogRead(A1) < 341) audio_value += 60;
	if(analogRead(A2) < 341) audio_value += 60;

	if(audio_value > 0) 
	{
		lastMsg = millis(); //save the time stamp from when we last had some action
		if(!servosEnabled)attach_servos();
	}
}
void action() { 
  if (!servosEnabled) attach_servos();
  servo.write(audio_value);
  SoftRcPulseOut::refresh();
  detach_servos();
} 
void set_minmax()
{
	//set the first parameter in the following functions to a number between 0 and 180.
	//I used 92 and 72 in my tests to give about 20 degrees of motion.
	//You may swap the large and small numbers to reverse direction.
	//Just play with them, upload the code, then ground pin 11 to run the sweep test.
	// Be sure to only play with these numbers while the jaw linkage is disconnected,
	//  otherwise, you risk hitting mechanical limits and damaging your linkage or servo!
	servo.setMinimumPulse(map(48,0,180,512,2400));
	servo.setMaximumPulse(map(80,0,180,512,2400));
}

In the end I ren out of time trying to get the "BUSY" connection to work with this sketch however with a few minor edits to the .mp3 files this now is working better. Since some of the .mp3 files were much shorter than others it now kind of mimics a random play which other liked....go figure.
Ill try again at getting the BUSY pin working with the DFPlayer mini and the Aduino nano another time.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.