Music and animation get out of sync

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 :slight_smile:

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;
}

ChatGPT.

QED

Try this: form an idea, try to write small chunks of code that work, then try to make the chunks work with the hardware, then try to make the chunks and the hardware work together... all the while, having the option to ask for help, here. In the mean time, ask ChatGPT why it is lousy at writing code.

3 Likes

add Serial.println information to code sequences so you can follow what your program is doing when you perform a specific action.
Add more and more Serial.println() information to get rid of your "blindness".

Hello glennmel

My standard advice:

Keep asking the robot until he/she/it gives you the correct result you expect.

One answer could probably be 42.

We are not a CharGPT repair service.

Hhehe. It is lousy but better than me. I have to say, as a non-programmer (animator by trade) I have learned a lot from asking it, but now I'm begining to wonder if I'm learning some bad habits.

Thanks.

Hello @glennmel - Anything that you write is better than anything a robot writes. Animation is a precision art. So is programming. The robot did not know or learn anything it wrote, it repeated numbers. It saw Arduino have pins numbering 0 to 13, so repeated to you Pin 0, Pin1... but you, as a human can take my words, "Pin 0 and Pin 1 are used for USB communication between host and Arduino, and not to be used in sketches while the using USB cable," and learn from it. You have just out-classed the multi-zillion-zloty AI, forever. Robots never learn, they just repeat. I spent hours of my days teaching a young "AI" bot that it was a refrigerator. GIGO is a real thing in robots. Garbage-in, garbage-out. Now, ask it to make a cake, and it will be "good enough" - flour, water, eggs, leaven, heat. It might be a pizza, it might be bread, it might be cake, but close enough.

You would like to press a button, play sound, move some servos. Two of those are great starter projects, the music not so much.

In your IDE, got to FILE >> EXAMPLES >> BUILT=IN >> DIGITAL >> BUTTON (or something like that). It has code and explanation why things are happening. You can find all those "BUILT-IN" examples on the Arduino web site (in three places):

Here: https://docs.arduino.cc/built-in-examples/

Here: https://www.arduino.cc/en/Tutorial/BuiltInExamples

Here: https://www.arduino.cc/en/Tutorial/HomePage

And you can ask questions at any stage... you do not need to be a rocket scientist to make arugula salad.

1 Like

Thank you for taking the time. I appreciate it and your kind suggestions.

For the record, I originally wrote my own code, learning from examples until it worked perfectly. But I was unhappy with the messy breadboard tangle of wires so I moved over to a pwm unaware it was fried, and couldn’t work out why it wasn’t working. That’s when I leaned into the ai for suggestions.

As someone who is totally new to this I’m pretty proud of myself for learning it on my own up to the point that I was truly stuck without asking, drawing through this forum to find the answers from past posts.

I’ll move the PIN numbers away from 0 and 1 and see what happens.

Thanks again.

Very good. I am sure you will do well in your new artform.

When you post questions, include diagrams with pin numbers, the devices and their datasheet (search: "device part number" datasheet), and the code you have. The more complete the information, the better the results.

Will do

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