Multiple servos running simultaneously

That is a nice video Liamviney. Seems you do nicer mechnic/hardware than I do. On the other hand I do programs a little better. Each to their own.

I've followed this thread and you are still miles off getting the code you need. I think the end result is more important for you than the joy of getting the program to work, so I have been so presumptious to write the code. Call it my contribution to the arts :slight_smile:

You still need to understand it to change it, I've tried not to use to much advanced C. It is easily modified to 4, 5 ... 11 servos, just change the #define at the top and the list of pin numbers to match. You can easily extend it to more "programs", just add more case 'x':{ ... } sections.

It compiles, but I have not tested the code. (I do have 3servos, but dont have time to set anything up at the moment).

Use at Your Risk. Your milage may vary. Do not wash in water above 50 degrees ...

/* Multiple Servos - written by MSquare for liamviney for a dynamic sculpture */

#include <Servo.h>
#define MAXSRV 3  // Adjust for number of servos. Adjust SrvPin list to match !
Servo Srv[MAXSRV];  // Set up for controlling 3 servos (max servos possible depends on Arduino type)
const int SrvPin[] = { 9, 10, 11 } ; //, 12, 8, 7, 6, 5, 4, 14, 15, 16 } ; // list of pins for each servo 

int Dir[MAXSRV] ; // current direction of Srv[i]
int Low[MAXSRV] ; // Low value where a servo changes direction
int Hi[MAXSRV] ; // High value where servo changes direction
unsigned long Tmr[MAXSRV] ; // timer value for each servo
unsigned long Slw[MAXSRV] ; // Slowness of each servo - number of millisecs between each degree step

char inchar ; // character read from Serial

/*   ==== Setup  ==== */
void setup() {
  for (int i=0; i<MAXSRV; i++ ) {
    Srv[i].attach(SrvPin[i]) ; 
    Srv[i].write(90) ;  // the servo will go to 90 reagrdless, but this initialises a variable we want to read inside Servo
    Dir[i] = 1 ; Low[i] = 45 ; Hi[i]= 135; Slw[i] = 20 ; // They will move in total unison
    delay(250) ; // without this *all* servos will snap to middle position almost simultaneously - overloading mechanics or powersupply
  }
  Serial.begin(19200);
}

/* === Main loop === */
void loop() {

/* == Input character & set "program" == */

  if (Serial.available() > 0 ) {
    inchar = Serial.read();
    Serial.println(inchar,BYTE); // echo the character
    // depending on the character we reprogram the current position, endstops and speed of each servo
    for ( int i=0; i<MAXSRV; i++ ) {
      switch (inchar) {
        case '1' : {
          Srv[i].write(45+i*5) ; // snap to someting in range 45-110
          Dir[i] = (i%2)*2-1 ;   // Sets direction alternating -1, 1
          Hi[i] = 135 ; Low[i] =45 ; Slw[i] = 40 ;
          break ; }
        case '2' : {
          Srv[i].write(90) ;     // snap to 90
          Dir[i] = 1 ; Low[i] = 85-i*5 ; Hi[i]=93+i*3 ; // Just so we get different values ....
          Slw[i] = i*10+30 ;     // Differnet speed for each servo
          break ; }
      } // end switch
      delay(150) ; // small delay bewteen each Srv.write() to avoid all servos jerking at once
    }// end loop
  }

/* == Move all servos one "step", if needed == */

  for ( int i=0 ; i<MAXSRV; i++ ) {
    if (millis() - Tmr[i] > Slw[i]) {   // is it time for this servo to move?
      int Pos = Srv[i].read() ;         // This is the last write() we gave to this servo
      if ( Pos < Low[i] ) Dir[i] = 1 ;  // time to change direction?
      if ( Pos > Hi[i]  ) Dir[i] = -1 ; //    -"-
      Srv[i].write( Pos+Dir[i] ) ;      // move the servo a tiny amount (this updates the .read() for next time)
      Tmr[i] = millis() ;               // reset the timer
    }
  }
  
/* == End of main loop == */  
}