strisce led in contemporanea con effetti diversi

Astro: piu che giochi di luce, era l'idea preliminare per un tipo di orologio da parete un po particolare (l'avevo postata come battuta nel topic dell'orologio di ghezzia, ma poi pensandoci mi e' venuta l'idea di studiarne la fattibilita' in un'ambiente reale) ... in pratica l'idea era di utilizzare una singola strip di led WS2812, tagliata a sezioni da 5 led l'una, ogni sezione dovrebbe comporre uno dei segmenti, piu altri due led per i punti che potrebbero essere indifferentemente in testa o in coda alla striscia ... il che farebbe in tutto 142 led per 4 cifre (o 214 led per 6 cifre, ma cosi sarebbe abbastanza esagerata, secondo me) ...

Per cui la sequenza di pilotaggio, principalmente, dovrebbe suddividere i led in gruppi da 5, uno per segmento (poi stara' allo sketch implementare la logica di creazione della matrice in modo che, ad esempio, tutti i segmenti siano in serie con i due punti alla fine, tipo abcdefgabcdefgabcdefgabcdefgpp, e pilotarli a gruppi di 5) ... la condizione particolare potrebbe essere l'intervento della sveglia, in cui ad esempio tutti i segmenti accesi cambiano di colore in modo casuale ed indipendente, oppure addirittura tutti i led accesi, ma quello sarebbe un "di piu" ... per ora stavo cercando di immaginarmi se e come sarebbe possibile creare la struttura di base del programma (anche perche' ancora non ho neppure i led, quindi per ora e' uno studio teorico) ... dato che i WS vanno pilotati tutti in serie, immagino che si dovrebbe creare un'array multidimensionale (ad esempio, le 4 cifre, ogni cifra contiene i 7 segmenti, ogni segmento contiene i 5 led), in modo che sia possibile gestirli con dei for nidificati (perche' credo che gestire una struttura simile in modo lineare possa creare molti piu problemi che con le matrici), ed iniziare a gestire il tutto, poi una volta visto se sia possibile farlo, si puo pensare ad implementare degli extra, come ad esempio la transizione dei segmenti da acceso a spento in modo "arcobaleno" invece che On/Off, o qualcos'altro ... ma prima di tutto, volevo farmi un'idea di massima sulla possibile fattibilita' del tutto, e sul fatto che un 328 potesse bastare, o se era meglio passare direttamente a qualcosa con piu ram disponibile per non trovarsi a secco di risorse a meta' dell'opera ...

gpb01:
... ho un 800mm F5.6, e ...

... vedi che avevo ragione ? ... :smiley: :smiley: :smiley:

eccomi qua, ho fatto i compiti:
2 strisce
effetto FastLed
millis()

tutti gli esempi in singoli void per non fare confusione. Questo il risultato:
tutte_le_strisce_in_sequenza(); si accendono i led stricia0 e poi striscia1 come ciclo for..OK

singola_striscia(); come sopra solo con una striscia, tutto OK

ora iniziamo con i millis()

io vorrei che a 3000 parta stricia0 (con effetto come singola_striscia, cioè che cambi colore in continuo) e a 8000 parta striscia1 senza che striscia0 si fermi

Invece sia che faccia un void con i due mills insieme o chiamo due separati void succede :
3000 parte striscia0 dopo i primi 20 led si ferma e si aggiorna solo ogni 3000
8000 parte striscia1 dopo i primi 20 led si ferma e si aggiorna solo ogni 8000

#include <FastLED.h>

#define LED_TYPE    WS2812B
#define COLOR_ORDER GRB
#define BRIGHTNESS          84
#define NUM_LEDS    20
#define NUM_STRIPS 2
CRGB leds[NUM_STRIPS][NUM_LEDS];

#define UPDATES_PER_SECOND 100

//parte millis
unsigned long previousMillis0= 0; 
unsigned long previousMillis1= 0;

 
const long tempostriscia0 = 3000;
const long tempostriscia1 = 8000;



CRGBPalette16 currentPalette;
TBlendType    currentBlending;

extern CRGBPalette16 myRedWhiteBluePalette;
extern const TProgmemPalette16 myRedWhiteBluePalette_p PROGMEM;
uint8_t colorIndex = 0;

void setup() {
   Serial.begin(19200);
    delay( 1000 ); // power-up safety delay
    //7 strisce nei pin da 4 a 10
    FastLED.addLeds<LED_TYPE, 4, COLOR_ORDER>(leds[0], NUM_LEDS).setCorrection( TypicalLEDStrip );
    FastLED.addLeds<LED_TYPE, 5, COLOR_ORDER>(leds[1], NUM_LEDS).setCorrection( TypicalLEDStrip );
  
    FastLED.setBrightness(  BRIGHTNESS );
    
    currentPalette = RainbowColors_p;
    currentBlending = LINEARBLEND;
}

void loop()
{
  
//tutte_le_strisce_in_sequenza();
//singola_striscia(); 
//singole_strisce_a_tempi_diversi(); 
singola_striscia0();
singola_striscia1();
}

void tutte_le_strisce_in_sequenza(){
   for( int x = 0; x < NUM_STRIPS; x++) {
    for( int i = 0; i < NUM_LEDS; i++) {
        leds[x][i] = ColorFromPalette(currentPalette, colorIndex, BRIGHTNESS, currentBlending);
    colorIndex += 1;//quanti colori salta da un loop all'altro, con 1 i colori sono contigui rosso-arancione-giallo-verde et.
    FastLED.show();
    FastLED.delay(1000 / UPDATES_PER_SECOND);
}
    }
}
void singole_strisce_a_tempi_diversi(){
Serial.println(millis());   
if (millis() - previousMillis0 > tempostriscia0) {
   previousMillis0 = millis();
    for( int i = 0; i < NUM_LEDS; i++) {
    leds[0][i] = ColorFromPalette(currentPalette, colorIndex, BRIGHTNESS, currentBlending);  //striscia0
    colorIndex += 1;//quanti colori salta da un loop all'altro, con 1 i colori sono contigui rosso-arancione-giallo-verde et.
    FastLED.show();
    FastLED.delay(1000 / UPDATES_PER_SECOND);
    }
    
}
if (millis() - previousMillis1 > tempostriscia1) {
   previousMillis1 = millis();
    for( int i = 0; i < NUM_LEDS; i++) {
    leds[1][i] = ColorFromPalette(currentPalette, colorIndex, BRIGHTNESS, currentBlending);  //striscia0
    colorIndex += 1;//quanti colori salta da un loop all'altro, con 1 i colori sono contigui rosso-arancione-giallo-verde et.
    FastLED.show();
    FastLED.delay(1000 / UPDATES_PER_SECOND);
    }
}
}

void singola_striscia(){  
    for( int i = 0; i < NUM_LEDS; i++) {
    leds[0][i] = ColorFromPalette(currentPalette, colorIndex, BRIGHTNESS, currentBlending);  //striscia0
    colorIndex += 1;//quanti colori salta da un loop all'altro, con 1 i colori sono contigui rosso-arancione-giallo-verde et.
    FastLED.show();
    FastLED.delay(1000 / UPDATES_PER_SECOND);
    }
}

void singola_striscia0(){  
   Serial.println(millis());   
if (millis() - previousMillis0 > tempostriscia0) {
   previousMillis0 = millis();
    for( int i = 0; i < NUM_LEDS; i++) {
    leds[0][i] = ColorFromPalette(currentPalette, colorIndex, BRIGHTNESS, currentBlending);  //striscia0
    colorIndex += 1;//quanti colori salta da un loop all'altro, con 1 i colori sono contigui rosso-arancione-giallo-verde et.
   FastLED.show();
   FastLED.delay(1000/ UPDATES_PER_SECOND);
    }
    
}
}
void singola_striscia1(){  
   Serial.println(millis());   
if (millis() - previousMillis1 > tempostriscia1) {
   previousMillis1 = millis();
    for( int i = 0; i < NUM_LEDS; i++) {
    leds[1][i] = ColorFromPalette(currentPalette, colorIndex, BRIGHTNESS, currentBlending);  //striscia0
    colorIndex += 1;//quanti colori salta da un loop all'altro, con 1 i colori sono contigui rosso-arancione-giallo-verde et.
   FastLED.show();
    FastLED.delay(1000 / UPDATES_PER_SECOND);
    }
    
}
}

Qualcuna ha soluzioni? sempre se è fattibile.

Grazie
P.S. Appassionato di fotografia anch'io.

VOGLIO CAMBIARE BANCO qui mi sento ignorantissimo :cold_sweat: :slightly_smiling_face:

io vorrei che a 3000 parta stricia0 (con effetto come singola_striscia, cioè che cambi colore in continuo) e a 8000 parta striscia1 senza che striscia0 si fermi

striscia0 si ferma perché la mcu è impegnata ad eseguire il ciclo for di striscia1. Sicuramente è fattibile ma al momento non so darti la soluzione, stavo appunto spulciando il codice interno della lib fastled.

Mantenendo il codice attuale funzionerebbe in ambiente multithread, dove ad esempio ogni funzione è un task eseguito in modo concorrente dallo scheduler.

Io ricordo che esiste uno scheduler in arduino.

Di sicuro senza fare uso di scheduler occorre fare a meno dell'istruzione for( int i = 0; i < NUM_LEDS; i++) { ecc.

la variabile i la puoi incrementare con i++ e i limiti li controlli con if, ma occorre renderela globale dichiarandola fuori da ogni funzione, ma in questo caso devi anche cambiargli il nome in striscia0Index o altro di simile.

I limiti di i li controlli con if (striscia0Index < NUM_LEDS) { al posto del for.

ciao.

con la libreria #include "looper.h" e lo scheduler
myScheduler.addJob(singola_striscia0, 3000);
myScheduler.addJob(singola_striscia1, 10000);

funziona come mills();

Prova ad usare la leOS2 sempre di Leo e scaricabile sempre dal suo sito ... leOS2 originale, leOS2 2.10, leOS2 2.2.0 ed infine leOS2 2.3.0 ...
... è un po' più complessa, ma dovrebbe andarti bene.

Guglielmo

leOS2 vanno in conflitto con qualcosa, i led si accendono a caso.
leOS1 funzionano come millis()

Credo che non si possa fare... mentre scrivevo mi è venuta l'idea:

basta togliere previousMillis0 = millis();

quindi: le strisce partono al tempostriscia previsto, e poi proseguono per i fatti suoi!!

Ora vedo di integrare il tutto sul programma più complesso.

Ciao e grazie

#include <FastLED.h>

#define LED_TYPE    WS2812B
#define COLOR_ORDER GRB
#define BRIGHTNESS          84
#define NUM_LEDS    20
#define NUM_STRIPS 2
CRGB leds[NUM_STRIPS][NUM_LEDS];

#define UPDATES_PER_SECOND 100

//parte millis
unsigned long previousMillis0= 0; 
unsigned long previousMillis1= 0;

 
const long tempostriscia0 = 3000;
const long tempostriscia1 = 8000;



CRGBPalette16 currentPalette;
TBlendType    currentBlending;

extern CRGBPalette16 myRedWhiteBluePalette;
extern const TProgmemPalette16 myRedWhiteBluePalette_p PROGMEM;
uint8_t colorIndex = 0;

void setup() {
   Serial.begin(19200);
    delay( 1000 ); // power-up safety delay
    //7 strisce nei pin da 4 a 10
    FastLED.addLeds<LED_TYPE, 4, COLOR_ORDER>(leds[0], NUM_LEDS).setCorrection( TypicalLEDStrip );
    FastLED.addLeds<LED_TYPE, 5, COLOR_ORDER>(leds[1], NUM_LEDS).setCorrection( TypicalLEDStrip );
  
    FastLED.setBrightness(  BRIGHTNESS );
    
    currentPalette = RainbowColors_p;
    currentBlending = LINEARBLEND;
}

void loop()
{
  
singola_striscia0();
singola_striscia1();
}

void singola_striscia0(){  
   Serial.println(millis());   
if (millis() - previousMillis0 > tempostriscia0) {
   //previousMillis0 = millis();
    for( int i = 0; i < NUM_LEDS; i++) {
    leds[0][i] = ColorFromPalette(currentPalette, colorIndex, BRIGHTNESS, currentBlending);  //striscia0
    colorIndex += 1;//quanti colori salta da un loop all'altro, con 1 i colori sono contigui rosso-arancione-giallo-verde et.
   FastLED.show();
   FastLED.delay(1000/ UPDATES_PER_SECOND);
    }
 }
}
void singola_striscia1(){  
   Serial.println(millis());   
if (millis() - previousMillis1 > tempostriscia1) {
  // previousMillis1 = millis();
    for( int i = 0; i < NUM_LEDS; i++) {
    leds[1][i] = ColorFromPalette(currentPalette, colorIndex, BRIGHTNESS, currentBlending);  //striscia0
    colorIndex += 1;//quanti colori salta da un loop all'altro, con 1 i colori sono contigui rosso-arancione-giallo-verde et.
   FastLED.show();
    FastLED.delay(1000 / UPDATES_PER_SECOND);
    }    
}
}

polipo1970:
leOS2 vanno in conflitto con qualcosa, i led si accendono a caso.

... probabilmente interrompono la sequenza a metà (dato che i tempi li decide lo scheduler) e quindi le strisce NON rispondono più come dovrebbero.

Guglielmo

Infatti non si dovrebbe usare uno scheduler generico perché se interrompe il processo di scrittura sul bus, molto critico, i risultati sono sempre pessimi.
Se proprio si vuole usare uno scheduler è necessario scriverlo appositamente per l'uso con la FastLed, o altra libreria similare, in modo che non interrompa mai il programma mentre scrive sul bus dei led.

@polipo1970 mi sono divertito un po' in passato con i WS2812. Per controllare in modo diverso diverse striscie avevo utilizzato una MCU per ogni striscia che comunicava via seriale con una MCU master. I giochi di luce erano precaricati su ogni micro. Via seriale i comandi erano del tipo (striscia A fai gioco 1, striscia B fai gioco 2 ecc ecc) quando ho un attimo ti posto il codice se ti può interessare :slight_smile:

@polipo1970

Immaginavo che scegliessi di complicarti la vita con uno scheduler, perché come ti ho suggerito è la strada più semplice, tuttavia l'obbiettivo è quello di imparare e non quello di raggiungere il risultato desiderato.

Ho tirato in ballo lo scheduler a livello teorico solo per aiutarti a capire perché il tuo codice non fa quello che vuoi, diversamente ti avrei dato un link ad uno scheduler che ti risolve il problema.

Ora dimmi come vuoi procedere, vuoi risolvere o capire ed imparare?
A me sembra che tu sia disposto ad imparare ma come accade spesso (ed è naturale) nella sperimentazione sono più gli insuccessi che i successi, da ciò deriva un senso di frustrazione.

Lo scheduler che funziona potrebbe essere questo.
Tuttavia io non mi butterei a provare nell'immediato senza prima capire. Potenzialmente questo scheduler funziona perché i task sono eseguiti ciascuno con uno proprio stack e risultano totalmente indipendenti l'uno dall'altro.

Ora in questo contesto accade che due task vogliono condividere una sola risorsa e litigano per impiegarla. Per tirarsene fuori occorre competenza e alle volte non se ne ha abbastanza.

Dimentica per il momento gli scheduler e concentrati più su come si deve usare la lib fastled. In particolare il metodo show() che secondo me andrebbe chiamato una sola volta nel loop principale e non come fai tu in due loop (cicli for) separati.

Ciao.

Maurotec:
Lo scheduler che funziona potrebbe essere questo.

Mauro, il suo problema è che ... o NON applica uno "scheduling preemptive" e allora si ritrova con gli stessi problemi che ha avuto con millis(), o invece è "preemptive" e allora NON gli funzionano più le strisce perché, la trasmissione seriale dei bit ai LED NON può essere interrotta ed ha sue precise temporizzazioni, quindi ... così semplicemente NON lo fai.

Se vuole usare uno scheduler "preemptive" deve comunque mettere le mani nella libreria che usa affinché, nella parte di tramissione dati, dica allo scheduler che NON può essere interrotta (critical section).

Ritengo invece ottimo il suggerimento che dai nel tuo ultimo capoverso ... :wink:

Maurotec:
Dimentica per il momento gli scheduler e concentrati più su come si deve usare la lib fastled. In particolare il metodo show() che secondo me andrebbe chiamato una sola volta nel loop principale e non come fai tu in due loop (cicli for) separati.

Guglielmo

Mauro, il suo problema è che ... o NON applica uno "scheduling preemptive" e allora si ritrova con gli stessi problemi che ha avuto con millis(), o invece è "preemptive" e allora NON gli funzionano più le strisce perché, la trasmissione seriale dei bit ai LED NON può essere interrotta ed ha sue precise temporizzazioni, quindi ... così semplicemente NON lo fai.

Infatti gli è parsa la soluzione al problema e ha tentato, ma l'obbiettivo mica è quello, inoltre ogni soluzione comporta problemi da affrontare. Il mio intento non è quello di risolvergli il problema, sai benissimo che non abbiamo la soluzione in tasca e anche se l'avessimo... sai bene come siamo fatti. Intanto è venuto a conoscenza degli scheduler e sa che c'è ne sono più tipi, inoltre ha chiaro il motivo per cui se la CPU viene impegnata ad eseguire un ciclo di istruzione non può contemporaneamente eseguire un altro ciclo.

"doppiozero" ha trovato come soluzione l'impiego di più MCU (e quindi più CPU) sincronizzate ed è l'unico vero modo per eseguire codice parallelo.

Ciao.

C'è da dire che la documentazione di FastLED è carente, inoltre non la ho in locale, per verità non ho neanche arduino ide aggiornato.

Vedo se posso scaricarla domani, dovrei dedicarci un paio di ore almeno perché è davvero complessa e supporta varie piattaforme molto differenti tra loro.

Ciao.

doppiozero:
@polipo1970 mi sono divertito un po' in passato con i WS2812. Per controllare in modo diverso diverse striscie avevo utilizzato una MCU per ogni striscia che comunicava via seriale con una MCU master. I giochi di luce erano precaricati su ogni micro. Via seriale i comandi erano del tipo (striscia A fai gioco 1, striscia B fai gioco 2 ecc ecc) quando ho un attimo ti posto il codice se ti può interessare :slight_smile:

Sarebbe bello vedere anche l'implementazione hardware, deve essere molto "intrigante".

Allora, ho recuperato gli sketch. E' un lavoro ancora aperto quindi alcuni giochi di luce sono da sistemare. Il codice è anche commentato. :slight_smile:

Sarebbe bello vedere anche l'implementazione hardware, deve essere molto "intrigante".

Mmmm in realtà è molto banale, ATmega328 a 16MHz su breadboard. I pin RX degli slave sono tutti in parallelo connessi al TX del master. La libreria che ho utilizzato è la NEOPixel di Adafruit perchè con la FastLED ho avuto dei problemi.

Che dire ..spero che funzioni :grin: :grin: :stuck_out_tongue_closed_eyes:

ws2812_giochi_vari_master.ino.zip (399 Bytes)

ws2812_giochi_vari_slave_v3.zip (4.88 KB)

scusate se ne approfitto per fare una domanda :o :frowning:

Il metodo show() che secondo me andrebbe chiamato una sola volta nel loop principale e non come fai tu in due loop (cicli for) separati.

come si fà a richiamare una sola volta una funzione (se ho capito bene "show()" non è nient'altro che una funzione inventata)nel ciclo LOOP??????? :o :confused: :disappointed_relieved:

Scusate la domanda.

come si fà a richiamare una sola volta una funzione (se ho capito bene "show()" non è nient'altro che una funzione inventata)nel ciclo LOOP??????? :o :confused: :disappointed_relieved:

Credo intenda una sola volta per ogni "giro" del loop. Se la vuoi chiamare una sola volta e poi mai più devi utilizzare una variabile di stato

void loop(){

if (stato == 1){

show();

}
stato = 0;

}

quindi semplicemente aggiungo una variabile..... :o credevo che esistesse una scrittura altenativa alternativa :roll_eyes: