rotazione sincronizzata di due differenti ring Neopixels

Non credo sia un problema di questo progetto specifico considerano che magari non starà acceso giorni e giorni ma la forma corretta per gestire "l'overflow" di millis() è:
millis() - tempo_precedente > intervallo (o >= poco importa)

si, hai perfettamente ragione , ho sbagliato io a scrivere.
grazie per la segnalazione, ho corretto.

Grazie infinite, è perfetto. Sono riuscito perfettamente ad adattare e ad aggiungere anche altre funzioni seguendo i vostri consigli!!

Ottimo.
Una volta capito il meccanismo non è poi così complicato :wink:

Non so se è chiedere troppo ma sto cercando di implementare questo programma trovato su internet per eseguire il cambio di colore:

#include <Adafruit_NeoPixel.h>

#define PIN 7
#define STRIPSIZE 24

// Parameter 1 = number of pixels in strip
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
Adafruit_NeoPixel destra = Adafruit_NeoPixel(STRIPSIZE, PIN, NEO_GRBW + NEO_KHZ800);

void setup() {
  destra.begin();
  destra.setBrightness(25);  // Lower brightness and save eyeballs!
  destra.show(); // Initialize all pixels to 'off'
}

void loop() {
  // Some example procedures showing how to display to the pixels:
  rainbow(15);
}


void rainbow(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256; j++) {
    for(i=0; i<destra.numPixels(); i++) {
      destra.setPixelColor(i, Wheel((j) & 255));
    }
    destra.show();
    delay(wait);
  }
}

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  if(WheelPos < 85) {
   return destra.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } else if(WheelPos < 170) {
   WheelPos -= 85;
   return destra.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else {
   WheelPos -= 170;
   return destra.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}

byte trigScale(float val) {
  val += 1.0; // move range to [0.0, 2.0]
  val *= 127.0; // move range to [0.0, 254.0]

  return int(val) & 255;
}

/**
 * Map an integer so that [0, striplength] -> [0, 2PI]
 */
float map2PI(int i) {
  return PI*2.0*float(i) / float(destra.numPixels());
}

Questo programma funziona benissimo se lo eseguo.
Ho quindi provato ad unirlo al mio copiando e adattando le parti necessarie e ho ottenuto questo:

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif

#define PixelCount 24
#define PixelCountp 16
#define MILLIS_PASSO 30 // Ho moltiplicato per 10 per rallentare e vedere i singoli passi a velocità umana.
#define PASSI_STEP_GRANDE 2
#define PASSI_STEP_PICCOLO 3

Adafruit_NeoPixel destra = Adafruit_NeoPixel(PixelCount, 7, NEO_GRBW + NEO_KHZ800);
Adafruit_NeoPixel destrap = Adafruit_NeoPixel(PixelCountp, 4, NEO_GRBW + NEO_KHZ800);

unsigned long lastMillisCerchioGrande = 0;
unsigned long lastMillisCerchioPiccolo = 0;
/*uint32_t color= 0x800080;*/
uint16_t j;
uint8_t currentPos;
uint8_t currentPosp;

void setup() {
  Serial.begin(9600);
  destra.begin();
  destra.setBrightness(55);
  destrap.begin();
  destrap.setBrightness(55);
  unsigned long currMillis = millis(); // Solo per avere lo stesso valore su tutte le assegnazioni. Pignoleria mia.
  lastMillisCerchioGrande = currMillis;
  lastMillisCerchioPiccolo = currMillis;  
}

void loop() {
  unsigned long currMillis = millis(); // Solo per avere lo stesso valore su tutte le operazioni. Pignoleria mia.
  avanzaCerchioGrande(currMillis);
  avanzaCerchioPiccolo(currMillis);
  for(j=0; j<256; j++);
}


uint32_t color(byte WheelPos) {
  if(WheelPos < 85) {
   return destra.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else if(WheelPos < 170) {
   WheelPos -= 85;
   return destra.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } else {
   WheelPos -= 170;
   return destra.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}

void avanzaCerchioGrande(unsigned long curr) {
  if (curr - lastMillisCerchioGrande >= MILLIS_PASSO * PASSI_STEP_GRANDE) {
    // Logica di avanzamento di un passo del cerchio grande.
    /*
     * 
     */
   /* Serial.print("G");*/
  if(++currentPos >= PixelCount){
    currentPos = 0;
  }
   destra.setPixelColor((currentPos + PixelCount - 1) % PixelCount, 0);
  destra.setPixelColor((currentPos + PixelCount + 0) % PixelCount, 0);
  destra.setPixelColor((currentPos + PixelCount + 1) % PixelCount, 0);
  destra.setPixelColor((currentPos + PixelCount + 2) % PixelCount, 0);
  destra.setPixelColor((currentPos + PixelCount + 3) % PixelCount, 0);
  destra.setPixelColor((currentPos + PixelCount + 4) % PixelCount, 0);
  destra.setPixelColor((currentPos + PixelCount + 5) % PixelCount, 0);
  destra.setPixelColor((currentPos + PixelCount + 6) % PixelCount, 0);
  destra.setPixelColor((currentPos + PixelCount + 7) % PixelCount, 0);
  destra.setPixelColor((currentPos + PixelCount + 8) % PixelCount, color(j & 255));
  destra.setPixelColor((currentPos + PixelCount + 9) % PixelCount, color(j & 255));
  destra.setPixelColor((currentPos + PixelCount + 10) % PixelCount, color(j & 255));
  destra.setPixelColor((currentPos + PixelCount + 11) % PixelCount, color(j & 255));
  destra.setPixelColor((currentPos + PixelCount + 12) % PixelCount, 0);
  destra.setPixelColor((currentPos + PixelCount + 13) % PixelCount, 0);
  destra.setPixelColor((currentPos + PixelCount + 14) % PixelCount, 0);
  destra.setPixelColor((currentPos + PixelCount + 15) % PixelCount, 0);
  destra.setPixelColor((currentPos + PixelCount + 16) % PixelCount, 0);
  destra.setPixelColor((currentPos + PixelCount + 17) % PixelCount, 0);
  destra.setPixelColor((currentPos + PixelCount + 18) % PixelCount, 0);
  destra.setPixelColor((currentPos + PixelCount + 19) % PixelCount, 0);
  destra.setPixelColor((currentPos + PixelCount + 20) % PixelCount, color(j & 255));
  destra.setPixelColor((currentPos + PixelCount + 21) % PixelCount, color(j & 255));
  destra.setPixelColor((currentPos + PixelCount + 22) % PixelCount, color(j & 255));
  destra.setPixelColor((currentPos + PixelCount + 23) % PixelCount, color(j & 255));     
    lastMillisCerchioGrande += MILLIS_PASSO * PASSI_STEP_GRANDE;
  }
  destra.show();
  destrap.show();
}

void avanzaCerchioPiccolo(unsigned long curr) {
  if (curr - lastMillisCerchioPiccolo >= MILLIS_PASSO * PASSI_STEP_PICCOLO) {
    // Logica di avanzamento di un passo del cerchio grande.
    /*
     * 
     */
   /* Serial.print("P");*/
  if(++currentPosp >= PixelCountp){
    currentPosp = 0;
  }
   destrap.setPixelColor((currentPosp + PixelCountp - 1) % PixelCountp, 0);
  destrap.setPixelColor((currentPosp + PixelCountp + 0) % PixelCountp, 0);
  destrap.setPixelColor((currentPosp + PixelCountp + 1) % PixelCountp, 0);
  destrap.setPixelColor((currentPosp + PixelCountp + 2) % PixelCountp, 0);
  destrap.setPixelColor((currentPosp + PixelCountp + 3) % PixelCountp, 0);
  destrap.setPixelColor((currentPosp + PixelCountp + 4) % PixelCountp, 0);
  destrap.setPixelColor((currentPosp + PixelCountp + 5) % PixelCountp, color(j & 255));
  destrap.setPixelColor((currentPosp + PixelCountp + 6) % PixelCountp, color(j & 255));
  destrap.setPixelColor((currentPosp + PixelCountp + 7) % PixelCountp, color(j & 255));
  destrap.setPixelColor((currentPosp + PixelCountp + 8) % PixelCountp, 0);
  destrap.setPixelColor((currentPosp + PixelCountp + 9) % PixelCountp, 0);
  destrap.setPixelColor((currentPosp + PixelCountp + 10) % PixelCountp, 0);
  destrap.setPixelColor((currentPosp + PixelCountp + 11) % PixelCountp, 0);
  destrap.setPixelColor((currentPosp + PixelCountp + 12) % PixelCountp, 0);
  destrap.setPixelColor((currentPosp + PixelCountp + 13) % PixelCountp, color(j & 255));
  destrap.setPixelColor((currentPosp + PixelCountp + 14) % PixelCountp, color(j & 255));
  destrap.setPixelColor((currentPosp + PixelCountp + 15) % PixelCountp, color(j & 255));
    lastMillisCerchioPiccolo += MILLIS_PASSO * PASSI_STEP_PICCOLO;
  }
  destra.show();
  destrap.show();
}

byte trigScale(float val) {
  val += 1.0; // move range to [0.0, 2.0]
  val *= 127.0; // move range to [0.0, 254.0]

  return int(val) & 255;
}

/**
 * Map an integer so that [0, striplength] -> [0, 2PI]
 */
float map2PI(int i) {
  return PI*2.0*float(i) / float(destra.numPixels());
}

Il risultato è soltanto un singolo colore che rimane fisso,anche se non è mai stato impostato se non con il codice copiato. C'è qualcosa che dovrei scrivere in più? Perchè nel programma funzionante non c'è nient'altro e funziona comunque?

Ti sembrerò scortese ma ti dirò solo quello che in realtà è, se continui a copiaincollare codice di altri senza capire cosa stai facendo non caverai mai un ragno dal buco, e il tuo post è la conferma di ciò che ti sto dicendo righe del tipo

for(j=0; j<256; j++);

sono messe li a casaccio senza un reale motivo solo perché nell'altro programma era presente il for (con un motivo specifico) non è copiando pari pari che otttieni il risultato.
Il programma che hai guardato ha una logica differente rispetto al tuo (o quantomeno è implementato in modo differente) quindi non riuscirai ad adattarlo semplicemente copiandolo.
Quindi poniti la domanda come voglio che cambi il colore? Parte il giro con un colore e man mano che avanza deve variare? Deve variare ad ogni giro completo?
Hai usato la funzione volor (solo su tre pixel ma vabbé non è chiaro perché ma non è li il problema) guarda il parametro che usi e prova a controllare il flusso del programma, dovresti riuscire a capire come mai il colore non varia mai

No, non sei scortese, hai ragione. Non è così che imparo. Lo scrivere qui sul forum è la mia ultima spiaggia, prima di scrivere passo ore a provare a cercare di capire cosa serve una tale funzione (spesso con risultati insufficienti è vero). In questo caso ho capito che la sezione

uint32_t Wheel(byte WheelPos) {
  if(WheelPos < 85) {
   return destra.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } else if(WheelPos < 170) {
   WheelPos -= 85;
   return destra.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else {
   WheelPos -= 170;
   return destra.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}

Serve per attribuire dei valori a wheel o a color a seconda del programma e anche che l'incremento di j serve per avere l'aumento dei valori del colore. Però, con tutto il rispetto, se non vuoi darmi la soluzione con una spiegazione dei motivi dei miei errori per farmi imparare e correggere l'errore anche il semplice dirmi "hai sbagliato, i programmi hanno due logiche diverse. Dovresti riguardare cosa hai scritto" non mi aiuta perché da solo non riesco a capire il perché è sbagliato in quanto il mio pensiero non è ancora sintonizzato sulla logica di Arduino. Quindi se ho due programmi e mi sembrano simili, nel senso che mi sembra di seguire tutti i ragionamenti fatti per il programma funzionante, almeno prova a spiegarmi il perché è errato in modo tale magari di farmi capire come correggere

ok forse era un po' troppo criptico da comprendere, non incrementi mai j che usi come parametro della funzione color.

Quindi dovrei incrementare j nei void tipo avanzaCerchioGrande come nel programma funzionante? Ci avevo già provato ma il risultato non cambiava, anzi, mi capitavano messaggi di errore dove uno dei due void diceva di non essere specificato. Anche se quelle parti di programma non venivano minimamente modificate però, come mai mi succedeva?

Senza sapere gli errori e come avevi fatto la modifica è impossibile dare una risposta.
I messaggi d'errori li avevi per le modifiche apportate alle funzioni, funzioni non void. void è il tipo della funzione, ovvero una funzione che non restituisce nulla.
Fai le modifiche e in caso d'errori posta il codice e l'errore che riscontri

unsigned long lastMillisCerchioGrande = 0;
unsigned long lastMillisCerchioPiccolo = 0;
/*uint32_t color= 0x800080;*/
uint8_t currentPos;
uint8_t currentPosp;

void setup() {
  Serial.begin(9600);
  destra.begin();
  destra.setBrightness(55);
  sinistra.begin();
  sinistra.setBrightness(55);
  destrap.begin();
  destrap.setBrightness(55);
  sinistrap.begin();
  sinistrap.setBrightness(55);
  unsigned long currMillis = millis(); // Solo per avere lo stesso valore su tutte le assegnazioni. Pignoleria mia.
  lastMillisCerchioGrande = currMillis;
  lastMillisCerchioPiccolo = currMillis;  
}

void loop() {
  unsigned long currMillis = millis(); // Solo per avere lo stesso valore su tutte le operazioni. Pignoleria mia.
  avanzaCerchioGrande(currMillis);
  avanzaCerchioPiccolo(currMillis);
}


uint32_t color(byte WheelPos) {
  if(WheelPos < 85) {
   return destra.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else if(WheelPos < 170) {
   WheelPos -= 85;
   return destra.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } else {
   WheelPos -= 170;
   return destra.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}

void avanzaCerchioGrande(unsigned long curr) {
uint16_t j;

  if (curr - lastMillisCerchioGrande >= MILLIS_PASSO * PASSI_STEP_GRANDE) {
    // Logica di avanzamento di un passo del cerchio grande.
    /*
     * 
     */
   /* Serial.print("G");*/
  if(++currentPos >= PixelCount){
    currentPos = 0;
  }
  for(j=0; j<256; j++){
   destra.setPixelColor((currentPos + PixelCount - 1) % PixelCount, 0);
[...]
  destra.setPixelColor((currentPos + PixelCount + 7) % PixelCount, 0);
  destra.setPixelColor((currentPos + PixelCount + 8) % PixelCount, color(j & 255));
  destra.setPixelColor((currentPos + PixelCount + 9) % PixelCount, color(j & 255));
  destra.setPixelColor((currentPos + PixelCount + 10) % PixelCount, color(j & 255));
  destra.setPixelColor((currentPos + PixelCount + 11) % PixelCount, color(j & 255));
  destra.setPixelColor((currentPos + PixelCount + 12) % PixelCount, 0);
[...]
  destra.setPixelColor((currentPos + PixelCount + 19) % PixelCount, 0);
  destra.setPixelColor((currentPos + PixelCount + 20) % PixelCount, color(j & 255));
  destra.setPixelColor((currentPos + PixelCount + 21) % PixelCount, color(j & 255));
  destra.setPixelColor((currentPos + PixelCount + 22) % PixelCount, color(j & 255));
  destra.setPixelColor((currentPos + PixelCount + 23) % PixelCount, color(j & 255));   
   sinistra.setPixelColor((-currentPos + PixelCount - 1) % PixelCount, 0);
[...]
  sinistra.setPixelColor((-currentPos + PixelCount + 7) % PixelCount, 0);
  sinistra.setPixelColor((-currentPos + PixelCount + 8) % PixelCount, color(j & 255));
  sinistra.setPixelColor((-currentPos + PixelCount + 9) % PixelCount, color(j & 255));
  sinistra.setPixelColor((-currentPos + PixelCount + 10) % PixelCount, color(j & 255));
  sinistra.setPixelColor((-currentPos + PixelCount + 11) % PixelCount, color(j & 255));
  sinistra.setPixelColor((-currentPos + PixelCount + 12) % PixelCount, 0);
[...]
  sinistra.setPixelColor((-currentPos + PixelCount + 19) % PixelCount, 0);
  sinistra.setPixelColor((-currentPos + PixelCount + 20) % PixelCount, color(j & 255));
  sinistra.setPixelColor((-currentPos + PixelCount + 21) % PixelCount, color(j & 255));
  sinistra.setPixelColor((-currentPos + PixelCount + 22) % PixelCount, color(j & 255));
  sinistra.setPixelColor((-currentPos + PixelCount + 23) % PixelCount, color(j & 255));  
  }
    lastMillisCerchioGrande += MILLIS_PASSO * PASSI_STEP_GRANDE;
  destra.show();
  sinistra.show();
  destrap.show();
  sinistrap.show();
}
}

void avanzaCerchioPiccolo(unsigned long curr) {
  uint16_t j;
  if (curr - lastMillisCerchioPiccolo >= MILLIS_PASSO * PASSI_STEP_PICCOLO) {
    // Logica di avanzamento di un passo del cerchio grande.
    /*
     * 
     */
   /* Serial.print("P");*/
  if(++currentPosp >= PixelCountp){
    currentPosp = 0;
  }
  for(j=0; j<256; j++){
   destrap.setPixelColor((currentPosp + PixelCountp - 1) % PixelCountp, 0);
[...]
  destrap.setPixelColor((currentPosp + PixelCountp + 4) % PixelCountp, 0);
  destrap.setPixelColor((currentPosp + PixelCountp + 5) % PixelCountp, color(j & 255));
  destrap.setPixelColor((currentPosp + PixelCountp + 6) % PixelCountp, color(j & 255));
  destrap.setPixelColor((currentPosp + PixelCountp + 7) % PixelCountp, color(j & 255));
  destrap.setPixelColor((currentPosp + PixelCountp + 8) % PixelCountp, 0);
[...]
  destrap.setPixelColor((currentPosp + PixelCountp + 12) % PixelCountp, 0);
  destrap.setPixelColor((currentPosp + PixelCountp + 13) % PixelCountp, color(j & 255));
  destrap.setPixelColor((currentPosp + PixelCountp + 14) % PixelCountp, color(j & 255));
  destrap.setPixelColor((currentPosp + PixelCountp + 15) % PixelCountp, color(j & 255));
   sinistrap.setPixelColor((-currentPosp + PixelCountp - 1) % PixelCountp, 0);
[...]
  sinistrap.setPixelColor((-currentPosp + PixelCountp + 4) % PixelCountp, 0);
  sinistrap.setPixelColor((-currentPosp + PixelCountp + 5) % PixelCountp, color(j & 255));
  sinistrap.setPixelColor((-currentPosp + PixelCountp + 6) % PixelCountp, color(j & 255));
  sinistrap.setPixelColor((-currentPosp + PixelCountp + 7) % PixelCountp, color(j & 255));
  sinistrap.setPixelColor((-currentPosp + PixelCountp + 8) % PixelCountp, 0);
[...]
  sinistrap.setPixelColor((-currentPosp + PixelCountp + 12) % PixelCountp, 0);
  sinistrap.setPixelColor((-currentPosp + PixelCountp + 13) % PixelCountp, color(j & 255));
  sinistrap.setPixelColor((-currentPosp + PixelCountp + 14) % PixelCountp, color(j & 255));
  sinistrap.setPixelColor((-currentPosp + PixelCountp + 15) % PixelCountp, color(j & 255));
  }
    lastMillisCerchioPiccolo += MILLIS_PASSO * PASSI_STEP_PICCOLO;
  destra.show();
  sinistra.show();
  destrap.show();
  sinistrap.show();
}
}

byte trigScale(float val) {
  val += 1.0; // move range to [0.0, 2.0]
  val *= 127.0; // move range to [0.0, 254.0]

  return int(val) & 255;
}

/**
 * Map an integer so that [0, striplength] -> [0, 2PI]
 */
float map2PI(int i) {
  return PI*2.0*float(i) / float(destra.numPixels());
}

Questo era il programma che avevo fatto prima di quello postato precedentemente.Era stato fatto cercando di mantenermi fedele al programma di esempio. L'ho scartato in quanto, oltre a non avere un cambio del colore, mi rallenta anche l'avanzamento dei led infatti ho optato per la progressione di j nel loop per avere la velocità giusta. Immagino che il rallentamento sia dovuto al fatto che prima di passare all'azione successiva deve completare tutto il processo di for no? Qualche consiglio per migliorare?
(Ho tagliato alcune parti per rientrare nei caratteri: fino alla definizione dei led che era uguale al post precedente e le parti "[...]" che erano uguali)