Hi everyone,
I hope you can help me on this task. I'm using a PS2 joypad to control the outputs of an Arduino UNO. The general working flow is as follows:
- The directional buttons are used to control three leds (up = yellow led, left = red led, green = right led);
- When any of these buttons are pressed a delay time counter is started to register for how long it has been hold;
- When the button is released the delay time and an indicator of which button was activated are stored in memory vectors (up to 20 memory positions each).
The recording memory mode is toggled ON/OFF by the SELECT button. A playback mode is activated by the START button and only works when the recording mode is OFF. The playback mode should reproduce the directions and the delay times recorded in the memory vectors backwards, and here is where my code fails. The memory vectors are being stored correctly, but sometimes after executing the playback mode -- playMemory() function -- the program automatically toggles ON the recording mode and stores all three directions in the memory with a very short delay time, which is related to the delay() command at the end of the loop() function. However, when the while() loop is removed from the playMemory() function this behaviour does not happen.
Can any of you understand why this is happening? I guess that it may be cause of misusing of the millis() function as timer somehow, but I don't see how to correct it. Probably there is another way to do this using the timer library, by I'll also include servos and a buzzer in the final project. According to some documentation I've been reading it seems that I can't use this library if the project already includes servos, buzzers and millis() or delay() functions, am I right?
This is the whole code:
#include <PS2X_lib.h>
#define BR 10 // white led - indicator for recording mode ON/OFF
#define VM 11 // red led - left button
#define AM 12 // yellow led - up button
#define VD 13 // green led - right button
int memTimes[20]; // delay time for each command
char memDirections[20]; // records which button is pressed
int memPosition = 0; // position in memory vector
unsigned long delayTime = 0; // variable for delay time counting
bool memoryModeCurr = LOW; // current state for the memory mode button
bool memoryModePrev = LOW; // previous state for the memory mode button
void playMemory();
void recordMemory();
PS2X CONTROLE;
void setup() {
Serial.begin(9600);
pinMode(BR, OUTPUT);
pinMode(VM, OUTPUT);
pinMode(AM, OUTPUT);
pinMode(VD, OUTPUT);
CONTROLE.config_gamepad(2,4,3,5,false,false); // (clock, command, attention, data, Pressures?, Rumble?)
}
void loop() {
static bool recordingMode; // state of the recording Mode
CONTROLE.read_gamepad();
// ON|OFF for the recording mode
memoryModeCurr = CONTROLE.ButtonPressed(PSB_SELECT);
if (memoryModeCurr && !memoryModePrev) {
recordingMode = !recordingMode; // Sometimes after executing playMemory() this state changes by itself, sometimes it doesn't. Why?
Serial.println("recordingMode state has changed.");
}
else {
digitalWrite(BR, LOW);
}
memoryModePrev = memoryModeCurr;
if (recordingMode && (memPosition < 20)) recordMemory();
if (CONTROLE.ButtonPressed(PSB_START) && (memPosition > 0) && !recordingMode) playMemory();
delay(25);
}
void playMemory() {
Serial.println("Playback mode activated.");
for (int mP=memPosition; mP>=0; mP--){
Serial.println(memDirections[mP]);
delayTime = millis();
while ((millis()-delayTime) <= memTimes[mP]) { // if this loop is removed, the issue does not happen
}
}
delayTime = millis();
}
void recordMemory() { // This function works.
digitalWrite(BR, HIGH);
// UP BUTTON
if (CONTROLE.ButtonPressed(PSB_PAD_UP)) { // gets the starting time
delayTime = millis();
}
if (CONTROLE.Button(PSB_PAD_UP)) { // turns on the led while the button is being pressed
digitalWrite(AM, HIGH);
}
if (CONTROLE.ButtonReleased(PSB_PAD_UP)) { // turns off the led and stores the button pressed and the delay time in the memory vector
digitalWrite(AM, LOW);
memTimes[memPosition] = millis() - delayTime;
memDirections[memPosition] = 'U';
memPosition++;
}
// LEFT BUTTON
if (CONTROLE.ButtonPressed(PSB_PAD_LEFT)) { // gets the starting time
delayTime = millis();
}
if (CONTROLE.Button(PSB_PAD_LEFT)) { // turns on the led while the button is being pressed
digitalWrite(VM, HIGH);
}
if (CONTROLE.ButtonReleased(PSB_PAD_LEFT)) { // turns off the led and stores the button pressed and the delay time in the memory vector
digitalWrite(VM, LOW);
memTimes[memPosition] = millis() - delayTime;
memDirections[memPosition] = 'L';
memPosition++;
}
// RIGHT BUTTON
if (CONTROLE.ButtonPressed(PSB_PAD_RIGHT)) { // gets the starting time
delayTime = millis();
}
if (CONTROLE.Button(PSB_PAD_RIGHT)) { // turns on the led while the button is being pressed
digitalWrite(VD, HIGH);
}
if (CONTROLE.ButtonReleased(PSB_PAD_RIGHT)) { // turns off the led and stores the button pressed and the delay time in the memory vector
digitalWrite(VD, LOW);
memTimes[memPosition] = millis() - delayTime;
memDirections[memPosition] = 'R';
memPosition++;
}
// OUTPUTS
if (CONTROLE.ButtonReleased(PSB_PAD_RIGHT) || CONTROLE.ButtonReleased(PSB_PAD_LEFT) || CONTROLE.ButtonReleased(PSB_PAD_UP)){
Serial.print("Delay Time: ");
Serial.println(memTimes[memPosition-1]);
Serial.print("Button pressed: ");
Serial.println(memDirections[memPosition-1]);
Serial.print("Memory vector position: ");
Serial.println(memPosition-1);
Serial.print("Everything: ");
for (int k=0; k<memPosition; k++){
Serial.print(memTimes[k]);
Serial.print(" -- ");
Serial.println(memDirections[k]);
}
Serial.println();
}
}
And this is an example of the output:
recordingMode state has changed.
Delay Time: 605
Button pressed: U
Memory vector position: 0
Everything: 605 -- U
Delay Time: 526
Button pressed: L
Memory vector position: 1
Everything: 605 -- U
526 -- L
Delay Time: 474
Button pressed: R
Memory vector position: 2
Everything: 605 -- U
526 -- L
474 -- R
recordingMode state has changed.
Playback mode activated.
R
L
U <-- This time it worked correctly.
Playback mode activated.
R
L
U <-- This time it worked correctly.
Playback mode activated.
R
L
U
recordingMode state has changed. <-- This time it didn't! It toggled ON the recording mode by itself.
Delay Time: 27
Button pressed: R
Memory vector position: 5
Everything: 605 -- U
526 -- L
474 -- R
27 -- U <-- Related to delay(25)
27 -- L <-- Related to delay(25)
27 -- R <-- Related to delay(25)
I appreciate any help that you can give me. Comments about code optimizing are also welcome if you have some.