Timer non funziona

Ciao a tutti.
Gentilmente potete dirmi se ce qualche errore in questo codice?
L'intenzione è quella di accendere il led integrato se la temp. è inferiore a 20° per 5 secondi.
Se abbasso la temperatura il led si accende ma poi non si spegne piu a meno che la temperatura non salga oltre i 20 gradi.

// C++ code
//
int temp = 0;

int pin_4 = 0;

void setup()
{
  pinMode(A0, INPUT);
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop()
{
  temp;

  temp = (-40 + 0.488155 * (analogRead(A0) - 20));
  if (temp < 20) {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(5000); // Wait for 5000 millisecond(s)
    digitalWrite(LED_BUILTIN, LOW);
  }
}

Non si spegne più perché dopo lo spegnimento finisce subito il loop, subito ricomincia e, essendo la temperatura minore di 20, subito si riaccende!
Metti un altro delay dopo lo spegnimento.
Comunque i delay bloccano anche qualunque altra cosa inserirai nel loop!

Ciao @Datman e grazie per l'intervento. In realtà lo sto simulando su un sito online. Non so se posso dire il nome... Ripeto che il led non si spegne anche se la temperatura è superiore a 20°.

Con una temperatura maggiore di 20 gradi come potrebbe spegnersi?... L'unico spegnimento sta nell'if(temp<20)!

Questa istruzione nel loop non serve a nulla
Se lo ha scritto il simulatore direi che ha dei problemi seri.

Il problema è come dice datman al post n. 2
Se temp minore 20 entri, accendi, 5 sec, spegni e poi... al secondo giro di loop rientri in quel if.
Non hai nulla per ricordare che hai già fatto il lampeggio quando da 20 sei andato sotto.

Certo che puoi... Wokwi? TinkerCad?
Magari condividi anche il link al progetto così possiamo anche noi provarlo.

2 Likes

ok L'ho migliorato un pochettino. Adesso si spegne se la temperatura va oltre i 20 gradi. Io pero vorrei che si spegnesse a prescindere dopo tot tempo. Credo che va inserito un timer all'accensione della lampadina.

Crea una variabile booleana per ricordare che hai acceso la lampadina.
Nel if, oltre alla temperatura, confronta anche la nuova variabile.
Non dimenticare di reimpostare la variabile quando è necessario riaccenderla.
Hai già un esempio nel tuo TinkerCad

1 Like

Prova questa versione, vedi se funziona tutto (non l'ho provata) e soprattutto nota le modifiche quindi facci sapere se comprendi cosa è stato modificato, come, e perché (serve per non darti la "pappa pronta" ed aiutarti a capire alcune cose che sono necessarie):

#define TEMPO 5000
#define P_SENSOR A0
#define P_LED 4
int temp;

boolean LedAcceso = false;
unsigned long t0 = 0;

void setup() {
  pinMode(P_SENSOR, INPUT);
  pinMode(P_LED, OUTPUT);
}

void loop(){
  temp = (-40 + 0.488155 * (analogRead(P_SENSOR) - 20));
  if (temp < 20 && !LedAcceso) {
    digitalWrite(P_LED, HIGH);
    LedAcceso = true;
    t0 = millis();
  }
  if (temp >= 20 || (LedAcceso && millis()-t0 >= TEMPO)) {
    digitalWrite(P_LED, LOW);
    LedAcceso = false;  
  }
}
1 Like

Guada che lo faccio proprio per imparare... E' da un po che ci provo. Adesso volevo mettermi a provare il metodo a blocchi.

Cmq grazie per l'impegno ma non funziona.
La lampadina si accende al di sotto dei 20 gradi e si spegne oltre i 20.

Il led deve spegnersi 5 sec dopo laccensione. Il millis mi ricordo che conta il tempo dal momento che si accende l'arduino. Non tiene conto del evento (la lampadina che si accende).

Credo che vuol dire: con led acceso e "millis" maggiore o uguale a "TEMPO" spegni la lampadina. Ok ma non lo fa.

Credo che debba esserci un modo per far partire un delay dal ultimo evento.

La funzione millis() no, ma se cerchi di capire il codice che ti ho scritto, è per questo che ti ho introdotto la variabile "t0" che rappresenta il "tempo zero" ossia il valore di millis() nel momento in cui accendo il led ("t0 = millis();").

Ok, ma sai, come ti dicevo non vorrei darti la "pappa pronta" ma portarti a modificare il codice capendo cosa fare. Quindi deve accendersi se scende sotto ai 20 gradi e spegnersi dopo 5 secondi, indipendentemente dal valore corrente dei gradi (e non riaccendersi se la temperatura resta ? Mi pare semplice, ti do' un consiglio: usa il linguaggio naturale per descrivere passo-passo la procedura (quindi una riga per ogni criterio od operazione, ed indentandoli se interni ad una condizione) sotto forma di commento nel codice, ed alla fine converti ogni passo nelle relative istruzioni.
Per farti un esempio, questi sarebbero i commenti relativi al codice che ti ho postato io (quindi da correggere):

  // Leggi la temperatura
  // Se la temperatura è bassa ed il led non è ancora acceso
    // allora accendi il led
  // Se la temperatura è corretta o se sono passati 5 secondi
    // allora spegni il led

Limitandoti quindi ai commenti, riesci a scrivere in questo modo una versione che, seppure per ora in linguaggio naturale, descrive il funzionamento che desideri?

Il perché è già stato detto. Non è che non si spegne, ma se la temperatura è ancora sotto i 20, si riaccende subito. In pratica il codice gestisce due situazioni possibili: spento in attesa che la temperatura scenda sotto i 20, e pausa acceso, ma poi ritorna a gestire la prima situazione e si riaccende subito:

7657465

Quello che manca, anche nella descrizione iniziale a parole, è cosa deve avvenire dopo che il LED si è spento.

È chiaro che non si deve subito riaccendere, e per fare questo basta una variabile bool per disabilitare la condizione di accensione (avevo visto un codice tinkercad funzionante dopo il suggerimento corretto di @gonpezzi del post #8, prima delle ultime modifiche...)

Non si sa poi se qualcosa deve "riarmare" il processo. Si può immaginare che questo qualcosa sia la temperatura che risale oltre un certo valore, ma non è stato ancora esplicitato, mentre è un aspetto fondamentale del progetto. In tal caso il codice deve gestire tre diverse situazioni:

87967856765

Come farlo dipende da diversi fattori... usando delay e codice bloccante? Usando millis e codice non bloccante? Si può fare anche con i blocchi, anche se secondo me è più difficile.

1 Like

Si ma infatti è la descrizione che non è chiara/completa, ed è il motivo per cui il mio primo codice non funziona esattamente come dice lui.
Attendiamo che formalizzi la cosa con i commenti come gli consigliavo nel mio ultimo post, perché un codice da fargli provare ce l'avrei pure ma non voglio dare la "pappa pronta" :wink:

Questo codice fa proprio quello che intendevo. Il led si accende per 5 secondi se la temperatura scende sotto i 20 gradi. Dopo l'accensione del led la temperatura non influisce piu in alcun modo l'accensione o lo spegnimento del led. il led si accende una sola volta.

// Dichiarazioni delle variabili
int temperaturaPin = A0;
int ledPin = 4;
bool ledAcceso = false;
bool ledGiaAccesso = false;
unsigned long tempoIniziale;

void setup() {
  // Inizializza il LED come output
  pinMode(ledPin, OUTPUT);
}

void loop() {
  // Leggi la temperatura dal sensore TMP36
  float temperatura = leggiTemperatura(temperaturaPin);

  // Se la temperatura è inferiore a 20 gradi, il LED non è gia acceso e non è mai stato acceso prima
  if (temperatura < 20 && !ledAcceso && !ledGiaAccesso) {
    // Accendi il LED
    digitalWrite(ledPin, HIGH);
    ledAcceso = true;
    ledGiaAccesso = true;

    // Imposta il tempo iniziale solo quando il LED viene acceso per la prima volta
    tempoIniziale = millis();
  }

  // Se il LED è acceso e sono passati almeno 5 secondi
  if (ledAcceso && (millis() - tempoIniziale >= 5000)) {
    // Spegni il LED
    digitalWrite(ledPin, LOW);
    ledAcceso = false;
  }
}

float leggiTemperatura(int pin) {
  // Leggi il valore analogico dal sensore TMP36
  int valoreLettura = analogRead(pin);

  // Tensione di alimentazione del sensore (5V)
  float tensioneAlimentazione = 5.0;

  // Converti il valore analogico in gradi Celsius secondo la formula del TMP36
  float temperaturaCelsius = ((valoreLettura / 1024.0) * tensioneAlimentazione - 0.5) * 100.0;

  return temperaturaCelsius;
}
1 Like

Ok, questo è un processo completamente non bloccante a tre stati :+1:

Alla fine il processo si assesta nel terzo e li rimane (a meno di non farlo "ripartire" azzerando la variabile di blocco.

E giustamente con 3 stati servono come minimo due flag:
log2(3) = 1.58 = 2 bit

Oppure una sola variabile che indica lo stato attuale:

void loop() {
  // Leggi la temperatura dal sensore TMP36
  float temperatura = leggiTemperatura(temperaturaPin);

  // Se la temperatura è inferiore a 20 gradi, il LED non è gia acceso e non è mai stato acceso prima
  if (temperatura < 20  &&  0 == stato) {
    // Accendi il LED
    digitalWrite(ledPin, HIGH);
    stato = 1;

    // Imposta il tempo iniziale solo quando il LED viene acceso per la prima volta
    tempoIniziale = millis();
  }

  // Se il LED è acceso e sono passati almeno 5 secondi
  if (1 == stato  &&  (millis() - tempoIniziale >= 5000)) {
    // Spegni il LED
    digitalWrite(ledPin, LOW);
    stato = 2;
  }
}

Ma se la temperatura torna sotto i 20°C non succede più nulla!

Quindi si puo fare a meno delle booleane?
"log2(3) = 1.58 = 2 bit" questo cosa vuol dire?

Si esatto nel post 7 credo si capisca che deve spegnersi a prescindere dalla temperatura.

Ho installato un riscaldatore ausiliario sulla macchina ma mi capita a volte di dimenticarlo acceso.
In realtà, quando arriva in temperatura consuma pochissimo ma vorrei evitare comunque di lasciarlo acceso. Con questo codice, quando premo il telecomando accendo l'arduino il quale controlla la temperatura del motore e se inferiore alla soglia accende il riscaldatore per tot minuti. La lampadina nella simulazione, una volta accesa doveva essere insensibile alla temperatura perche da li a breve il motore si riscalda e quindi mi spegne il riscaldatore.

Grazie a tutti per i consigli.

log2(N) arrotondato per eccesso all'intero più vicino, è la quantità minima di bit di memoria, flag, o variabili bool, che servono per distinguere N diversi stati.

Per fare senza flag/bool si puo'usare una sola variabile di stato come indicato nell'esempio.

Questa cosa la dovrò approfondire perché non lo capisco :slight_smile:
Quello che mi dispiace è che non trovo una sezione di questo forum oppure in altri siti dove vengono dati piu esempi per spiegare una determinata funzione.
Qui ho trovato la spiegazione delle funzioni ma ce una, al massimo due righe. Richiedono piu tempo ma in alquni video on line qualcuno spiega mentre scrive il codice.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.