Go Down

Topic: Funzione Millis() due cicli - non capisco (Read 2468 times) previous topic - next topic

stomosto

Ciao a tutti,
avevo già scritto nel forum e siete stati di grandissimo aiuto, spero lo sarete ancora adesso con questa mia banale domanda per voi facilissima :)
non riesco a capire come impostare la funzione millis, ho cercato in mille modi ciò di cui ho bisogno ma non trovo nulla, solo esempi sul lampeggio dei led con un tempo fisso;
quello che vorrei fare, è far funzionare una ventola per, ad esempio 2 minuti e farla stare ferma 15 minuti.
ho guardato tutti i tutorial ma non riesco proprio a capire come si gestiscono questi due tempi, se mi scrivete un mini sketch di esempio ve ne sarei grato, grazie mille per la disponibilità.

stomosto

Mi sto scervellando per una banalità ma proprio non arrivo al punto;
dichiaro due tempi (di prova uso 5 secondi e 1 secondo con il pin 13)
ma la regola dell' if non la riesco a capire per far si che stia acceso 5 secondi e 1 secondo spento e via dicendo,
per favore aiutatemi :)
grazie

cyberhs

#2
Apr 08, 2014, 11:14 am Last Edit: Apr 08, 2014, 05:05 pm by cyberhs Reason: 1
Non l'ho provato ma dovrebbe funzionare.

Code: [Select]

#define FanPin 13          // ventola
#define TempoOn 1000       // 1 secondo
#define TempoOff 5000      // 5 secondi

unsigned int Timer = 0;  // ERRORE deve essere di tipo LONG
unsigned long Timer = 0;

boolean Status = false;                // false = 0 = OFF, true = 1 = ON

void setup() {
 pinMode(FanPin, OUTPUT);
 Serial.begin(9600);                   // monitor (Rx=0; Tx=1)
 Timer = millis();                        // timer started
}

void loop() {

 if (Status == false) {                 // OFF
   if (millis() - Timer > TempoOff) {
     Status = !Status;
     digitalWrite(FanPin) = Status; //SINTASSI ERRATA
     digitalWrite(FanPin, Status);   //SINTASSI CORRETTA
     Timer = millis();                   // timer started
   }
 }
 else {                                       // ON
   if (millis() - Timer > TempoON) {
     Status = !Status;
     digitalWrite(FanPin) = Status; //SINTASSI ERRATA
     digitalWrite(FanPin, Status);   //SINTASSI CORRETTA
     Timer = millis();                   // timer started
   }
 }
}

leo72

Il problema lo devi semplificare.
Tu hai da accendere un LED, poi spengerlo e riaccenderlo dopo un tot. Hai bisogno di una variabile in cui salvare millis ed una variabile di stato per sapere com'è il LED.

Potresti pensare ad una cosa simile:
1. avvio del programma: memorizzi in una variabile unsigned long il valore di millis attuale
2. ciclo principale
3. controlli se millis è >= al valore che hai memorizzato in precedenza e <= di quel valore più la durata dello stato on.
4. se sì, controlli se il led è spento: se è spento lo accendi, se è acceso lo spengi
5. se è > del valore di durata più l'intervallo, cambi nuovamente lo stato al led
6. controlli lo stato attuale: se il led è spento, vuol dire che al prox giro lo dovrai accendere, per cui salvi nella variabile il valore di millis + tempo di off
7. altrimenti salvi il tempo di millis + il tempo di on perché al prox giro lo dovrai spengere
8. torni al punto 2.

Poi ti consiglio questo mio articolo.


stomosto

Grazie mille a entrambi per la spiegazione,
leo72, conosco molto bene il tuo sito e ti faccio i miei complimenti.
però ho provato in mille modi a prendere spunto dai tuoi esempi, a scomporli e ricomporli come voglio ma non ottengo quello di cui ho bisogno, o il led lampeggia, oppure mi fa un lampeggio solo e poi nulla..non riesco proprio a venirne a capo essendo una cosa stupidissima :(

stomosto

Lo sketch del signor  cyberhs mi è stato utilissimo e funziona, chiunque avesse bisogno per eseguire un comando simile è a disposizione di tutti :) l'unico errorino è nel digitalWrite che dovrebbe essere digitalWrite(FanPin, Status);
grazie mille anche a leo72 per la disponibilità. :)

stomosto

ho trovato un altro piccolo errore nello sketch di cyberhs, ovvero, dopo un pò di volte che il ciclo si ripeteva, andava tutto in conflitto tra 0 e 1 ad una velocità non visibile sul LED, ma sembrava rimanere sempre acceso.
l'errore è nella dichiarazione della variabile del timer che dev'essere "unsigned long" e non solo unsigned :)

cyberhs

Vorrei poter dire che gli errori li ho fatti apposta per farti imparare, ma purtroppo non è così...

paulus1969

Oppure puoi usare una forma un po' più compatta come:

Code: [Select]

unsigned long ton = 1000;
unsigned long toff = 5000;
unsigned long interval = ton;
unsigned long previousMillis = 0;
boolean ledstate = 1;
byte ledpin = 13;

void setup()
{
delay (1000);
pinMode (ledpin, OUTPUT);
digitalWrite (ledpin, HIGH);
previousMillis = millis();
}

void loop()
{
if (millis() - previousMillis > interval)
  {
    ledstate ^=1;
    previousMillis = millis();
    digitalWrite (ledpin, ledstate);
     if (ledstate) {interval = ton;}
     else {interval = toff;}
  }
}


In pratica, interval viene definito come ton se ledstate è 1 (acceso) e come toff se è 0 (spento), all'inizio è acceso.
Se non ho sbagliato a scrivere il codice (spero di non aver commesso troppi errori, ma il concetto credo si capisca), quando passano interval millisecondi viene invertito ledstate, viene passato a ledpin e viene impostato interval.

leo72

Se fate gli sketch voi al posto suo, lui non impara nulla  ;)

paulus1969

Vero, ma per una cosa così semplice credo che la cosa migliore sia mettere un piccolo codice di esempio e spiegare cosa si sta facendo. Poi starà a lui prendere spunto piuttosto che fare copia incolla, ma quando gli servirà per qualcosa dovrà in ogni caso adattare il codice alle esigenze specifiche.
D'altra parte anche nel link che hai indicato tu c'è il codice di esempio, spiegato ed anche (ben) commentato.  :smiley-mr-green:

leo72

Infatti, metto i link proprio perché il codice è spiegato e commentato. In questo modo l'utente può leggere la spiegazione e vedere, riga per riga, cosa fa il programma.

Go Up