Incomprensione millisec e timer diversi

Buongiorno a tutti.
Dovrei comandare un relè, che una volta avviato Arduino, lo chiude per 60 secondi.
Dopodiché, dovrei mantenerlo aperto per 5 minuti.
Passati i 5 minuti, ricominciare da capo.

Per ora sono solo riuscito a farlo rimanere apero/chiuso 60 secondi. Non so come implementare una pausa più lunga. Dovrei aggiungere un secondo timer?

int rele = 5;
int relestate = LOW;
unsigned long previousMillis = 0;
const long interval = 60000; 


//SETUP
pinMode(rele, OUTPUT);


//LOOP

    unsigned long currentMillis = millis();

    if (currentMillis - previousMillis >= interval)
    {
      previousMillis = currentMillis;
      if (relestate == LOW)
      {
        relestate = HIGH;
      }
      else
      {
        relestate = LOW;
      }
      digitalWrite(rele, relestate);
    }
}

Si, puoi fare due volte la stessa cosa (ovviamente con variabili diverse), una volta per accendere ed una seconda volta per spegnere, condizionando la cosa al fatto che il relè sia acceso o spento :wink:

Guglielmo

Penso proprio sia qui, che mi complico la vita...

Per esempio, posso usare unsigned long currentMillis = millis(); ?
Ovviamente mettendo
unsigned long currentMillis2 = millis();
Oppure c'è il rischio di mandare in conflitto il timer?

Dai una lettura a questo thread

Ciao.

Grazie,sembra interessante e fare al mio caso.
Ma mi sono incastrato e mi tiene conto solo dell'intervallo che gli do, e cicla con quei secondi.
Dove gli dico il 2° timer?

Si capisco, li però c'è anche uno switch case che potresti usare per implementare una macchina a stati finiti, qui c'è una piccola demo da cui trarre spunto.

Wow....è davvero così complicato per "dire ad un relè", quando partire e per quanto tempo? :face_with_peeking_eye:
Quindi, da quello che ho capito, mi conviene fare degli "stati" e "variabili", che andrò a richiamare con switch case ?

Vado verso la giusta strada?

Sno, complicato è ciò che ci appare tale. La direzione che hai presupposto è una delle tante possibili.

Detta così vuole dire che non hai capito come funziona. In base al valore assunto dalla variabile di stato state viene eseguito il case n. Dentro ad ogni case puoi assegnare valori a variabili e quindi anche alla variabile state.

Si può fare in tanti modi anche senza switch case, c'è da vedere se poi ti sembra sempre complicato.

Su wokwi ho scritto uno sketch di esempio, vedi se va be e se lo comprendi. Salvatelo poiché non rimarrà allungo il link.

Ciao.

1 Like

Grazie...Domani vedrò d'immergermi. Perchè è vero, sembra facile, ma non lo è. Solo comprendendo i possibili casi lo diventa! Grazie mille.

Prego, aggiungo qualcosa con l'intento di chiarire.

Più che parlare di relè, qui dovremmo concentrarci solo sullo stato di un pin, poi cosa ci colleghi a questo pin poco importa, nel senso che puoi anche collegarci un led, poiché ad esempio un relè necessità di un circuito di comando, questo può o meno essere optoisolato ecc. Cosa ci colleghiamo lo affrontiamo dopo, per adesso io lo considero collegato ad un led con la sua resistenza in serie.

Il led deve accendersi, rimanere in questo stato per ts (1minuto) tempo. Scaduto ts si spegne è resta in questo stato per tn (5 minuti) tempo.

Il tutto ricomincia d'accapo. Si tratta quindi di stati sequenziali e per questi si può usare delay() che sarà uno degli stati posti in sequenza. Tuttavia delay() ha il brutto "difetto" di impegnare la CPU per tutto il tempo specificato dentro le parentesi tonde. Durante questo tempo la CPU non potrà eseguire altro codice e questo penalizza la reattività.

Ciao.

Esattamente. Infatti con delay era semplice, ma non potevo occupare tempo, fermando tutto. Invece così, il programma sembra una sorta di multitasking (anche se non lo è). Ma se tutto il codice, è impostato bene, e si sa cosa si ha compilato, tutto fila liscio.Ed inoltre è sempre pronto per delle aggiunte. Io con questo progettino sono partito che, dovevo solo sapere 1 temperatura tramite seriale.
Pian piano ho fatto in modo che mi controlla 2 temperature con 2 sensori digitali con risoluzione a 12bits (ma la uso a 11) tramite OneWire, e relative ventole indipendenti con mosfet. Le singole temperature vengono visualizzate su lcd i2c e cambia l'icona se l'una o l'altra (o entrambe)sono attive, e ritorna sull'lcd "il sorriso" se le temperature sono nel "range". Schermata di benvenuto all'accensione! Ed ora un bel relè che raffredda la circuiteria ogni "tot tempo", e senza interrompere il flusso del programma.

Prossimo step, penso di aggiungere un menù con pulsanti all'lcd!!!!

Ho solo 2 domande:
_Che timer viene usato per la funzione millisec?
_E' possibile usare 2 millis distinti per 2 funzioni diverse? Oppure si va ad appesantire e/o complicare il tutto?

Grazie

millis() è SOLO una funzione che va a leggere il valore di un "contatore" che viene incrementato ogni millisecondo dall'accensione di Arduino, quindi ... la puoi richiamare dove e quando ti pare, sempre il valore di quel contatore ti da :wink:

Ah ... l'incremento del "contatore" è comandato tramire un interrupt collegato a Timer0.

Guglielmo

Se porta avanti nel tempo più processi in parallelo si che lo è :wink:
Si tratta di multitasking a divisione di tempo di tipo cooperativo realizzato interamente via software: ogni processo deve essere strutturato appositamente per lasciare il controllo al successivo nel più breve tempo possibile.

Questo fa la stessa cosa, ma in modo differente.

Nota il link resta valido per un paio di giorni al massimo.

Come ti ha spiegato @gpb01 puoi usare millis() per salvarti il tempo in millesimi di secondo in più variabili diverse ed avere quindi temporizzazioni diverse.

Diciamo che si presta a modifiche senza compromettere il funzionamento di altre parti di codice, stessa cosa per quello postato di seguito.

#define PIN_RELAY 13
// per test 6000UL, per i minuti aggiungere uno zero 
#define MIN_TO_MILLIS(m) (m * 6000UL)

bool g_relayState = HIGH;
bool g_relayOldState = LOW;

uint32_t g_saveMillis;
uint32_t g_interval;

void setup()
{
    Serial.begin(115200);
    pinMode(PIN_RELAY, OUTPUT);
    g_interval = MIN_TO_MILLIS(1);

    Serial.println(MIN_TO_MILLIS(1));
    Serial.println(MIN_TO_MILLIS(2));

    g_saveMillis = millis();

} // end void setup()


void loop() {
 
  if ( millis() - g_saveMillis > g_interval ) {
      g_relayState = !g_relayState;
      g_saveMillis = millis();
  }

  if (g_relayState != g_relayOldState) {
    digitalWrite(PIN_RELAY, g_relayState);
    g_relayOldState = g_relayState;
    if (g_relayState) {
        g_interval = MIN_TO_MILLIS(1);
    } else {
        g_interval = MIN_TO_MILLIS(5);

    }
  }
    
} // end void loop()

Ciao.

1 Like

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