solo a scopo di prendere familiarità con il codice di arduino stavo provando a modificare con concetti miei un classico circuito pulsante-led (giusto per prendere dimestichezza con il codice).
In dettaglio, ho arrichito al codice di accensione pulsante con i comandi Serial.println che inviano a schermo l'azione effettuata.
La mia idea era:
Finchè non viene premuto il pulsante a video mi dovrebbe comparire il messaggio "premere per ....."
Non appena viene rilevata la pressione del pulsante con If (val == LOW*) a video compare la scritto "Acceso..." o "Spento..."
Attualmente a video mi compaiono queste scritte ma in continuazione. (Come è giusto che sia in un loop)
Ma veniamo alla domanda vera e propria, esiste un modo per uscire dalla routine o di intercettare la pressione del tasto del tipo:
Inizia il loop
se il tasto non è premuto faccio comparire la scritta "premere per..." ed esco dalla routine finche non intercetto la pressione è faccio comparire la scritta "Acceso.." esco dalla routine fino alla prossima presione ecc...
Spero di essere stato chiaro.
Posto il codice
Saluti
#define Led 13
#define Btn_Led 7
int statoLed = LOW; //dichiaro variabile e la imposto su LOW
int val = 0;
void setup () {
Serial.begin(9600); //inizializzo la porta seriale
pinMode(Led, OUTPUT);
pinMode(Btn_Led, INPUT);
}
void loop()
{
val = digitalRead(Btn_Led);
if (val == LOW)
{
if (statoLed == LOW)
{
statoLed = HIGH;
digitalWrite(Led, HIGH);
Serial.println("Acceso...");
delay(100);
} else {
statoLed = LOW;
digitalWrite(Led, LOW);
Serial.println("Spento...");
delay(100);
}
}
else {
Serial.println("premi il pulsante per accendere/spegnere");
}
}
Certo che puoi, è più un controllo delle scritte che della pressione tasto, un flag a 1 appena la scritta è apparsa che va a 0 quando viene premuto il tasto
Kestrel82:
Ma veniamo alla domanda vera e propria, esiste un modo per uscire dalla routine o di intercettare la pressione del tasto del tipo:
Inizia il loop
se il tasto non è premuto faccio comparire la scritta "premere per..." ed esco dalla routine finche non intercetto la pressione è faccio comparire la scritta "Acceso.." esco dalla routine fino alla prossima presione ecc...
Per "sentire" un ingresso ci sono due possibilità: il polling periodico attraverso un loop, oppure usare gli interrupt.
Il polling è ciò che stai facendo. Se serve eseguire o non eseguire determinate cose in diversi momenti la soluzione è quella di pablos (si parla di elaborazione "a stati", dove una o più variabili contengono un'informazione sullo stato corrente e permettono di creare rami di programma da eseguire solo a certe condizioni).
Diciamo che nello stretto caso in questione basta spostare la stampa fuori loop, ad esempio mettendola nel setup.
L'uso degli interrupt invece permette di lavorare in modo totalmente asincrono, ma richiede delle accortezze per non incorrere in problemi di concorrenza, potrebbe non essere compatibile con tutte le board, e può interferire con altre funzionalità (vedi delay/millis).
Personalmente considero gli interrupt l'ultima spiaggia, da usare quando il farne a meno renderebbe il codice davvero complesso o impossibile da realizzare.
Ho fatto semplicemente una modifica e tutto sembra funzionare, però non riesco a spiegarmi come mai il sistema ora si comporti così. Nel senso che cosa modifica di così tanto, il loop è rimsto uguale, quindi dovrebbe presentarsi cosi:
Kestrel82:
il loop è rimsto uguale, quindi dovrebbe presentarsi cosi:
Acceso....
Acceso....
Acceso....
Acceso....
Spento...
Spento...
E non lo fa?
Qualcuo mi spiega quale effetto ha a livello concettuale lo spostamenti della scritta:
Serial.println("premere per accendere/spegnere") nel Void setup?
La funzione setup viene eseguita una volta sola all'inizio prima della chiamata ciclica a loop.
Tecnicamente c'è una funzione main "nascosta" che "orchestra" il funzionamento di setup e loop, dovrebbe essere fatta più o meno così:
Il loop contiene un ramo if principale che viene eseguito solo quando l'ingresso è LOW.
Se L'ingresso è HIGH il contenuto dell'if non viene eseguito e non compare nessuna scritta, mentre quando l'ingresso è LOW si entra nell'if principale e poi nell'if interno.
Claudio_F:
Il loop contiene un ramo if principale che viene eseguito solo quando l'ingresso è LOW.
Se L'ingresso è HIGH il contenuto dell'if non viene eseguito e non compare nessuna scritta, mentre quando l'ingresso è LOW si entra nell'if principale e poi nell'if interno.
Che stupito che sono! Hai ragione, avevo fatto quella modifica e non avevo provato ad usarla per questo sono andato in confusione. Sarebbe bastato esaminare attentamente il codice.
Le azioni posso anche essere sospese a secondo dell' input della seriale. Del tipo
Serial.println("Premi 'S' per continuare");
while (1) { // ciclo perenne
byte answer = Serial.read();
answer &= 95; // conversione in maiuscolo
if (answer == "S") break; // se S esce il ciclo
}
Poi beh, io per mia natura odio i cicli infiniti che non sono davvero infiniti, per cui farei tuttalpiù:
while (Serial.read () & 95 != 'S')
;
Infine, per rendere i caratteri maiuscoli/minuscoli ci sono apposite funzioni nella libreria C: toupper()/tolower(), che lo fanno in modo affidabile, portabile e leggibile.
Kestrel82:
Ho fatto semplicemente una modifica e tutto sembra funzionare, però non riesco a spiegarmi come mai il sistema ora si comporti così. Nel senso che cosa modifica di così tanto, il loop è rimsto uguale, quindi dovrebbe presentarsi cosi:
Qualcuo mi spiega quale effetto ha a livello concettuale lo spostamenti della scritta:
Serial.println("premere per accendere/spegnere") nel Void setup?
Grazie
a dir la verità Serial.println cosi com'è adesso lo trovo quasi incomprensibile se non "fatto male"
una scritta che si aggiorna a velocità più alta di quella che l occhio percepisce e per di più sempre lo stesso valore visualizzato e di solito in molti scketc è addirittura "disturbante" :o
per il serial monitor (debug) ci vorrebbe qualcosa al max una stampa ogni tot secondi