usare il while or not?

buona sera a tutti,
mi sono già presentato in un post precedente.
sto facendo sempre piccoli esperimenti per imparare bene a programmare l’arduino per un progetto piu grande.

ho programmato arduino per far si che accenda in sequenza 4 led e quando si accendono tutti riparte da capo
e questo è il codice

int mieiLed [4]= {6,9,10,11};
int ledAccesi = 0;
void setup() {
for(int x = 6; x<12;x++) {
pinMode(x, OUTPUT);
}
}
void loop() {
digitalWrite(6, HIGH);
delay(500);
digitalWrite(9, HIGH);
delay(500);
digitalWrite(10, HIGH);
delay(500);
digitalWrite(11, HIGH);
delay(500);
for(int x = 6; x<12;x++) {
digitalWrite(x, LOW);
}
delay(500);
}

adesso però vorrei aggiungere una funzione che indipendente da quello che fanno i led devono anche reagire alla luminosità dell’ambiente circostante.
ho già scritto un codice a riguardo che è questo:

const int sensoreLuce = A0;
const int ledGiallo = 9;

int valoreIn = 0; //quantità di luce che entra
int valoreOut = 0; //quantità di luce che esce

void setup() {
Serial.begin(9600);
pinMode(sensoreLuce, INPUT);
pinMode(ledGiallo, OUTPUT);
}

void loop() {
valoreIn = analogRead(sensoreLuce);
Serial.print("Livello luce: ");
Serial.println(valoreIn);
delay(200);

int valoreOut = 10;
int pwm = map(valoreOut, 0,1023, 0,255);
analogWrite(ledGiallo, valoreIn);
delay(0);

adesso per unirli devo usare la funzione while? se si come faccio a dire che mentre i led lampeggiano devono anche reagire alla luminosità?

spero di essere stato chiaro grazie in anticipo
Simone

Risposta semplice, non puoi! Perché non puoi? perché ti trovi in un ambiente single thread senza scheduling, caratteristica dei microcontrollori.
Cosa vuol dire? Vuol dire che l'AVR si occupa solo di eseguire le istruzioni a lui comunicate sequenzialmente, quindi non può cosi di base simulare la contemporaneità dei processi, come avviene in un normale PC.
In un normale programma in CPP creerei due thread, uno per la sequenza e uno per la luminosità e li farei eseguire al processore, che continuerebbe ad alternarli facendo credere di eseguire le due operazioni contemporaneamente.
Come risolvere allora, beh bisogna giocare di astuzia, per esempio i delay sono elementi da dimenticare se si vuole raggiungere un risultato simile e bisogna imparare a gestire le temporizzazioni con millis().
Fai una piccola ricerca su google.

adesso per unirli devo usare la funzione while? se si come faccio a dire che mentre i led lampeggiano devono anche reagire alla luminosità?

spero di essere stato chiaro grazie in anticipo

Il while non risolve, purtroppo non è così semplice, inoltre la funzione loop() è di per se un ciclo infinito.
Chiarissimo e inoltre non sei il primo che affronta questo problema, per cui cerca la funzione millis() nei vecchi topic.
La funzione millis() e il suo uso si è rivelata essere lo zoccolo duro per il principiante, se trovi difficoltà il web è pieno di esempi, anche il vecchi topic ne discutono tanto, gli esempi sono anche forniti assieme all'ambiente di sviluppo.

La funzione delay si dice essere "bloccante" e questo impedisce di eseguire il resto del codice. La funzione delay è paragonabile al tasto pausa.

Mentre millis è paragonabile a guardare l'ora (in ms) sull'orologio, salvarne il valore ed effettuare un calcolo relativo del tempo trascorso. Tramite il costrutto if si valuta se è trascorso o meno l'intervallo di tempo specificato.

Ciao.

Per capire come si usa la millis(), devi studiare prima QUI, poi QUI ed infine leggi anche QUI e QUI ... vedrai che ti sarà tutto più chiaro :wink:

Guglielmo

ok inizierò a studiare come un matto :D. comunque voi intende di usare la funzione millis() come delle pausa tra un funzione e l'altra? cioè di alternare le funzioni velocissimamente in modo da farle sembrare una funzione unica?
grazie degli aiuti

Con delay() Arduino aspetta che un certo tempo é passato non facendo niente
Con millis() controlla di continuo se é tempo di fare qualcosa.
Ciao Uwe

void loop() {
  digitalWrite(6, HIGH);
  delay(500);
  digitalWrite(9, HIGH);
  delay(500);
  digitalWrite(10, HIGH);
  delay(500);
  digitalWrite(11, HIGH);
  delay(500);
  for(int x = 6; x<12;x++) {
    digitalWrite(x, LOW);
  }
  delay(500);
  }

La funzione ‘delay’ si comporta come il tasto pausa di un riproduttore audio/video (o come il tasto pausa/play di un elettrodomestico). Quindi è come se mettessi in pausa il microcontroller, in realtà il controller esegue codice in ciclo per il tempo specificato nel parametro delay.

Guardando dentro il microcontroller scopriamo che c’è un registro contatore genericamente chiamato PC (Program Counter), il quale contiene il valore di memoria su cui si trova l’istruzione da eseguire. Attenzione a non confondere le istruzioni interne al microcontroller con quelle fornite dal linguaggio C.

Esiste una istruzione interna di nome “nop” che equivale a consumare un ciclo di clock senza fare nulla. Se la frequenza di clock permettesse di eseguire una istruzione ogni millesimo di secondo, per realizzare la funzione delay basterebbe fare eseguire 500 volte l’istruzione ‘nop’, quello che avviene è proprio questo, tranne che il clock è più rapido.

Per evitare di impegnare il micro ad eseguire 500 volte ‘nop’ (impedendo al resto delle istruzioni di essere eseguite) ci si è inventati un timer di sistema rudimentale. Immagina di programmare il timer hardware interno al micro in modo che ogni millesimo di secondo un contatore va in overflow. Abilitando l’interrupt su overflow otteniamo l’esecuzione di una specifica routine ogni millesimo di secondo. La routine in questione incrementa un contatore, la funzione millis() restituisce il valore di questo contatore.

Il modo di usare millis sconvolge totalmente il codice di sopra, tanto che è impossibile temporizzare in modo semplice l’esecuzione di codice. Anziché ritardare l’esecuzione della prossima istruzione tramite delay, usiamo una espressione condizionale, per eseguire del codice o meno. L’espressione condizionale con millis richiede anche una operazione matematica, solitamente una sottrazione tra il valore di millis() e il valore memorizzato in precedenza, se il risultato supera l’intervallo, del codice viene eseguito, diversamente si esegue l’istruzione seguente il blocco di codice legato alla if.

Peseduo codice :
Se (valore attuale contatore millisecondi) - (valore contatore millisecondi precedente) è maggiore o uguale (>=) di intervallo {
// il codice da eseguire superato l’intervallo.
// è fondamentale qui salvare il tempo restituito da millis() dentro (valore contatore millisecondi precedente)

}
// Se l’intervallo di tempo non è ancora passato, si continua ad eseguire codice a partire da questo punto.

Grazie al fatto che la funzione loop() è appunto un ciclo infinito, la funzione termina e inizia all’infinito e quindi la condizione if, verrà nuovamente valutata e prima o poi, la valutazione sarà vera, e il blocco di codice delimitato da {} verrà eseguito.

Ciao.

Per xsimo86x.
Mi sono permesso di scrivere alcune osservazioni sui due sketch. Spero che possano essere utili per migliorare il tuo apprendimento.
D’altronde le considero così prolisse e elementari per il livello generale di questo forum che ho pensato di metterle in un allegato in modo da non annoiare chi ha già un buon livello di conoscenza.
Non vorrei che MauroTec la considerasse una critica a lui rivolta. Il suo post E’ AL GIUSTO LIVELLO per questo forum, ma il mio non lo considero tale, e quindi rivolto specificatamente a tutti quelli che come xsimo86x sono ancora alle primissime armi.
Il codice che ho scritto non è stato verificato. Possono esserci errori

Forum20151201a.txt (4.17 KB)

Non vorrei che MauroTec la considerasse una critica a lui rivolta.

Assolutamente no, se non lo è, non vedo perché considerarla una critica.
Se lo fosse (una critica) non ci vedrei nulla di male, certo vorrei saperne di più.

Riguardo a millis(), in passato l'ho spiegata in tanti modi e tante salse e solo in un caso
un utente mi ha risposto qualcosa di simile a quanto scrivo: Finalmente uno che si è spiegato terra terra.

In quel post ricordo di avere fatto l'esempio reale di appuntare su un pezzo di carta l'orario segnato dall'orologio, effettuare
una sottrazione e sottoporla a verifica condizionale " se maggiore di intervallo ".

Leggendo il .txt allegato mi accorgo di non avere notato l'array di cui parli, considera che a questo livello di apprendimento
copiano senza sapere cosa fa il codice, quindi magari ha pescato un suggerimento ma non è riuscito a metterlo in atto completamente.

Per mia esperienza, ho costatato che in certi casi nonostante le spiegazioni diverse, l'utente non riesce a fare suo il meccanismo legato a millis(), quindi mi sono inventato qualcosa per spiegare delay e millis, sperando che l'assieme delle informazioni (incluse quelle che hai fornito), gli permettessero di afferrare il meccanismo. In altri casi, l'utente acquisisce padronanza, dopo avere provato i vari esempi. Sicuramente il background acquisito, anche il altre materie, aiuta alcuni utenti, altri brancolano nel buio davanti l'evidenza e non ti nascondo che vorrei sapere che è per questo e per quello che accade ciò.

Riguardo al while presente nel .txt, esso si comporta come delay, quindi è bloccante, tanto vale usare delay, non credi?

Ciao.

PS: Dal mio punto di vista avresti fatto bene a postare il tuo intervento senza usare l'allegato.

credo che voi siate stati tutti molto precisi in quanto detto e vi ringrazio per la vostra collaborazione grazie a pgiagno per le sue correzione che mi fanno pensare a come voi siate arrivati a sapere questo e sicuramente molto altro. i codici da me scritti sono solo la mia intuizione leggendo parti del libro starter kit, che a parer mio senza offendere nessuno, non spiega precisamente come strutturare un programma fatto bene, io mi aspettavo qualcosa di più completo e spiegazioni su come strutturare un codice nel miglior modo possibile. la mia domanda dunque diventa dove avete imparato? e dove posso imparare per bene a come compilare un IDE per bene? comunque adesso studierò bene i codici che mi avete dato.

grazie