Program acting random

hello,

I have a task of triggering a serial mp3 player. Right now I have a code that plays the three songs that I need but sometimes it plays them out of order and repeats them. I was hoping someone could tell me what i am doing wrong here. Thank you.

mp3_next_button.ino (3.59 KB)

OP code in code tags so everyone can see it. How to post code, see #7.

#include <SoftwareSerial.h>
const int buttonPin = 2; //trigger input on pin 2
int buttonState = 0;
#define ARDUINO_RX 12//should connect to TX of the Serial MP3 Player module
#define ARDUINO_TX 13//connect to RX of the module
SoftwareSerial mySerial(ARDUINO_RX, ARDUINO_TX);//init the serial protocol, tell to myserial wich pins are TX and RX

////////////////////////////////////////////////////////////////////////////////////
//all the commands needed in the datasheet(http://geekmatic.in.ua/pdf/Catalex_MP3_board.pdf)
static int8_t Send_buf[8] = {0} ;//The MP3 player undestands orders in a 8 int string
//0X7E FF 06 command 00 00 00 EF;(if command =01 next song order)
#define NEXT_SONG 0X01
#define PREV_SONG 0X02

#define CMD_PLAY_W_INDEX 0X03 //DATA IS REQUIRED (number of song)

#define VOLUME_UP_ONE 0X04
#define VOLUME_DOWN_ONE 0X05
#define CMD_SET_VOLUME 0X06//DATA IS REQUIRED (number of volume from 0 up to 30(0x1E))
#define SET_DAC 0X17
#define CMD_PLAY_WITHVOLUME 0X22 //data is needed  0x7E 06 22 00 xx yy EF;(xx volume)(yy number of song)

#define CMD_SEL_DEV 0X09 //SELECT STORAGE DEVICE, DATA IS REQUIRED
#define DEV_TF 0X02 //HELLO,IM THE DATA REQUIRED

#define SLEEP_MODE_START 0X0A
#define SLEEP_MODE_WAKEUP 0X0B

#define CMD_RESET 0X0C//CHIP RESET
#define CMD_PLAY 0X0D //RESUME PLAYBACK
#define CMD_PAUSE 0X0E //PLAYBACK IS PAUSED

#define CMD_PLAY_WITHFOLDER 0X0F//DATA IS NEEDED, 0x7E 06 0F 00 01 02 EF;(play the song with the directory \01\002xxxxxx.mp3

#define STOP_PLAY 0X16

#define PLAY_FOLDER 0X17// data is needed 0x7E 06 17 00 01 XX EF;(play the 01 folder)(value xx we dont care)

#define SET_CYCLEPLAY 0X19//data is needed 00 start; 01 close

#define SET_DAC 0X17//data is needed 00 start DAC OUTPUT;01 DAC no output
////////////////////////////////////////////////////////////////////////////////////


void setup()
{
  pinMode (buttonPin, INPUT_PULLUP); //establish buttonPin as input for trigger

  Serial.begin(9600);//Start our Serial coms for serial monitor in our pc
  mySerial.begin(9600);//Start our Serial coms for THE MP3
  delay(500);//Wait chip initialization is complete
  sendCommand(CMD_SEL_DEV, DEV_TF);//select the TF card
  delay(200);//wait for 200ms

}
void loop()
{
  buttonState = digitalRead(buttonPin);

  if (buttonState == LOW) { // when button pushed start the sequence
    sendCommand(CMD_PLAY_W_INDEX, 0001);//play the first song
    delay(27000); //wait for song to finish
  }
  {
    buttonState = digitalRead(buttonPin);

    if (buttonState == LOW) { // when button pushed start the sequence
      sendCommand(CMD_PLAY_W_INDEX, 0002);//play the second song
      delay(9000); //wait for song to finsih
    }
  }
  {
    buttonState = digitalRead(buttonPin);

    if (buttonState == LOW) { // when button pushed start the sequence
      sendCommand(CMD_PLAY_W_INDEX, 0003);//play the third song
      delay(20000);//wait for song to finish then go back to top of loop

    }
  }
}
void sendCommand(int8_t command, int16_t dat)
{
  delay(20);
  Send_buf[0] = 0x7e; //starting byte
  Send_buf[1] = 0xff; //version
  Send_buf[2] = 0x06; //the number of bytes of the command without starting byte and ending byte
  Send_buf[3] = command; //
  Send_buf[4] = 0x00;//0x00 = no feedback, 0x01 = feedback
  Send_buf[5] = (int8_t)(dat >> 8);//datah
  Send_buf[6] = (int8_t)(dat); //datal
  Send_buf[7] = 0xef; //ending byte
  for (uint8_t i = 0; i < 8; i++) //
  {
    mySerial.write(Send_buf[i]) ;//send bit to serial mp3
    Serial.print(Send_buf[i], HEX); //send bit to serial monitor in pc
  }
  Serial.println();
}

The loop function is called up to tens, or even hundreds of thousands of times per second.

The same button push can do three different things, depending on the particular moment during the execution of loop() when the button push happens to be detected.

How is the Arduino supposed to know which of the three actions is the one you wanted?

Keep in mind that when you use delay(), all the Arduino does is delay.

What would be the best way to have it do the first action when button is pressed then wait for the button to be pressed again and then trigger action two, and so on?

Should I not be using delay()?

delay() is fine if you don't need the Arduino to do anything BUT delay (like read a "stop playing" button). To avoid delay(), here is a fine tutorial on how to do that.

You could have a state variable that keeps track of the song last played. When the button is pushed, play the next song and change the state variable accordingly.

Okay thank you. I tried to incorporate the state variable but I don’t think I am doing it right, as I’m getting the same issue. I’m just learning this stuff so thanks for your patience. Am i headed in the right direction?

#include <SoftwareSerial.h>
const int buttonPin = 2; //trigger input on pin 2
int buttonState = 0;
int lastButtonState = 0;
int buttonPushCounter = 0;
#define ARDUINO_RX 12//should connect to TX of the Serial MP3 Player module
#define ARDUINO_TX 13//connect to RX of the module
SoftwareSerial mySerial(ARDUINO_RX, ARDUINO_TX);//init the serial protocol, tell to myserial wich pins are TX and RX

////////////////////////////////////////////////////////////////////////////////////
//all the commands needed in the datasheet(http://geekmatic.in.ua/pdf/Catalex_MP3_board.pdf)
static int8_t Send_buf[8] = {0} ;//The MP3 player undestands orders in a 8 int string
//0X7E FF 06 command 00 00 00 EF;(if command =01 next song order)
#define NEXT_SONG 0X01
#define PREV_SONG 0X02

#define CMD_PLAY_W_INDEX 0X03 //DATA IS REQUIRED (number of song)

#define VOLUME_UP_ONE 0X04
#define VOLUME_DOWN_ONE 0X05
#define CMD_SET_VOLUME 0X06//DATA IS REQUIRED (number of volume from 0 up to 30(0x1E))
#define SET_DAC 0X17
#define CMD_PLAY_WITHVOLUME 0X22 //data is needed  0x7E 06 22 00 xx yy EF;(xx volume)(yy number of song)

#define CMD_SEL_DEV 0X09 //SELECT STORAGE DEVICE, DATA IS REQUIRED
#define DEV_TF 0X02 //HELLO,IM THE DATA REQUIRED

#define SLEEP_MODE_START 0X0A
#define SLEEP_MODE_WAKEUP 0X0B

#define CMD_RESET 0X0C//CHIP RESET
#define CMD_PLAY 0X0D //RESUME PLAYBACK
#define CMD_PAUSE 0X0E //PLAYBACK IS PAUSED

#define CMD_PLAY_WITHFOLDER 0X0F//DATA IS NEEDED, 0x7E 06 0F 00 01 02 EF;(play the song with the directory \01\002xxxxxx.mp3

#define STOP_PLAY 0X16

#define PLAY_FOLDER 0X17// data is needed 0x7E 06 17 00 01 XX EF;(play the 01 folder)(value xx we dont care)

#define SET_CYCLEPLAY 0X19//data is needed 00 start; 01 close

#define SET_DAC 0X17//data is needed 00 start DAC OUTPUT;01 DAC no output
////////////////////////////////////////////////////////////////////////////////////


void setup()
{
  pinMode (buttonPin, INPUT_PULLUP); //establish buttonPin as input for trigger

  Serial.begin(9600);//Start our Serial coms for serial monitor in our pc
  mySerial.begin(9600);//Start our Serial coms for THE MP3
  delay(500);//Wait chip initialization is complete
  sendCommand(CMD_SEL_DEV, DEV_TF);//select the TF card
  delay(200);//wait for 200ms

}
void loop()
{
  buttonState = digitalRead(buttonPin);

  if (buttonState!= lastButtonState) { //when button pushed start the sequence
    if (buttonState == LOW){
  
    sendCommand(CMD_PLAY_W_INDEX, 0001);//play the first song
    delay(2000); //wait for song to finish
    }
  }
  
  //lastButtonState = buttonState;

buttonState = digitalRead(buttonPin);

  if (buttonState!= lastButtonState) { //when button pushed start the sequence
    if (buttonState == LOW){
  
    sendCommand(CMD_PLAY_W_INDEX, 0002);//play the first song
    delay(2000); //wait for song to finish
    }
  }
  
   lastButtonState = buttonState;



   
}

 void sendCommand(int8_t command, int16_t dat)
{
  delay(20);
  Send_buf[0] = 0x7e; //starting byte
  Send_buf[1] = 0xff; //version
  Send_buf[2] = 0x06; //the number of bytes of the command without starting byte and ending byte
  Send_buf[3] = command; //
  Send_buf[4] = 0x00;//0x00 = no feedback, 0x01 = feedback
  Send_buf[5] = (int8_t)(dat >> 8);//datah
  Send_buf[6] = (int8_t)(dat); //datal
  Send_buf[7] = 0xef; //ending byte
  for (uint8_t i = 0; i < 8; i++) //
  {
    mySerial.write(Send_buf[i]) ;//send bit to serial mp3
    Serial.print(Send_buf[i], HEX); //send bit to serial monitor in pc
  }
  Serial.println();
}

A state variable records a desired machine state and could be anything. In my example, I had in mind something like “last_song = the last song played”.

When you detect a button press and want to decide which song to play, check the value of last_song and choose accordingly. Simple example:

Edited to use switch…case instead of if

  switch (last_song) 
  {
    case 1: 
        play_song(2);
        last_song = 2;
        break;
    case 2:
       play_song(3);
       last_song = 3;
       break;
    case 3:
    default:
     play_song(1);
     last_song = 1;
   }

You can use another state variable to hold the last button state, which might be used to detect “press and release”.

So how would i incorporate the button into the switch...case code? Kind of confused about that part.

The switch case code just picks and plays the next song. Modify as necessary and put it in the appropriate place of a working program to detect button pushes.