Oscillazioni funzione map()

Buonasera,

come da titolo sto “sviluppando” il software per un regolatore di temperatura proporzionale.

Lo scopo di questo di progetto è quello di variare la potenza ad una ventola in modo direttamente proporzionale alla temperatura rilevata da un sensore di temperatura LM35.

In particolare il sistema dovrebbe:

  • misurare la temperatura e filtrare il segnale in modo da eliminare tutti i vari rumori che il sensore potrebbe acquisire

  • in base alla temperatura rilevata commutare l’alimentazione in PWM della ventola

  • eseguire altre funzioni aggiuntive, ma in questo caso non sono di particolare importanza poiché non presentano particolari problemi


Detto ciò, i miei problemi iniziano con il settaggio del valore del PWM, in particolare la funzione che lo gestisce è la seguente:

void setPWM() {

  //AVVIO CON VENTOLA A VELOCITA' MIN. 
  if((tempC > 0) && (tempC <= Tmin)){  
    PWM_val = PWMmin;                                                   
  }

  //VENTOLA MODULATA 
  if((tempC >= Tmin) && (tempC <= Tmax)){   
        PWM_val = map(tempC, Tmin, Tmax, PWMmin, PWMmax);
        PWM_val = constrain(PWM_val, 0, 255);
	}

  // TEMP ALLARM
  //nessuna anomalia
  if(tempC < Tmax){ 
    STATUS_temp = false;
  }

  // TEMP ALLARM
  //temperatura troppo alta
  if((tempC > Tmax) && (tempC > Tmax + HIST)){ 
    PWM_val = 255; 
    STATUS_temp = true;
	}

  analogWrite(pwm_CTL,PWM_val);
}

come si può vedere la temperatura viene proporzionalmente mappata tramite la funzione map() nell’intervallo di valori (Tmin, Tmax) → (PWMmin, PWMmax)

dove rispettivamente:

  • Tmin: valore di temperatura minimo
  • Tmax: valore di temperatura massimo
  • PWMmin: potenza minima della ventola
  • PWMmax: potenza massima della ventola

Ho concepito questo tipo di soluzione poiché quando la temperatura rilevata è inferiore a Tmin la ventola sia bloccata e quindi ruoti ad una velocità costante sin da quando il sistema viene acceso.

Mentre, in maniera opposta, quando la temperatura sale sopra a Tmin venga eseguita la vera e propria la modulazione della potenza fino al valore Tmax oltre il quale venga eseguita una condizione di allarme nella quale il sistema avrà portato il valore di potenza della ventola al massimo (255).

Numericamente i valori sono per il momento provvisori e sono i seguenti:

Tmin = 35°C
Tmax = 45°C
PWMmin = 114
PWMmax = 255


Il sistema funziona veramente bene e ne sono molto soddisfatto ma:
Vorrei migliorare il comportamento rispetto alle isteresi che si verificano durante i fronti di salita e di discesa della temperatura, dal grafico (linea blu) si vede che il valore di PWM oscilla in modo molto rapido portando ad una oscillazione della velocità della ventola.
Allo stesso modo ottengo salti molto ampi tra ogni ciclo del programma di conseguenza vorrei migliorare anche questo apsetto, anche se credo dipenda molto dagli intervalli mappati della funzione map() che forse sono troppo ristretti.
Non vorrei ancora implementare un controllo di tipo P.I.D poiché mi sembra un pò troppo complicato (lo devo ancora studiare per bene :sweat_smile:) anche se non credo di poterlo implementare perché l’HW che sto utilizzando non è molto potente.


Come hardware utilizzo un Attiny85 @ 8Mhz, il segnale PWM è a 8bit e l’ADC è a 10bit.
Per questioni costruttive e di numero di pin disponibili non posso utilizzare un riferimento di tensione interno all’MCU o esterno regolato tramite integrato (ad esempio TL431).

L’unico filtro per il segnale in ingresso che ho implementato è una media di 20 valori campionati ogni 20ms che però come si può vedere dal grafico (linea arancio) non stabilizza bene il valore di temperatura letta.

void getTEMP() {
  tempC = 0;
  tempC_sum = 0;

  for (byte i = 0; i < 20; i++){
    tempC_sum += ((analogRead(tempPIN)/1023.00) * 498.10);
    delay(20);
  }

  tempC = tempC_sum / 20.00;
}

Ma tutto sommato fornisce valori abbastanza veritieri rispetto al valore fornito da altri strumenti.



Spero, grazie all'aiuto del forum, di risolvere questi problema di natura software.

Ringrazio in anticipo per le risposte fornite

Saluti

Penso che se si applica anche un filtro mediano all'uscita PWM si migliorerebbe la risposta e se i filtri sono a media mobile si migliorerebbe ancora di più. Si può provare.
Saluti.

1 Like

Innanzitutto ti ringrazio,@gonpezzi per la tua rapida risposta.

Tornando al progetto, se non ho capito male, implementando una funzione che faccia la media di n valori di uscita o comunque una media che tenga conto dei valori precedenti, quindi della “storia” del segnale potrei migliorare la risposta del mio sistema.

Ho visto il link che hai gentilmente fornito, in poche parole la libreria non fa altro che rilevare tot valori e metterli in un array per poi far “shiftare” tale array ed infine fare la media ad ogni ciclo.
In tal caso tale processo potrebbe essere fatto anche senza l’aiuto di una libreria?


Ringrazio nuovamente per le risposte fornite

Saluti

Ciao

Come regola, è sempre cosa buona pubblicare il programma completo. Anche semplicemente il tipo di una variabile può essere la causa di un problema apparentemente inspiegabile.

Inoltre dovresti scegliere con più cura i nomi delle variabili, ad esempio in TEMP ALARM (con una sola "L" in inglese) STATUS_temp sembra "temperatura di stato" (?...) e con le maiuscole si indicano le costanti, mentre per le variabili si usano le minuscole. D'altra parte, alternando parole in maiuscolo e in minuscolo finisci per confonderti e poi non riesci a capire perché, ad esempio, la funzione ti da errore quando fai analogWrite (pwm_CTL, pwm_val); mentre la variabile si chiama PWM_val (e non si capisce che pwm_CTL è l'uscita PWM). :slight_smile:

1 Like

Se possibile. Spiacente non è in italiano, traduci con google il seguente LINK porta un buon codice di esempio.
Saluti.

1 Like

non fa altro che rilevare tot valori e metterli in un array per poi far “shiftare” tale array ed infine fare la media ad ogni ciclo

Si fa anche senza shift (e senza libreria), basta un indice che scorre sull'array e ritorna all'inizio quando è arrivato alla fine.

L'operazione si può fare tanto sui valori in ingresso che su quelli in uscita (quindi con due array).

La media mobile, come ogni altro filtro, introduce però un certo ritardo nella risposta, perché il valore ottenuto dipende anche dai valori di N campioni precedenti.

1 Like

Un'altra possibilità sarebbe quella di applicare un fitro passa basso (digitale) sia al segnale di ingresso che al valore di PWM in uscita.

Low-pass filter - Wikipedia

Se può interessare, ho un paio di notebook python condivisi su Google Colab di ausilio per calcolare i coefficienti per le funzioni di trasferimento sia per un classico LPF che per un filtro Butterworth LPF.

1 Like

L'LM35 è un sensore lineare con uscita in tensione, quindi per filtrare il segnale da eventuali disturbi captati dal cavo di collegamente è sufficiente interporre un semplice filtro passa basso RC, ad esempio 2,2kohm e 100uF per una costante di tempo di 220ms.

1 Like

Salve,

Innanzitutto vi ringrazio per le tante risposte ricevute. Ora ho parecchio materiale da studiare e da approfondire per poter modificare il codice del progetto.
Tengo a precisare che non ho ancora apportato alcuna modifica al codice, farò le eventuali modifiche nei prossimi giorni poiché al momento sono abbastanza impegnato.


Detto questo,

Ammetto di aver tralasciato il resto del programma perché a mio avviso non è influente nel problema delle oscillazioni e in secondo luogo per rendere più "sintetica" la descrizione del mio problema. In ogni caso ecco il codice completo

#include <SoftwareSerial.h>

//DEBUG ONLY
SoftwareSerial SWSERIAL(8, 0);  // RX, TX


const byte tempPIN = A2;
const byte vadcPIN = A3;
const byte pwm_CTL = 1;
const byte PGS     = 2;


float tempC;
float tempC_sum;
float VCC;
float VCC_sum;

byte PWM_val;

boolean STATUS_temp;
boolean STATUS_vcc;

const byte Tmin    = 35;
const byte Tmax    = 45;

const byte PWMmin  = 114;
const byte PWMmax  = 255;
const byte Vlow    = 11;
const byte HIST    = 1;
int RFSH = 1000;    


//---------------------------------------
// --MAIN SETUP--
//---------------------------------------

void setup() {
  
  //PWM freq. 
  TCCR1 = (TCCR1 & (0b11110000 | 0b0001));

  pinMode(pwm_CTL,OUTPUT);
  pinMode(PGS,OUTPUT);

  //SERIAL BEGIN (DEBUG ONLY)
  SWSERIAL.begin(4800);
}


//---------------------------------------
// --MAIN LOOP--
//---------------------------------------

void loop() {
  
  //TEMPERATURE SENS.
  getTEMP();

  //FAN PWM / SPEED SET
  setPWM();

  //VCC SENS.
  getVCC();

  //POWER GOOD SIGNAL SET (P.G.S)
  setPGS();

  //ALARM SET
  setALM();

  //DEBUG
  DATAMONITOR();


  delay(RFSH);
}


//---------------------------------------
//FUNCTIONS DEFINITION
//---------------------------------------

//TEMPERATURE SENS.
void getTEMP() {
  tempC = 0;
  tempC_sum = 0;

  for (byte i = 0; i < 20; i++){
    tempC_sum += ((analogRead(tempPIN)/1023.00) * 498.10);
    delay(20);
  }

  tempC = tempC_sum / 20.00;
}


//FAN PWM
void setPWM() {

  //AVVIO CON VENTOLA A VELOCITA' MIN. 
  if((tempC > 0) && (tempC <= Tmin)){  
    PWM_val = PWMmin;                                                   
  }

  //VENTOLA MODULATA
  if((tempC >= Tmin) && (tempC <= Tmax)){   
		PWM_val = map(tempC, Tmin, Tmax, PWMmin, PWMmax);
		PWM_val = constrain(PWM_val, 0, 255);
	}




  // TEMP ALARM
  // nessuna anomalia
  if(tempC < Tmax){ 
    STATUS_temp = false;
  }

  // TEMP ALARM 
  //temperatura troppo alta
  if((tempC > Tmax) && (tempC > Tmax + HIST)){ 
    PWM_val = 255; 
    STATUS_temp = true;
	}

  analogWrite(pwm_CTL,PWM_val);
}


//VCC SENS.
void getVCC() {
  VCC = 0;
  VCC_sum = 0;

  for (byte i = 0; i < 20; i++){
    VCC_sum += (((analogRead(vadcPIN)/1023.00) * 4.98) * 13.70);
    delay(20);
  }

  VCC = VCC_sum / 20.00;
}


//POWER GOOD SIGNAL SET (P.G.S)
void setPGS(){
  
  // STATO NORMALE , nessuna anomalia
  if(VCC >= Vlow){ 
    STATUS_vcc = false;
    digitalWrite(PGS,HIGH);
  }

  //ALLARME TENSIONE BASSA
  if((VCC <= Vlow) && (VCC < Vlow - HIST)){  
    STATUS_vcc = true;
    digitalWrite(PGS,LOW);
  }
}


//ALARM SET
void setALM(){

  //STATO DI ALLARME
  if ((STATUS_vcc == true) || (STATUS_temp == true)){
    SWSERIAL.println("ALLARME TEMP.! / ALLARME TENSIONE BASSA!");   //DEBUG
  }

  //STATO NORMALE , nessuna allarme
  if ((STATUS_vcc == false) && (STATUS_temp == false)){
    //
    
  }
}


//SERIAL DEBUG 
void DATAMONITOR(){
    
    //plot 
    SWSERIAL.print(tempC);
    SWSERIAL.print(",");
    SWSERIAL.println(PWM_val);

}

Oltre alla funzione che gestisce il PWM non c’è molto effettivamente ed in particolar modo sono presenti le funzioni che:

  • rileva la temp.;
  • setta il PWM;
  • rileva la tensione di alimentazione;
  • setta un pin allo stato alto o basso in base al valore della tensione;
  • definisce cosa deve fare il sistema nella condizione di allarme (per ora lo scrive solo nella seriale);
  • invia i dati nella seriale per debug;

Ammetto di esserci andato giù pesante con la definizione dei nomi delle variabili e dei pin questa volta :laughing: .
Ho dato poi il nome di STATUS_temp/STATUS_vcc perché sono le variabili che definiscono i due allarmi (lo stato appunto) della temperatura e dell’alimentazione, ho quindi ritenuto adatto chiamarli in questo modo per questo motivo.
In seguito comunque cambierò i nomi delle varie variabili e costanti.

Si è vero, ho già provveduto a rimediare l’errore. Grazie per avermelo fatto notare


Grazie per il link, ho visto che in questo caso fa uso anche di un buffer circolare per rendere più efficiente il programma, non ho ben capito come funziona ed è per questo che lo dovrò approfondire anche perché ho visto che in molte soluzioni, che ho trovato in rete, lo si utilizza.

Potrei comunque pensare in prima battuta di implementare un buffer "normale" e poi passare a quello circolare per ottimizzare il codice.


Forse mi sono espresso male :sweat_smile: , con shiftare intendevo proprio lo scorrimento dei valori nel buffer proprio per eseguire la media mobile.

In questo caso non è un problema, infatti il sistema deve rispondere a cambiamenti di temperatura abbastanza lenti, non è un problema se si introducono ritardi nel filtraggio del segnale.


Un momento, ma un filtro passa basso non sarebbe utile per “eliminare” una determinata frequenza da un certo segnale?
In questo caso non andrei solo a “smussare” le creste dei picchi delle oscillazione del segnale invece di renderlo più stabile?

Forse potrebbe essere una possibile soluzione quella di implementare un sistema “ibrido” ovvero
una funzione a due stadi, nel quale il primo è costituito dalla media mobile o comunque la media classica di n valori e successivamente, come secondo stadio, un filtro passa basso per migliorare ancora di più la stabilità del segnale.


Anche il datasheet mi sembra che citi la possibilità di aggiungere un filtro al segnale in uscita. Ma come dicevo prima in questo caso non si ottiene uno “smusso” delle creste dei picchi delle oscillazione del segnale invece di renderlo più stabile?

In ogni caso vorrei proseguire con l’approccio software poiché mi piacerebbe approfondire meglio la questione.


Ringrazio ancora una volta tutti per le risposte fornite

Saluti

Quello che intendevo, è intervenire sul segnale di uscita per eliminare le oscillazioni.
Da quel che vedo, sul segnale di controllo PWM hai delle oscillazioni "fastidiose" nel range dei 10Hz più o meno.
Ad ogni modo il notebook Python a cui facevo riferimento è questo qui. Alla fine dei calcoli ottieni i coeficienti a_i e b_i da usare nel polinomio della funzione di trasferimento LPF.

  float x0 = 0;
  float y[] = {0, 0};
  .................
  // Digital LPF
  y[0] = a_i* y[1] + b_i* (lastVal+ x0);
  x0 = lastVal;
  y[1] = y[0];

Se i dati che hai usato per il plot li hai disponibili come csv, posso modificare il notebook al fine di usare quelli come test al posto delle due sinusoidi.

Quindi in questo caso l'effetto della media (mobile o non) e del LFP sarebbe lo stesso?
Avrebbe senso, quindi, implementare entrambi i filtri?

Credo che le oscillazioni avvengano con una frequenza minore di 10Hz, il grafico è campionato a 1s circa tra una misurazione e l’altra.
Credo che l’oscillazione si attesti attorno ad 1Hz.

Il file per fare il plot non è in .csv però sono valori valori separati da “;” quindi dovrebbero essere comunque interpretabili da Python, credo.

Per quanto riguarda il notebook devo dire che è davvero interessante purtroppo però è ancora un po' “acerbo” per i miei gusti, poiché devo ancora capire i vari passaggi matematici. :sweat_smile:

Saluti


log_test2.txt

24,39;114
24,73;114
24,49;114
24,95;114
28,24;114
24,81;114
24,44;114
25,78;114
25,27;114
25,59;114
24,39;114
26,17;114
25,37;114
24,81;114
24,98;114
23,71;114
25,93;114
25,32;114
25,56;114
26,90;114
25,37;114
26,15;114
25,64;114
24,49;114
27,53;114
26,22;114
25,51;114
25,12;114
27,49;114
25,39;114
25,59;114
26,17;114
26,17;114
25,73;114
28,39;114
26,29;114
26,78;114
24,98;114
24,98;114
26,80;114
26,49;114
27,92;114
25,61;114
25,59;114
26,24;114
26,34;114
26,68;114
26,51;114
27,02;114
28,07;114
26,80;114
27,51;114
27,61;114
27,70;114
27,83;114
28,05;114
27,75;114
28,17;114
29,58;114
29,75;114
30,46;114
29,31;114
30,19;114
31,06;114
31,19;114
33,11;114
31,79;114
31,87;114
31,77;114
33,08;114
32,70;114
32,40;114
32,65;114
33,28;114
33,30;114
33,79;114
34,25;114
34,55;114
34,08;114
33,67;114
34,25;114
34,23;114
35,13;114
36,08;128
33,96;114
35,42;114
35,96;114
35,54;114
36,10;128
35,54;114
36,44;128
36,61;128
36,59;128
36,40;128
36,74;128
37,17;142
36,83;128
37,25;142
37,27;142
37,64;142
37,71;142
37,95;142
38,27;156
37,91;142
38,76;156
37,37;142
39,10;170
39,00;170
38,83;156
39,37;170
39,12;170
40,56;184
41,53;198
40,97;184
42,90;212
41,26;198
41,90;198
41,82;198
41,87;198
42,24;212
42,46;212
42,38;212
42,90;212
42,82;212
42,97;212
42,94;212
43,36;226
43,70;226
43,46;226
43,29;226
43,65;226
44,11;240
45,23;240
45,26;240
45,50;240
44,72;240
45,43;240
45,55;240
45,53;240
46,13;255
46,65;255
46,72;255
47,18;255
47,47;255
47,50;255
47,84;255
48,06;255
48,40;255
48,54;255
48,93;255
48,81;255
49,03;255
49,35;255
49,52;255
49,71;255
49,83;255
49,83;255
50,00;255
49,93;255
50,05;255
50,13;255
50,22;255
50,20;255
50,05;255
50,10;255
50,08;255
50,22;255
49,81;255
49,79;255
49,81;255
49,74;255
49,74;255
49,69;255
49,79;255
49,44;255
49,35;255
49,30;255
48,96;255
48,91;255
48,84;255
48,64;255
48,37;255
48,69;255
48,20;255
48,37;255
47,94;255
47,69;255
47,64;255
47,52;255
47,35;255
47,06;255
46,79;255
46,84;255
46,55;255
46,43;255
46,26;255
46,18;255
45,94;255
45,67;255
45,84;255
45,65;255
45,38;255
45,43;255
44,99;240
44,72;240
44,55;240
44,48;240
44,58;240
44,82;240
44,21;240
43,85;226
43,24;226
43,53;226
43,55;226
43,50;226
43,04;226
42,68;212
43,02;226
42,77;212
43,14;226
42,38;212
42,46;212
42,51;212
42,63;212
41,70;198
42,85;212
41,97;198
42,14;212
41,87;198
42,14;212
42,04;212
41,73;198
41,78;198
41,65;198
41,82;198
41,63;198
41,26;198
41,26;198
40,95;184
41,41;198
40,53;184
41,75;198
40,32;184
41,19;198
40,53;184
42,29;212
40,15;184
41,24;198
40,12;184
41,97;198
39,80;170
39,07;170
39,34;170
38,34;156
38,00;156
38,27;156
37,78;142
38,71;156
38,32;156
37,81;142
38,54;156
37,39;142
38,42;156
37,86;142
38,42;156
37,73;142
38,34;156
37,88;142
37,73;142
37,78;142
37,52;142
37,54;142
37,54;142
37,39;142
37,39;142
37,47;142
37,32;142
37,10;142
37,00;142
36,91;128
37,15;142
36,71;128
37,49;142
36,83;128
36,79;128
37,27;142
36,54;128
36,74;128
36,74;128
36,40;128
36,47;128
36,69;128
36,71;128
36,37;128
36,79;128
36,35;128
36,32;128
36,08;128
36,30;128
35,91;114
36,81;128
36,30;128
35,76;114
36,25;128
35,40;114
36,08;128
35,79;114
36,44;128
35,18;114
36,54;128
34,96;114
36,64;128
35,18;114
36,79;128
34,64;114
35,76;114
35,08;114
35,20;114
36,88;128
35,06;114
35,50;114
35,96;114
34,74;114
34,59;114
35,79;114
36,13;128
34,06;114
34,67;114
33,96;114
34,35;114
34,06;114
34,16;114
35,67;114
34,55;114
34,45;114
34,18;114
35,45;114
34,25;114
34,57;114
34,38;114
34,20;114
34,55;114
34,28;114
34,06;114
34,33;114

Dal punto di vista matematico non direi proprio.
Potrebbe aver senso applicare una media mobile (magari esponenziale) ai valori letti dal sensore e filtrare l'uscita, anche se non mi sembrano "instabili" le letture fatte dal sensore ad occhio.

In quest'ultima settimana ho giocato parecchio con questi notebook per mettere a punto un controllore PI per un loop a velocità costante di un motore+encoder e devo dire che il filtro LPF (nel mio caso sull'ingresso), ha contribuito parecchio a rendere tutto più "smooth".

Ho provato a caricare le tue misurazioni, ma con una frequenza di campionamento cosi bassa è difficile estrapolare informazioni chiare.
Riesci a fare una misurazione tipo a 100Hz o meglio ancora 1Khz?

Il notebook aggiornato è questo. Ho rimosso il plot della FFT che tanto a queste frequenze non si apprezza molto.

Ok, sono riuscito a rilevare le misure con una frequenza di campionamento maggiore ad 1Hz.
In particolare ho escluso tutte le altre funzioni non necessarie del programma lasciando solo la regolazione della potenza della ventola attiva.
In questo momento l’unico “bottleneck” del sistema è il ciclo for() che rileva 20 misure ogni 20 ms. Ottenendo quindi con una frequenza di f = 1 / 0,4s = 2,5Hz.

Questo valore è quindi la maggiore frequenza di campionamento, che in questo momento riesco ad ottenere, spero che sia servito a qualcosa, anche perché vedo dal grafico che l’oscillazione è superiore al valore definito in precedenza.

In futuro potrei variare il delay nel ciclo for() oppure ridurre le misure anche se non so quanti benefici può portare tale operazione

Allego il grafico che ho ottenuto ed il log del test.

A questo proposito ho visto che sul notebook viene calcolata omega(velocità angolare) che ha come formula 2 x pi x f dove f è la frequenza espressa in Hertz.

In oltre viene espressa (con samplingFreq = 10) una frequenza di 10Hz bensì di appunto 1Hz.
In questo caso essendo poco esperto sia di Python che riguardo la matematica utilizzata in questi passaggi tale valore dovrebbe corrispondere alla frequenza di taglio del filtro?
Potrebbe essere, quindi, essere stato questo il problema del notebook?

Grazie in anticipo per le risposte
Saluti


log_test2.txt

22,25;114
21,11;114
21,16;114
21,03;114
21,55;114
21,28;114
21,08;114
21,01;114
21,30;114
21,03;114
21,11;114
20,82;114
21,13;114
21,06;114
21,20;114
21,06;114
21,08;114
21,03;114
21,20;114
21,25;114
20,94;114
21,28;114
21,03;114
21,08;114
21,52;114
21,11;114
21,52;114
21,08;114
21,13;114
21,18;114
21,11;114
21,16;114
21,16;114
21,33;114
21,37;114
21,08;114
21,30;114
21,06;114
21,20;114
21,35;114
20,91;114
21,45;114
20,91;114
21,13;114
21,13;114
21,16;114
21,52;114
20,89;114
21,69;114
21,35;114
21,40;114
20,99;114
21,25;114
21,20;114
21,72;114
21,52;114
21,25;114
21,59;114
22,03;114
21,52;114
21,93;114
22,08;114
21,37;114
22,03;114
21,74;114
21,74;114
22,35;114
22,15;114
22,06;114
22,23;114
22,03;114
22,35;114
22,08;114
22,79;114
22,15;114
22,03;114
22,76;114
22,47;114
22,47;114
22,88;114
22,79;114
22,71;114
22,76;114
22,76;114
22,96;114
22,81;114
23,03;114
23,59;114
23,52;114
23,20;114
23,42;114
23,42;114
23,40;114
24,00;114
23,76;114
23,86;114
24,03;114
23,79;114
24,00;114
24,27;114
24,25;114
24,25;114
24,44;114
24,78;114
24,44;114
24,49;114
24,76;114
24,98;114
25,03;114
25,15;114
25,32;114
25,17;114
25,51;114
25,76;114
25,42;114
25,88;114
25,64;114
25,93;114
26,12;114
26,27;114
26,32;114
26,12;114
26,46;114
26,49;114
26,51;114
26,71;114
26,97;114
27,17;114
27,02;114
27,32;114
27,32;114
27,14;114
27,49;114
27,58;114
27,75;114
27,97;114
27,97;114
27,80;114
27,97;114
28,22;114
28,34;114
28,39;114
28,78;114
28,46;114
28,75;114
29,21;114
29,14;114
29,19;114
29,65;114
29,58;114
29,36;114
29,29;114
29,58;114
29,77;114
29,92;114
30,02;114
30,02;114
29,92;114
30,31;114
30,26;114
30,26;114
30,38;114
30,63;114
30,67;114
30,94;114
30,97;114
31,33;114
31,26;114
31,11;114
31,38;114
31,41;114
31,58;114
31,75;114
31,87;114
31,92;114
32,09;114
32,33;114
32,43;114
32,45;114
32,77;114
32,79;114
32,72;114
32,94;114
33,16;114
33,21;114
33,01;114
33,35;114
33,64;114
33,64;114
34,06;114
33,74;114
33,96;114
33,79;114
34,18;114
34,40;114
34,42;114
34,79;114
34,72;114
34,76;114
34,96;114
34,98;114
35,08;114
35,30;114
35,42;114
35,45;114
35,59;114
35,71;114
35,76;114
35,88;114
36,01;128
36,13;128
36,32;128
36,32;128
36,42;128
36,76;128
36,54;128
36,91;128
36,83;128
36,81;128
37,03;142
36,96;128
37,42;142
37,27;142
37,52;142
37,71;142
37,81;142
37,69;142
37,95;142
38,12;156
37,86;142
38,17;156
38,44;156
38,29;156
38,47;156
38,44;156
38,44;156
38,68;156
38,78;156
38,85;156
39,15;170
39,32;170
39,39;170
39,10;170
39,61;170
39,37;170
39,73;170
39,97;170
39,90;170
39,68;170
40,17;184
40,73;184
41,53;198
40,53;184
41,39;198
41,07;198
41,02;198
41,07;198
41,22;198
41,58;198
41,48;198
41,82;198
41,87;198
41,78;198
41,95;198
42,21;212
42,29;212
42,14;212
42,68;212
42,53;212
42,56;212
42,80;212
42,77;212
42,85;212
43,21;226
42,85;212
43,14;226
42,90;212
43,29;226
43,31;226
43,36;226
43,65;226
43,75;226
43,75;226
44,06;240
43,92;226
44,21;240
44,09;240
44,28;240
44,55;240
44,50;240
44,92;240
44,79;240
44,79;240
45,16;240
45,09;240
45,16;240
45,35;240
45,60;240
45,57;240
45,38;240
45,50;240
45,99;240
46,01;255
46,28;255
46,21;255
46,38;255
46,55;255
46,40;255
46,67;255
46,77;255
46,84;255
46,91;255
47,03;255
47,03;255
47,23;255
47,42;255
47,55;255
47,69;255
47,69;255
47,74;255
48,06;255
48,15;255
48,18;255
48,42;255
48,50;255
48,64;255
48,84;255
48,81;255
48,81;255
48,98;255
49,01;255
49,15;255
49,30;255
49,32;255
49,47;255
49,62;255
49,57;255
49,81;255
49,96;255
50,15;255
50,10;255
50,05;255
50,35;255
50,44;255
50,32;255
50,74;255
50,61;255
50,74;255
50,98;255
50,78;255
51,03;255
50,95;255
51,49;255
51,34;255
51,39;255
51,51;255
51,59;255
51,76;255
51,76;255
51,83;255
51,93;255
52,20;255
52,15;255
52,05;255
52,20;255
52,56;255
52,51;255
52,56;255
52,66;255
52,37;255
52,73;255
52,78;255
52,80;255
53,05;255
53,29;255
53,29;255
53,39;255
53,34;255
53,39;255
53,34;255
53,29;255
53,51;255
53,41;255
53,68;255
53,61;255
53,71;255
54,09;255
53,61;255
53,83;255
53,95;255
53,92;255
54,09;255
54,05;255
54,27;255
53,95;255
54,00;255
54,00;255
54,29;255
53,90;255
54,00;255
54,27;255
54,07;255
54,17;255
54,24;255
54,19;255
54,19;255
54,14;255
54,17;255
54,09;255
54,17;255
54,39;255
54,09;255
54,46;255
54,12;255
54,07;255
54,22;255
54,24;255
54,07;255
54,05;255
54,29;255
54,24;255
53,88;255
54,12;255
53,90;255
54,07;255
53,92;255
53,97;255
53,80;255
53,73;255
53,80;255
53,88;255
53,51;255
53,80;255
53,68;255
53,71;255
53,58;255
53,46;255
53,56;255
53,41;255
53,36;255
53,51;255
53,34;255
53,39;255
53,44;255
53,12;255
53,51;255
53,17;255
53,19;255
53,10;255
53,17;255
53,10;255
52,85;255
52,93;255
52,78;255
52,76;255
52,78;255
52,66;255
52,34;255
52,83;255
52,61;255
52,54;255
52,59;255
52,34;255
52,24;255
52,34;255
52,29;255
52,32;255
52,10;255
52,07;255
52,27;255
51,98;255
51,78;255
51,88;255
51,73;255
51,66;255
51,56;255
51,51;255
51,59;255
51,49;255
51,49;255
51,37;255
51,47;255
51,25;255
51,27;255
51,17;255
50,78;255
51,15;255
51,00;255
51,15;255
50,78;255
50,71;255
50,66;255
50,69;255
50,74;255
50,59;255
50,42;255
50,35;255
50,47;255
50,39;255
50,35;255
50,22;255
50,15;255
49,91;255
50,13;255
49,96;255
49,91;255
49,83;255
49,71;255
49,74;255
49,79;255
49,69;255
49,66;255
49,59;255
49,30;255
49,32;255
49,20;255
49,13;255
49,06;255
49,01;255
48,91;255
48,81;255
48,71;255
48,69;255
48,62;255
48,67;255
48,57;255
48,59;255
48,54;255
48,52;255
48,50;255
48,32;255
48,03;255
47,96;255
48,08;255
48,06;255
48,03;255
47,59;255
47,74;255
47,67;255
47,64;255
47,40;255
47,47;255
47,57;255
47,57;255
47,45;255
47,35;255
47,28;255
47,08;255
47,23;255
46,91;255
47,25;255
47,08;255
46,91;255
46,77;255
46,65;255
46,69;255
46,50;255
46,65;255
46,43;255
46,50;255
46,40;255
46,33;255
46,23;255
46,18;255
46,21;255
46,06;255
45,94;255
45,99;255
45,74;255
45,84;255
45,87;255
45,72;255
45,57;255
45,70;255
45,48;255
45,48;255
45,43;255
45,33;255
45,35;255
45,21;255
45,35;255
45,31;255
45,06;255
45,11;255
45,06;255
44,92;240
44,77;240
44,62;240
44,65;240
44,45;240
44,41;240
44,53;240
44,70;240
44,58;240
44,38;240
44,48;240
44,21;240
44,36;240
44,26;240
43,82;226
43,75;226
44,02;240
44,09;240
43,99;226
43,80;226
43,75;226
43,55;226
43,92;226
43,55;226
43,53;226
43,36;226
43,36;226
43,33;226
43,53;226
43,24;226
43,29;226
43,19;226
43,24;226
43,26;226
43,14;226
42,94;212
43,26;226
43,19;226
42,70;212
43,24;226
43,04;226
42,77;212
42,70;212
42,85;212
42,77;212
42,68;212
42,75;212
42,73;212
42,68;212
42,75;212
42,51;212
42,48;212
42,48;212
42,51;212
42,38;212
42,29;212
42,24;212
42,41;212
42,21;212
42,07;212
42,29;212
42,34;212
42,09;212
42,04;212
42,02;212
41,95;198
41,78;198
41,90;198
41,92;198
41,78;198
41,95;198
41,65;198
42,02;212
41,51;198
41,90;198
41,48;198
41,48;198
41,53;198
41,68;198
41,75;198
41,48;198
41,44;198
41,36;198
41,24;198
41,51;198
41,22;198
41,12;198
41,24;198
41,09;198
41,24;198
41,05;198
41,17;198
40,88;184
41,78;198
41,02;198
40,78;184
40,75;184
41,17;198
40,80;184
41,29;198
40,70;184
41,17;198
40,70;184
40,97;184
40,92;184
40,85;184
40,90;184
41,31;198
40,68;184
40,92;184
40,78;184
40,68;184
40,44;184
40,51;184
41,07;198
40,07;184
40,07;184
40,58;184
40,49;184
40,34;184
40,83;184
40,22;184
40,24;184
40,07;184
40,19;184
40,56;184
40,15;184
40,80;184
40,49;184
40,46;184
40,15;184
39,88;170
39,37;170
39,41;170
39,32;170
39,07;170
39,12;170
38,95;156
39,29;170
39,03;170
38,83;156
39,15;170
39,10;170
39,15;170
39,15;170
39,03;170
39,10;170
38,85;156
38,88;156
39,05;170
38,95;156
38,51;156
38,81;156
38,78;156
38,68;156
38,76;156
38,59;156
38,39;156
38,73;156
38,59;156
38,61;156
38,61;156
38,54;156
38,61;156
38,64;156
38,39;156
38,37;156
38,39;156
38,34;156
38,08;156
38,37;156
38,42;156
38,20;156
38,08;156
38,12;156
38,20;156
37,91;142
38,05;156
37,98;142
38,12;156
37,91;142
37,98;142
38,15;156
37,73;142
37,88;142
38,03;156
37,83;142
37,86;142
37,76;142
37,93;142
38,00;156
37,69;142
37,83;142
37,64;142
37,86;142
37,69;142
37,88;142
37,78;142
37,54;142
37,81;142
37,69;142
37,54;142
37,61;142
37,49;142
37,69;142
37,49;142
37,47;142
37,42;142
37,27;142
37,54;142
37,39;142
37,49;142
37,20;142
37,37;142
37,25;142
37,10;142
37,30;142
36,91;128
37,20;142
37,15;142
37,08;142
37,15;142
36,93;128
37,10;142
37,13;142
36,93;128
37,03;142
36,83;128
36,71;128
36,98;128
36,93;128
37,05;142
36,86;128
36,66;128
36,74;128
36,86;128
36,69;128
36,76;128
36,54;128
36,83;128
36,71;128
36,81;128
36,57;128
36,69;128
36,44;128
36,37;128
36,71;128
36,66;128
36,59;128
36,42;128
36,32;128
36,30;128
36,15;128
36,08;128
36,30;128
36,23;128
36,49;128
36,15;128
36,08;128
36,27;128
36,30;128
36,01;128
36,23;128
36,03;128
36,08;128
35,91;114
36,08;128
35,96;114
35,81;114
35,93;114
35,96;114
36,06;128
35,76;114
35,91;114
35,93;114
35,67;114
35,91;114
35,79;114
35,93;114
35,69;114
35,74;114
35,84;114
35,69;114
35,84;114
35,86;114
35,81;114
35,69;114
35,84;114
35,62;114
35,57;114
35,62;114
35,62;114
35,35;114
35,15;114
35,54;114
35,52;114
35,45;114
35,25;114
35,50;114
35,40;114
35,32;114
35,30;114
35,30;114
35,37;114
35,32;114
35,35;114
35,35;114
35,28;114
35,35;114
35,30;114
35,20;114
35,25;114
35,28;114
35,30;114
35,20;114
35,30;114
35,11;114
35,11;114
35,06;114
35,08;114
35,08;114
35,15;114
35,11;114
35,08;114
35,03;114
34,96;114
34,94;114
34,89;114
34,86;114
34,89;114
34,86;114
34,84;114
34,79;114
34,81;114
34,84;114
34,79;114
34,74;114
34,67;114
34,74;114
34,69;114
34,62;114
34,67;114
34,57;114
34,57;114
34,57;114
34,35;114
34,35;114
34,38;114
34,38;114
34,40;114
34,33;114
34,35;114
34,28;114
34,18;114
34,33;114
34,30;114
34,30;114
34,28;114
34,25;114
34,30;114
34,20;114
34,38;114
34,28;114
34,20;114
34,16;114
34,18;114
34,16;114
35,15;114

Ciao, non ho avuto modo di provare con il nuovo set di dati (anche se non credo che cambi poi molto), però non avevo fatto caso che hai questo delay(20) inserito in un ciclo for sia in getTemp() che in getVCC() che in totale fanno un "tempo morto" di 800mS.

Francamente non mi sembra un buon approccio. Il tempo di reazione del tuo controllore è influenzato da queste pause.
Se proprio vuoi fare una media aritmetica ogni 20mS usa millis() per scandire il tempo ed evita il ciclo for.
Ad esempio potresti accumulare le letture in un array, oppure usare un filtro a media mobile o addirittura uno a media mobile esponenziale (Exponentially Weighted Moving Average - EWMA)

// alpha -> 0.0 - 1.0
output = alpha * actualReading + (1 - alpha) * lastOutput