miglior approccio per gestione isteresi in ambito termoregolazione

maubarzi:
Che frulli per le mie cose sto processore invece di fare continue pause caffè ripetendo di continuo NOP NOP NOP...

In realtà durante la delay() tutto fa meno che delle NOP :smiley: :smiley: :smiley: :smiley:

Guglielmo

Vero, ci pucia anche i biscotti dentro il caffè e mescola, scusa la dimenticanza :wink:

Tornando seri, ovvio che tutte le attività attivate da interrupt continuano a funzionare proprio per la natura delle interrupt ma se non ci sono interrupt....

maubarzi:
Tornando seri, ovvio che tutte le attività attivate da interrupt continuano a funzionare proprio per la natura delle interrupt ma se non ci sono interrupt....

NI ... nel senso che l'ATmega328P è solo una piccola MCU a 8 bit e ... quando parte una ISR, disabilita gli interrupt e, sino a quando quella singola ISR non è terminate, anche gli altri interrupt sono fermi ... ::slight_smile:

Non a caso si chiede di fare le ISR le più veloci possibili (es. basta, se necessario, acquisire un valore e alzare una flag e poi, vedendo la flag alzata, fare tutto nel loop, lasciando la possibilità ad altri interrupt di partire) ...

Guglielmo

maubarzi:
Poi, se non è troppo complicato per te, io userei un array per salvare le letture

Gli array mi sono indigesti...:slight_smile:

droidprova:
adesso è più chiaro. Devo provare assolutamente il tuo codice...

Intanto ti chiedo anche: ma per far funzionare al meglio il tutto, per la sonda ds18b20, è meglio settare una certa risoluzione tra tutte quelle disponibili?

l'idea che ti è stata suggerita di calcolare solo con i numeri interi è da prendere in considerazione,

non si vede l'utilità a interrogare la sonda ad ogni "secondo" . E nemmeno i centesimi di grado, in un termostato ambientale

droidprova:
x docdoc, il tuo ultimo codice è simile al mio postato ad inizio topic tranne che per else presente (nel mio). Vero?

Si, la logica è la stessa (tranne i "<=" e ">=" invece di "<" e ">" ma è ben poco influente), quindi per me è un problema più che altro di valori, ossia un valore di isteresi t_h troppo piccolo: non deve essere paragonabile alla risoluzione della lettura, se metti 0.2 gradi ed il sensore ha 0.25 è inevitabile che fluttui!

Inoltre una variazione di 0.2 gradi ce l'hai anche solo avvicinando una mano a 10cm dal sensore... E considera che leggo che quello ha una approssimazione di +/-0.5°C (non parlo di risoluzione ma di approssimazione della lettura!) quindi per me come isteresi devi prevedere ALMENO un valore doppio della approssimazione, quindi metti t_h=1 o t_h=0.8, non di meno.

Se questa ampiezza dovesse essere troppo ampia per qualche ragione (ma mantenere una temperatura a meno di 1 grado di variazione mi pare applicabile a qualsiasi applicazione "normale") dovresti scegliere un sensore diverso, ma la misurazione non deve avere alcun "disturbo", ossia non deve esserci alcuna sorgente di calore nelle vicinanze, non deve circolare aria da zone più calde o fredde, eccetera, e comunque per mitigare questi disturbi devi fare una media temporale (diciamo 30 secondi, con letture ogni 2 secondi, tanto non credo che nel frattempo nessuno muoia assiderato :wink: ).

Gli array mi sono indigesti...:slight_smile:

Eh però ti conviene iniziare a digerirli. :slight_smile: anche perché per fare la "media mobile" ti servono, esattamente come ti ha descritto maubarzi.
Ad esempio, se fai una lettura ogni 2 secondi e vuoi coprire gli ultimi 30 secondi, ti serve un array di 15 elementi:

#define NUM_LETTURE 15
int lettura[NUM_LETTURE];

dove lettura[0] è l'ultima lettura, lettura[1] la penultima, e così via. Quindi con una variabile tieni traccia di quanti elementi sono nella coda:

byte num = 0;

e ad ogni lettura fai una cosa del tipo:

...
  // Leggo il valore nella variabile "temp" quindi:
  // Sposto "avanti" tutti gli elementi
  for (int i=num-1; i>0; i--)
    lettura[i] = lettura[i-1];
  // Registro la nuova lettura
  lettura[0] = temp;
  // Aggiorno il contatore elementi
  if ( num < NUM_LETTURE-1 )
    num++;
  // calcolo la media
  int media = 0;
  for (int i=0; i<num; i++)
    media += lettura[i];
  media /= num;
...

droidprova:
Gli array mi sono indigesti...:slight_smile:

uno che vuole programmare e gli stanno indigesti gli array è come uno che va al cinema e gli da fastidio stare seduto
Deve urgentemente capire "se stesso"

Io pensavo ad una cosa un po' diversa, ma la tua forse è più intuitiva per uno che sta iniziando ora con lo svezzamento sugli array.

Io intendevo che i valori restavano sempre fermi ma variava ad ogni lettura la posizione dove memorizzare quello nuovo.
Tipo la lettura 1 in posizione 0 (visto che gli array sono zero based)
la lettura 5 in posizione 4,
la lettura 15 in posizione 14
la lettura 16 in posizione 0 sovrascrivendo il valore letto 15 turni fa, non 15 perchè l'array lo abbiamo ipotizzato da 15.

La media la fai sempre sommando tutti i valori che alla prima lettura li inizializzi tutti allo stesso valore appena letto, giusto per avere la logica di lettura lineare e sempre uguale anche il primo giro, parti cioè da una media di 15 valori uguali che poi cambiano a seconda delle successive letture.

Quindi:

  1. leggo un valore
  2. lo salvo nel punto attualmente corrente
  3. incremento il puntatore alla cella corrente.
  4. se arrivato a fondo scala lo faccio ripartire da 0
  5. calcolo la media dei 15 valori dell'array
  6. valuto la soglia...
    ...

Capisco però che vedere l'array sempre ordinato sia più intuitivo, cioè facendo scorrere i valori all'indietro in modo che a regime scrivo sempre sulla posizione 14 dopo aver spostato tutti i valori sulla cella precedente.
In questo caso non c'è tanto da discutere, la penalizzazione sulle prestazioni è trascurabile...quindi meglio la scelta più facile.

Poi resto convinto che il problema siano le oscillazioni e i valori di isteresi come ha spiegato @docdoc meglio di quanto fatto da me nel mio precedente post

@Standardoil sto ancor ridendo per la metafora...

@Standardoil : indigesti nel senso che ho difficoltà a comprenderli quindi a digerirli, ma io ho la super volontà di imparare a usarli. E anche con il vostro aiuto so che posso farcela. Grazie :slight_smile:

nell'esempio di docdoc però non è contemplato il ritardo sul campionamento, o mi sbaglio?

maubarzi:

Io intendevo che i valori restavano sempre fermi ma variava ad ogni lettura la posizione dove memorizzare quello nuovo.

E' come mi venne spontaneo fare nel contatore geiger per fare un integratore che visualizzasse costantemente il valore misurato negli ultimi 10-30-60 secondi: conto i secondi da 1 a n ciclicamente, ricominciando dall'inizio, e alla fine di ogni secondo metto il numero di impulsi rilevati in un corrispondente elemento di un array di 10-30-60 elementi; poi faccio la somma di tutti gli elementi facendo una scansione rapida e rapporto a 1 minuto per calcolare i cpm (impulsi al minuto).

Nel frattempo che la digestione degli array abbia inizio, volevo dirvi che il codice al messaggio #18 fa quello che deve, ed è già un bel inizio per me, almeno cado su un cuscino.

Grazie a tutti per gli interventi.

Continuo a studiare e provare!

droidprova:
nell'esempio di docdoc però non è contemplato il ritardo sul campionamento, o mi sbaglio?

No perché la porzione di codice che ti ho indicato è quella relativa ad UNA nuova lettura da inserire nella coda, eventuali temporizzazioni o altri criteri vanno gestite a monte (la parte con i puntini"..." che non conosco...).