Programma con millis()

Salve ragazzi ho un problema in un programma e vorrei un aiuto. Voglio realizzare un progetto in cui tramite un pulsante riesco ad accendere una luce ma con un ritardo di 3 secondi. Mi spiego meglio. Devo tener premuto il pulsante per 3 secondi per accendere la luce in modo permanente. Dopodiché se premo il pulsante per altri 3 secondi si spegne. Spero possiate aiutarmi. Grazie.

e? Hai giá incominciato o vorresti che Te lo schiviamo noi? Ciao Uwe

Ho iniziato ma sbagliato tutto quindi se potete scrivermelo mi fareste un piacere. Grazie

Benito1995: Ho iniziato ma sbagliato tutto quindi se potete scrivermelo mi fareste un piacere. Grazie

Devi contare 3 secondi, ovvero una differenza di 3000 tra millis() e valore precedente millis. Devi però anche avere una variabile di stato, a cui assegni valore solo 1 o 0 per sapere se stai contando perchè il led è spento (stato==0) o se stai contando perchè il led è acceso e lo vuoi spegnere (stato==1) Quando passano i 3 secondi - se lo stato==0 allora stato=1 - se lo stato==1 allora stato=0 Poi, in tutti i casi, il led=stato digitalWrite(led,stato);

non è comunque semplice, alla pressione del tasto deve partire il count ma se viene rilasciato prima del previsto si deve ri-azzerare, credo.
se si tiene premuto a lungo oltre i 6 secondi deve spegnere on non far nulla? dover almeno rilasciare il tasto e ripremere per 3 secondi per spegnere?

se pulsante premuto memorizzazione valore millis() in una variabile.

controllo se pulsante é ancora premuto e differenza millis() attuali e millis iniziali é maggiore di 3000. Se sí fai qualcosa Se no non fai niente o resetta tutto.

Ciao Uwe

ciao

if (pulsante ==HIGH){
   start = millis();
if (start + 3000 < millis() ) {
    state=1;
  }
}
digitalWrite (led, state);

cosi non funziona, ogni loop start riprende i millis().

inserendo una variabile di stato start memorizza i millis() una sola volta, ma forse c'è una strada migliore

if ( stato == 0) {
    start = millis();
    stato = 1;
 }

In effetti non è così semplice come pare a prima vista:

const byte ledPin=13;
const byte btnPin=12;
int stato;
unsigned long start;

void setup()
{ Serial.begin(9600);
  pinMode(ledPin,OUTPUT);
  pinMode(btnPin,INPUT);
  stato=LOW;
  start=0;
}

void loop()
{ if(digitalRead(btnPin)==HIGH)
  { if(start==0) start=millis();   
  }
  else
  { start=0;
  }
  if(millis()>=start+3000 && start>0)
  { if(stato==LOW)
      stato=HIGH;
    else
      stato=LOW;
    start=0;
  }
  digitalWrite (ledPin, stato);
  Serial.print(digitalRead(btnPin));
  Serial.print("\t");
  Serial.print(stato);
  Serial.print("\t");
  Serial.print(start);
  Serial.print("\t");
  Serial.println(millis());
}

Scritto così funziona. Se però tieni SEMPRE premuto il tasto, ogni 3 secondi si accende/spegne.

Con questa versione se tieni premuto sempre, fa solo uno scatto. ;D Non come quello di prima che ogni 3 sec scattava. Aggiunto variabile di stato "rilasciato" per sapere se il tasto è stato lasciato

const byte ledPin=13;
const byte btnPin=12;
int stato,rilasciato;
unsigned long start;

void setup()
{ Serial.begin(9600);
  pinMode(ledPin,OUTPUT);
  pinMode(btnPin,INPUT);
  stato=LOW;
  start=0;
  rilasciato=1;
}

void loop()
{ if(digitalRead(btnPin)==HIGH)
  { if(start==0 && rilasciato==1) start=millis();   
  }
  else
  { start=0;
    rilasciato=1;
  }
  if(millis()>=start+3000 && start>0)
  { stato=(stato==LOW ? HIGH : LOW);  // inverte stato usando if in linea del C
    start=0; 
    rilasciato=0;
  }
  digitalWrite (ledPin, stato);
  Serial.print(digitalRead(btnPin));
  Serial.print("\t");
  Serial.print(stato);
  Serial.print("\t");
  Serial.print(start);
  Serial.print("\t");
  Serial.println(millis());
}

Oppure puoi lavorare sul rilascio del tasto ... al momento del rilascio controlli quanto tempo e' rimasto premuto, e decidi cosa fare ...

Etemenanki: Oppure puoi lavorare sul rilascio del tasto ... al momento del rilascio controlli quanto tempo e' rimasto premuto, e decidi cosa fare ...

Cosi ?

const byte ledPin=13;
const byte btnPin=12;
int stato;
unsigned long start;

void setup()
{ Serial.begin(9600);
  pinMode(ledPin,OUTPUT);
  pinMode(btnPin,INPUT);
  stato=LOW;
  start=0;
}

void loop()
{ if(digitalRead(btnPin)==HIGH)
  { if(start==0) start=millis();   
  }
  else
  { if(start>0)
    { if(millis()>=start+3000 && start>0)
      { stato=(stato==LOW?HIGH:LOW);
      }
      start=0;   
    }
  }
  digitalWrite(ledPin, stato);
  Serial.print  (digitalRead(btnPin)); Serial.print("\t"); 
  Serial.print  (stato);               Serial.print("\t"); 
  Serial.print  (start);               Serial.print("\t");
  Serial.print  (millis());            Serial.print("\t");
  Serial.println(millis()-start);
}

mitico nid :D

nid69ita: Cosi ? ...

Io lo faccio in modo un po diverso, ma solo perche' la routine che avevo studiato all'origine mi serviva per fare tre diverse cose, quindi dovevo discriminare sia la pressione che il tempo ... una cosa del genere (riscritto al volo col notepad, spero di essermelo ricordato giusto :P)...

{
    stato = digitalRead(pin)            //leggi pin pulsante
    if ((stato != statoprec) && (statoprec == 0))   // pulsante appena premuto
    {
        statoprec = stato;          //setta flag per pulsante premuto
        millisprec = millis();          //setta variabile controllo tempo
        ... //qui ci vanno tutte le operazioni da compiere 
        ... //solo alla PRESSIONE del tasto, UNA SOLA VOLTA
    }
    if ((stato != statoprec) && (statoprec == 1))   //pulsante appena rilasciato
    {
        statoprec = stato;          //resetta flag per pulsante rilasciato
        if (millis() - millisprec <= 500)   //pulsante premuto - di mezzo secondo
        {
        ... //qui ci vanno tutte le operazioni da compiere al RILASCIO del tasto, 
        ... //UNA SOLA VOLTA, solo se il tasto e' rimasto premuto per meno di 500mS
        }
        else                    //pulsante premuto + di mezzo secondo
        {
        ... //qui ci vanno tutte le operazioni da compiere al RILASCIO del tasto, 
        ... //UNA SOLA VOLTA, solo se il tasto e' rimasto premuto per piu di 500mS
        }
    }
}

@etem, nel primo posto, "... //solo alla PRESSIONE del tasto, UNA SOLA VOLTA" qui, non c'e' un possibile problema con il debounce ? Avevi da qualche parte un piccolo delay o fai da hw ?

ciao volevo provare ad aiutarti anche io ...

ho fatto un programma simile per il mio corso ho cambiato 2 parametri per passartelo ma non ho avuto modo di testarlo...

ho commentato tutto quindi non dovrei spiegare molto qui ... puoi cambiare le variabili e settare i tuoi pin e come esempio utilizzo un led, tutto dopo sta in base alle tue necessità spero di essere utile ciao..

#define attesa 3000 // costante del tempo pulsante 3 secondi (3000 milli secondi)

int pin_pusante = 11;
int pin_led = 12;

void setup(){
  pinMode(pin_pusante,INPUT);     // qui metto il pulsante
  pinMode(pin_led,OUTPUT);        // qui metto il led
}

long    tempo_start;               // variabile per contare il tempo della durata del pulsante
boolean stato_led = LOW;

void loop(){
  if(digitalRead(pin_pusante) == HIGH){           // se premo il punstante allora....
    if(tempo_start == 0){                         // se è la prima volta che premo il pulsante da quando ho resetato la variabile allora ....
      tempo_start = millis();                     // faccio ripartire il conteggio da questo momento
      
    } else if( millis() > tempo_start+attesa ){  // altrimenti se sono passati 3 secondi ...
      stato_led = !stato_led;                     // inverto lo stato del led (se era basso diventa altro e viceversa)
      digitalWrite(pin_led, stato_led);           // setto il pin
      
    }
    
    delay(100);                         // aspetto un delay per eliminare vari disturbi di contatto
  }
  else{                                 // altrimenti ...
     tempo_start = 0;                   // resetto il tempo della durata del pulsante
  }
}

nid69ita: ...Avevi da qualche parte un piccolo delay o fai da hw ?

Sempre rigorosamente da hardware, anche perche' lo sketch alla fine doveva controllare 6 pulsanti richiamati da subroutines, e se ci avessi messo dei delay, avrei inchiodato tutto ... invece con una resistenza da 100 ohm ed un condensatore da 100nF per pulsante, ho eliminato il problema prima ancora che si presentasse ;)

EDIT: ovviamente nello sketch completo ogni subroutine aveva le proprie variabili globali, mentre l'esempio e' generico per un pulsante solo ...

Io per accendere il led dopo 3 secondi ho optato per questa soluzione e mi ha funzionato.

int pulsante=2;
int led=13;

void setup() {
pinMode(led,OUTPUT);
pinMode(pulsante,INPUT);
}

void loop() {
if(digitalRead(pulsante)==HIGH){
  delay(3000);
  if(digitalRead(pulsante)==HIGH){
    digitalWrite(13,HIGH); } }
}

E poi faccio la stessa cosa anche per spegnerlo.

Benito1995: Io per accendere il led dopo 3 secondi ho optato per questa soluzione e mi ha funzionato.

int pulsante=2;
int led=13;

void setup() { pinMode(led,OUTPUT); pinMode(pulsante,INPUT); }

void loop() { if(digitalRead(pulsante)==HIGH){   delay(3000);   if(digitalRead(pulsante)==HIGH){     digitalWrite(13,HIGH); } } }




E poi faccio la stessa cosa anche per spegnerlo.

quel delay blocca tutto il resto del programma, in pratica vuoi solo accendere e spegnere il led tralasciando tutto il resto ?

Benito1995:
E poi faccio la stessa cosa anche per spegnerlo.

E se tengo premuto il tasto per 20 secondi che succede ? ;D

nid69ita: Con questa versione se tieni premuto sempre, fa solo uno scatto. ;D Non come quello di prima che ogni 3 sec scattava. Aggiunto variabile di stato "rilasciato" per sapere se il tasto è stato lasciato

const byte ledPin=13;
const byte btnPin=12;
int stato,rilasciato;
unsigned long start;

void setup() { Serial.begin(9600);   pinMode(ledPin,OUTPUT);   pinMode(btnPin,INPUT);   stato=LOW;   start=0;   rilasciato=1; }ragazzi buongiorno.. riesumo questo post in quanto credo che con una semplice modifica possa andare bene per il mio scopo. Va benissimo lo sketch in questione solo che vorrei che restasse acceso solo finchè il tasto è premuto. In pratica: premo il pulsante per 3 secondi si accende il led, si spegna appena lascio il pulsante... grazie mille

void loop() { if(digitalRead(btnPin)==HIGH)   { if(start==0 && rilasciato==1) start=millis(); 
  }   else   { start=0;     rilasciato=1;   }   if(millis()>=start+3000 && start>0)   { stato=(stato==LOW ? HIGH : LOW);  // inverte stato usando if in linea del C     start=0;     rilasciato=0;   }   digitalWrite (ledPin, stato);   Serial.print(digitalRead(btnPin));   Serial.print("\t");   Serial.print(stato);   Serial.print("\t");   Serial.print(start);   Serial.print("\t");   Serial.println(millis()); }