Hi all. I have this code which is a combination of me and chatGPT. On button press, it plays music from a module I have set to pin 8 and starts the animation. If I stop it and start it and stop it and start it, the animation plays and the music does not, or the music plays and the anim does not, or neither works or both work. I hope this makes sense.
I'm not sure what is causing it and I'm becoming blind to it. I thought I'd put it down for a day but hoped one of you might be able to steer me in the right direction.
my code has all of the animation data stripped out to make it less cumbersome for you
Thanks!
Glenn
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
// Initialize the Adafruit PWM Servo Driver
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
// Define minimum and maximum pulse lengths
uint16_t SERVOMIN = 150;
uint16_t SERVOMAX = 600;
// Assign each servo to a PWM pin on the driver board
uint8_t headServo = 0;
uint8_t mouthServo = 1;
uint8_t chestServo = 2;
uint8_t bellyServo = 3;
uint8_t footServo = 4;
uint8_t micServo = 5;
// Define frame duration for 30 frames per second
const unsigned long frameDuration = 1000 / 30;
unsigned long lastFrame = 2000;
// Define per-frame data arrays for each servo
const float mouthData[] PROGMEM = { 90.0 };
const float headData[] PROGMEM = { 125.17 };
const float chestData[] PROGMEM = { 90.0 };
const float bellyData[] PROGMEM = { 90.0 };
const float footData[] PROGMEM = { 89.53};
const float micData[] PROGMEM = { 90.0 };
// Define pin and state variables for the button
int buttonPin = 2; // The pin the button is connected to
bool animateServos = false; // Controls whether the servo animation is active
bool lastButtonState = HIGH; // Stores the last state of the button
unsigned long currentFrame = 0; // Current frame in the animation sequence
bool animationComplete = false; // Tracks if the animation has completed
const int Music = 8; // the number of the Music pin
void setup() {
Serial.begin(9600);
pinMode(Music, OUTPUT);
digitalWrite(Music, HIGH); //stop it playing striaght away
// Set the button as an input with an internal pull-up resistor
pinMode(buttonPin, INPUT_PULLUP);
// Start the PWM driver and set its frequency
pwm.begin();
pwm.setPWMFreq(60);
delay(10);
// Set servos to their initial static positions
setStaticPositions();
}
void loop() {
// Read the current state of the button
bool currentButtonState = digitalRead(buttonPin);
// Check for button state changes
if (currentButtonState != lastButtonState) {
if (currentButtonState == LOW) {
digitalWrite(Music, LOW);
animateServos = !animateServos; // Toggle animation state
currentFrame = 0; // Reset frame counter
if (!animateServos) {
setStaticPositions(); // Return to static positions
}
delay(20); // Debounce delay
}
else {
digitalWrite(Music, HIGH);
}
lastButtonState = currentButtonState;
}
// Run the servo control loop if animateServos is true
if (animateServos) {
unsigned long currentMillis = millis();
if (currentMillis - lastFrame >= frameDuration) {
lastFrame = currentMillis;
// Control each servo using its specific data array
controlServo(headServo, headData, currentFrame % 2000);
controlServo(mouthServo, mouthData, currentFrame % 2000);
controlServo(chestServo, chestData, currentFrame % 2000);
controlServo(bellyServo, bellyData, currentFrame % 2000);
controlServo(footServo, footData, currentFrame % 2000);
controlServo(micServo, micData, currentFrame % 2000);
digitalWrite(Music, HIGH);
currentFrame++; // Increment the frame counter
// Check if the animation cycle is complete
if (currentFrame >= 2000) {
animateServos = false; // Stop animation
setStaticPositions(); // Return to static positions
}
}
}
}
// Set static positions for each servo
void setStaticPositions() {
controlServo(headServo, 125); // Static position for head
controlServo(mouthServo, 90); // Static position for mouth
controlServo(chestServo, 90); // Static position for chest
controlServo(bellyServo, 90); // Static position for belly
controlServo(footServo, 90); // Static position for foot
controlServo(micServo, 90); // Static position for mic
}
// Function to control a servo based on frame data
void controlServo(uint8_t servoNum, const float servoData[], int frameNumber) {
float rotationData;
memcpy_P(&rotationData, &servoData[frameNumber % 2000], sizeof(float)); // Modulo operation for looping animation data
uint16_t pulseWidth = map(rotationData, 0, 180, SERVOMIN, SERVOMAX);
pwm.setPWM(servoNum, 0, pulseWidth);
}
// Overloaded function to control a servo to a specific position
void controlServo(uint8_t servoNum, float position) {
uint16_t pulseWidth = map(position, 0, 180, SERVOMIN, SERVOMAX);
pwm.setPWM(servoNum, 0, pulseWidth);
}
// Map a value from one range to another
long map(long x, long in_min, long in_max, long out_min, long out_max) {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}