[RISOLTO] Pulsante premuto per un tot. di tempo

Buongiorno a tutti!!!

Avrei bisogni di una diritta:

ho scritto il seguente codice per controllare un led con due bottoni:

#define led 8
#define accendi 2
#define spegni 3
int stato = 0;

void setup(){
  pinMode (led, OUTPUT);
  pinMode (accendi, INPUT);
  pinMode (spegni, INPUT);

  digitalWrite(led, stato); 
}

void loop(){

if (digitalRead(accendi) > 0) {
  stato = HIGH;
}

if (digitalRead(spegni) > 0){
  stato = LOW;
  }
  
  digitalWrite (led, stato);
}

Adesso dovrei inserire la variabile "tempo".

In pratica dovrei fare in modo che il mio led si accendi se e solo se il pulsante di accensione risulta acceso per un tot. di tempo (diciamo 5 secondi), altrimenti non deve succedere nulla.

Avevo pensato ad un millis(), ma a quanto pare questa funzione parte da quando l'arduino inzia a ricevere corrente, e non da quando io clicco il bottone.

Qualcuno puo darmi qualche diritta?

Grazie a tutti anticipatamente!

Mi sa che non hai ben chiaro come utilizzare Millis.
Leggi questo bel articolo di Leo72, dove spiega per filo e per segno il concetto che sta dietro all'utilizzo di Millis. :wink:
http://www.leonardomiliani.com/2013/programmiamo-i-compiti-con-millis/

Puoi fare così:
prendi 2 variabili inizio e tempo.Inizio prende millis() quando pulsante è premuto. tempo prende inizio+5000(se vuoi 5 secondi).Quando tempo==millis() accendi il led.
Se non hai capito chiedi pure e cercherò di essere più chiaro.

Grazie per le info. Avevo letto quell'articolo subito dopo aver pubblicato il topic e mi ha chiarito le idee, anche se non ho ancora risolto il problema.

Il passaggio che mi manca è proprio quello di creare la variabile "inizio" quando clicco il bottone e far continuare il contatore solo se il pulsante continua ad essere premuto

:S

Comunque ti consiglio di controllare prima che il tuo programma funzioni correttamente (mi sembra strano che scritto così con un pulsante lo accendi e resta acceso e con l'altro lo spegni.)

Comunque ti consiglio di controllare prima che il tuo programma funzioni correttamente (mi sembra strano che scritto così con un pulsante lo accendi e resta acceso e con l'altro lo spegni.)

Perchè pensi questo?

Funziona perfettamente poichè i pulsanti mi controllano la variabile "stato" assegnando permanentemente "HIGH" oppure "LOW" che compare poi nel digitalWrite!

per fare in modo che il contatore continui solo se il pulsante è premuto fai:

//dichiari variabili inizio,tempo,controllo,passaggio(a cui assegni 0)
if (digitalRead(accendi) > 0){
inizio =millis();
tempo=inizio+5000;
while(millis()<tempo&&controllo==0){
if (digitalRead(accendi) !> 0){
controllo=1;
}else{
passaggio=1);
}
if(controllo==0&&passaggio==1){
 stato = HIGH;
}
passaggio=0;
controllo=0;
}

Ti invito ancora comunque a controllare il tuo codice (ora lo provo) ma credo non funzioni.

ho aggiornato il codice come mi hai consigliato ma non mi pare che funzioni :S ( l'ho portato a 2 secondi in modo da rendere più veloci le prove)

#define led 8
#define accendi 2
#define spegni 3
int stato = 0;

int inizio = 0;
int controllo = 0;
int tempo = 0;
int passaggio = 0;

void setup(){
  pinMode (led, OUTPUT);
  pinMode (accendi, INPUT);
  pinMode (spegni, INPUT);
  digitalWrite(led, stato); 
}

void loop(){

if (digitalRead(accendi) > 0){
  inizio = millis();
  tempo = inizio + 2000;
  while(millis()< tempo && controllo == 0) {
    if (digitalRead(accendi) != 0){
      controllo = 1;
    }
    else{
      passaggio = 1;}
  }
      
      if( controllo == 0 && passaggio == 1){
  stato = HIGH;
}
passaggio = 0;
controllo = 0;
}

if (digitalRead(spegni) > 0){
  stato = LOW;
  }
  
  digitalWrite (led, stato);
}

p.s.

Ti invito ancora comunque a controllare il tuo codice (ora lo provo) ma credo non funzioni.

l'ho provato più volte ed ha sempre funzionato (anche ora).

Ti porgo le mie più sincere scuse. Il tuo programma funziona correttamente.
per quello che chiedi il codice da utilizzare è il seguente:

#define led 8
#define accendi 2
#define spegni 3
int stato = 0;
float inizio=0;
float tempo=0;
int controllo=0;
int passaggio=0;

void setup(){
  pinMode (led, OUTPUT);
  pinMode (accendi, INPUT);
  pinMode (spegni, INPUT);
  digitalWrite(led, stato); 

}
void loop(){

if (digitalRead(accendi) > 0){
inizio =millis();
tempo=inizio+5000;
while(millis()<tempo&&controllo==0){
if (digitalRead(accendi) <= 0){
controllo=1;
}else{
passaggio=1;
}
if(controllo==0&&passaggio==1){
 stato = HIGH;
}
passaggio=0;
controllo=0;
}

}

if (digitalRead(spegni) > 0){
  stato = LOW;
  }
  
  digitalWrite (led, stato);
}

L'ho controllato e a me funziona (anche se è un po' lento).

Figurati non c'è mica bisogno di scusarsi !!!!!!

Cmq il programma funziona (quasi) alla perfezione sei stato gentilissimo =)

l'unico problema è che pare che non rispondi correttamente e subito allo spegnimento :S

pare infatti che per poter spegnere il led devo aspettare un po di tempo il che mi pare un po strano e poco funzionale :S
Per vedere se effettivamente non mi stavo fleshando io ho provato a portare a 10 secondi invece di 5 l'intervallo, e per poter spegnere il led devo aspettare un botto di tempo.
hai idea del perchè?

inoltre ho notato che il tempo in cui clicco il pulsante di accensione rimane "memorizzato" nel senso che se clicco per 5 secondi, poi lascio e dopo un po di tempo clicco per altri 5 questo si accende senza aspettare i 10 secondi che ho impostato!!!

pare infatti che per poter spegnere il led devo aspettare un po di tempo il che mi pare un po strano e poco funzionale :S

Per vedere se effettivamente non mi stavo fleshando io ho provato a portare a 10 secondi invece di 5 l'intervallo, e per poter spegnere il led  devo aspettare un botto di tempo.
hai idea del perchè?

Sinceramente non so perchè e non dovrebbe farlo(credo).

inoltre ho notato che il tempo in cui clicco il pulsante di accensione rimane "memorizzato" nel senso che se clicco per 5 secondi, poi lascio e dopo un po di tempo clicco per altri 5 questo si accende senza aspettare i 10 secondi che ho impostato!!!

Anche qui non so perchè e non dovrebbe farlo(credo).

Dovremo aspettare che qualcun'altro risponda :~ :~

Intanto per alleggerire un pochino il codice e renderlo un attimo più intuitivo l'ho riscritto così

#define led 8
#define accendi 2
#define spegni 3

int stato = 0;

void setup(){
  pinMode (led, OUTPUT);
  pinMode (accendi, INPUT);
  pinMode (spegni, INPUT);
  digitalWrite(led, stato); 

}
void loop(){
  
float inizio = 0;
float tempo = 0;
int controllo = 0;
int passaggio = 0;
int trasf = 1000;

int secondi = 5 * trasf;

if (digitalRead(accendi) > 0){
inizio = millis();
tempo = inizio + secondi;
while (millis() < tempo && controllo == 0){
if (digitalRead(accendi) <= 0){
controllo=1;
}else{
passaggio=1;
}
if(controllo == 0 && passaggio == 1){
 stato = HIGH;
}
passaggio = 0;
controllo = 0;
}
}

if (digitalRead(spegni) > 0){
  stato = LOW;
  }
  
  digitalWrite (led, stato);
}

Per ora continuo a studiarlo ed a capire quali sono i punti di debolezza ed il perchè degli errori intanto che qualcuno venga in mio aiuto XD. Ti ringrazio!

Innanzitutto mi sa che il Reference di millis non è stato letto ... :stuck_out_tongue:

Altrimenti sapreste che per utilizzare millis() la variabile dev'essere una unsigned long e non una int.

Cercando di semplificare il più possibile lo sketch, prova questo.
Non ho avuto modo di testarlo, ma dovremmo esserci.

#define led 8
#define accendi 2
#define spegni 3
unsigned long inizio = 0;
int controllo = 0;
unsigned long tempo = 5000L;


void setup(){
  pinMode (led, OUTPUT);
  pinMode (accendi, INPUT);
  pinMode (spegni, INPUT);
  digitalWrite(led, LOW); 
}

void loop(){
  if (digitalRead(accendi)==HIGH && controllo == 0){
    inizio = millis();
    while(digitalRead(accendi)==HIGH) {
      if ((millis()-inizio)>=tempo){
        controllo = 1;
        return;
      }
    } 
    if(controllo == 1) {
      digitalWrite(led, HIGH);
    }
  }
  if (digitalRead(spegni)==HIGH){
    digitalWrite(led, LOW);
    controllo = 0;
  }
}

purtroppo il tuo codice Brado non mi funziona :S

volevo chiederti però cosa significa la L affianco a 5000 nel tempo ed ora cmq mi metto a studiare anche il tuo codice per capirne il funzionamento e cercare di farlo partire :wink:

Ciao, volevo dare anche un mio piccolo contributo.
Due suggerimenti, il primo è che le variabili contenente il valore di millis() dovrebbero essere unsigned long per non incorrere in potenziali problemi.
Il secondo consiglio è volto alla semplificazione del codice anche se ti costringerà a rivedere molto di quanto già scritto, ovvero visto che premendo il pulsante di accensione devi attendere N secondi prima di accendere effettivamente il led e che se il pulsante viene rilasciato prima di questo tempo N non deve accadere nulla ti consiglierei di non utilizzare tutte quelle variabili ma semplicemente azzerare la variabile inizio quando il pulsante viene rilasciato ovvero:

unsigned long inizio = millis();
if (digitalRead(accendi)  == HIGH){
   if(millis() - inizio >= secondi){
       digitalWrite (led, HIGH);
   }
}
else{
  inizio = millis();
}
if (digitalRead(spegni)  == HIGH){
  digitalWrite (led, LOW);
}

In questo modo fai tutto con due variabili, il codice a mio parere è molto più intuitivo da capire, eviti di fare un sacco di digitalWrite che non servono a nulla.
Inoltre ti consiglio di integrare il codice con il deBounce per la lettura dello stato dei pulsanti per evitare letture sporche
Ciao

Ciao, il codice di fabpolli mi sembra corretto tuttavia a me non funziona =( =(
probabilmente ho dichiarato male qualcosa (ho allegato mio codice).

#define led 8
#define accendi 2
#define spegni 3

void setup(){
  pinMode (led, OUTPUT);
  pinMode (accendi, INPUT);
  pinMode (spegni, INPUT);
  digitalWrite(led, LOW); 
}

void loop(){
  int secondi = 5*1000;
  unsigned long inizio = millis();
if (digitalRead(accendi)  == HIGH){
   if(millis() - inizio >= secondi){
       digitalWrite (led, HIGH);
   }
}
else{
  inizio = millis();
}
if (digitalRead(spegni)  == HIGH){
  digitalWrite (led, LOW);
}
}

Inoltre ti consiglio di integrare il codice con il deBounce per la lettura dello stato dei pulsanti per evitare letture sporche

in questo caso il deBounce non dovrebbe servire visto che gli eventuali 'rimbalzi' del pulsante accendi sarebbero inferiori ai 5 secondi e quelli del pulsante spegni farebbero spegnere il led che però è già spento.

Mi sono confuso, non devi mettere "return;" ma "break;"

#define led 8
#define accendi 2
#define spegni 3
unsigned long inizio = 0;
int controllo = 0;
unsigned long tempo = 5000L;


void setup(){
  pinMode (led, OUTPUT);
  pinMode (accendi, INPUT);
  pinMode (spegni, INPUT);
  digitalWrite(led, LOW); 
}

void loop(){
  if (digitalRead(accendi)==HIGH && controllo == 0){
    inizio = millis();
    while(digitalRead(accendi)==HIGH) {
      if ((millis()-inizio)>=tempo){
        controllo = 1;
        break;
      }
    } 
    if(controllo == 1) {
      digitalWrite(led, HIGH);
    }
  }
  if (digitalRead(spegni)==HIGH){
    digitalWrite(led, LOW);
    controllo = 0;
  }
}

hard_uino:
Ciao, il codice di fabpolli mi sembra corretto tuttavia a me non funziona =( =(
probabilmente ho dichiarato male qualcosa (ho allegato mio codice).

#define led 8

#define accendi 2
#define spegni 3

void setup(){
 pinMode (led, OUTPUT);
 pinMode (accendi, INPUT);
 pinMode (spegni, INPUT);
 digitalWrite(led, LOW);
}

void loop(){
 int secondi = 5*1000;
 unsigned long inizio = millis();
if (digitalRead(accendi)  == HIGH){
  if(millis() - inizio >= secondi){
      digitalWrite (led, HIGH);
  }
}
else{
 inizio = millis();
}
if (digitalRead(spegni)  == HIGH){
 digitalWrite (led, LOW);
}
}







> Inoltre ti consiglio di integrare il codice con il deBounce per la lettura dello stato dei pulsanti per evitare letture sporche


in questo caso il deBounce non dovrebbe servire visto che gli eventuali 'rimbalzi' del pulsante accendi sarebbero inferiori ai 5 secondi e quelli del pulsante spegni farebbero spegnere il led che però è già spento.

Ciao, non ti funziona perché l'inizializzazione e la dichiarazione della variabile inizio non è da mettere nel loop ma nel setup altrimenti ad ogni giro si reinizializza e il tempo "non passa mai"!
Avevo riportato la dichiarazione per il problema del tipo che non doveva essere float ma unsigned long

MOD
Anche l'altra variabile (ma in generale tutte le variabili) devi dichiararla al di fuori del loop, altrimenti non ha molto senso definire una variabile che di fatto diventa come una costante

Ciao, il codice di fabpolli mi sembra corretto tuttavia a me non funziona smiley-cry smiley-cry

Non funziona perchè devi sostituire ad "unsigned long inizio = millis()" "unsigned long inizio = 0" e portarla nella dichiarazione di tutte le variabili

#define led 8
#define accendi 2
#define spegni 3

unsigned long inizio = 0;

void setup(){
  pinMode (led, OUTPUT);
  pinMode (accendi, INPUT);
  pinMode (spegni, INPUT);
  digitalWrite(led, LOW);
}

void loop(){

int secondi = 5 * 1000;

if (digitalRead(accendi) == HIGH){
   if(millis() - inizio >= secondi){
       digitalWrite (led, HIGH);
   }
}

else{
  inizio = millis();
}

if (digitalRead(spegni)  == HIGH){
  digitalWrite (led, LOW);
}
}

In questo modo funziona alla perfezione.

Ho controllato anche il tuo codice Brado e pare che funzioni anch'esso alla perfeione :wink: !!!

Grazie mille a tutti =) =) =)

Per la storia del debounce in realtà serve sempre in linea generale anche in questo caso perché non hai considerato il caso in cui il led è acceso e viene sfiorato il pulsante spegnimento, sena la debounce si rischi di spegnere il led anche se l'utente in realtà non voleva farlo per una semplice lettura sporca.. ad ogni modo vedi tu se introdurre il debounce o meno :wink:
Ciao