//This is the code for the studdy buddy, note that the bread board mini is supposed to be the DF Player Mini
//DF PLayer Fuctions
/*
//----Set volume----
myDFPlayer.volume(10); //Set volume value (0~30).
myDFPlayer.volumeUp(); //Volume Up
myDFPlayer.volumeDown(); //Volume Down
//----Set different EQ----
myDFPlayer.EQ(DFPLAYER_EQ_NORMAL);
// myDFPlayer.EQ(DFPLAYER_EQ_POP);
// myDFPlayer.EQ(DFPLAYER_EQ_ROCK);
// myDFPlayer.EQ(DFPLAYER_EQ_JAZZ);
// myDFPlayer.EQ(DFPLAYER_EQ_CLASSIC);
// myDFPlayer.EQ(DFPLAYER_EQ_BASS);
//----Set device we use SD as default----
// myDFPlayer.outputDevice(DFPLAYER_DEVICE_U_DISK);
myDFPlayer.outputDevice(DFPLAYER_DEVICE_SD);
// myDFPlayer.outputDevice(DFPLAYER_DEVICE_AUX);
// myDFPlayer.outputDevice(DFPLAYER_DEVICE_SLEEP);
// myDFPlayer.outputDevice(DFPLAYER_DEVICE_FLASH);
//----Mp3 control----
// myDFPlayer.sleep(); //sleep
// myDFPlayer.reset(); //Reset the module
// myDFPlayer.enableDAC(); //Enable On-chip DAC
// myDFPlayer.disableDAC(); //Disable On-chip DAC
// myDFPlayer.outputSetting(true, 15); //output setting, enable the output and set the gain to 15
//----Mp3 play----
myDFPlayer.next(); //Play next mp3
delay(1000);
myDFPlayer.previous(); //Play previous mp3
delay(1000);
myDFPlayer.play(1); //Play the first mp3
delay(1000);
myDFPlayer.loop(1); //Loop the first mp3
delay(1000);
myDFPlayer.pause(); //pause the mp3
delay(1000);
myDFPlayer.start(); //start the mp3 from the pause
delay(1000);
myDFPlayer.playFolder(15, 4); //play specific mp3 in SD:/15/004.mp3; Folder Name(1~99); File Name(1~255)
delay(1000);
myDFPlayer.enableLoopAll(); //loop all mp3 files.
delay(1000);
myDFPlayer.disableLoopAll(); //stop loop all mp3 files.
delay(1000);
myDFPlayer.playMp3Folder(4); //play specific mp3 in SD:/MP3/0004.mp3; File Name(0~65535)
delay(1000);
myDFPlayer.advertise(3); //advertise specific mp3 in SD:/ADVERT/0003.mp3; File Name(0~65535)
delay(1000);
myDFPlayer.stopAdvertise(); //stop advertise
delay(1000);
myDFPlayer.playLargeFolder(2, 999); //play specific mp3 in SD:/02/004.mp3; Folder Name(1~10); File Name(1~1000)
delay(1000);
myDFPlayer.loopFolder(5); //loop all mp3 files in folder SD:/05.
delay(1000);
myDFPlayer.randomAll(); //Random play all the mp3.
delay(1000);
myDFPlayer.enableLoop(); //enable loop.
delay(1000);
myDFPlayer.disableLoop(); //disable loop.
delay(1000);
//----Read imformation----
Serial.println(myDFPlayer.readState()); //read mp3 state
Serial.println(myDFPlayer.readVolume()); //read current volume
Serial.println(myDFPlayer.readEQ()); //read EQ setting
Serial.println(myDFPlayer.readFileCounts()); //read all file counts in SD card
Serial.println(myDFPlayer.readCurrentFileNumber()); //read current play file number
Serial.println(myDFPlayer.readFileCountsInFolder(3)); //read file counts in folder SD:/03
*/
//Libaries
#include "Arduino.h" // Include the core Arduino library
#include "DFRobotDFPlayerMini.h"
#include <LiquidCrystal.h>
//DF player items
#ifdef ESP32
#define FPSerial Serial1 // For ESP32, use hardware serial port 1
#else
#include <SoftwareSerial.h> // Include SoftwareSerial library for non-ESP32 boards
SoftwareSerial FPSerial(16, 17); // Define SoftwareSerial on pins 16 (RX) and 17 (TX)
#endif
DFRobotDFPlayerMini player; // Create an instance of the DFRobotDFPlayerMini class
//the df player uses the Rx and the Tx pins (rx2 and tx2, note that second pin behind the power pin on DF connects to RX2 and third connects to TX2), sometimes you need to push en (restart on esp32) to get the df to connect
//Button items (pins are diffrent than diagram)
int button_back = 5;
int button_forward = 18;
int button_select = 19;
int buttonState_back;
int buttonState_forward;
int buttonState_select;
//There is no need for Switch items since it is just to actully disconnect the power
//LCD items
const int rs = 13, en = 12, d4 = 14, d5 = 27, d6 = 26, d7 = 25;// note that the pins are diffrent from the diagram
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
//Ultra Sonic items (pins are diffrent than diagram)
const int trigPin = 15;
const int echoPin = 2;
//define sound speed in cm/uS
#define SOUND_SPEED 0.034
#define CM_TO_INCH 0.393701
//create variables
long duration;
float distanceCm;
float distanceIn;
//System Variables
int trackSelected = 1;
int trackRandomized = 1;
int randomOrNot = 0;
int randomOrNotLoop = 0;
int trackSelectedLoop = 0;
float recordedPositionIn = 0;
float recordedPositionIn_WithPositiveTolorence = 0;
float recordedPositionIn_WithNegitiveTolorence = 0;
int PushToRecordLoop = 0;
int setTolorenceLoop = 0;
int tolorenceIn = 1;
int ActiveLoop = 0;
int TotalTracks = 1;
int TotalTracksLoop = 0;
int SelectingTrackCount = 0;
void setup() {
// put your setup code here, to run once:
//Serial Moniter and DF player
#ifdef ESP32
FPSerial.begin(9600, SERIAL_8N1, 16, 17); // Start serial communication for ESP32 with 9600 baud rate, 8 data bits, no parity, and 1 stop bit
#else
FPSerial.begin(9600); // Start serial communication for other boards with 9600 baud rate
#endif
Serial.begin(115200); // Start the Serial monitor communication with 115200 baud rate
Serial.println(F("DFRobot DFPlayer Mini Demo")); // Print a demo start message
Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)")); // Print initialization message
if (!player.begin(FPSerial)) { // Initialize the DFPlayer Mini with the defined serial interface
Serial.println(F("Unable to begin:")); // If initialization fails, print an error message
Serial.println(F("1.Please recheck the connection!")); // Suggest rechecking the connection
Serial.println(F("2.Please insert the SD card!")); // Suggest checking for an inserted SD card
while(true); // Stay in an infinite loop if initialization fails
}
Serial.println(F("DFPlayer Mini online.")); // Print a success message if initialization succeeds
player.volume(30); // Set the DFPlayer Mini volume to 30 (max is 30, mute is 0)
//Setting up Buttons
pinMode(button_back, INPUT_PULLUP); //The pull up means that I do not need an external resistor, note that LOW is now when the button is pushed and HIGH is when it is not pushed
pinMode(button_forward, INPUT_PULLUP);
pinMode(button_select, INPUT_PULLUP);
buttonState_back = digitalRead(button_back);
buttonState_forward = digitalRead(button_forward);
buttonState_select = digitalRead(button_select);
//Setting up Switches is not needed since it is just to physically disconnect the power
//Setting up LCD
lcd.begin(16, 2);
//Setting up Ultra Sonic
pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
pinMode(echoPin, INPUT); // Sets the echoPin as an Input
}
//Fuctions
void testDF()//play the first three mp3 tracks one after another for 3 seconds
{
player.play(1);
delay(3000);//note that this cuts off the track at 3 seconds it does not play the track then wait three seconds
player.play(2);
delay(3000);
player.play(3);
delay(3000);
}
void readButtons()//read the three buttons and set the buttons states to be correct
{
buttonState_back = digitalRead(button_back);
buttonState_forward = digitalRead(button_forward);
buttonState_select = digitalRead(button_select);
}
//LCD Fuctions
void HelloLCD()//Introduce the study buddy
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print ("Hello I Am");
lcd.setCursor(0,1);
lcd.print ("Study Buddy");
Serial.print("Hello Screen");
}
void RandomOrNotLCD()//To decide if the track played is specific or random
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print ("Press + for random");
lcd.setCursor(0,1);
lcd.print ("Press - to select");
Serial.print("Random or not screen");
}
void SelectSoundLCD()//Ask for the sound that will be used to be selected
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print ("Select Sound Track");
lcd.setCursor(0,1);
lcd.print ("Number");
Serial.print("Selecting Track Number LCD");
}
void SoundSelectedLCD()//Tell that the track was selected
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print ("Sound Selected");
Serial.print("Sound Selected");
}
void PushToRecordLCD()//Tell that you need to push select
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print ("Push Select");
lcd.setCursor(0,1);
lcd.print ("Then Move");
Serial.print("Select then Move");
}
void moveNowLCD()//Tell that you need to move
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print ("Move Into");
lcd.setCursor(0,1);
lcd.print ("Position");
Serial.print("Get into Position on LCD");
}
void SecondsPassedLCD()//Note that it is halfway till time it will record
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print ("30 Seconds");
lcd.setCursor(0,1);
lcd.print ("Left");
Serial.print("30 Seconds Left to get into position");
}
void PositionRecordedLCD()//note that the postion your in has been recored and that you need to physically use the off switch when done
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print ("Position Recorded");
Serial.print("Position Recorded");
}
void RandomTrackLCD()
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print ("Random Track");
lcd.setCursor(0,1);
lcd.print ("Selected");
Serial.println("Random Track Selected LCD");
}
void DecisionLCD()//this displays the correct LCD screen depending on if the random or selection track was made
{
Serial.println("Decision LCD");
if(randomOrNot == 1){//if they want to select the track themselves
SelectSoundLCD();//Ask for the sound that will be used to be selected
}else if(randomOrNot == 2){//if they want a random track each time
RandomTrackLCD();
}
}
void SelectingTheTrackLCD()//this explains how to select the track, that they should press forword to change the track and press select to confirm the track
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print ("Use + to change track");
lcd.setCursor(0,1);
lcd.print ("Use - to go back");
Serial.print("giving instructions for how to select track");
}
void TrackBeingSelectedLCD()
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print ("Current Track");
lcd.setCursor(0,1);
lcd.print (trackSelected);
Serial.print("current track displayed");
}
void SettingDistanceLCD()//This lets the user know that we will now be going threw the steps of setting the distance
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print ("Now to");
lcd.setCursor(0,1);
lcd.print ("Record Position");
Serial.print("letting user know position will be recorded soon");
}
void SettingGiveLCD()
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print ("Set Tolorence");
lcd.setCursor(0,1);
lcd.print ("Of Position");
delay(2000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print ("Of Position");
lcd.setCursor(0,1);
lcd.print ("In Inches");
delay(2000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print ("Use +");
lcd.setCursor(0,1);
lcd.print ("Then Select");
Serial.print("letting user know to set the tolorence");
}
void ActiveLCD()
{
Serial.print("Showing user activate screen");
lcd.clear();
lcd.setCursor(0,0);
lcd.print ("Activating");
lcd.setCursor(0,1);
lcd.print ("Studdy Buddy");
delay(2000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print ("Push Select");
lcd.setCursor(0,1);
lcd.print ("Or Turn Off");
delay(2000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print ("When Done");
lcd.setCursor(0,1);
lcd.print ("Now Activating");
}
void howManyTracksLCD()//This has the user tell how many tracks there are incase they choose to have it be random
{
Serial.print("Having the user tell how many tracks there are");
lcd.clear();
lcd.setCursor(0,0);
lcd.print ("How Many");
lcd.setCursor(0,1);
lcd.print ("Total Tracks");
delay(4000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print ("Push +");
lcd.setCursor(0,1);
lcd.print ("Then Select");
}
void howManyTracksLoopLCD()
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print ("Current Number");
lcd.setCursor(0,1);
lcd.print (TotalTracks);
Serial.print("Current Total Tracks:");
Serial.print(TotalTracks);
}
//Ulra Sonic
void find_distance()//uses the ultra sonic to find the distance and then print it on the serial monitor
{
// Clears the trigPin
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
// Sets the trigPin on HIGH state for 10 micro seconds
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// Reads the echoPin, returns the sound wave travel time in microseconds
duration = pulseIn(echoPin, HIGH);
// Calculate the distance
distanceCm = duration * SOUND_SPEED/2;
// Convert to inches
distanceIn = distanceCm * CM_TO_INCH;
// Prints the distance in the Serial Monitor
Serial.print("Distance (cm): ");
Serial.println(distanceCm);
Serial.print("Distance (inch): ");
Serial.println(distanceIn);
delay(1000);
}
//Other Fuctions
void howManyTracks()// not done, This has the user tell how many tracks there are incase they choose to have it be random
{
while(TotalTracksLoop == 0)
{
howManyTracksLoopLCD();
if(buttonState_forward == LOW){ //if forward is pushed increase the total tracks
TotalTracks = TotalTracks + 1;
Serial.print("Current Total Tracks increased to:");
Serial.print(TotalTracks);
}
if(buttonState_back == LOW && TotalTracks > 1){ //if forward is pushed and the total tracks is more than one decrease the total tracks
TotalTracks = TotalTracks - 1;
Serial.print("Current Total Tracks decreased to:");
Serial.print(TotalTracks);
}
if(buttonState_select == LOW){//push select to end the loop
TotalTracksLoop = 1;
break;
}
}
}
void RandomOrNotSelect()//The if statment tells if the person wants the track played to be random or not
{
while(randomOrNotLoop == 0)//While the desision for the track to be random or not has not been made run the loop
{
Serial.print("Making Decision");
if(buttonState_back == LOW){//if the back button is pressed then they want to select the track them selves
randomOrNot = 1;
Serial.print("Selecting Track");
randomOrNotLoop = 1;
}else if (buttonState_forward == LOW){//if the forword button is pressed then they want to randomize
randomOrNot = 2;
Serial.print("Random Track");
randomOrNotLoop = 1;
}
}
}
void SelectingTheTrack()//the process of selecting the track that is being played //if the user needs to select the track then they will
{
if(randomOrNot == 2){//if this fuction is not needed
Serial.print("User will not select track, since randomized chosen");
}
while(randomOrNot == 1)//since user wants to select the track, go threw that process
{
if(SelectingTrackCount == 0){
SelectingTheTrackLCD();//tells instruction
delay(2000);// wait so they can read
SelectingTrackCount = 1;
}
Serial.print("User will now select track, current track is");
Serial.print(trackSelected);
TrackBeingSelectedLCD();//This shows which track is currently selected
if (buttonState_forward == LOW && trackSelected < TotalTracks){//if the forword button is pressed and the current track is less than the total number of tracks then they want the next track instead
trackSelected = trackSelected + 1;
Serial.print("Added one to the current track number");
}
if (buttonState_back == LOW && trackSelected > 1){//if the back button is pressed and the track selected is not the first track then they want the past track instead
trackSelected = trackSelected - 1;
Serial.print("Subtracted one from the current track number");
}
if(buttonState_select == LOW){//if the select button is pressed then they want the current track
randomOrNot = 3; //this will end the loop
break; //this will also end the loop
}
}
}
void SettingDistance()//This has the user go threw the process of recording the distance the Ultra sonic sensor will calabrate to
{
while(PushToRecordLoop == 0)
{
PushToRecordLCD();//Tells that you need to push select
if(buttonState_select == LOW){
PushToRecordLoop = 1;
break;
}
}
moveNowLCD();
Serial.print("One minute to get into positon");
delay(30000);//waits for 30 seconds
SecondsPassedLCD();
delay(30000);//waits for 30 seconds
Serial.print("One minute has passed");
find_distance();
recordedPositionIn = distanceIn;//set user position to be where they currently are
PositionRecordedLCD();
}
void SettingGive()
{
while(setTolorenceLoop == 0)
{
if(buttonState_forward == LOW){// if forward is pushed increase tolorence
Serial.print("Increasing");
tolorenceIn = tolorenceIn + 1;
Serial.print("Tolorence is (in inches)");
Serial.print(tolorenceIn);
}
if(buttonState_back == LOW && tolorenceIn > 1){//if back is pushed and the tolorence is not one or below decrease
Serial.print("Decreasing");
tolorenceIn = tolorenceIn - 1;
Serial.print("Tolorence is (in inches)");
Serial.print(tolorenceIn);
}
if(buttonState_select == LOW){//Select ends the loop
setTolorenceLoop = 1;
break;
}
}
recordedPositionIn_WithPositiveTolorence = recordedPositionIn + tolorenceIn;//creating the positive tolorence line
recordedPositionIn_WithNegitiveTolorence = recordedPositionIn - tolorenceIn;//creating the negative tolorence line
}
void ActiveRun()//not done
{
while(ActiveLoop == 0)
{
find_distance();//checks the users current position
if(randomOrNot == 1){//if a specific track was selected
if(recordedPositionIn_WithPositiveTolorence >= distanceIn || recordedPositionIn_WithNegitiveTolorence <= distanceIn){// if the users current position is further away or on the positive tolorence line OR if the user is colser or on the negitive tolorence line
Serial.println("User outside tolorence bounds, playing selected track");
player.play(trackSelected);
delay(1000);
Serial.println("Finished the track, now looking for position");
}
}else if(randomOrNot == 2){//else if user stated they wanted a random track
if(recordedPositionIn_WithPositiveTolorence >= distanceIn || recordedPositionIn_WithNegitiveTolorence <= distanceIn){// if the users current position is further away or on the positive tolorence line OR if the user is colser or on the negitive tolorence line
Serial.println("User outside tolorence bounds, playing randomized track");
trackRandomized = random(1,TotalTracks);//make the random number between 1 and the total number of tracks
player.play(trackRandomized);//play the random track
delay(1000);
Serial.println("Finished the track, now looking for position");
}
}
if(buttonState_select == LOW){// if select is pushed then end the loop
Serial.println("Reseting Studdy Buddy");
ActiveLoop = 1;
break;
}
}
}
void loop() {
// put your main code here, to run repeatedly:
Serial.println("Begining Studdy Buddy Void Loop");
readButtons();//read the buttons at the begining of every loop
HelloLCD();//Introduce the study buddy
howManyTracksLCD();//how many tracks are there LCD
howManyTracks();//have the user input how many tacks there are
RandomOrNotLCD();//To decide if the track played is specific or random
RandomOrNotSelect();//This is the process of selecting
DecisionLCD();//this displays the correct LCD screen depending on if the random or selection track was made
SelectingTheTrack();//if the user needs to select the track then they will
SettingDistanceLCD();//This lets the user know that we will now be going threw the steps of setting the distance
delay(3000);
SettingDistance();//This has the user go threw the process of recording the distance the Ultra sonic sensor will calabrate to
SettingGiveLCD();//This tells the user to set the tolorence of where they will be
SettingGive();//This has the user set the tolorence of where they will be
Serial.println("Activating Studdy Buddy");
ActiveLCD();//This lets the user know that the studdy buddy is active, it also tells that you need to turn off in order to reset it
delay(3000);
lcd.clear();//this is so the lcd doesnt get burned in
ActiveRun;//this either plays the selected track or it runs a randomized track
Serial.println("Ending Studdy Buddy Void Loop");
//Speeding up simulation
delay(10); // this speeds up the simulation
}