Verificare eventuali rallentamenti della MCU

Sono sicuramente paranoico e me ne scuso, ma ho sempre il dubbio che (e non so per quale motivo) io mi possa perdere dei segnali che arrivano sui pin.

Tempo fa avevo chiesto consigli su come evitare lo stop del programma durante la l'acquisizione della temperatura con sonde DS18B20. Ho risolto mettendo nello sketch la richiesta di calcolo della temperatura, faccio girare il programma normalmente e dopo cinque secondi (ho super abbondato) viene richiesta la temperatura e nuovamente viene richiesto il calcolo della temperatura al sensore.
Al mio arduino ci sto collegando sempre più cose. Oltre ad un conteggio di impulsi (che ovviamente devo essere letti tutti), ora vorrei provare a collegarci un DHT22. Ho cercato sui datasheet e sembra non vi siano problematiche simili ai sensori Dallas, unico accorgimento è che tra una lettura e l'altra devono passare almeno due secondi.

Veniamo alla mia richiesta: pensate possa essere una soluzione quella di inserire nello sketch una semplicissima funzione tipo blink (pin 1 sec a livello alto e uno a livello basso) utilizzando ovviamente la funzione millis().
Farei la stessa cosa su un altro arduino dove gira SOLO lo sketch di blink. Colelgo i due arduino all'oscilloscopio e vedo se l'arduino "farcito e caricato" rallenta rispetto a quello libero.

E' una prova stupida oppure posso effettivamente vedere se lo sketch subisce rallentamenti?

Allora parlare di rallentamento su una MCU single core single thread non ha senso non vi è nulla che può rallentarla con occupazione risorse da altri processi, quello che accade è che se sta facendo qualcosa (Es. un ciclo while) le altre istruzioni (esterne al while) non possono essere eseguite.
Hai necessità di ricevere impulsi e devi catturarli tutti? la soluzione è l'uso degli interrupt che come dice il loro nome interrompono il flusso standard dell'esecuzione del codcie per fare ciò che c'è nell'ISR dell'interrupt (la quale deve essere eseguita nel minor tempo possibile poiché quando sei dentro l'ISR gli interrupt sono disattivi) nel tuo caso potresi limitarti ad incrementare una variabile, nel loop principale quando hai terminato di leggere la temperatura verificherai il valore della variabile e farai ciò che devi

ciao :slight_smile:

beh io semplicemente misurerei quanto tempo "passa" dall'inizio del ciclo loop e dalla sua fine con la funzione millis().

void loop() {
  start=millis();
  /*
   * Il tuo Programma
   */
  Serial.println(millis()-start);
}

così che ti dice quanto tempo impiega il loop ad essere eseguito, così dalle misure vedi se rallenta o meno :slight_smile:

Spero sia quello che cercavi ... :slight_smile:

MD

Come sempre grazie per i preziosi consigli.

@fabpolli: Mi sono espresso male, in effetti è come dici tu: intendo proprio che se la MCU è impegnata a fare altro (vedi esempio dei sensori DS18B20 che impiegano fino a 750ms per inviare il dato) non esegue altre istruzioni.
Approfondisco la mia fobia: un sensore mi invia impulsi per ogni W assorbito. Nel peggiore delle ipotesi potrei avere un impulso ogni secondo e questo non dovrebbe essere un problema.
Vorrei aggiungere un anemometro e qua gli impulsi si fanno più veloci. Se ad esempio una struzione richiedesse 750ms, potrei perdermi qualche impulso. Convengo con te che l'utilizzo degli interrupt sia la soluzione (a proposito, ci sono problemi nell'utilizzare 2 pin di interrupt? Uno per anemometro ed uno per il sensore assorbimenti?)

@Matteo: spesso le soluzioni più semplici sono le migliori! Il tuo suggerimento mi evita di scomodare l'oscilloscopio :slight_smile: Grazie!

Ripeto, è una mia fobia (stupida) quella di pensare che vi siano ritardi "esagerati" dovuti ad alcune istruzioni o cicli ecc.

In questo caso potrebbe non essere una fobia ma una casistica reale, non so quanti impulsi dia l'anemometro in un secondo ma se fossero anche solo due potresti perderli (o perderne uno) se stai interrogando la sonda DS18B20.
Se stai usando una uno hai la possibilità di definire due ISR su due distinti interrupt (pin 2 e 3) senza problemi.
Unica cosa dentro l'ISR fai il meno possibile e non puoi usare millis() ad esempio perché dentro l'ISR come detto gli interrupt sono spenti. (Se proprio ti serve il tempo usa micros() )

l'alternativa potrebbe esser di decentrare, o meglio assegnare alcuni compiti ad un secondo arduino, e poi far dialogare entrambi tramite seriale :slight_smile:

Per esempio con uno misuri la temperatura con la sonda ... e sull'altro utilizzi l'anemometro :slight_smile:

ed infine incroci i dati tra i due tramite seriale :slight_smile:

la mia è un'ipotesi, dipende tutto dal progetto in se :slight_smile:

MD

L'utilizzo di un secondo arduino è già stato pianificato nel caso riscontrassi problematiche.
Preferirei ovviamente evitare hardware aggiuntivo, ma se necessario ben venga.

Vi farò sapere!

Ancora grazie!

figurati :slight_smile:

buon lavoro

MD

MatteoDerrico:
beh io semplicemente misurerei quanto tempo "passa" dall'inizio del ciclo loop e dalla sua fine con la funzione millis().

... direi che per queste cose la funzione micros() è molto più adeguanta non vi pare ? ? ?

Permmete di apprezzare ritardi mille volte inferiori :wink:

Guglielmo

Beh sicuramente .... ma onestamente non la conoscevo.... :frowning:

terrò a mente :slight_smile:

MD

Pensavo di poter ribattere al caro Guglielmo ed invece ecco che la sua dritta si rivela fondata.
Dico questo perché per i primi due minuti vedevo un tempo di loop di 300ms circa (165 e 285) e non mi sembrava il caso di scomodare i microsecondi.
Poi a quanto pare arduino (in realtà è un nodemcu) si è stabilizzato. Invio i dati della durata loop ad un serverino ogni minuto e i valori sono sempre compresi tra 0 e 1ms. Ovviamente qua ci sta a verificare con i microsecondi.

Qua sotto un grafico (in millisecondi):

occhio che alcune librerie bloccano gli interrupt quando devono eseguire letture o altro per cui occorre verificare le librerie in uso se si vogliono usare gli interrupt

khriss75:
Pensavo di poter ribattere al caro Guglielmo ed invece ecco che la sua dritta si rileva fondata.

:stuck_out_tongue_closed_eyes: :stuck_out_tongue_closed_eyes: :stuck_out_tongue_closed_eyes:
Scusa non ho resistito

Patrick_M:
occhio che alcune librerie bloccano gli interrupt quando devono eseguire letture o altro per cui occorre verificare le librerie in uso se si vogliono usare gli interrupt

... la micros(), contrariamente alla millis(), è comunque "interrupt safe", tanto è vero che la si può usare all'interno di una ISR :wink:

Guglielmo

Aggiorno giusto per dare qualche info.
Aggiornato lo sketch per leggere in microsecondi.
tempo loop quando non deve fare quasi nulla ma verificare solo se c'è un impulso e calcolare il delta tra un impulso e l'altro più un paio di moltiplicazioni: 800us circa
tempo loop per leggere valore umidità e temperatura da un DHT22: 278477us
tempo loop per leggere i valori di temperatura di 3 sonde DS18B20 (con codice ottimizzato per non avere ritardi): 44825us

Lo sketch gira su un nodemcu ed ogni valore letto lo butta su seriale ed invia al server tramite MQTT.
E' attivo un loop anche per aggiornamento dello sketch via OTA.

Proprio ora, per leggere DHT22 e 3 sonde Dallas: 320729us