Trasformare codice con delay in millis

Salve, ho creato un codice con i delay e mi funziona. Ora mi è venuto in mente di aggiungere un'altra funzione ma i delay non vanno più bene perchè bloccano l'esecuzione del codice. Il pezzo di codice in questione è questo:

void controllo_automatico() {
  stampa_testo(0,0,"Tensione Assente ");
  delay(2000);  // Aspetta 2 secondi
  digitalWrite(pin_start,1);  // Attiva il relè per aprire
  stampa_testo(0,0,"Apre cancello ");
  delay(500);  // Aspetta mezzo secondo
  digitalWrite(pin_start,0);  //  Spegne il relè per aprire
  delay(30000);  // Aspetta 30 secondi
  digitalWrite(pin_stop,1);  //  Attiva il relè per lo stop
  stampa_testo(0,0,"Cancello fermo ");
  controllo = 1;  // Questa variabile viene posta a 1 per indicare che la tensione è mancata
}

Come si può trasformare il tutto con millis()?
Con un delay riesco a farlo ma qui ce ne son troppi in sequenza.

void setup() {
  // put your setup code here, to run once:
  controllo_automatico(true);
}

void loop() {
  // put your main code here, to run repeatedly:
  controllo_automatico(false);
}

void controllo_automatico(bool start) {
  static uint32_t lastTime = millis();
  static uint8_t state = 0;
  if (start == true) state = 1;

  switch (state) {
    case 0:
      break;

    case 1:
      lastTime = millis();
      stampa_testo(0, 0, "Tensione Assente ");
      state = 2;
      break;

    case 2:  // Aspetta 2 secondi
      if (millis() - lastTime >= 2000) state = 3;
      break;

    case 3:
      digitalWrite(pin_start, 1); // Attiva il relè per aprire
      stampa_testo(0, 0, "Apre cancello ");
      lastTime = millis();
      state = 4;
      break;

    case 4:   // Aspetta mezzo secondo
      if (millis() - lastTime >= 500) state = 5;
      break;

    case 5:
      digitalWrite(pin_start, 0); //  Spegne il relè per aprire
      lastTime = millis();
      state = 6;
      break;

    case 6:    // Aspetta 30 secondi
      if (millis() - lastTime >= 30000) state = 7;
      break;

    case 7:
      digitalWrite(pin_stop, 1); //  Attiva il relè per lo stop
      stampa_testo(0, 0, "Cancello fermo ");
      controllo = 1;  // Questa variabile viene posta a 1 per indicare che la tensione è mancata
      state = 0;  // go idle
      start = false;
      break;
  }
}

Grazie per l'aiuto, avevo iniziato a scrivere qualcosa di simile ma utilizzando gli if e una variabile step per indicare la successione, sicuramente il tuo sistema è più leggibile. Ho notato un errore, all'inizio della funzione controllo_automatico, hai messo state=0. Se chuiamo la funzione con true, viene stampato il messaggio: Tensione assente, esce dal case, va nel loop e torna a chiamare la funzione controllo_automatico, mi mette la variabile state=0 e quindi mi stampa di nuovo: Tensione assente, esce dal case va nel loop e rifà sempre questo all'infinito. L'idea è buona, la devo modificare per farla funzionare.

@anon57585045: Buongiorno, come forse avrai letto, la sezione Italiana del forum ha un suo REGOLAMENTO (che ti chiediamo gentilmente di leggere) e richiede che, cortesemente, se non l'hai già fatta, tu faccia la tua presentazione NELL'APPOSITA DISCUSSIONE spiegando bene quali esperienze hai in elettronica e programmazione, affinché noi possiamo conoscere la tua esperienza ed esprimerci con termini adeguati. :slight_smile:

Un altra cosa, qui nella sezione Italiana, NON scriviamo l'intero codice agli utenti (NON diamo la "pappa fatta"), ma cerchiamo di spiegargli cosa devono fare in modo che siano loro a farlo ... in merito il punto 16.13 del succitato regolamento spiega bene le motivazioni. Tiello presente per il futuro :wink:

Grazie,

Guglielmo

Non ho chiesto di darmi il codice ma come si poteva trasformare in millis(), mi basta l'idea. Infatti ho scritto che avevo iniziato a scrivere un codice simile ma con gli if. Comunque ho risolto i problemi presente nel codice di aarg.

bool no_tensione=0;
bool controllo=0;
byte state=1;
uint32_t lastTime = millis();

void setup(){
}

void loop(){
no_tensione = digitalRead(4);
 if (no_tensione == 0 && controllo == 0) controllo_automatico(); 
}

void controllo_automatico() {

  switch (state) {

    case 1:
      lastTime = millis();
      stampa_testo(0, 0, "Tensione Assente ");
      state = 2;
      break;

    case 2:  // Aspetta 2 secondi
      if (millis() - lastTime >= 2000) state = 3;
      break;

    case 3:
      digitalWrite(pin_start, 1); // Attiva il relè per aprire
      stampa_testo(0, 0, "Apre cancello ");
      lastTime = millis();
      state = 4;
      break;

    case 4:   // Aspetta mezzo secondo
      if (millis() - lastTime >= 500) state = 5;
      break;

    case 5:
      digitalWrite(pin_start, 0); //  Spegne il relè per aprire
      lastTime = millis();
      state = 6;
      break;

    case 6:    // Aspetta 30 secondi
      if (millis() - lastTime >= 3000) state = 7;
      break;

    case 7:
      digitalWrite(pin_stop, 1); //  Attiva il relè per lo stop
      stampa_testo(0, 0, "Cancello fermo ");
      controllo = 1;  // Questa variabile viene posta a 1 per indicare che la tensione è mancata
      state = 1;  // go idle
      break;
  }
}

... ma io infatti non ho scritto a te :wink:

Guglielmo

Me ne sono accorto dopo, :sweat_smile:

1 Like

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