Lampeggio indipendente LED + crossfade

Buongiorno a tutti, da tempo ho in mente di realizzare uno sketch che mi permetta di far lampeggiare indipendentemente 12 LED e contemporaneamente di far fare a 6 strisce di LED un crossfade.
Per il lampeggio sono riuscito tramite millis, ma per il crossfade non ho trovato granchè in rete, anche perchè mi piacerebbe fare una cosa particolare.
Innanzitutto il codice per il lampeggio dei LED è il seguente che per adesso è limitato a due LED giusto per fare delle prove (lo amplierò successivamente)

unsigned long t1, dt1;
unsigned long t2, dt2;

int tled1 = 600;
int tled2 = 350;

int st1 = LOW;
int st2 = LOW;

void setup() {
  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);
}

void loop() {
  dt1 = millis() - t1;
  if (dt1 > tled1) {
    st1 = !st1;
    digitalWrite(12, st1);
    t1 = millis();
  }


  dt2 = millis() - t2;
  if (dt2 > tled2) {
    st2 = !st2;
    digitalWrite(13, st2);
    t2 = millis();
  }
  
}

a questo dovrei aggiungere la possibilità di fare un crossfade tra le strisce LED; nel dettaglio:

1 - fade in striscia 1
2 - striscia 1 resta accesa un tot di minuti (es. 2 minuti)
3 - fade out striscia 1 e nel frattempo fade in striscia 2
4 - striscia 2 resta accesa altro tot di minuti diverso da striscia 1 (es. 4 minuti)
5 - fade out striscia 2 e fade in striscia 3

così per 6 strisce LED dove il tempo di fade e il tempo di accensione permanente siano impostabili singolarmente per ogni striscia.
Ho trovato tutti sketch che utilizzano il delay, ma visto il multitasking non va bene per il mio progetto, oppure con la libreria "LEDFader", ma non ho ben capito il meccanismo.
Premetto che non sono un programmatore e sono alle prime armi con un linguaggio come il C; a suo tempo avevo imparato il Pascal (scolastico) quindi qualche concetto di programmazione ce l'ho.
Aspetto qualche consiglio e magari qualche riga di codice a titolo di esempio.
Grazie a tutti

Cosa non ti è chiaro della ledfader?

Sono riuscito a dar fare al LED il fade in che poi resta acceso, gli ho fatto fare il fade in e il fade out in loop, ma non riesco a fargli fare il fade in poi acceso continuo per tot minuti e poi fade out. Non ho il codice a portata di mano, se serve posso postarlo in seguito

Devi usare dei timer sequenziali (ciclici)

Guarda qui: passo a passo a spasso

Anzi cerca "aiutateci ad aiutarvi" e segue i varii link

Scusa la curiosità, ma come li connetti questi 12 led?
Direttamente al mega?
Se è così, hai verificato di non fargli erogare troppa corrente? In caso contrario ti potrebbe uscire un bell'effetto fumo o addirittura fuoco, molto realistico ;D

Maurizio

In effetti non ho spiegato come vengono collegati; Arduino piloterà dei mosfet IRLZ44N che faranno defluire i 12V alle strisce e ai singoli LED (con opportuna resistenza in serie).
Per il lampeggio indipendente dei LED ho risolto, per il crossfade delle strisce ho trovato questo sketch senza delay che usa il millis ed è perfetto:

unsigned long grStartMillis;
unsigned long rbStartMillis;
unsigned long bgStartMillis;
unsigned long currentMillis;
const unsigned long grPeriod = 1000; 
const unsigned long rbPeriod = 1000;
const unsigned long bgPeriod = 1000;
const byte redLed = 13;   
const byte blueLed = 10;   
const byte greenLed = 9;

void setup()
{
  Serial.begin(115200);  //start Serial in case we need to print debugging info
  pinMode(redLed, OUTPUT);
  pinMode(greenLed, OUTPUT);
  pinMode(blueLed, OUTPUT);
  grStartMillis = millis();  //start time of blinking LED
  rbStartMillis = millis();  //start time of fading LED
  bgStartMillis = millis();
}

void loop()
{
  currentMillis = millis();  //get the current time
  if (currentMillis - grStartMillis >= grPeriod)  //test whether the period has elapsed
  {
    for(int i=0; i<255; i++) {
    analogWrite(redLed, i);
    analogWrite(greenLed, 255-i);
    analogWrite(blueLed, 0);
        }
    grStartMillis = currentMillis;  //IMPORTANT to save the start time of the current LED state.
  }
  if (currentMillis - rbStartMillis >= rbPeriod)  //test whether the period has elapsed
  {
     // fade from red to blue
  for(int i=0; i<255; i++) {
    analogWrite(redLed, 255-i);
    analogWrite(greenLed, 0);
    analogWrite(blueLed, i);
  }
    rbStartMillis = currentMillis;  //IMPORTANT to save the start time of the current LED state.
  }
  if (currentMillis - bgStartMillis >= bgPeriod)  //test whether the period has elapsed
  {
     // fade from red to blue
  for(int i=0; i<255; i++) {
    analogWrite(redLed, 255-i);
    analogWrite(greenLed, 0);
    analogWrite(blueLed, i);
  }
    bgStartMillis = currentMillis;  //IMPORTANT to save the start time of the current LED state.
  }
}

Mi resta solo da aggiungere un tempo di “delay” quando la striscia è al suo punto massimo di illuminazione, cioè che resti accesa per tot minuti prima di iniziare il nuovo crossfade, perchè con questo sketch il crossfade è continuo tra un colore e l’altro.

Guarda

Il crossfade non è concettualmente differente dal lampeggio

Se il lampeggio ha 2 soli stati:
Acceso e spento

Il crossfade ne avrà 4
Che saranno....

...spento, fade in, acceso, fade out...

E quindi, avendo scritto correttamente un programma che gestisce multipli timer a due stati

Ed essendo andato a vedere, con esempi, un programma che gestisce timer multipli polistadio,

Ora....

Un po' come dallo psicologo che ti fa arrivare da solo alla soluzione, ma mi piace, così si impara.
Secondo me tra un crossfade e l'altro ci vorrebbe un "if", del tipo "if led blu=255 allora tienilo acceso per 3 minuti" (che andrebbero segnati in ms); il problema adesso è tradurlo in C (a meno che la mia teoria non sia sbagliata)

Standardoil:
Guarda

Il crossfade non è concettualmente differente dal lampeggio

Il suggerimento più utile che ho ricevuto, mi ha spinto a riflettere un po’ e ora ci sto lavorando…
Grazzzzzie!!!

Ci sei poi riuscito?

Allora, innanzitutto chiedo scusa per il mancato aggiornamento, ma siccome ci lavoro a tempo perso (e tempo perso ne ho veramente poco), sono arrivato a una conclusione; grazie a qualche esempio trovato online e un po’ di fantasia ho riscritto da capo il tutto, ovvero ho preso un codice che ho trovato in rete che somigliava parecchio a quello che dovevo fare io e me lo sono modificato a piacere. Lo devo dire che non è tutta farina del mio sacco; in ogni caso sono riuscito e inserirò il codice completo a lavoro ultimato come da regolamento ma mi serve ancora un piccolo aiuto, intanto il codice “provvisorio” è questo:

/*
  Effetto alba-tramonto con 6 colori senza utilizzo di "Delay()"
  Modificato e personalizzato da M.R.
  Venerdì 18 settembre 2020
*/

#define ROSSO_PIN 3
#define ROSA_PIN 5
#define BIANCO_PIN 6
#define GIALLO_PIN 9
#define ARANCIONE_PIN 10
#define BLU_PIN 11

byte ROSSO, ROSA, BIANCO, GIALLO, ARANCIONE, BLU; 
byte ROSSO_A = 0;
byte ROSA_A = 0; 
byte BIANCO_A = 0;
byte GIALLO_A = 0;
byte ARANCIONE_A = 0;
byte BLU_A = 0;
int led_delay = 0;
byte colour_count = 1;                //Count the colours out
#define colour_count_max 6              //Set this to the max number of colours defined
#define colour_delay 2000             //Define the delay between changing colours in ms
#define time_at_colour 1000           //Time to stay on a colour in ms

//Some Time values for BLINK
unsigned long t1, dt1;
unsigned long t2, dt2;

//Some Time values for FADE
unsigned long TIME_LED = 0;
unsigned long TIME_COLOUR = 0;

int tled1 = 600;
int tled2 = 350;

int st1 = LOW;
int st2 = LOW;

//Define Colours here.
//Rosso
#define C1_ROSSO 255
#define C1_ROSA 0
#define C1_BIANCO 0
#define C1_GIALLO 0
#define C1_ARANCIONE 0
#define C1_BLU 0
//Rosa
#define C2_ROSSO 0
#define C2_ROSA 255
#define C2_BIANCO 0
#define C2_GIALLO 0
#define C2_ARANCIONE 0
#define C2_BLU 0
//Bianco
#define C3_ROSSO 0
#define C3_ROSA 0
#define C3_BIANCO 255
#define C3_GIALLO 0
#define C3_ARANCIONE 0
#define C3_BLU 0
//Giallo
#define C4_ROSSO 0
#define C4_ROSA 0
#define C4_BIANCO 0
#define C4_GIALLO 255
#define C4_ARANCIONE 0
#define C4_BLU 0
//Arancione
#define C5_ROSSO 0
#define C5_ROSA 0
#define C5_BIANCO 0
#define C5_GIALLO 0
#define C5_ARANCIONE 255
#define C5_BLU 0
//Blu
#define C6_ROSSO 0
#define C6_ROSA 0
#define C6_BIANCO 0
#define C6_GIALLO 0
#define C6_ARANCIONE 0
#define C6_BLU 255


void setup()
{

  //Sezione relativa al BLINK
  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);
  
  //Sezione relativa al FADE
  
  //Assign initial values
  ROSSO = C1_ROSSO;
  ROSA = C1_ROSA;
  BIANCO = C1_BIANCO;
  GIALLO = C1_GIALLO;
  ARANCIONE = C1_ARANCIONE;
  BLU = C1_BLU;
    
  //Get the led_delay speed
  led_delay = (colour_delay - time_at_colour) / 255; 

  analogWrite(ROSSO_PIN, 0);
  analogWrite(ROSA_PIN, 0);
  analogWrite(BIANCO_PIN, 0);
  analogWrite(GIALLO_PIN, 0);
  analogWrite(ARANCIONE_PIN, 0);
  analogWrite(BLU_PIN, 0);

}

void loop()
{

  //Sezione BLINK
  dt1 = millis() - t1;
  if (dt1 > tled1) {
    st1 = !st1;
    digitalWrite(12, st1);
    t1 = millis();
  }


  dt2 = millis() - t2;
  if (dt2 > tled2) {
    st2 = !st2;
    digitalWrite(13, st2);
    t2 = millis();
  }
  //Sezione FADE
  //Rest of your program - Avoid using delay(); function!

  if(millis() - TIME_LED >= led_delay){
    TIME_LED = millis();

    //Run the LED Function to check and adjust the values
    LED();
  }

  if(millis() - TIME_COLOUR >= colour_delay){
    TIME_COLOUR = millis();

    //Run the Colour Change function
    COLOUR();
  }

}

void LED()
{

  //Check Values and adjust "Active" Value
  if(ROSSO != ROSSO_A){
    if(ROSSO_A > ROSSO) ROSSO_A = ROSSO_A - 1;
    if(ROSSO_A < ROSSO) ROSSO_A++;
  }
  
  if(ROSA != ROSA_A){
    if(ROSA_A > ROSA) ROSA_A = ROSA_A - 1;
    if(ROSA_A < ROSA) ROSA_A++;
  }
  
  if(BIANCO != BIANCO_A){
    if(BIANCO_A > BIANCO) BIANCO_A = BIANCO_A - 1;
    if(BIANCO_A < BIANCO) BIANCO_A++;
  }

  if(GIALLO != GIALLO_A){
    if(GIALLO_A > GIALLO) GIALLO_A = GIALLO_A - 1;
    if(GIALLO_A < GIALLO) GIALLO_A++;
  }
  
  if(ARANCIONE != ARANCIONE_A){
    if(ARANCIONE_A > ARANCIONE) ARANCIONE_A = ARANCIONE_A - 1;
    if(ARANCIONE_A < ARANCIONE) ARANCIONE_A++;
  }
  
  if(BLU != BLU_A){
    if(BLU_A > BLU) BLU_A = BLU_A - 1;
    if(BLU_A < BLU) BLU_A++;
  }
  
  //Assign modified values to the pwm outputs for each colour led
  analogWrite(ROSSO_PIN, ROSSO_A);
  analogWrite(ROSA_PIN, ROSA_A);
  analogWrite(BIANCO_PIN, BIANCO_A);
  analogWrite(GIALLO_PIN, GIALLO_A);
  analogWrite(ARANCIONE_PIN, ARANCIONE_A);
  analogWrite(BLU_PIN, BLU_A);

}

void COLOUR()
{

  //Increment the colour by one or go back to 1 if maxed out
  if(colour_count < colour_count_max) colour_count++;
  else colour_count = 1;

  if(colour_count == 1){
    ROSSO = C1_ROSSO;
    ROSA = C1_ROSA;
    BIANCO = C1_BIANCO;
    GIALLO = C1_GIALLO;
    ARANCIONE = C1_ARANCIONE;
    BLU = C1_BLU;
  } else if(colour_count == 2){
    ROSSO = C2_ROSSO;
    ROSA = C2_ROSA;
    BIANCO = C2_BIANCO;
    GIALLO = C2_GIALLO;
    ARANCIONE = C2_ARANCIONE;
    BLU = C1_BLU;
  } else if(colour_count == 3){
    ROSSO = C3_ROSSO;
    ROSA = C3_ROSA;
    BIANCO = C3_BIANCO;
    GIALLO = C3_GIALLO;
    ARANCIONE = C3_ARANCIONE;
    BLU = C3_BLU;
  } else if(colour_count == 4){
    ROSSO = C4_ROSSO;
    ROSA = C4_ROSA;
    BIANCO = C4_BIANCO;
    GIALLO = C4_GIALLO;
    ARANCIONE = C4_ARANCIONE;
    BLU = C4_BLU;
  } else if(colour_count == 5){
    ROSSO = C5_ROSSO;
    ROSA = C5_ROSA;
    BIANCO = C5_BIANCO;
    GIALLO = C5_GIALLO;
    ARANCIONE = C5_ARANCIONE;
    BLU = C5_BLU;
  } else if(colour_count == 6){
    ROSSO = C6_ROSSO;
    ROSA = C6_ROSA;
    BIANCO = C6_BIANCO;
    GIALLO = C6_GIALLO;
    ARANCIONE = C6_ARANCIONE;
    BLU = C6_BLU;
  } 
}

da qui mi manca ancora una cosa: la possibilità di variare a piacimento la durata di ogni singolo colore che qui invece è uguale per tutti.

Ho già provato ad apportare qualche modifica ma senza risultato.

ho aggiunto innanzitutto le variabili:

#define time_at_colour2 100

int led_delay2 = 0;

nel setup ho aggiunto:

 led_delay2 = (colour_delay - time_at_colour2) / 255;

nel loop ho aggiunto questo

if(millis() - TIME_LED >= led_delay2){
    TIME_LED = millis();

    //Run the LED Function to check and adjust the values
    LED2();
  }

e poi ancora questo

void LED2()
{

  //Check Values and adjust "Active" Value
  if(ROSSO != ROSSO_A){
    if(ROSSO_A > ROSSO) ROSSO_A = ROSSO_A - 1;
    if(ROSSO_A < ROSSO) ROSSO_A++;
  }
  
  if(ROSA != ROSA_A){
    if(ROSA_A > ROSA) ROSA_A = ROSA_A - 1;
    if(ROSA_A < ROSA) ROSA_A++;
  }
  
  if(BIANCO != BIANCO_A){
    if(BIANCO_A > BIANCO) BIANCO_A = BIANCO_A - 1;
    if(BIANCO_A < BIANCO) BIANCO_A++;
  }

analogWrite(ROSSO_PIN, ROSSO_A);
  analogWrite(ROSA_PIN, ROSA_A);
  analogWrite(BIANCO_PIN, BIANCO_A);

ma non accende questa ultima parte di led, esegue solo il resto e invece di accendere questa parte di led resta spento.

Ho sbagliato qualcosa?

Un consiglio:

Troppa confusione
Troppa carne al fuoco
Troppi ripensamenti, ovvero non ti dedichi abbastanza a capire cosa fa il tuo programma e quindi capire come modificarlo

Prova a fare una cosa per volta:

Primo un lampeggio di un solo led, asimmetrico come tempi, ovvero che rimane acceso tempo differente di quanto rimane spento

Secondo, stessa cosa per 2 led, con tempi tutti differenti

Terzo, basta lampeggiare, passiamo al fading
Riprendi la libreria, e vedi come si comporta
Leggi bene gli esempi, che ci arrivi a fare quello che vuoi, con un solo led

Quarto, stessa cosa, per 2 led

Quinto adesso lo fai con 6 led, poi riprendi in mano il programma che lampeggiava due led e lo fai con 6

Sesto e ultimo passo: fondi i due programmi

Domanda: sei andato a vedere dove ti dicevo?

Sì sono andato a leggere e tutte le prove che hai detto le ho fatte, prima con un LED poi con due, poi fade e crossfade, se no non sarei arrivato fin qui, ora sto provando ad aggiungere la possibilità di personalizzare l'accensione dei singoli colori, forse avrei dovuto farlo prima, senza la "confusione" del codice completo, ma è una cosa che mi è venuta in mente dopo

Beh, dal tuo listato non sembrava che tu avessi fatto quelle prove

Quindi adesso sei a posto

Beh è quello che ho partorito, adesso come ripeto mi sono bloccato a un punto e non riesco a uscirne, speravo in un suggerimento

Lo hai avuto

Anzi, più di uno

Per prima cosa mettili in pratica

Cominciamo dall’inizio, partiamo da due LED (poi incrementiamo)

#define ROSSO_PIN 3
#define ROSA_PIN 5


byte ROSSO, ROSA;
byte ROSSO_A = 0;
byte ROSA_A = 0; 

int led_delay = 0;
byte colour_count = 1;                //Count the colours out
#define colour_count_max 2              //Set this to the max number of colours defined
#define colour_delay 200            //Define the delay between changing colours in ms
#define time_at_colour 100           //Time to stay on a colour in ms

//Some Time values
unsigned long TIME_LED = 0;
unsigned long TIME_COLOUR = 0;

//Define Colours here.
//Rosso
#define C1_ROSSO 255
#define C1_ROSA 0

//Rosa
#define C2_ROSSO 0
#define C2_ROSA 255


void setup()
{

  //Assign initial values
  ROSSO = C1_ROSSO;
  ROSA = C1_ROSA;
  
    
  //Get the led_delay speed
  led_delay = (colour_delay - time_at_colour) / 255; 

  analogWrite(ROSSO_PIN, 0);
  analogWrite(ROSA_PIN, 0);
  
}

void loop()
{

  //Rest of your program - Avoid using delay(); function!

  if(millis() - TIME_LED >= led_delay){
    TIME_LED = millis();

    //Run the LED Function to check and adjust the values
    LED();
  }

  if(millis() - TIME_COLOUR >= colour_delay){
    TIME_COLOUR = millis();

    //Run the Colour Change function
    COLOUR();
  }

}

void LED()
{

  //Check Values and adjust "Active" Value
  if(ROSSO != ROSSO_A){
    if(ROSSO_A > ROSSO) ROSSO_A = ROSSO_A - 1;
    if(ROSSO_A < ROSSO) ROSSO_A++;
  }
  
  if(ROSA != ROSA_A){
    if(ROSA_A > ROSA) ROSA_A = ROSA_A - 1;
    if(ROSA_A < ROSA) ROSA_A++;
  }
  
  
  
  //Assign modified values to the pwm outputs for each colour led
  analogWrite(ROSSO_PIN, ROSSO_A);
  analogWrite(ROSA_PIN, ROSA_A);
  
}

void COLOUR()
{

  //Increment the colour by one or go back to 1 if maxed out
  if(colour_count < colour_count_max) colour_count++;
  else colour_count = 1;

  if(colour_count == 1){
    ROSSO = C1_ROSSO;
    ROSA = C1_ROSA;
    
  } else if(colour_count == 2){
    ROSSO = C2_ROSSO;
    ROSA = C2_ROSA;
  }
    
}

Eureka!!! Funziona!!!
Adesso aggiungiamo la funzione che tiene accesi i LED con tempi differenti

#define ROSSO_PIN 3
#define ROSA_PIN 5


byte ROSSO, ROSA;
byte ROSSO_A = 0;
byte ROSA_A = 0; 

int led_delay = 0;
int led_delay2 = 0;
byte colour_count = 1;                //Count the colours out
#define colour_count_max 2              //Set this to the max number of colours defined
#define colour_delay 200            //Define the delay between changing colours in ms
#define time_at_colour 100           //Time to stay on a colour in ms
#define time_at_colour2 500

//Some Time values
unsigned long TIME_LED = 0;
unsigned long TIME_COLOUR = 0;

//Define Colours here.
//Rosso
#define C1_ROSSO 255
#define C1_ROSA 0

//Rosa
#define C2_ROSSO 0
#define C2_ROSA 255


void setup()
{

  //Assign initial values
  ROSSO = C1_ROSSO;
  ROSA = C1_ROSA;
  
    
  //Get the led_delay speed
  led_delay = (colour_delay - time_at_colour) / 255;
  led_delay2 = (colour_delay - time_at_colour2) / 255; 

  analogWrite(ROSSO_PIN, 0);
  analogWrite(ROSA_PIN, 0);
  
}

void loop()
{

  //Rest of your program - Avoid using delay(); function!

  if(millis() - TIME_LED >= led_delay){
    TIME_LED = millis();

    //Run the LED Function to check and adjust the values
    LED();
  }

if(millis() - TIME_LED >= led_delay2){
    TIME_LED = millis();

    //Run the LED Function to check and adjust the values
    LED2();
  }

  if(millis() - TIME_COLOUR >= colour_delay){
    TIME_COLOUR = millis();

    //Run the Colour Change function
    COLOUR();
  }

}

void LED()
{

  //Check Values and adjust "Active" Value
  if(ROSSO != ROSSO_A){
    if(ROSSO_A > ROSSO) ROSSO_A = ROSSO_A - 1;
    if(ROSSO_A < ROSSO) ROSSO_A++;
  }
  
  
  
  
  //Assign modified values to the pwm outputs for each colour led
  analogWrite(ROSSO_PIN, ROSSO_A);
  
}

void LED2()
{

  if(ROSA != ROSA_A){
    if(ROSA_A > ROSA) ROSA_A = ROSA_A - 1;
    if(ROSA_A < ROSA) ROSA_A++;
  }

analogWrite(ROSA_PIN, ROSA_A);
}

void COLOUR()
{

  //Increment the colour by one or go back to 1 if maxed out
  if(colour_count < colour_count_max) colour_count++;
  else colour_count = 1;

  if(colour_count == 1){
    ROSSO = C1_ROSSO;
    ROSA = C1_ROSA;
    
  } else if(colour_count == 2){
    ROSSO = C2_ROSSO;
    ROSA = C2_ROSA;
  }
    
}

Non funziona, c’è qualcosa che non va, ma non trovo il “qualcosa”

Se li vuoi far andare in modo indipendente, dovresti avere anche un TIME_LED2

Poi non ho capito bene cosa vuoi ottenere con l'ultimo codice postato per cui mi fermo qui, altrimenti rischio di scrivere tonnellate di cose che non centrano nulla con il problema sul banco degli imputati.

Se mi scrivi esattamente cosa ti aspetti e anche cosa invece ottieni, procediamo in modo mirato a spiegare i sintomi.

Maurizio