controllo stato ingresso tramite millis

Samve a tutti ragazzi. Ho bisogno di un piccolo aiuto. Sto costruendo per aiutare un amico un sistema di gestione elettronica per una piccola automobile. Ho quasi fatto tutto ma mi manca una cosa importante. Dovrei far cambiare stato a un uscita solo dopo che un determinato ingresso cambi stato per almeno 5 secondi consecutivi. Il problema che non posso utilizzare il while perche avrei sempre il codice bloccato. Dovrei utilizzare il millis. Ho provato ma non ne vengo a capo. Premetto che col millis ho gia realizzato le frecce e il tergicristallo che vengono attivati e continuano a funzionare nonostante il codice vada avanti. Qualche piccola riga di codice? Grazie come sempre

ciao

boolean ingresso = false
unsigned long tempo_ingresso
...
...
...
se tasto premuto {
  ingresso = true
  tempo_ingresso = millis()
}
else {ingresso = false}
...
...
...
se (ingresso && (millis()-tempo_ingresso > 5000){
  fai quello che devi fare
  }
...
...

Naturalmente non puoi fare copia incolla ;)

ciao pippo72

Grazie pippo come sempre. Una sola domanda giusto per capire... ho visto che molte volte utilizzate il boolean invece di mettere esempio if digitaRead High... come mai? C'è un motivo specifico?

scusami, mi rispondo da solo. Ho capito in quel caso è solo una variabile che utilizzare ad esempio 0 o 1 utilizzi false o true

ciao

Mi correggo:

...
se (tasto premuto && ingresso == false) {
  ingresso = true
  tempo_ingresso = millis()
}
else {ingresso = false}
...

Altrimenti finchè il tasto è premuto tempo_ingresso viene continuamente aggiornata.

scusate

pippo72

pippo72: ciao

Mi correggo:

...
se (tasto premuto && ingresso == false) {
  ingresso = true
  tempo_ingresso = millis()
}
else {ingresso = false}
...

Altrimenti finchè il tasto è premuto tempo_ingresso viene continuamente aggiornata.

scusate

pippo72

buongiorno... allora ho scritto questo codice ma non funziona nulla.. dove sbaglio? ps ho messo alto il pulsante in quanto sto lavorando con le resistenze pullup.

#define USCITA_FILTRATA_5_BUTTON 48
#define USCITA_FILTRATA_5_LED 27
boolean USCITA_FILTRATA_5 = false;
unsigned long USCITA_FILTRATA_5_TEMPO = 0;
void setup() {
  pinMode(USCITA_FILTRATA_5_BUTTON, INPUT);
  pinMode(USCITA_FILTRATA_5_LED, OUTPUT);
  digitalWrite(USCITA_FILTRATA_5_BUTTON, HIGH);
}

void loop() {
  if (USCITA_FILTRATA_5_BUTTON == 0 && USCITA_FILTRATA_5 == false) {
    USCITA_FILTRATA_5 == true;
    USCITA_FILTRATA_5_TEMPO = millis();
  }
  else {
    USCITA_FILTRATA_5 == false;
  }
  if (USCITA_FILTRATA_5 == true && (millis() - USCITA_FILTRATA_5_TEMPO > 5000)) {
    digitalWrite(USCITA_FILTRATA_5_LED, HIGH);
  }
  else
  {
    digitalWrite(USCITA_FILTRATA_5_LED, LOW);
  }
}
#define USCITA_FILTRATA_5_BUTTON 48
if (USCITA_FILTRATA_5_BUTTON == 0 && USCITA_FILTRATA_5 == false) {

48 non sarà mai uguale a 0 :). Forse hai dimenticato qualche digitalRead().

Hai ragione devo mettere il digital read :) ti faccio sapere

 USCITA_FILTRATA_5_BUTTON_STATO = digitalRead(USCITA_FILTRATA_5_BUTTON);
  if (USCITA_FILTRATA_5_BUTTON_STATO == 0 && USCITA_FILTRATA_5 == false) {
    USCITA_FILTRATA_5 == true;
    USCITA_FILTRATA_5_TEMPO = millis();
Serial.println (USCITA_FILTRATA_5_BUTTON_STATO);
  }
  else {
    USCITA_FILTRATA_5 == false;
  }
  if (USCITA_FILTRATA_5 == true && (millis() - USCITA_FILTRATA_5_TEMPO > 5000)) {
    digitalWrite(USCITA_FILTRATA_5_LED, HIGH);
  }
  else
  {
    digitalWrite(USCITA_FILTRATA_5_LED, LOW);
  }

Modificato in questa maniera ma continua a non funzionare... ho anche provato a mettere un Serial.print dentro il primo if e a video stampo lo stato "0" quando il pulsante è premuto. ma COntinua a non funzionare.

Ripassa la differenza tra

=

e

==

:).

ahhaha scusa ma il doppio uguale non serve per fare un paragone mentre il singolo serve per un assegnazione? cmq ho provato in ambedue i modi ma cosi continua a non funzuonare..

#define USCITA_FILTRATA_5_BUTTON 48
#define USCITA_FILTRATA_5_LED 27
boolean USCITA_FILTRATA_5 = false;
unsigned long USCITA_FILTRATA_5_TEMPO = 0;
int USCITA_FILTRATA_5_BUTTON_STATO = 0;

void setup() {
  pinMode(USCITA_FILTRATA_5_LED, OUTPUT);
  pinMode(USCITA_FILTRATA_5_BUTTON, INPUT);
  digitalWrite(USCITA_FILTRATA_5_BUTTON, HIGH);
}

void loop() {
  USCITA_FILTRATA_5_BUTTON_STATO = digitalRead(USCITA_FILTRATA_5_BUTTON);
  if (USCITA_FILTRATA_5_BUTTON_STATO == 0 && USCITA_FILTRATA_5 == false) {
    USCITA_FILTRATA_5 = true;
    USCITA_FILTRATA_5_TEMPO = millis();
  }
  else {
    USCITA_FILTRATA_5 = false;
  }
  if (USCITA_FILTRATA_5 == true && (millis() - USCITA_FILTRATA_5_TEMPO > 5000)) {
    digitalWrite(USCITA_FILTRATA_5_LED, HIGH);
  }
  else
  {
    digitalWrite(USCITA_FILTRATA_5_LED, LOW);
  }
}

non capisco dove sbaglio sto ancora provando. help please :-)

if (USCITA_FILTRATA_5 == true && (millis() - USCITA_FILTRATA_5_TEMPO > 5000))

L'istruzione sopra dovrebbe generare un avviso da parte del compilatore a cui segue anche un suggerimento. Questo avviso può apparire o meno a seconda dei flag passati al compilatore, se non trovi questo avviso forse l'ide ne disabilita la visualizzazione.

Il messaggio del compilatore richiama l'attenzione sul fatto che l'espressione che esprima la condizione tra parentesi, può essere tradotta in diversi modi. Il compilatore allora suggerisce di usare le parentesi tonde con il fine di rendere univoca la traduzione.

( true && (millis() - USCITA_FILTRATA_5_TEMPO) > 5000) Sicuramente non vuoi che il compilatore traduca così l'espressione.

Per cui:

if ( (USCITA_FILTRATA_5 == true) && ( (millis() - USCITA_FILTRATA_5_TEMPO) > 5000 ) ) )

Quella sopra è una espressione che può essere tradotta in un solo modo pertanto non è ambigua. Valuta per prima cosa (USCITA_FILTRATA_5 == true), se è vera continua a valutare il resto, se è falsa evita di valutare la continuazione della espressione.

Questo può o meno essere ciò che fa assumere un comportamento non voluto, in ogni caso è sempre meglio seguire i suggerimenti del compilatore o anche meglio non farlo fiatare per niente scrivendo delle espressioni non equivocabili, prive di ambiguità.

Ciao.

mauro grazie per la risposta... in realtà nella compilazione non ricevo nessun avviso, ne di errore ne di nulla. provo a fare come hai scritto ma ripeto non ricevo nessun avviso da parte dell'ide mi sa quindi che è disabilitato come dici...

ps c'è una parentesi tonda in più nella tua soluzione?

allora ho scritto il codice in questo modo per cercare di vedere dove fosse il problema.

#define USCITA_FILTRATA_5_BUTTON 48
#define USCITA_FILTRATA_5_LED 27
boolean USCITA_FILTRATA_5 = false;
unsigned long USCITA_FILTRATA_5_TEMPO = 0;
unsigned long result = 0;
int USCITA_FILTRATA_5_BUTTON_STATO = 0;

void setup() {
  pinMode(USCITA_FILTRATA_5_LED, OUTPUT);
  pinMode(USCITA_FILTRATA_5_BUTTON, INPUT);
  digitalWrite(USCITA_FILTRATA_5_BUTTON, HIGH);
  Serial.begin(9600);
}

void loop() {
  USCITA_FILTRATA_5_BUTTON_STATO = digitalRead(USCITA_FILTRATA_5_BUTTON);
  if ((USCITA_FILTRATA_5_BUTTON_STATO == 0) && (USCITA_FILTRATA_5 == false)) {
    USCITA_FILTRATA_5 = true;
    USCITA_FILTRATA_5_TEMPO = millis();

  }
  else {
    USCITA_FILTRATA_5 = false;
  }
result=(millis() - USCITA_FILTRATA_5_TEMPO);
  Serial.println(result);
  if ( (USCITA_FILTRATA_5 == true) && ( result > 5000 ) ) {
    digitalWrite(USCITA_FILTRATA_5_LED, HIGH);
  
  }
  else
  {
    digitalWrite(USCITA_FILTRATA_5_LED, LOW);
  }
}

Quello che ho notato e che quando apro la seriale e premo il pulsante il tempo "result" resta sempre sotto i 3 massimo 5 millisecondi e non potrà quindi mai arrivare ai 5 secondi che mi servono. Sembra proprio che sia il problema che pippo voleva evitare con la sua correzione nel suo secondo post ma che in realtà avviene lo stesso.

creado che la soluzione più ovvia sia il calcolare quanto tempo passa tra la pressione del tasto e il suo rilascio. Sto provando a scrivere lo scketch vediamo cosa ne esce.

bruco1987:
creado che la soluzione più ovvia sia il calcolare quanto tempo passa tra la pressione del tasto e il suo rilascio. Sto provando a scrivere lo scketch vediamo cosa ne esce.

Ma quello che serve a te’ e’ che l’uscita cambi stato dopo, ad esempio, 5 secondi che l’ha fatto l’ingresso, anche se nel frattempo l’ingresso e’ tornato allo stato iniziale, o solo se rimane in quello stato per piu dei 5 secondi ?

In ogni caso, se usi un primo if per settare un flag e memorizzare millis in una variabile, seguito da un’if dentro un’altro if, con una variabile che esegue l’if esterno solo quando l’ingresso e’, ad esempio, alto, ed una seconda che esegue l’if interno solo se il tempo e’ trascorso, dovresti risolverla …

tipo … (pseudocodice)

SE (ingresso alto) E (flag1 = 0)
imposta flag1 = 1
memorizza millis

SE (ingresso alto) E (flag1 = 1)
SE (tempo trascorso)
attiva uscita
imposta flag1 = 0

Il primo if setta la flag e memorizza il tempo una sola volta nel momento in cui premi il pulsante (flag1 serve a dirgli di non rifarlo in continuazione), il secondo controlla il tempo (usando la variabile con millis memorizzati nel primo) solo se il pulsante e’ ancora premuto E il ciclo non e’ gia stato eseguito (perche’ nel momeno in cui lo esegui resetti anche la flag) … certo e’ minimalista e senza troppi controli, ma dovrebbe funzionare come punto di partenza :wink:

Etemenanki: Ma quello che serve a te' e' che l'uscita cambi stato dopo, ad esempio, 5 secondi che l'ha fatto l'ingresso, anche se nel frattempo l'ingresso e' tornato allo stato iniziale, o solo se rimane in quello stato per piu dei 5 secondi ?

In ogni caso, se usi un primo if per settare un flag e memorizzare millis in una variabile, seguito da un'if dentro un'altro if, con una variabile che esegue l'if esterno solo quando l'ingresso e', ad esempio, alto, ed una seconda che esegue l'if interno solo se il tempo e' trascorso, dovresti risolverla ...

tipo ... (pseudocodice)

SE (ingresso alto) E (flag1 = 0) imposta flag1 = 1 memorizza millis

SE (ingresso alto) E (flag1 = 1) SE (tempo trascorso) attiva uscita imposta flag1 = 0

Il primo if setta la flag e memorizza il tempo una sola volta nel momento in cui premi il pulsante (flag1 serve a dirgli di non rifarlo in continuazione), il secondo controlla il tempo (usando la variabile con millis memorizzati nel primo) solo se il pulsante e' ancora premuto E il ciclo non e' gia stato eseguito (perche' nel momeno in cui lo esegui resetti anche la flag) ... certo e' minimalista e senza troppi controli, ma dovrebbe funzionare come punto di partenza ;)

Buon pomeriggio...l 'uscita deve essere in HIGH solo se l'ingresso è in quello stato per più di 5 secondi CONSECUTIVI. Quindi se rilasciamo il pulsante deve tornare allo stato iniziale e ricominciare. Se poi, una volta acceso il led, lascio il pulsante torna tutto allo stato iniziale :)

allora eccomi... SONO RIUSCITO :) posto in maniera da condividere. in realtà potremmo chiamare questo sketch con "uscita filtrata all'eccitazione". In giro non c'è nessun esempio del genere. Grazie a tutti come sempre alla prossima.

const byte ledPin = 13;
const byte btnPin = 12;
unsigned long start;
boolean flag1 = false;


void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  pinMode(btnPin, INPUT);
  digitalWrite(btnPin, HIGH);

}

void loop() {
  if ((digitalRead(btnPin) == LOW) && (flag1 == false)) {
    flag1 = true;
    start = millis();
  }
  if ((digitalRead(btnPin) == LOW) && (flag1 == true))
    if ((millis() - start) > 3000) {
      digitalWrite(ledPin, HIGH);
      flag1 = false;
    }
  if (digitalRead(btnPin) == HIGH){
    digitalWrite(ledPin, LOW);
    start=0;
    flag1 = false;
  }
}

Puoi anche utilizzare la variabile "start" come flag, se start == 0 significa che non ho ancora salvato il tempo, se è diversa ho già salvato il tempo.

Tuttavia in questo momento ho altro per la testa e non riesco a mostrarti un esempio, per cui se hai ottenuto il risultato che volevi lascialo cosi. Ho dovuto usare tempistiche simili per il key pad multifunzione, dove dopo n millisecondi di pressione avviene una ripetizione del tasto premuto, più aumenta il tempo in cui il tasto rimane premuto più rapidamente il tasto viene ripetuto. Serviva per un controller con display + 4 tasti multifunzione, si presentava il problema di potere modificare dei valori visualizzati sul display di una unità, ma se parti da 0 per arrivare a 20000 ci vuole un secolo, quindi più tempo rimane premuto il tasto SU più rapidamente viene incrementato il dato a display.

Ciao.