Buongiorno a tutti,
avrei bisogno di qualche chiarimento sull'esecuzione del codice in generale.
Il void setup viene eseguito una sola volta all'avvio e qua ci siamo.
Il void loop continua a girare (ovviamente salvo errori o blocchi) eseguendo in sequenza le varie istruzioni.
La prima domanda: se nel mio sketch devo fare eseguire alcuni calcoli solo a determinate condizioni, è meglio creare una funzione apposita e richiamarla oppure mettere solo delle condizioni che se non valide fanno saltare al blocco successivo?
Faccio un esempio, è meglio cosi:
void loop()
se il pulsante 1 viene premuto allora esegui void saluta
se il valore della fotoresistenza al pinA3 è > di 55 allora esegui void luce
void saluta()
print "buongiorno"
void luce()
print "è giorno!"
attiva pin4 e alza la serranda
L'altro caso prevede invece dei semplici if then...
Quel che a me interessa è dare priorità ad una funzione, ad esempio, se il valore della fotoresistenza > di 55 deve eseguire tutta la funzione anche se viene premuto il pulsante 1.
Insomma a me interessa che vengano svolti alcuni calcoli (che possono impegnare il micro anche per 300ms ad esempio) anche se subentrano altre richieste.
Chiedo questo perché sto avendo problemi con uno sketch (avevo già chiesto info) dove devo contare il tempo che intercorre tra due impulsi (tra un impulso e l'altro possono passare da un secondo fino a svariati minuti). Ho aggiunto la lettura di 5 sensori DS18B20 e se l'impulso cade proprio quando il micro è impegnato con la conversione, rischio di perderlo.
Forse la via più sicura è quella di utilizzare interrupt, corretto? In quel caso, il micro dovrebbe eseguire quanto richiesto per poi tornare a terminare la conversione della temperatura.
Grazie!
Parto dalla seconda domanda, si se la richiesta deve essere prioritaria la gestione via interrupt è la soluzione. La cosa migliore è fare le operazioni minime indispensabili all'interno della ISR delle interrput e gestire il resto della richiesta nel loop (Es. nell'ISR mi valorizzao la variabile che l'evento è stato scatenato e il millis() di quando è avvenuto, nel loop se la variabile è settata faccio dei conti, leggo le sonde, stampo millis sulla seriale ecc. e resetto la variabile. La ISR deve essere il più veloce possibile) chiaro che cosa fare nell'ISR come operazioni minime dipende da cosa stia gestendo l'interrupt, in ogni caso nell'ISR "less is more" più veloce è meglio è.
Per la questione delle funzioni, dove possibile e/o dove il solito codice viene richiamato da più parti è sempre bene usarle, rendono il codice più pulito e manuntenibile, unica cosa da tenere a mente è non fare funzioni che si autorichiamano (e che ne richiamano in casscata molte altre) molte volte perché si va in contro all'esaurimento dello stack, per il resto dipende anche da come si vuol organizzare il codice:
loop
if(pulsantePremuto)
funzioneSaluta()
funzioneSaluta()
Ciao
oppure
loop
funzioneSaluta()
funzioneSaluta()
if(pulsantePremuto)
Ciao
Sono entrambe valide e dipende anche da come le condizioni rendano il codice più leggibile
Tempo addietro qualcuno (Guglielmo credo) aveva indicato questo come un buon punto d'inizio per iniziare a scrivere codice per MCU in modo corretto in alternativa alle costose e super restrittive regole MISRA C
Grazie!
Ok per interrupt che ha priorità.
Se però richiamo una funzione e nel tempo di esecuzione avviene un evento che ne richiama un'altra che succede?
Ipotizzo inventando numeri e tempi di esecuzione...
if impulso sul pin2 --> esegui void calcolopower()
if millis() > 5000 --> esegui void controllotemperature()
void calcolopower()
delta = tempo_attuale - tempo_precedente
esegui dei calcoli su delta ed invia i risultati su seriale //tempo impiegato 100ms
void controllotemperature()
leggi il valore di sonda 1 esegui i calcoli necessari e invia il valore via seriale
leggi il valore di sonda 2 esegui i calcoli necessari e invia il valore via seriale
..........
leggi il valore di sonda 5 esegui i calcoli necessari e invia il valore via seriale
// tempo necessario per esecuzione 2 secondi (ripeto, tempi inventati)
In questo caso non c'è interrupt quindi se sto eseguendo void controllotemperature() per due secondi anche se arrivano impulsi non verranno presi in considerazione, esatto?
Intendo dire, una volta avviata una funzione deve terminare perché riprenda il void loop... giusto?
Se void calcolopower() fosse richiamato da un interrupt invece bloccherebbe l'esecuzione di void controllotemperature() per poi completarla una volta fatti i calcoli di power... ho capito bene?
Perdonatemi queste banalità!
Per fabpolli Grazie della segnalazione, avevo già letto qualcosa, ma non lo trovavo più...
Si hai capito bene, per codificare bene la cosa dovresti strutturare il programma in un modo simile a questo:
tempo_precedente = 0;
volatile tempo_attuale=0;
volatile impulso_ricevuto=false;
loop
if(impulso_ricevuto)
calcolopower()
if millis() > 5000 --> esegui void controllotemperature()
ISR_Impulso
tempo_attuale=millis();
impulso_ricevuto=true;
funziona a patto che tra un impulso e il successivo non possa intercorrere un tempo inferiore all'esecuzione dell'intero loop, se così fosse dovresti gestire un array di rilevazioni degli impulsi