se interruttore alto attiva un uscita altrimenti me ne attivi un'altra

Progetti Arduino
Avatar utente
pgv
Messaggi: 484
Iscritto il: gio 17 set 2020, 13:16
Località: Ginevra

Re: se interruttore alto attiva un uscita altrimenti me ne attivi un'altra

Messaggio da pgv »

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

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);
  }
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:

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);
  }
}
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:

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);
  }
}
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!!!
RoccoCostruzioni
Messaggi: 51
Iscritto il: mer 9 set 2020, 21:16

Re: se interruttore alto attiva un uscita altrimenti me ne attivi un'altra

Messaggio da RoccoCostruzioni »

So benissimo PGV che i delay sono bloccanti ma nel mio caso non mi interessa per il semplice fatto che le funzioni verranno eseguite una alla volta, quando serviranno e se serviranno, comunque voglio approfondire la questione tabellina magari apro io stesso un altro post, anzi lo faccio adesso e vorrei, se non le dispiace PGV, che lei partecipasse, detto questo torniamo al mio codice che con l'implementazione di GUIDO ottengo l'effetto desiderato ma se io al posto di comandare ledPinTIMERON e ledPinTIMEROFF volevo comandare pulsON e pulsOFF e quindi l'uscita dell'alimentatore, senza dover mettere due relè?
ps. ho aperto un'altro post sulla questione tabellina se volete rispondere sarò lieto di approfondire, magari così altri utenti possono avere beneficio
Rispondi