domenica 5 dicembre 2021

Arduino.millis.azioniComposte

Eseguire azioni composte

Una azione composta è appunto composta da singole azioni dove la sequenza di queste è rilevante. Ad esempio 3 pin di arduino configurati come OUTPUT devono essere accesi in sequenza. Una azione composta di questo tipo è da considerare eseguita quando tutte le 3 uscite risultano HIGH. 

digitalWrite(pin1, HIGH);
digitalWrite(pin2, HIGH);
digitalWrite(pin3, HIGH);

Questo esempio appare banale perché non abbiamo specificato delle sequenze temporali. Introduciamo le sequenze temporali usando la funzione delay() che ricordiamo avere un comportamento non desiderato definito da molti "bloccante".

digitalWrite(pin1, HIGH);
delay(1000);
digitalWrite(pin2, HIGH);
delay(2000);
digitalWrite(pin3, HIGH);
Serial.println("compito completato"); 

Da un lato il delay() ci permette di mettere in sequenza temporale 3 singole azioni che una volta compiute noi consideriamo come un "compito completato".

Rispettare queste azioni con delle tempistiche usando millis() al posto di delay() ci sconvolge il ragionamento. Usando millis() ci troviamo nella condizione in cui altro codice viene eseguito nell'intervallo di tempo di 3 secondi e dobbiamo considerare "compito completato" solo quando tutte le 3 uscite pin1, pin2 e pin3 sono nello stato HIGH. Visto che abbiamo 3 digitalWrite() usiamo 3 variabili di stato, es: statoPin1, statoPin2 e statoPin3.

void loop() {

    // qui il codice che modifica il valore delle 3 variabili di stato

digitalWrite(pin1, statoPin1);
digitalWrite(pin2, statoPin2);
digitalWrite(pin3, statoPin3);

}

Al posto di // qui il codice ... dobbiamo inserire il codice che modifica il valore delle 3 variabili di stato in funzione del tempo che scorre. Il codice sotto esegue immediatamente la prima, dopo 1000ms la seconda e dopo 2000ms la terza azione.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
const byte pin1 = 2;
const byte pin2 = 3;
const byte pin3 = 4;
// variabili di stato
bool statoPin1 = LOW;
bool statoPin2 = LOW;
bool statoPin3 = LOW;

// saveMillis è usata per temporizzare le azioni
uint32_t saveMillis = 0;
uint32_t intervallo = 0:   // potrebbe essere 1000 al posto di 0

void setup() {

    pinMode(pin1, OUTPUT);
    pinMode(pin2, OUTPUT);
    pinMode(pin3, OUTPUT);
    
    Serial.begin(9600);
}
   
void loop() {

    if (statoPin1 == LOW) {

        statoPin1 = HIGH;
        intervallo = 1000;      // vale 1000ms
        saveMillis = millis();

    }

    if (millis() - saveMillis >= intervallo) {

        if (statoPin2 == LOW) {

            statoPin2 = HIGH;
            intervallo = 2000;  // se prima era 1000ms ora è 2000ms
            saveMillis = millis();

        } else {

            statoPin3 = HIGH;
        }
    }
    
    digitalWrite(pin1, statoPin1);
    digitalWrite(pin2, statoPin2);
    digitalWrite(pin3, statoPin3);
    
    if (statoPin1 && statoPin2 && statoPin3) {
        // questo messaggio apparirà dopo circa 3 secondi dopo il reset.
        Serial.println("compito completato);
    }

}

Notate come da riga 24 a 30 nel corpo della if ci entra una sola volta e mai più. Quando serve questo comportamento abbiamo necessità di una variabile di stato che una volta modificata nel corpo della if impedirà di essere eseguita altre volte (ricordate che la funzione loop() termina e ricomincia all'infinito).


Licenza Creative Commons
Quest'opera è distribuita con Licenza Creative Commons Attribuzione - Condividi allo stesso modo 4.0 Internazionale

Nessun commento:

Posta un commento