Effetto Onda con Servomotori

Ciao a tutti,
Per un progetto ho bisogno di poter comandare 5 servomotori con un effetto "Onda".
Quello che intendo è che date 5 ampiezze di movimento dei motori, differenti per ogni motore, loro eseguano il loro movimento partendo ad intervalli di tempo prestabiliti. Ed inoltre che il movimento sia fluido.
Al momento per avere un movimento fluido uso cicli, come for e while per gestire l'invio dei .write().

Ho fatto delle prove per con delay() ma come poi ho scoperto questa funzione attende l'esecuzione dell'operazione precedente prima di continuare. Quindi i motori non si muovono simultaneamente.

Una cosa che non ho specificato è che se non è possibile gestire gli intervalli tramite il tempo, va bene anche gestirli rispetto alla rotazione del servo precedente.

Quello che vi chiedo è su cosa devo orientarmi per realizzare un'applicazione del genere, ci sono delle funzioni/librerie dedicate oppure dei trucchetti?

Quello che intendo, parlando di spostamenti dei servo è questo:

Servo1:-----1234567---------------------------------------------------
Servo2:-----------123456789------------------------------------------
Servo3:----------------1234--------------------------------------------
Servo4:--------------------123456-------------------------------------
Servo5:----------------------------123---------------------------------

Dove con i tratteggi intendo "il servo è fermo" e con i numeri "il servo avanza di: #"

Grazie mille per l'attenzione :wink:

Come dice sempre Guglielmo...

Devi studiarti come si usa la millis(), prima QUI, poi QUI ed infine leggi anche QUI e QUI

Poi al limite posta lo skecth così si può ragionare su qualcosa di concreto.

Grazie, il mio problema è che non sapevo proprio dell'esistenza di una funzione che potesse gestire queste cose.

Ho fatto una prova e sono riuscito ad ottenere l'effetto desiderato, utilizzando millis().
Il problema è che il codice è proprio brutto da vedere e sono sicuro che si potrebbe snellire in qualche operazione.
Di questo ne risente il movimento dei servo che non è fluido quando si stanno muovendo tutti e 5.
Avete qualche consiglio?

int start[9][5] =  { ...  {50,  50,  30, 130, 95}  ... };
int finish[9][5] =  { ... {140,  180,  150, 30,  1} ... }
int angle[5];
int servodelay = 50;
int servostep = 1;
unsigned long startMillis;
unsigned long currentMillis;
const unsigned long period[5] = {20000, 20000, 20000, 20000, 20000}; \\ durata del movimento
int interval[5] = {0, 2000, 4000, 6000, 8000}; \\ instanti di partenza


void setup() {
  s1.attach(13);  s1.write(start[0][0]);
  s2.attach(12);  s2.write(start[0][1]);
  s3.attach(9);   s3.write(start[0][2]); 
  s4.attach(10);  s4.write(start[0][3]);
  s5.attach(11);  s5.write(start[0][4]); 
}
void loop() {
...

  startMillis = millis();

...

while ((angle[0] < finish[6][0]) || (angle[1] < finish[6][1]) || (angle[2] < finish[6][2]) || (angle[3] > finish[6][3]) || (angle[4] > finish[6][4]) ) {
          currentMillis = millis();  //get the current time
          if ((currentMillis - startMillis > interval[0]) && (currentMillis - startMillis < period[0] + interval[0])) {
            s1.write(angle[0]);
            delay(servodelay);
            angle[0] += servostep;
            currentMillis = millis();
          }
          if ((currentMillis - startMillis > interval[1]) && (currentMillis - startMillis < period[1] + interval[1])) {
            s2.write(angle[1]);
            delay(servodelay);
            angle[1] += servostep;
            currentMillis = millis();
          }
          if ((currentMillis - startMillis > interval[2]) && (currentMillis - startMillis < period[2] + interval[2])) {
            s3.write(angle[2]);
            delay(servodelay);
            angle[2] += servostep;
            currentMillis = millis();
          }
          if ((currentMillis - startMillis > interval[3]) && (currentMillis - startMillis < period[3] + interval[3])) {
            s4.write(angle[3]);
            delay(servodelay);
            angle[3] -= servostep;
            currentMillis = millis();
          }
          if ((currentMillis - startMillis > interval[4]) && (currentMillis - startMillis < period[4] + interval[4])) {
            s5.write(angle[4]);
            delay(servodelay);
            angle[4] -= servostep;
            currentMillis = millis();
          }
        }

Dove ci sono i puntini (...) è perchè ci sono altri pezzi di codice che servono per altro.

--- ti rammento che, da regolamento, è permesso fare "up" solo dopo 48 ore dall'ultimo post. Grazie - gpb01

Ho risolto in questo modo, usando la libreria VarSpeedServo trovata su GitHub:

#include <VarSpeedServo.h> // external library for variable speed servo

VarSpeedServo s1, s2, s3, s4, s5; // servo initialization

// INTESITY PARAMETER
int start[9][5] =  {         //columns=finger(0=thumb,4=littlefinger)
  {50,  35,  35, 145, 130},  //a1      {50,  35,  35, 145, 130}
  {50,  35,  35, 145, 130},  //a2      {100, 105, 55, -105, -120}
  {50,  35,  35, 145, 130},  //a3
  {50,  35,  35, 145, 130},  //p1
  {50,  35,  35, 145, 130},  //p2
  {50,  35,  35, 145, 130},  //p3
  {50,  35,  35, 145, 130},  //w1
  {50,  35,  35, 145, 130},  //w2
  {50,  35,  35, 145, 130}   //w3
};
int amplitude [9][5] = {
  {100, 105, 55, -105, -120},//a1
  {100, 105, 55, -105, -120},//a2
  {100, 105, 55, -105, -120},//a3
  {100, 105, 55, -105, -120},//p1
  {100, 105, 55, -105, -120},//p2
  {100, 105, 55, -105, -120},//p3
  {100, 105, 55, -105, -120},//w1
  {100, 105, 55, -105, -120},//w2
  {100, 105, 55, -105, -120},//w3
};

// wave exercise starting intervals
int interval[10] = {   0,    1000, 2000,  3000,  4000, // close
                       7000, 8000, 9000, 10000, 11000  // open
                   };

void(* software_reboot)(void) = 0; // reboot function

int servospeed = 20;               //speed of the servos
int rip;                           // number of repetitions
int i = 0;                         //repetitions counter
int j = 0;                         //intensity counter
char READ[20];                     //serial read array
unsigned long startMillis;         //time counter for wave exercise
unsigned long currentMillis;       //time counter for wave exercise
currentMillis = millis();
    // close
    if (currentMillis - startMillis > interval[0]) {
      s1.write(start[j][0] + amplitude[j][0], servospeed);
    }
    if (currentMillis - startMillis > interval[1]) {
      s2.write(start[j][1] + amplitude[j][1], servospeed);
    }
    if (currentMillis - startMillis > interval[2]) {
      s3.write(start[j][2] + amplitude[j][2], servospeed / 2);
    }
    if (currentMillis - startMillis > interval[3]) {
      s4.write(start[j][3] + amplitude[j][3], servospeed);
    }
    if (currentMillis - startMillis > interval[4]) {
      s5.write(start[j][4] + amplitude[j][4], servospeed);
      s1.wait(); s2.wait(); s3.wait(); s4.wait(); s5.wait();
    }
    // REBOOT
    reboot;
    // open
    if (currentMillis - startMillis > interval[5]) {
      s5.write(start[j][4], servospeed);
    }
    if (currentMillis - startMillis > interval[6]) {
      s4.write(start[j][3], servospeed);
    }
    if (currentMillis - startMillis > interval[7]) {
      s3.write(start[j][2], servospeed / 2);
    }
    if (currentMillis - startMillis > interval[8]) {
      s2.write(start[j][1], servospeed);
    }
    if (currentMillis - startMillis > interval[9]) {
      s1.write(start[j][0], servospeed);
      s1.wait(); s2.wait(); s3.wait(); s4.wait(); s5.wait();
    }
    // REBOOT
    reboot;