Randomizzare impulsi elettrici

Buonasera a tutti,
Sono alle prese con un modellino di B-17 americano di piccolissime dimesioni (11x11cm) e volevo creargli un'ambientazione che rendesse l'idea del fatto che sia un bombardiere. Avevo pensato di posizionarlo sopra a del cotone, le nuvole, in tal modo che sembri che esca da esse. Dato che è un bombardiere avevo pensato di mettere sotto le nuvole 4-5 led rossi che si accendessero in tempi diversi a potenze diverse, dovrebbero rappresentare le nuvole (cotone) che si illuminano di rosso (led)con le esplosioni sottostanti. È possibile farli accendere singolarmente in tempi random e a potenze diverse (diversi tipi di esplosioni)? Al momento punterei di farlo senza Arduino: solo circuito elettrico, ma se è possibile solo con Arduino allora userò quello. Dispongo di un Arduino Mega (già impiegato in un altro progetto) e di Uno.

Buona serata e buon ferragosto a tutti

Per poterne parlare sul forum Arduino deve essere impiegato quindi ti rispondo solo per quella parte. Con Arduino puoi pilotare i led in PWM per decidere l'intensità luminosa, guarda il reference dell'istruzione analogWrite applicata ai pin digitali per questo.
Per la parte di casualità guarda l'istruzione Random e RandomSeed e applica il risultato per calcolare i vari intervalli gestiti con la funzione millis (trovi tonnellate di topic sul forum se non sai come usarla)
L'istruzione random di Arduino non genera veri e propri numeri casuali ma credo che per il tuo scopo possa andare bene

1 Like

... mmm ... sarebbe bene che rileggessi il REGOLAMENTO ed in particolare il punto 16.11 :wink:

Guglielmo

Dai uno sguardo qui:

https://forum.arduino.cc/t/la-pappa-e-fatta/598251

Credo troverai quello che ti serve

Buongiorno,
Ho provato a fare ciò che avete detto seguendo dei miei vecchi sketch ed ho ottenuto ciò, potrebbe funzionare?

int var;

void setup() {
  pinMode(3, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
}

void loop() {
  switch(var){
    case 0:
    analogWrite(3, random(125, 255));
    break;
    case 1:
    analogWrite(5, random(125, 255));
    break;
    case 2:
    analogWrite(6, random(125, 255));
    break;
    case 3:
    analogWrite(10, random(125, 255));
    break;
    case 4:
    analogWrite(11, random(125, 255));
    break;
  }
  delay(random(10, 2500));
}

Teoricamente i LED dovrebbero illuminarsi in modo casuale ad una potenza casuale.
Ho inserito come min e max di potenza dei LED 125 e 255 perché se li alimentiamo ad una potenza inferiore tendono a non illuminarsi abbastanza. è da considerare il fatto che non sono esposti all'aria aperta ma sotto uno strato di cotone.

Buon ferragosto

emmm ... scusa, ma ... non vedo dove, nel loop(), la variabile 'var' venga incrementata per andare da 0 a 4. Viene inizializzata a 0 quando la dichiari globalmente e poi ... :roll_eyes:

Guglielmo

Oltre a quello, mi sembra che i tuoi case si limitino ad accendere a caso i led (in questo caso, come dice giustamente Guglielmo, UN led e basta), ma senza pause casuali di buio, senza fade in spegnimento per simulare l'effetto esplosione che vorresti, e senza poter avere piu di un comando alla volta perche' il delay() e' bloccante :wink:

A livello di montaggio invece, vuoi poi racchiudere il tutto in resina trasparente o sotto una cupola in vetro ? ... se no, il cotone alla lunga si rovinera' e sporchera', probabilmente (ma questa e' una cosa a cui potrai pensare alla fine comunque).

Ho scritto questo sketch e credo si avvicini già di più ad un prodotto finale funzionante. Nonostante ciò non ho potuto fare a meno dei delay() e mi viene in mente la domanda: si possono far girare su Arduino due sketch/comandi contemporaneamente?

Sketch:



int led1;
int led2;
int led3;
int led4;
int led5;
int var[1] [5];

void setup() {
  pinMode(3, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
}

void loop() {
  var[1] [0] = random(0,1);
  var[1] [1] = random(0,1);
  var[1] [2] = random(0,1);
  var[1] [3] = random(0,1);
  var[1] [4] = random(0,1);

  led1 = random(125, 255);
  led2 = random(125, 255);
  led3 = random(125, 255);
  led4 = random(125, 255);
  led5 = random(125, 255);
  
  if(var[1] [0] == 1){ analogWrite(3, led1);}else{ digitalWrite(3, LOW);}
  if(var[1] [1] == 1){ analogWrite(5, led2);}else{ digitalWrite(5, LOW);}
  if(var[1] [2] == 1){ analogWrite(6, led3);}else{ digitalWrite(6, LOW);}
  if(var[1] [3] == 1){ analogWrite(10, led4);}else{ digitalWrite(10, LOW);}
  if(var[1] [4] == 1){ analogWrite(11, led5);}else{ digitalWrite(11, LOW);}
  
  if(random(0, 1) == 1){ 
  for(int i = led1; i < 1; i--){
    delay(20);
  }else{
    if(led1 <=124){
      digitalWrite(3, LOW);
      delay(250);
      digitalWrite(3, HIGH);
        for(int i = 255; i < 1; i--){
      delay(20);
    }}
  if(random(0, 1) == 1){ 
  for(int i = led2; i < 1; i--){
    delay(20);
  }else{
    if(led2 <=124){
    digitalWrite(5, LOW);
    delay(250);
    digitalWrite(5, HIGH);
    for(int i = 255; i < 1; i--){
    delay(20);
  }}
  if(random(0, 1) == 1){ 
  for(int i = led3; i < 1; i--){
    delay(20);
  }else{
    if(led3 <=124){
    digitalWrite(6, LOW);
    delay(250);
    digitalWrite(6, HIGH);
    for(int i = 255; i < 1; i--){
    delay(20);
  }}
  if(random(0, 1) == 1){ 
  for(int i = led4; i < 1; i--){
    delay(20);
  }else{
    if(led4 <=124){
    digitalWrite(10, LOW);
    delay(250);
    digitalWrite(10, HIGH);
    for(int i = 255; i < 1; i--){
    delay(20);
  }}
  if(random(0, 1) == 1){ 
  for(int i = led5; i < 1; i--){
    delay(20);
  }else{
    if(led5 <=124){
    digitalWrite(11, LOW);
    delay(250);
    digitalWrite(11, HIGH);
    for(int i = 255; i < 1; i--){
    delay(20);
  }}
}

Ora i LED si accendono più di uno però per lo spegnimento si spengono in successione e non contemporaneamente.. Come posso fare?

Ovviamente, essendo la MCU unica con un singolo "core", la riposta è no, non puoi avere due parti di programma che girano simultaneamnete, ma ... come si fa sempre, puoi simulare la cosa :wink:

In pratica ... devi studiarti come si usa la funzione millis(), prima QUI, poi QUI e QUI e QUI e tutti gli articoli che sono in QUESTA pagina ... vedrai che poi ti sarà tutto più chiaro :wink:

Guglielmo

Anche qui:

e qui:

Seguendo i vostri consigli ho scritto questo sketch:

//attribuzione di un nome ai pin relativi ai LED

int led1 = 3;            
int led2 = 5;
int led3 = 6;
int led4 = 10;
//creazione di variabili che definiscono un intervallo di accensione per ogni LED
unsigned long t1; 
unsigned long t2; 
unsigned long t3; 
unsigned long t4;
//creazione di variabili che definiscono un intervallo di attesa per ogni LED
unsigned long attesaT1;
unsigned long attesaT2;
unsigned long attesaT3;
unsigned long attesaT4;
//creazione di variabili che definiscono il tempo di millis() dall'accensionde per ogni LED 
unsigned long pT1;
unsigned long pT2;
unsigned long pT3;
unsigned long pT4;
//creazione di variabili che definiscono il tempo di millis() dallo spegnimento per ogni LED 
unsigned long pAT1;
unsigned long pAT2;
unsigned long pAT3;
unsigned long pAT4;
//creazione di variabili che definiscono lo stato del led (0:spento, 1:acceso)
boolean aT1 = 0;
boolean aT2 = 0;
boolean aT3 = 0;
boolean aT4 = 0;




 
void setup() {
  //definizione della modalità di utilizzo dei pin
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
  //definizione dell'attesa per l'accensione dei LED dall'inizio dello sketch
  attesaT1=random(250, 5000);
  attesaT2=random(250, 5000);
  attesaT3=random(250, 5000);
  attesaT4=random(250, 5000);
}

void loop() {
  checkAttesaT();
  checkT();
}




void checkAttesaT(){
  if(millis() - pAT1 >= attesaT1 && aT1 == 0){    //se è trascorso l'attesa ed il LED è spento allora...+
    t1 = random(250, 2000);                       //porta la durata del led acceso ad un valore casuale compreso tra 250 e 2000ms
    pT1 = millis();                               //porta "l'ora" che definisce l'accensione del LED a millis()
    analogWrite(led1, random(125, 255));          //accendi il LED ad un valore compreso tra 125 e 255
    aT1 = 1;                                      //porta la variabile che definisce lo stato del LED a  (acceso)
  }                                               //la cosa si ripeete per ogni LED
  if(millis() - pAT2 >= attesaT2 && aT2 == 0){
    t2 = random(250, 2000);
    pT2 = millis();
    analogWrite(led2, random(125, 255));
    aT2 = 1;
  }
  if(millis() - pAT3 >= attesaT3 && aT3 == 0){
    t3 = random(250, 2000);
    pT3 = millis();
    analogWrite(led3, random(125, 255));
    aT3 = 1;
  }
  if(millis() - pAT4 >= attesaT4 && aT4 == 0){
    t4 = random(250, 2000);
    pT4 = millis();
    analogWrite(led4, random(125, 255));
    aT4 = 1;
  }}


void checkT(){
  if(millis() - pT1 >= t1 && aT1 == 1){       //se è trascorso il tempo definito dall'intervallo dall'accensione del LED ed il LED è acceso allora...
    attesaT1 = random(250, 2000);             //porta la durata dell'attesa ad un valore casuale compeso tra 250 e 2000ms
    pAT1 = millis();                          //porta il valore che segna l'inizio dell'attesa a millis()
    analogWrite(led1, 0);                     //spegni il LED
    aT1 = 0;                                  //porta la variabile che definisce lo stato del LED a 0 (spento)
  }                                           //la cosa si ripeete per ogni LED
  if(millis() - pT2 >= t2 && aT2 == 1){       
    attesaT2 = random(250, 2000);
    pAT2 = millis();
    analogWrite(led2, 0);
    aT2 = 0;
  }
  if(millis() - pT3 >= t3 && aT3 == 1){
    attesaT3 = random(250, 2000);
    pAT3 = millis();
    analogWrite(led3, 0);
    aT3 = 0;
  }
  if(millis() - pT4 >= t4 && aT4 == 1){
    attesaT4 = random(250, 2000);
    pAT4 = millis();
    analogWrite(led4, 0);
    aT4 = 0;
  }}

Teoricamente questo sketch mi permette si accendere diversi LED contemporaneamente per tempi diversi. Per il "problema" dei 50 giorni di durata non ho provveduto dato che lo accenderò e spegnerò quando voglio io e non credo che lo lascerò acceso per 50 giorni consecutivi...
Lo sketch è parecchio lungo e poco ottimizzato, non so come fare per ottimizzarlo al momento dato che sono 4 LED diversi che devono fare le stesse cose, detta così sembra fattibile, ma io proprio non ci riesco... :sweat_smile:
Un altro problema che devo risolvere è come fare per dare l'effetto bomba durante l'intervallo in cui il LED rimane acceso (il LED in teoria si dovrebbe spegnere gradualmente oppure spegnersi di colpo e riaccendersi per poi spegnersi gradualmente). Come codice avevo realizzato il seguente:

però c'è di mezzo il delay...

Prova a dare uno sguardo alla libreria softpwm

A questo punto credo che l'esplosione non abbia più a vedere con il generatore random. Però l'esplosione attraverso le nuvole sono assimilabili ai bagliori, quindi accensione rapida fino alla massima intensità spegnimento e riaccensione per poi tornare spento progressivamente. Con i giochi di luce si produce spesso molto codice per modellarli.

Mi domanda ma questo aereo non ha luci di coda, di ala ecc giusto? ...perché se è un bombardiere non si deve fare notare.

Ha mitragliatrici?
Se si queste sembra facile modellarle.

Ciao.

Allora, al momento io ho un aereo di metallo, che ho costruito io, è di 11x11cm e ha delle mitragliatrici lunghe 0,5cm e larghe 1mm. Non ha alcuni LED al suo interno e credo che dalle dimensioni non sia possibile metterglieli...
Io con lo spegnimento dei LED volevo dare l'idea di una bomba la cui luce si va attenuando.Al momento credo sia l'unico problema.

Vi lascio una foto:

Ha una mitragliatrice sul tettuccio, alla fine della fusoliera e una sotto al muso, in teoria ne dovrebbe avere una anche sotto la fusoliera, ma è stata abbattuta mentre la montavo :sweat_smile:
Per dare idea delle dimensione (nonostante quelle citate) il foglio dietro è un A3

Non so chi dei due non ha capito :sweat_smile:, ma il problema è il fatto che in più azioni che si vanno quasi a sovrapporre, quindi per ogni LED dovrei mettergli un codice che per ogni millisecondo mi diminuisce la potenza data al LED.

if(random(0, 1) == 1){ 
  for(int i = led2; i < 1; i--){
    delay(20);
  }else{
    if(led2 <=124){
    digitalWrite(5, LOW);
    delay(250);
    digitalWrite(5, HIGH);
    for(int i = 255; i < 1; i--){
    delay(20);

lo sketch l'ho recuperato da alcuni post precedenti

Quindi abbiamo che lo spegnimento totale del LED dura 20ms * 255 = 5sec. Quindi per 5sec lo sketch avrá per possibili 4 volte contemporaneamente uno script che dura 5sec... e lo sketch sarà circa:

if(millis() - tempoAccensione < tempoSpegnimento &&  millis() - prevTime = 1){
  prevTime = millis();
  tempoSpegnimento--;
  analogWrite(LED, potenzaLED-1)
  potenzaLED--;
}

Dove tempoAccensione è "l'ora" dell'accensione del LED e tempoSpegnimento è il tempo che impiega il LED a spegnersi (5100ms --> 20ms * 255). Ad ogni ripetizione del ciclo si va ad aggiornare diminuendo di 1 sia il tempo che impiega il LED a spegnersi che la potenza del LED. prevTime è una variabile che permette l'attivazione del ciclo if() ogni secondo invece che ogni volta che aggiorna Arduino (velocissimo).
Spero di essermi spiegato bene :grin:

Tu.

Devi strutturare una macchina a stati con un numero di task pari al numero massimo di esplosioni contemporanee, ogni singola esplosione comanderà il suo led in pwm, anche RGB, su ogni task ci sara' una singola esplosione con tutti i suo parametri : colore,intensità,durata, rampa di accensione , rampa di spegnimento, intervallo di pausa tra la successiva, puoi applicare la randomizzazione su uno o più dei 6 parametri di ogni singola esplosione

Solo come possibile suggerimento ... ed usare 4 funzioni, una per ogni led, a cui passare solo l'intensita' di accensione (ed una flag per "avvisarle" dello start) e che poi fanno loro il fade-out con dei for indipendentementi dal resto ?

Mi spiego meglio, passo alla funzione (nome a caso) "void led1()" il valore fra 128 e 255 generato random, piu la flag (nome a caso) "led1on" per dirgli di iniziare il ciclo, la funzione accende il led 1 al valore passato, rimette la flag a 0 (per poter rilevare se nel frattempo arriva un'altro valore e ripartire dall'inizio) ed inizia il ciclo for che lo spegne gradualmente (controllato con millis cosi non e' bloccante), in quel modo basterebbe che il ciclo principale si limitasse a generare i valori a caso con intervalli a caso e passarli alle relative funzioni.

Certo in quel modo non si potrebbe pilotare anche la durata degli spegnimenti (o meglio, si potrebbe ma bisognerebbe passargli anche un secondo valore da usare nel for, oppure generarli all'interno delle funzioni di volta in volta, ma credo questo si possa vedere alla fine, quando il resto funzionera'), pero' dovrebbe semplificare un po la gestione del tutto, o sbaglio ?

Peraltro in questo modo, se arrivasse un nuovo valore al ciclo che sta facendo il fading mentre il led e' ancora acceso, lo riaccenderebbe al massimo simulando una doppia esplosione casuale anche quella :wink:

Oppure l'idea e' troppo folle ?

(poi avevo anche un'altra idea a livello hardware per ottenere lampi che iniziano piu chiari e sbiadiscono verso l'arancio/rosso, ma quella e' ancora piu folle :stuck_out_tongue: )

Come dici tu non sarebbe possibile la contemporaneità (oppure sì, prova a spiegare un po' )

Invece per il cambio luminosità e tonalità in discesa e ottenuto in HW ho immaginato che tu abbia pensato a tre gruppi RC caricati dall'uscita di arduino e che alimentano una terna RGB di led
Col blu e il verde che hanno C minori
Ci ho preso?

Scusate, ma ultimamente mi sono un po' perso...
@icio ha parlato di task, suppongo siano funzioni, ma non ne sono sicuro... Mentre per il discorso dei parametri significherebbe 4*6 =24 cicli if() e più di codice per ogni LED se ho capito giusto... :thinking:

@Etemenanki ha parlato di flag e di fading di cui non ho la più pallida idea di cosa siano :sweat_smile:

@Standardoil mi dispiace ma non ho capito molto... Stai parlando dei colori del LED giusto? :thinking:

Scusate per lo "stordimento" :sweat_smile: