Re: se interruttore alto attiva un uscita altrimenti me ne attivi un'altra
Inviato: mar 13 ott 2020, 13:07
Primo e soprattutto: se il codice funziona in maniera soddisfacente per l'utente, e' perfetto.
Passiamo pero' in modalita' didattica. Giusto per riassumere, io ho suggerito la possibilita' di implementare il programma, che mi sembra di capire genera uscite temporizzate sulla base di una serie di ingressi temporizzati (le conseguenze delle uscite sul particolare strumento, o sul surriscaldamento globale, le possiamo vedere separatamente, non hanno influenza sul software che le controlla se non tramite le specifiche di questo stesso), non come una serie di
che per l'amor del cielo funziona, con una struttura piu' organizzata nella quale, manipolando una "Tabellina" (che si traduce in un vettore di struct, se vogliamo essere pignoli) in cui possiamo specificare tra quanto tempo a partire dal momento in cui la inseriamo in tabella deve essere eseguita una certa funzione e se deve essere eseguita ripetutamente con un certo periodo o una volta sola. Questo schema di programmazione (che non ho inventato io e che viene anche chiamato "Scheduler cooperativo") e' in grado di provvedere tutte le funzionalita' della sequenza di if() e delay(), ma in piu' ha il vantaggio di rendere ragionevolmente piu' facile modificare e mantenere il codice se ce ne fosse bisogno in un futuro piu' o meno immediato (e meno immediata e' la manutenzione del codice piu' e' importante che essa sia facile). Inoltre, la sequenza di if() e delay() ha alcuni difettucci:
1. durante le chiamate a delay(), il sistema NON e' in grado di processare eventuali cambiamenti negli ingressi. Anzi, ogni ingresso viene esaminato solo una volta per esecuzione del ciclo loop() a meno di andare a leggerlo in piu' punti del ciclo stesso, ovviamente.
Caso assurdo: se loop() contiene un totale di 10 secondi di delay(), io posso dover tenere premuto un pulsante per 10 secondi perche' il micro se ne accorga e faccia quel che deve fare;
2. anche se oggi ci assicuriamo che le chiamate a delay() non possono interferire con il corretto funzionamento del programma e dello strumento che esso controlla, eventuali aggiunte (o rimozioni) di chiamate a delay() possono cambiare questo stato di cose.
Caso assurdo:
Anche se siamo sicuri che tra l'attivazione di ingresso1 e quella di ingresso2 passano almeno 600 millisecondi, e quindi con il listato qui sopra siamo sicuri che non perderemo mai un impulso in ingresso (perche' le delay() terminano prima del magico intervallo di 600 millisecondi), se aggiugniamo un terzo ingresso:
Oops. Possiamo perdere segnali in ingresso, e dobbiamo rivedere tutta la temporizzazione del programma.
3. Durante l'esecuzione della delay() il processore non fa (quasi) niente altro (risponde a interrupt). Se non hai conti da fare va bene, ma immagina che uno dei tuoi ingressi in realta' sia una sequenza di numeri che sono l'output di un analizzatore di spettro, e tu devi cercare picchi e vallate, magari calcolando FFT e filtri sui tuoi dati in ingresso...
Insomma, se organizzi il tuo sistema in modo da poterlo descrivere come una serie di
<se si attiva questo ingresso, fai questa cosa dopo tot tempo>
<se si attiva questo ingresso, fai questa cosa dopo tot tempo>
<se si attiva questo ingresso, fai questa cosa dopo tot tempo>
<se si attiva questo ingresso, fai questa cosa dopo tot tempo>
ti conviene utilizzare il modello dello Scheduler, perche' ti sara' piu' facile aggiungere, togliere e modificare, e inoltre potrai sfruttare meglio la tua CPU.
Detto questo, scendo dalla cattedra e ribadisco:
Se funziona in maniera soddisfacente per l'utente finale, il software va benissimo!!!
Passiamo pero' in modalita' didattica. Giusto per riassumere, io ho suggerito la possibilita' di implementare il programma, che mi sembra di capire genera uscite temporizzate sulla base di una serie di ingressi temporizzati (le conseguenze delle uscite sul particolare strumento, o sul surriscaldamento globale, le possiamo vedere separatamente, non hanno influenza sul software che le controlla se non tramite le specifiche di questo stesso), non come una serie di
Codice: Seleziona tutto
if(condizione1) {
digitalWrite(uscita1, HIGH);
delay(durata1);
digitalWrite(uscita1, LOW);
}
...
if(condizione2) {
digitalWrite(uscita2, HIGH); // Per cambiare qui attiviamo una uscita e ne disattivimao un'altra dapprincipio
digitalWrite(uscita3, LOW);
delay(durata2);
digitalWrite(uscita2, LOW); // E poi disattiviamo la prima e attiviamo la seconda. Tanto per cambiare...
digitalWrite(uscita3, HIGH);
}
...
if (condizioneN) {
delay(attesaN); // Tanto per cambiare, qui aspettiamo anche PRIMA di attivare l'uscita
digitalWrite(uscitaN, HIGH);
delay(durataN);
digitalWrite(uscitaN, LOW);
}
1. durante le chiamate a delay(), il sistema NON e' in grado di processare eventuali cambiamenti negli ingressi. Anzi, ogni ingresso viene esaminato solo una volta per esecuzione del ciclo loop() a meno di andare a leggerlo in piu' punti del ciclo stesso, ovviamente.
Caso assurdo: se loop() contiene un totale di 10 secondi di delay(), io posso dover tenere premuto un pulsante per 10 secondi perche' il micro se ne accorga e faccia quel che deve fare;
2. anche se oggi ci assicuriamo che le chiamate a delay() non possono interferire con il corretto funzionamento del programma e dello strumento che esso controlla, eventuali aggiunte (o rimozioni) di chiamate a delay() possono cambiare questo stato di cose.
Caso assurdo:
Codice: Seleziona tutto
void loop() {
if (digitalRead(ingresso1) == HIGH) {
digitalWrite(uscita1, HIGH);
delay(500);
digitalWrite(uscita1, LOW);
}
if (digitalRead(ingresso2) == HIGH) {
digitalWrite(uscita2, HIGH);
delay(500);
digitalWrite(uscita2, LOW);
}
}
Codice: Seleziona tutto
void loop() {
if (digitalRead(ingresso1) == HIGH) {
digitalWrite(uscita1, HIGH);
delay(500);
digitalWrite(uscita1, LOW);
}
if (digitalRead(ingresso2) == HIGH) {
digitalWrite(uscita2, HIGH);
delay(500);
digitalWrite(uscita2, LOW);
}
if (digitalRead(ingresso3) == HIGH) {
digitalWrite(uscita3, HIGH);
delay(1000); <== ATTENZIONE
digitalWrite(uscita3, LOW);
}
}
3. Durante l'esecuzione della delay() il processore non fa (quasi) niente altro (risponde a interrupt). Se non hai conti da fare va bene, ma immagina che uno dei tuoi ingressi in realta' sia una sequenza di numeri che sono l'output di un analizzatore di spettro, e tu devi cercare picchi e vallate, magari calcolando FFT e filtri sui tuoi dati in ingresso...
Insomma, se organizzi il tuo sistema in modo da poterlo descrivere come una serie di
<se si attiva questo ingresso, fai questa cosa dopo tot tempo>
<se si attiva questo ingresso, fai questa cosa dopo tot tempo>
<se si attiva questo ingresso, fai questa cosa dopo tot tempo>
<se si attiva questo ingresso, fai questa cosa dopo tot tempo>
ti conviene utilizzare il modello dello Scheduler, perche' ti sara' piu' facile aggiungere, togliere e modificare, e inoltre potrai sfruttare meglio la tua CPU.
Detto questo, scendo dalla cattedra e ribadisco:
Se funziona in maniera soddisfacente per l'utente finale, il software va benissimo!!!