Hey, there.
I'm working on animating a toy that my brother is prototyping. It will have only three features: it will play a designated noise from an MP3 module, be illuminated with an LED module, and will rotate about its axis via a motor. The order of operations are as described below:
There is only one, single NO momentary switch that the user will press. Other hardware is:
*MP3 Module - DY-SV8F,
*LED Module - inductively-powered LED Module (works on same premise as Qi wireless charging for your cell phone), and
*1 - 3 RPM DC Motor.
Each press of this momentary switch will do the following:
First Press:
*Play Track 1 on MP3 Module; Track 1 shall play ONCE (approximately 11 seconds).
*Turn on LED Module; LED Module shall turn on and remain lit.
Second Press:
*Play Track 2 on MP3 Module; Track 2 shall play in a continuous loop.
*LED Module remains lit; Turn on Motor; LED Module shall remain lit; Motor shall turn on and remain on.
Third Press:
*Track 2 on MP3 Module shall stop. No sound from MP3 module for this state.
*LED Module shall remain lit.
*Motor shall remain on.
Fourth Press:
*Play Track 3 on MP3 Module; Track 3 shall play ONCE.
*At the conclusion of Track 3 (approximately 9 seconds), turn off LED Module and Motor.
Here are the issues I'm having with my code:
*When I first plug in my hardware, everything is silent and patiently waiting for the first button press, which is the desired state.
*When I press the button the first time, Track 1 plays and the LED module turns on. The issue is that Track 1 on the MP3 module plays in a continuous loop. It should be noted that the code is written to do this, so it is doing exactly what it's programmed to do. I need help telling the code to only play the track once. For this particular MP3 module, the operating state is rather simple - when the pin for Track 1 is held LOW, it plays the track and will continue to play it in an infinite loop. To stop the track, you must drive the pin for Track 1 HIGH.
*When I press the button a second time, the LEDs turn off, the Motor turns on, and it plays track 1 on the MP3 player just once.
*When I press the button a third time, the motor and LED modules turn off, and Track 1 plays in a looping fashion.
*When I press the button a fourth time, nothing happens.
*When I press the button a fifth time, the Motor and LED modules turn on, and Track 1 plays in a looping fashion.
Code below:
#include "SoftwareSerial.h"
const int ledPin = 7;
const int motorPin = 8;
const int trackOnePin = 9;
const int trackTwoPin = 10;
const int trackThreePin = 11;
const int buttonPin = 12;
int buttonPushCounter = 0; //new
int buttonState = HIGH; //using built-in pullup resistor.
int lastButtonState = LOW;
int ledState = LOW; //initializes the LED module to OFF.
int motorState = LOW; //initializes the motor to OFF.
int trackOneState = HIGH; //initializes track one on the MP3 module to OFF.
int trackTwoState = HIGH; //initializes track two on the MP3 module to OFF.
int trackThreeState = HIGH; //initializes track three on the MP3 module to OFF.
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;
void setup() {
// put your setup code here, to run once:
pinMode(buttonPin, INPUT_PULLUP);
pinMode(trackOnePin, OUTPUT);
pinMode(trackTwoPin, OUTPUT);
pinMode(trackThreePin, OUTPUT);
pinMode(ledPin, OUTPUT);
pinMode(motorPin, OUTPUT);
//Writes the inialized states based on the declarations above. Maybe these lines aren't needed?
digitalWrite(trackOnePin, trackOneState);
digitalWrite(trackTwoPin, trackTwoState);
digitalWrite(trackThreePin, trackThreeState);
digitalWrite(ledPin, ledState);
digitalWrite(motorPin, motorState);
}
void loop() {
// put your main code here, to run repeatedly:
int reading = digitalRead(buttonPin);
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != buttonState) {
buttonState = reading;
if (buttonState == LOW && buttonPushCounter<5) { //If the button has been pressed AND the buttonPushCounter is less than 5, then increment the buttonPushCounter by one.
buttonPushCounter++;
} //I was thinking that an ELSE argument might be helpful - I tried to put an else argument that would reset the buttonPushCounter back to zero, but this obviously didn't work,
//since when I WASN'T pushing the button, it was restarting the count to zero everytime the loop looked at this decision.
}
}
switch (buttonPushCounter) {
case 1: //When buttonPushCounter = 1. I'm still learning how to use Switch...Case, so I'm not sure if I'm just doing this wrong, or if there is a better way. Anyways...
if (trackOneState = HIGH) { //If track one is not playing, then:
ledState = !ledState; //Toggles (turns on) LED module, and
trackOneState = !trackOneState; //Toggles (plays) track one, and
digitalWrite(ledPin, ledState); //Writes the state of the LED module, and
digitalWrite(trackOnePin, trackOneState); //Writes the state of Track One.
break; //Breaks out so that when the code whips around again, and it sees that we are still in Case 1, it will go to "else," and
} else { //breaks out again until the counter increments. Switch...Case logic continues in similar fashion when the counter increments.
break;
}
case 2:
if (trackTwoState = HIGH) {
trackOneState = !trackOneState;
motorState = !motorState;
trackTwoState = !trackTwoState;
digitalWrite(trackOnePin, trackOneState);
digitalWrite(motorPin, motorState);
digitalWrite(trackTwoPin, trackTwoState);
break;
} else {
break;
}
case 3:
if (trackTwoState = LOW) {
trackTwoState = !trackTwoState;
digitalWrite(trackTwoPin, trackTwoState);
break;
} else {
break;
}
case 4:
if (trackThreeState = HIGH) {
trackThreeState = !trackThreeState;
delay(9000);
motorState = !motorState;
ledState = !ledState;
digitalWrite(trackThreePin, trackThreeState);
digitalWrite(motorPin, motorState);
digitalWrite(ledPin, ledState);
break;
} else {
break;
}
default: //I don't know why I restated these conditions, but I thought that since the code is whipping around in this loop, it made sense to me to ensure that the states of the variables were explicitly set.
ledState = LOW; //led module off
motorState = LOW; //motor off
trackOneState = HIGH; //track 00001 off
trackTwoState = HIGH; //track 00002 off
trackThreeState = HIGH; //track 00003 off
digitalWrite(ledPin, ledState);
digitalWrite(motorPin, motorState);
digitalWrite(trackOnePin, trackOneState);
digitalWrite(trackTwoPin, trackTwoState);
digitalWrite(trackThreePin, trackThreeState);
buttonPushCounter = 0; //I moved the "initialize the counter back to zero" logic here, as this is (in my mind) what my default condition should be...reset the counter to zero if we have any value other than 1-4.
}
lastButtonState = reading;
}