Play music file on computer through Arduino UNO?

The project is a robotic arm that is supposed to move in sync with music. The music will be a file on my computer.
I've written some code to control 5 different servos on Arduino UNO, now I would like to communicate between the Arduino and an MQTT broker to be able to play a music file on the computer while starting the Arduino.

Can I use Arduino UNO and an MQTT library or do I have to switch to an ESP8266 nodemcu? This code does not seem to work on the esp, the servos do not move and there is no error.

Here is the UNO code to control the robot:

#include <Servo.h>

int moves[][5] = { // array with each servo's angle for each step/move
  // repetition means no move

  {1, 45, 45}, // motor 4 and 5: 90 no move, +/- decides direction
  {180, 70, 90},
  {120, 100, 180}, // 4, 5: 1 unit is 1/4 pi.
  /*{1, 100, 180},
  {1, 135, 180},
  {1, 135, 180},
  {1, 100, 180},
  {1, 100, 180}, 
  {1, 100, 180}*/
};


int beats[] = { // beats per step/move. nr 0 is getting to start position..
  4, 4, 4
};


class Dancer // creates a class to keep all functions necessary
{
    Servo servo;              // the servo
    int pos;                  // current servo position
    int increment;            // increment to move for each interval (0, -1 or 1)
    float updateInterval;     // interval between updates, ms
    unsigned long lastUpdate; // last update of position, ms
    float bps;                // beats per second
    float mspb;               // milliseconds per beat
    int degrees;              // degrees to move
    long startMillis;         // milliseconds at start of each move
    int angle;                // destination angle
    int beats;                // beats for said move
    int msTot;                // total milliseconds
    float w;   

  public:
    Dancer(int bpm, float ws) // initiates each servo, and calculates mspb
    {
      bps = bpm / 60;
      mspb = 1000 / bps;

      w = ws;
    }


    void Attach(int pin) // attaches each servo to respective pin in setup
    {
      servo.attach(pin);
    }

    void write(int rotate)
    {
      servo.write(rotate);
    }


    void contValues(int vinkel) // decide direction and set start time.
    // use 'takter'? can be longer and shorter...
    {
      msTot = vinkel * w; // time for movement

      if (vinkel == 90)
      {
        angle = 90;
      }

      else if (vinkel > 1)
      {
        angle = 180;
      }

      else if (vinkel < 1)
      {
        angle = 0;
      }

      startMillis = millis();

    }


    void Increment(int vinkel, int takter)  // calculates increment and updateInterval
    { // by given values (angle and beats)

      angle = vinkel;
      beats = takter;

      msTot  = beats * mspb;
      pos = servo.read();

      if (angle == pos) { // if the servo shouldn't move, increment = 0
        // servo increments one time (degrees = 1)
        degrees = 1;
        increment = 0;
      }

      else if (angle > pos) { // either ++ or -=1.

        degrees = angle - pos;
        increment = 1;
      }

      else if (angle < pos) {

        degrees = pos - angle;
        increment = -1;
      }
      updateInterval = msTot / degrees; // time between each update.

      startMillis = millis();
    }


    int Update() { // updates the servo

      pos = servo.read();

      if (pos == angle) { // if the angle has been reached (ms not precise)

        increment = 0;
      }

      if ((millis() - lastUpdate) >= updateInterval) { // time to update

        lastUpdate = millis();  // 'reset' lastUpdate
        pos += increment;       // increase/decrease pos
        servo.write(pos);       // update servo

        Serial.println(pos);            // check the values in monitor
        Serial.println(lastUpdate);
        Serial.println(updateInterval);
        Serial.println(msTot);
      }

      if ((millis() - startMillis) >= msTot) { // if the total time has run, break while loop
        return 1;
      }

      else { // otherwise, keep looping
        return 0;
      }
    }


    int contServo()
    { // update continuous servo

      servo.write(angle); // direction, 0, 180 or 90. maxspeed.

      if ((millis() - startMillis) > msTot) // if position is reached, stop rotating
      {
        angle = 90; // stop servo
        return 1; // ready
      }

      else
      {
        return 0; // keep looping
      }
    }
};
// end of class

int antalSteg = sizeof(beats) / sizeof(beats[0]); // amount of steps/moves
int bpm = 94; // a song's bpm, different for each
int i = 0; // int to for-loop and iterations.
float w = 0.25; // 1/4 pi / sec. 1 unit is 1/4 pi, 45 deg.

int b; // ints to break while-loop
int s;
int e;
int n;
int h;

Dancer base(bpm, w);     // creates an instance of each servomotor/joint
Dancer shoulder(bpm, w); // passing the 'bpm' and 'w' argument
Dancer elbow(bpm, w);
Dancer neck(bpm, w);
Dancer head(bpm, w);


void setup()
{
  WiFi.begin(ssid, password);
  Serial.begin(9600); // initiate Serial monitor

  base.Attach(2);      //D4 // calls the function Attach
  shoulder.Attach(0);  // D3attaches each servo to resp pin
  elbow.Attach(16); //D0
  neck.Attach(3);
  head.Attach(6);

  base.write(0);
  shoulder.write(0);
  elbow.write(0);

  delay(2000);
  
}


void loop()
{

  for (i; i < antalSteg; i++) { // iterates for each step

    base.Increment(moves[i][0], beats[i]);      // calls function Increment
    shoulder.Increment(moves[i][1], beats[i]);  // passes arguments angle and beats
    elbow.Increment(moves[i][2], beats[i]);     // from the arrays moves and beats
    // neck.Increment(moves[i][3], beats[i]);
    // head.Increment(moves[i][4], beats[i]);

    b, s, e = 0; // reset the ints to 0

    while (b + s + e/* + n + h */< 3) { // loops the Update function
      // if all return 1, break loop
      b = base.Update();
      s = shoulder.Update();  // updates the servo accordingly
      e = elbow.Update();     // returns either value 1 or 0
      //n = neck.Update();
      //h = head.Update();
    }
  }
}

(Code tags added by Moderator)

If you are going to do MQTT messaging, then you can't use the UNO. The NodeMCU is a good option, but the pin numbers will be different from the UNO.

Okay, thank you for your response. Are there any other differences between a UNO and nodemcu that I should be aware of? I have previously worked with both, but separately, so I have never had to change with a functioning code.

The NodeMCU only has one analog port. Change your GPIO port assignments and you should be OK.

Okay, thank you very much!

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