Funzione semplice...aiuto

Ciao ho un quesito credo banalissimo ma che non riesco a risolvere.
In pratica vorrei che allo stato alto di un pin, mi accendesse un led per 3 secondi e poi me lo spegnesse.

int switchState = 0;

void setup() {
  
  pinMode(3, INPUT);
  pinMode(13, OUTPUT);
 
}

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

Il problema è che così se lo stato del pin rimane alto, il led rimane acceso ugualmente. Vorrei che il led si accendesse per 3 sec e si spegnesse (1 volta) anche se il pin di ingresso continua ad essere alto.
Come fare??
Grazie
Ciao
Rinpe

Perche' alla fine del tuo delay (che non sarebbe da usare in quanto blocca tutto), il micro spegne il led, ma poi ricontrolla lo stato del pulsante, lo trova ancora alto, e lo riaccende (ma l'operazione e' talmente veloce che non la noti) ...

Dovresti usare un doppio if, o qualcosa di simile, per leggere il pulsante, cambiando nel frattempo una variabile che usi solo come "flag" per quel pulsante (in modo da sapere se nel frattempo il pulsante era stato rilasciato o meno) ... e per il tempo di accensione, usare millis, cosi il programma e' libero di continuare a girare e fare altre cose, anche mentre il led e' acceso (con delay no, si blocca tutto finche' non si spegne)

Per favore usa i tag appositi per includere il codice

Rinpe:
Come fare??

Inoltre l'analisi non mi sembra completa.
Durante i 3 secondi se il pin 3 cambia stato, che devi fare ?

Scusate per non aver inserito il codice con l’apposito tag.
Ad ogni modo durante i 3 secondi se il pin 3 cambia stato credo non debba fare nulla. Dico credo perché il problema non sarebbe proprio mio, me l’ha chiesto un amico. Io non sono esperto ma pensavo di non soffermarmi su questa presunta banalità.
Non ho capito molto bene come si può fare con il discorso della variabile come flag. Un piccolo esempio?
Scusate ancora.
Grazie
Rinpe

Guarda gli esempi nell'IDE

  • Blink Without Delay: blinking an LED without using the delay() function.
  • Button: use a pushbutton to control an LED.
  • Debounce: read a pushbutton, filtering noise.
  • Button State Change: counting the number of button pushes.

Buttato giu al volo, quindi devi controllarteli, io non lo posso fare perche' qui in negozio non ho l'ide installata, ed a casa non ho ancora un pc funzionante.

Pseudo-codice per eseguire funzioni diverse con tempi di pressione
del pulsante diversi, o diverse funzioni alla pressione ed al rilascio,
supponendo di aver attivato la pullup interna dell'ingresso pulsante
e di aver collegato il pulsante fra ingresso e massa (se e' l'opposto
e' necessario invertire la logica di controllo)

stato e' la variabile che contiene lo stato del pulsante e stato_prec e' 
il flag per controllare il momento in cui e' premuto o rilasciato, mentre
millis_prec e' la variabile di controllo per gli intervalli non bloccanti

NOTA: I DEBOUNCE SI FANNO CON LE RETI RC, NON CON I DELAY !!!!!!!!!

Esempio per diverse operazioni alla pressione e/o al rilascio

{
	stato = digitalRead(pin)	 //leggi ingresso pulsante
	if ((stato != stato_prec) && (stato_prec == 1)) // pulsante appena premuto
	{
		stato_prec = stato;  	//setta flag per pulsante premuto
		...
		...
		qui ci vanno tutte le operazioni da compiere 
		alla PRESSIONE del tasto, UNA SOLA VOLTA
		...
		...
	}
	if ((stato != stato_prec) && (stato_prec == 0)) //pulsante appena rilasciato
	{
		stato_prec = stato; 	//resetta flag per pulsante rilasciato
		...
		...
		qui ci vanno tutte le operazioni da compiere 
		al RILASCIO del tasto, UNA SOLA VOLTA
		...
		...
	}
}
	
............................................................................	
	

Esempio per diverse operazioni con pressioni di durata diversa (piu o meno 
di mezzo secondo, in questo esempio, ma puo essere qualsiasi intervallo di tempo)
Ovviamente, in questo caso le operazioni sono eseguite solo al rilascio del tasto

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

sono due esempi differenti, il primo puo eseguire una o piu operazioni, una sola volta, nel momento in cui il pulsante viene premuto, ed una o piu operazioni diverse, sempre una sola volta, nel momento in cui viene rilasciato, indifferentemente dal tempo per cui lo si tiene premuto ... il secondo puo eseguire, nel momento in cui il pulsante viene rilasciato, differenti operazioni a secondo del tempo in cui il pulsante e' stato mantenuto premuto ... entrambi usano un flag per discriminare il momento in cui il pulsante viene premuto e rilasciato e per evitare di eseguire serie di operazioni consecutive se il pulsante resta premuto.

Ci sono sicuramente sistemi piu "eleganti" per farlo, ma io non sono un programmatore, e fin'ora solo questo mi e' venuto in mente :stuck_out_tongue:

grazie Etemenanki sembra che il tuo primo suggerimento di sketch sia ok. Ho solo fatto in modo che quello che deve eseguire lo faccia non al rilascio del pulsante ma al premere.
Ho passato la soluzione al mio amico speriamo sia ok anche per lui.
Grazie ancora
Ciao
Rinpe

Che soluzione hai adottato Rinpe, per far si che esegua non al rilascio ma dopo X secondi che è premuto?

Il primo esempio ... puoi scegliere se far eseguire le istruzioni al rilascio, alla pressione, oppure anche due diversi codici uno alla pressione ed uno al rilascio, dipende da dove le scrivi ...

ok, grazie.
Ma se uso il secondo esempio, dove tiene conto del tempo pulsante premuto, dovrebbe essere uguale giusto? quindi se sposto la parte di controllo del tempo nella "if" del pulsante premuto dovrebbe funzionare in questo modo:

  • premo il pulsante
    -dopo x secondi esegue qualcosa
    -rilascio
    -fine

quello che non riesco a fare è questo:

-premo pulsante
-dopo 3 secondi accendo un led
-rilascio
-fine

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

dovrebbe essere così?

Credo di aver capito, tu vuoi accendere un led solo dopo tre secondi che il pulsante e' premuto (ovviamente, se per tutti i 3 secondi e' rimasto premuto), e suppongo che se viene rilasciato prima dei 3 secondi, non debba fare nulla ... allora potresti usare un terzo ciclo if dopo i due che controllano i cambi di stato, e controllare che le due condizioni siano vere insieme (tempo trascorso E pulsante ancora premuto) ... non devi mettere il controllo dentro i primi if, perche' vengono eseguiti una sola volta ad ogni cambio di stato, e poi ignorati fino al successivo cambio di stato ...

Una cosa del genere dovrebbe funzionare, ma devi adattarla e provarla tu, io adesso non ho modo di farlo ...

{
	stato = digitalRead(pin)	 //leggi ingresso pulsante
	if ((stato != stato_prec) && (stato_prec == 1)) // pulsante appena premuto
	{
		stato_prec = stato; 	//setta flag per pulsante premuto
		millis_prec = millis();	//setta variabile controllo tempo
	}
	if ((stato != stato_prec) && (stato_prec == 0)) //pulsante appena rilasciato
	{
		stato_prec = stato; 	//resetta flag per pulsante rilasciato
	}		
	if ((millis() - millis_prec => 3000) && (stato_prec == 0)) //pulsante ancora premuto dopo 3 sec
	{
		... //i tuoi comandi qui
	}
}