Animatronic Elf w/ audio

I am building a animatronic Elf on the shelf using a UNO board. I have 2 servos . Servo A to nod head up and down (yes) and Servo B to shake head side to side (No).
I am using a 4 button RF remote to control the project.
Button A cycles through several mp3 audio files that I am writing a script/story for.
Button B shakes head side to side (No)
Button C nods head up and down (yes)
Button D is not assigned yet

I would like to add some audio files to buttons B and C - So when I press button B the elf will shake head side to side and say No. I'd like to record several mp3 files for the negative responses and several for the affirmative as well.. So the code would cycle through several files before returning to the first file.

I have the system working except for the audio functions of buttons B & C.. The servos are working fine and the Audio on button A works fine.

Can someone help with the code for buttons B & C ?

Here is the code so far



#include <Servo.h>
#include <SoftwareSerial.h>

Servo servoA;
Servo servoB;

const int buttonAPin = 9; // Button A
const int buttonBPin = 10; // Button B
const int buttonCPin = 11; // Button C
const int buttonDPin = 12; // Button D
const int ledPin = 13; // Used as 5V output for QIACHIP module

int buttonAState = LOW;
int lastButtonAState = LOW;
unsigned long lastDebounceTimeA = 0;
unsigned long debounceDelay = 50;

int buttonBState = LOW;
int lastButtonBState = LOW;
unsigned long lastDebounceTimeB = 0;

int buttonCState = LOW;
int lastButtonCState = LOW;
unsigned long lastDebounceTimeC = 0;

SoftwareSerial mySerial(3, 2); // RX, TX for DF Player Mini

void setup() {
  servoA.attach(6);
  servoB.attach(7);

  pinMode(buttonAPin, INPUT);
  pinMode(buttonBPin, INPUT);
  pinMode(buttonCPin, INPUT);
  pinMode(buttonDPin, INPUT);
  pinMode(ledPin, OUTPUT);

  mySerial.begin(9600);

  pinMode(13, OUTPUT); // Set pin 13 as 5V output for QIACHIP module
  digitalWrite(13, HIGH); // Set pin 13 high to provide 5V
}

void loop() {
  // Button A handling
  int readingA = digitalRead(buttonAPin);
  if (readingA != lastButtonAState) {
    lastDebounceTimeA = millis();
  }
  if ((millis() - lastDebounceTimeA) > debounceDelay) {
    if (readingA != buttonAState) {
      buttonAState = readingA;
      if (buttonAState == HIGH) {
        // Button A pressed
        playNextMP3();
      }
    }
  }
  lastButtonAState = readingA;

  // Button B handling
  int readingB = digitalRead(buttonBPin);
  if (readingB != lastButtonBState) {
    lastDebounceTimeB = millis();
  }
  if ((millis() - lastDebounceTimeB) > debounceDelay) {
    if (readingB != buttonBState) {
      buttonBState = readingB;
      if (buttonBState == HIGH) {
        // Button B pressed
        continuousRotateServoA();
      }
    }
  }
  lastButtonBState = readingB;

  // Button C handling
  int readingC = digitalRead(buttonCPin);
  if (readingC != lastButtonCState) {
    lastDebounceTimeC = millis();
  }
  if ((millis() - lastDebounceTimeC) > debounceDelay) {
    if (readingC != buttonCState) {
      buttonCState = readingC;
      if (buttonCState == HIGH) {
        // Button C pressed
        continuousRotateServoB();
      }
    }
  }
  lastButtonCState = readingC;

  // Your existing code for button D handling
  // (e.g., playNextMP3())

  // Your existing code for continuous servo rotation
  // (e.g., continuousRotateServoB())
}

void playNextMP3() {
  static int mp3FileNumber = 1; // Assuming your files are numbered starting from 1
  static const int lastFileNumber = 4; // Change this to the last file number

  mySerial.write(0x7E);            // Start code
  mySerial.write(0xFF);            // Version
  mySerial.write(0x06);            // Command length
  mySerial.write(0x03);            // Command: Play specific file
  mySerial.write((byte)0x00);      // Reserved
  mySerial.write((byte)(mp3FileNumber >> 8));  // High byte of file number
  mySerial.write((byte)mp3FileNumber);          // Low byte of file number
  mySerial.write(0xEF);            // End code

  delay(500); // Adjust delay if needed
  mp3FileNumber++; // Move to the next file for the next press

  // Reset to the first file if the last file is reached
  if (mp3FileNumber > lastFileNumber) {
    mp3FileNumber = 1;
  }
}
void smoothMoveServo(Servo &servo, int targetPosition, int step, int delayTime) {
  int currentPosition = servo.read();
  
  if (currentPosition < targetPosition) {
    for (int pos = currentPosition; pos <= targetPosition; pos += step) {
      servo.write(pos);
      delay(delayTime);
    }
  } else {
    for (int pos = currentPosition; pos >= targetPosition; pos -= step) {
      servo.write(pos);
      delay(delayTime);
    }
  }
}

void continuousRotateServoA() {
  while (digitalRead(buttonBPin) == HIGH) {
    smoothMoveServo(servoA, 120, 1, 8); // Adjust target position, step, and delay time
    smoothMoveServo(servoA, 60, 1, 10);  // Adjust target position, step, and delay time
  }
  // Stop the servo when the button is released
  servoA.write(90);
}

void continuousRotateServoB() {
  while (digitalRead(buttonCPin) == HIGH) {
    smoothMoveServo(servoB, 110, 1, 10); // Adjust target position, step, and delay time
    smoothMoveServo(servoB, 60, 1, 10);  // Adjust target position, step, and delay time
  }
  // Stop the servo when the button is released
  servoB.write(90);
}

OK I've made a few minor changes to the code and I will include the newest version. Also here is a video of my project.
https://youtube.com/shorts/DnIvm8Dntb8?feature=share

Here is the current code - I will add the code I tried at the end, I was trying to use buttons to access files in the different folders - button A would access folder 001, Button B would access folder 002, Button C would access folder 3 and eventually button D would access folder 004


```cpp
#include <Servo.h>
#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h>

Servo servoA;
Servo servoB;

const int buttonAPin = 9; // Button A
const int buttonBPin = 10; // Button B
const int buttonCPin = 11; // Button C
const int buttonDPin = 12; // Button D
const int ledPin = 13; // Used as 5V output for QIACHIP module

int buttonAState = LOW;
int lastButtonAState = LOW;
unsigned long lastDebounceTimeA = 0;
unsigned long debounceDelay = 50;

int buttonBState = LOW;
int lastButtonBState = LOW;
unsigned long lastDebounceTimeB = 0;

int buttonCState = LOW;
int lastButtonCState = LOW;
unsigned long lastDebounceTimeC = 0;

SoftwareSerial mySerial(3, 2); // RX, TX for DF Player Mini

void setup() {
  servoA.attach(6);
  servoB.attach(5);

  pinMode(buttonAPin, INPUT);
  pinMode(buttonBPin, INPUT);
  pinMode(buttonCPin, INPUT);
  pinMode(buttonDPin, INPUT);
  pinMode(ledPin, OUTPUT);

  mySerial.begin(9600);

  pinMode(13, OUTPUT); // Set pin 13 as 5V output for QIACHIP module
  digitalWrite(13, HIGH); // Set pin 13 high to provide 5V
}

void loop() {
  // Button A handling
  int readingA = digitalRead(buttonAPin);
  if (readingA != lastButtonAState) {
    lastDebounceTimeA = millis();
  }
  if ((millis() - lastDebounceTimeA) > debounceDelay) {
    if (readingA != buttonAState) {
      buttonAState = readingA;
      if (buttonAState == HIGH) {
        // Button A pressed
        playNextMP3();
      }
    }
  }
  lastButtonAState = readingA;

  // Button B handling
  int readingB = digitalRead(buttonBPin);
  if (readingB != lastButtonBState) {
    lastDebounceTimeB = millis();
  }
  if ((millis() - lastDebounceTimeB) > debounceDelay) {
    if (readingB != buttonBState) {
      buttonBState = readingB;
      if (buttonBState == HIGH) {
        // Button B pressed
        continuousRotateServoA();
       }
    }
  }
  lastButtonBState = readingB;

  // Button C handling
  int readingC = digitalRead(buttonCPin);
  if (readingC != lastButtonCState) {
    lastDebounceTimeC = millis();
  }
  if ((millis() - lastDebounceTimeC) > debounceDelay) {
    if (readingC != buttonCState) {
      buttonCState = readingC;
      if (buttonCState == HIGH) {
        // Button C pressed
        continuousRotateServoB();
      }
    }
  }
  lastButtonCState = readingC;

  // Your existing code for button D handling
  // (e.g., playNextMP3())

  // Your existing code for continuous servo rotation
  // (e.g., continuousRotateServoB())
}

void playNextMP3() {
  static int mp3FileNumber = 1; // Assuming your files are numbered starting from 1
  static const int lastFileNumber = 4; // Change this to the last file number

  mySerial.write(0x7E);            // Start code
  mySerial.write(0xFF);            // Version
  mySerial.write(0x06);            // Command length
  mySerial.write(0x03);            // Command: Play specific file
  mySerial.write((byte)0x00);      // Reserved
  mySerial.write((byte)(mp3FileNumber >> 8));  // High byte of file number
  mySerial.write((byte)mp3FileNumber);          // Low byte of file number
  mySerial.write(0xEF);            // End code

  delay(500); // Adjust delay if needed
  mp3FileNumber++; // Move to the next file for the next press

  // Reset to the first file if the last file is reached
  if (mp3FileNumber > lastFileNumber) {
    mp3FileNumber = 1;
  }
}
void smoothMoveServo(Servo &servo, int targetPosition, int step, int delayTime) {
  int currentPosition = servo.read();
  
  if (currentPosition < targetPosition) {
    for (int pos = currentPosition; pos <= targetPosition; pos += step) {
      servo.write(pos);
      delay(delayTime);
    }
  } else {
    for (int pos = currentPosition; pos >= targetPosition; pos -= step) {
      servo.write(pos);
      delay(delayTime);
    }
  }
}

void continuousRotateServoA() {
  while (digitalRead(buttonBPin) == HIGH) {
    smoothMoveServo(servoA, 120, 1, 8); // Adjust target position, step, and delay time
    smoothMoveServo(servoA, 60, 1, 10);  // Adjust target position, step, and delay time
  }
  // Stop the servo when the button is released
  servoA.write(90);
}

void continuousRotateServoB() {
  while (digitalRead(buttonCPin) == HIGH) {
    smoothMoveServo(servoB, 110, 1, 10); // Adjust target position, step, and delay time
    smoothMoveServo(servoB, 60, 1, 10);  // Adjust target position, step, and delay time
  }
  // Stop the servo when the button is released
  servoB.write(90);
}
Here is the code I tried to use.. No audio at all 
```cpp
#include <Servo.h>
#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h>

Servo servoA;
Servo servoB;

const int buttonAPin = 9; // Button A
const int buttonBPin = 10; // Button B
const int buttonCPin = 11; // Button C
const int buttonDPin = 12; // Button D
const int ledPin = 13; // Used as 5V output for QIACHIP module

int buttonAState = LOW;
int lastButtonAState = LOW;
unsigned long lastDebounceTimeA = 0;
unsigned long debounceDelay = 50;

int buttonBState = LOW;
int lastButtonBState = LOW;
unsigned long lastDebounceTimeB = 0;

int buttonCState = LOW;
int lastButtonCState = LOW;
unsigned long lastDebounceTimeC = 0;

SoftwareSerial mySerial(3, 2); // RX, TX for DF Player Mini

void setup() {
  servoA.attach(6);
  servoB.attach(5);

  pinMode(buttonAPin, INPUT);
  pinMode(buttonBPin, INPUT);
  pinMode(buttonCPin, INPUT);
  pinMode(buttonDPin, INPUT);
  pinMode(ledPin, OUTPUT);

  mySerial.begin(9600);

  pinMode(13, OUTPUT); // Set pin 13 as 5V output for QIACHIP module
  digitalWrite(13, HIGH); // Set pin 13 high to provide 5V
}

void loop() {
  // Button A handling
  int readingA = digitalRead(buttonAPin);
  if (readingA != lastButtonAState) {
    lastDebounceTimeA = millis();
  }
  if ((millis() - lastDebounceTimeA) > debounceDelay) {
    if (readingA != buttonAState) {
      buttonAState = readingA;
      if (buttonAState == HIGH) {
        // Button A pressed
        playFilesInFolder(01);
      }
    }
  }
  lastButtonAState = readingA;

  // Button B handling
  int readingB = digitalRead(buttonBPin);
  if (readingB != lastButtonBState) {
    lastDebounceTimeB = millis();
  }
  if ((millis() - lastDebounceTimeB) > debounceDelay) {
    if (readingB != buttonBState) {
      buttonBState = readingB;
      if (buttonBState == HIGH) {
        // Button B pressed
        continuousRotateServoA();
        playFilesInFolder(02);
      }
    }
  }
  lastButtonBState = readingB;

  // Button C handling
  int readingC = digitalRead(buttonCPin);
  if (readingC != lastButtonCState) {
    lastDebounceTimeC = millis();
  }
  if ((millis() - lastDebounceTimeC) > debounceDelay) {
    if (readingC != buttonCState) {
      buttonCState = readingC;
      if (buttonCState == HIGH) {
        // Button C pressed
        continuousRotateServoB();
        playFilesInFolder(03);
      }
    }
  }
  lastButtonCState = readingC;

  // Your existing code for button D handling
  // (e.g., playNextMP3())

  // Your existing code for continuous servo rotation
  // (e.g., continuousRotateServoB())
}

void playFilesInFolder(int folder) {
  mySerial.write(0x7E);            // Start code
  mySerial.write(0xFF);            // Version
  mySerial.write(0x06);            // Command length
  mySerial.write(0x0F);            // Command: Play folder
  mySerial.write((byte)0x00);      // Reserved
  mySerial.write((byte)folder);    // Folder number
  mySerial.write(0xEF);            // End code

  delay(500); // Adjust delay if needed
}

void smoothMoveServo(Servo &servo, int targetPosition, int step, int delayTime) {
  int currentPosition = servo.read();
  
  if (currentPosition < targetPosition) {
    for (int pos = currentPosition; pos <= targetPosition; pos += step) {
      servo.write(pos);
      delay(delayTime);
    }
  } else {
    for (int pos = currentPosition; pos >= targetPosition; pos -= step) {
      servo.write(pos);
      delay(delayTime);
    }
  }
}

void continuousRotateServoA() {
  while (digitalRead(buttonBPin) == HIGH) {
    smoothMoveServo(servoA, 120, 1, 8); // Adjust target position, step, and delay time
    smoothMoveServo(servoA, 60, 1, 10);  // Adjust target position, step, and delay time
  }
  // Stop the servo when the button is released
  servoA.write(90);
}

void continuousRotateServoB() {
  while (digitalRead(buttonCPin) == HIGH) {
    smoothMoveServo(servoB, 110, 1, 10); // Adjust target position, step, and delay time
    smoothMoveServo(servoB, 60, 1, 10);  // Adjust target position, step, and delay time
  }
  // Stop the servo when the button is released
  servoB.write(90);
}

Any pointers would be appreciated

Thanks
Bob

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