NTC e riferimenti esterni un aiuto a capire

Prima di tutto sono un principiante e mi piace sperimentare per capire.

Ho uno sketch che mi preleva tensione e traduce in temperatura, ma qui non mi dilungo.

Leggo in giro per caso e incontro... “meglio avere un riferimento di tensione esterno”.

Esterno si, ma senza dirlo ad ARDUINO, Senza AREF per intenderci che scopro col tempo...

Ok. Non approfondisco creo una shield per conti miei e sperimento.

Metto GND in comune con il MEGA. Ho una tensione esterna stabilizzata (molto) non faccio riferimenti col MEGA, ma comunque do la lettura della tensione al PIN Analogico e qui sembra tutto funzionare, ma alla grande (all’inizio).

Infatti i valori di temperatura stampati in seriale si avvicinano al centesimo con altro rilevatore di temperatura digitale in mio possesso.

Quando il MEGA rimane acceso per un po’ mi accorgo che la temperatura arriva allo Zero ASSOLUTO, -273,15°C.

Sostituisco l’NTC il giorno dopo. Riaccendo e tutto funziona regolarmente. Dopo un po’ ancora la solita storia.

Morale:

  • Mi accorgo che non si è bruciato nulla, bene.
  • Ribalto lo sketch pensando che ci sia conflitto con qualche funzione e libreria. ahrggg.
  • Mi accorgo che se ARDUINO rimane a riposo per qualche minuto tutto funziona ancora come prima.
  • Stampo a Seriale i dati che vi accludo (faccio una sintesi per evitare il listato completo):

21:37:22.169 -> Temperatura °C 23.13
21:37:22.855 -> Temperatura °C 23.14
21:37:23.531 -> Temperatura °C 23.12
21:37:24.200 -> Temperatura °C 23.14
21:37:24.862 -> Temperatura °C 23.13
21:37:25.557 -> Temperatura °C 23.14
21:37:26.210 -> Temperatura °C 23.12
21:37:26.886 -> Temperatura °C 23.14
21:37:27.574 -> Temperatura °C 23.14
21:37:28.251 -> Temperatura °C 23.14
21:37:28.917 -> Temperatura °C 23.14
21:37:29.601 -> Temperatura °C 23.14
21:37:30.269 -> Temperatura °C 23.14

"" "" ""
21:41:27.285 -> Temperatura °C 23.18
21:41:27.956 -> Temperatura °C 23.17
21:44:44.613 -> Teperatura °C 1.55
21:44:44.941 -> Temperatura °C 0.69
21:44:45.781 -> Temperatura °C 0.08
21:44:46.440 -> Temperatura °C -0.57

21:44:49.157 -> ora 11:7Temperatura °C -4.10
21:44:49.830 -> ora 11:7Temperatura °C -4.89
21:44:50.508 -> ora 11:7Temperatura °C -5.66
21:44:51.184 -> ora 11:7Temperatura °C -6.50
21:44:51.880 -> ora 11:7Temperatura °C -7.38
21:44:52.533 -> ora 11:7Temperatura °C -8.32
21:44:53.233 -> ora 11:7Temperatura °C -9.34
21:44:53.917 -> ora 11:7Temperatura °C -10.35
"" "" ""
21:45:04.720 -> ora 11:8Temperatura °C -69.64
21:45:05.391 -> ora 11:8Temperatura °C -93.11
21:45:06.088 -> ora 11:8Temperatura °C -128.30

21:45:10.848 -> ora 11:8Temperatura °C -248.11
21:45:11.525 -> ora 11:8Temperatura °C -252.70
21:45:12.202 -> ora 11:8Temperatura °C -256.29
21:45:12.871 -> ora 11:8Temperatura °C -259.12
21:45:13.561 -> ora 11:8Temperatura °C -273.15
21:45:14.226 -> ora 11:8Temperatura °C -273.15

Alla fine desidero cercare di capire il fenomeno (chiedo lumi ai luminari).

1 - Perché pur avendo sbagliato l’approccio all’inizio funziona e poi no?

2 - Se voglio fare un riferimento esterno, mi sembra di aver capito che l’alimentazione esterna deve essere prelevata dalla mia shield (alimentata a 5V per l’esattezza nel mio caso e GND in comune ovviamente) e inviata nel PIN AREF, cioè collegare i 5V esterni al PIN AREF del MEGA, dico bene?

3 - Ho letto, approfondendo l’argomento, che si deve comunicare nello sketch il riferimento esterno per evitare danni al processore, ridico bene?

4 - Come faccio a dichiarare (prima) e (poi) essere sicuro che vada tutto per il meglio?

5 - Si deve farlo prima del SETUP, nel SETUP, DOPO oppure quando eseguo i il codice per trovare la temperatura?

Se non vi dispiace potete postarmi degli esempi prima di mandare a colare il mio MEGA?

Ho solo 10mila righe di codice alle mie spalle partendo da zero dal mese di gennaio di quest’anno, forse qualche passo avanti lo sto facendo.

Ringrazio anticipatamente chi mi darà consigli, vedi punti 2-3-4-5 e lumi sull’arcano, vedi punto 1.

Il riferimento ADC si configura tramite la funzione analogReference(type), qui la doc.

Nel setup() e prima di chiamare analogRead().

void setup()
{
    analogReference(EXTERNAL);
}

Nella mega hai 3 riferimenti interni:
DEFAULT 5.0 ( Vcc)
INTERNAL1V1 1.1V
INTERNAL2V56 2.56V

Il problema con i risultati dovrebbe risolversi configurando correttamente il riferimento esterno.
Nota che se da codice scegli un riferimento interno devi scollegare AREF dalla sorgente esterna di riferimento.

Ciao.

Quale NTC? Che Sketch? Circuito?

Per usare una tensione di riferimento esterna devi collegarla al pin AREF e settare nel SETUP() con analogReference(EXTERNAL); il riferimento esterno.

Solo nel Setup() o loop() puoi chiamare un altra funzione.

Ciao Uwe

Per rispondere alle richieste:
Il termistore è quello tipico piccolo di forma tonda che si trova anche nei kit.
Fa molto bene il suo dovere se collegato senza riferimenti esterni.

  • In quella esterna bisogna dichiarare il voltaggio oppure il MEGA riconosce il valore applicato?
  • Se bisogna dichiararlo dove devo mettere il valore?
  • Una ultima domanda esiste uno sketch che permetta di poter vedere se il MEGA funzioni ed i suoi pin stiano lavorando correttamente?

Grazie ancora.

Ho postato anche lo schema.
Naturalmente qui ho condensato il tutto. Sketch di seguito:

int tempPin = A0;
ecc.
void setup() {
}
void loop() {
  double mediaTemp = 0;
  int arrayTemp = 500;
  double tempReading[arrayTemp];

  while (ripeti fino a quando ho bisogno) // È inserito in un altro contesto io l’ho abbreviato così
  {
    //            // A0 è il pin di Arduino Mega collegato al sensore di temperatura

    //            // per fare una media
    for (int i = 0; i < arrayTemp; i++)
    {
      tempReading[i] = analogRead(tempPin);

      mediaTemp = mediaTemp + tempReading[i];
    } // questa è la tipica routine
    mediaTemp = mediaTemp / arrayTemp;
    double tempK = log(10000.0 * ((1024.0 / mediaTemp - 1)));
    tempK = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * tempK * tempK )) * tempK );   //  Temp Kelvin
    float tempC = tempK - 273.15;                                    // Converte Kelvin a Celcius
    float tempF = (tempC * 9.0) / 5.0 + 32.0;                        // Converte Celcius a Fahrenheit
    Serial.print(F("Temperatura °C "));
    Serial.println(tempC);
  }
}

Il riferimento non funziona cosí.

Con quel circuito hai solo una tensione precisa sul termistore ma la misura dipende dai 5V di Arduino.
In questo caso visto che la risposta dipende dalla tensione che viene aplicato al partitore NTC e resistenza é meglio usare la tensione "inprecisa" del alimentazione di Arduino.
Questo perché una variazione della tensione di alimentazione influenza sia il partitore che la misura dei ADC.

È meglio che colleghi il filo rosso al pin 5V del Arduino.

Tutto questo non giustifica che dopo un po leggi -273°C

Prova di usare tipi di variabili diversi.

 unsigned long mediaTemp = 0;
  int arrayTemp = 500;
  int tempReading[arrayTemp];

inoltre non Ti serve la variabile tempReading

for (int i = 0; i < arrayTemp; i++)
    {
        mediaTemp = mediaTemp + analogRead(tempPin);
    }

Ciao Uwe

… oppure usa una DS18B20!
Comunque, la tensione di riferimento deve essere uguale per l’ADC e per la sonda, quindi usa gli stessi 5V per entrambi.

Datman:
...
Comunque, la tensione di riferimento deve essere uguale per l'ADC e per la sonda, quindi usa gli stessi 5V per entrambi.

Non sono d' accordo.

Se un sensore o un insieme sensore/partitore resistivo danno un segnale che dipende oltre alla grandezza fisica da misurare anche dalla tensione di alimentazione allora é giusto che la tensione di riferimento é la stessa tensione di alimentazione oppure dipende direttamente da questa con per esempio un partitore resistivo. In questo caso una variazione della tensione influisce sia sul segnale del sensore che sulla conversione ADC ed é sempre giusta. Esempi di sensore sono tutti quelli che si mettono in un artitore resistivo come il Tuo NTc o PTC LDR, touch screen resistivo potentiometri ecc.

Se il sensore da un segnale di tensione in uscita che é indipendente dall'alimentazione allora la tensione di riferimento deve essere indipendente dall alimentazione se questa non al 100% stabile e si deve usare una tensione di riferimento interna o esterna prodotta da un circuito a posta. Esempi sono i LM35, LM335, TMP36, ecc.

Ciao Uwe

Invece io sono perfettamente d'accordo con te, Uwe! :slight_smile: Mi riferivo al caso in questione, in cui è usata una semplice NTC.

Usando Arduino, però, la soluzione più pratica, semplice, precisa e, comunque, economica, è la DS18B20, che fornisce già la temperatura in forma numerica.

Grazie per ora a tutti, ma non mi quadra ancora il punto 1.

Da cosa può dipendere?

Ora capisco perché l’hanno chiamato Arduino, esssssì.
È proprio un po’ ar...duino programmare e fare bene.

Ogni scienza è ardua, se si desidera che tutto funzioni bene! Anche accendere un LED può non essere elementare, ad esempio se è un LED da 70~100W e devi pilotarlo alla potenza nominale...

patdepri:
Grazie per ora a tutti, ma non mi quadra ancora il punto 1.

Il mio sospetto è che si scaldi la resistenza del partitore. Potrebbe scaldarsi anche l'NTC ma misureresti un aumento di temperatura. Però mi pare strano che arrivi a -273.

Io non ho ancora avuto il tempo di approfondire ma anche a me è capitato che facendo delle analogRead() a raffica, dopo un po', diciamo un centinaio di letture, mi danno come risultato zero.
Appena ho un attimo di tempo cerco di approfondire la questione perchè mi interessa venirne a capo.

Per il momento, il consiglio è di non leggere a raffica, cioè alla massima velocità, ma di diradare un pelo le letture, ad es. ogni 10s, ogni minuto, o anche più di rado, dipende dal motivo per cui leggi a raffica e se serve veramente farlo così rapidamente.

Però non con delay() ma schedulando con millis(), cosi ti studi e usi già il metodo giusto non bloccante :wink:

Ho fatto qualche test ed effettivamente, se si fanno un certo numero di analogRead() alla velocità della luce, dopo un po' il risultato è letture sempre più piccole fino ad arrivare a letture a zero.
Probabilmente, superando una certa velocità nel ripetere le letture, si ha una maggior scarica, rispetto alla carica, del condensatore interno che non ce la fa a starci dietro. Aggiungendo qualche elemento che rallenti, il problema si risolve.
Questo mi era capitato anche nelle prove per trovare un modo di generare un seme per random più variabile.
Nei test facevo letture a raffica per raccogliere dati e dopo un po' finivano a zero sballando tutto.

Ho fatto qualche test ed effettivamente, se si fanno un certo numero di analogRead() alla velocità della luce, dopo un po' il risultato è letture sempre più piccole fino ad arrivare a letture a zero.

Puoi indicare una procedura esatta per riprodurre questo difetto?

Ciao
Marco

Sulimarco:
Puoi indicare una procedura esatta per riprodurre questo difetto?

for (int i = 0; i < 1000; i++) {
  Serial.println(analogRead(A0));
}

Anche se la Serial.println potrebbe inserire un minimo ritardo per cui la lettura non arriva proprio a zero ma a qualche decina.
Nel teso dove arrivavo a zero raccoglievo circa 12 letture prima di stamparle e il prodotto di queste 12 letture era zero, quindi almeno una delle 12 diventava zero.
Nel mio caso il pin era lasciato volante, se collegato ad un sensore potrebbe dare risultati differenti.
Io ho riportato il mio caso.

Con il pin aperto nessuna misura ha senso ... mettici almeno un partitore resistivo e dagli una tensione costante !

Guglielmo

Il test è quello per il seme di random, ricordi? per questo era scollegato.
Lui non ha il caso specifico, ma fa comunque analogRead a raffica il più velocemente possibile e non so se arriva a zero o a qualche altra misura distorta a causa della velocità di ripetizione della lettura.
Mi suonava analogo come sintomo.
Stress del circuito di lettura che provoca distorsioni nel risultato.

maubarzi:
Lui non ha il caso specifico, ma fa comunque analogRead a raffica il più velocemente possibile e non so se arriva a zero o a qualche altra misura distorta a causa della velocità di ripetizione della lettura.

Hai presente la analogRead() come è fatta?

int analogRead(uint8_t pin)
{
	uint8_t low, high;

#if defined(analogPinToChannel)
#if defined(__AVR_ATmega32U4__)
	if (pin >= 18) pin -= 18; // allow for channel or pin numbers
#endif
	pin = analogPinToChannel(pin);
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
	if (pin >= 54) pin -= 54; // allow for channel or pin numbers
#elif defined(__AVR_ATmega32U4__)
	if (pin >= 18) pin -= 18; // allow for channel or pin numbers
#elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__)
	if (pin >= 24) pin -= 24; // allow for channel or pin numbers
#else
	if (pin >= 14) pin -= 14; // allow for channel or pin numbers
#endif

#if defined(ADCSRB) && defined(MUX5)
	// the MUX5 bit of ADCSRB selects whether we're reading from channels
	// 0 to 7 (MUX5 low) or 8 to 15 (MUX5 high).
	ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5);
#endif
  
	// set the analog reference (high two bits of ADMUX) and select the
	// channel (low 4 bits).  this also sets ADLAR (left-adjust result)
	// to 0 (the default).
#if defined(ADMUX)
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
	ADMUX = (analog_reference << 4) | (pin & 0x07);
#else
	ADMUX = (analog_reference << 6) | (pin & 0x07);
#endif
#endif


#if defined(ADCSRA) && defined(ADCL)
	// start the conversion
	sbi(ADCSRA, ADSC);

	// ADSC is cleared when the conversion finishes
	while (bit_is_set(ADCSRA, ADSC));

	// we have to read ADCL first; doing so locks both ADCL
	// and ADCH until ADCH is read.  reading ADCL second would
	// cause the results of each conversion to be discarded,
	// as ADCL and ADCH would be locked when it completed.
	low  = ADCL;
	high = ADCH;
#else
	// we dont have an ADC, return 0
	low  = 0;
	high = 0;
#endif

	// combine the two bytes
	return (high << 8) | low;
}

… ovvero lavora in “single conversion”, attiva una conversione, aspetta che sia terminata e da il risultato. Ogni conversione è indipendente (purchà siano ripettate le impedenze richieste) dalla predecente.

Guglielmo

maubarzi:
Il test è quello per il seme di random, ricordi? per questo era scollegato.

… e difatti quel test è una caxxata … per la “random” si fa UNA lettura e quella da un valore casuale … farle letture a raffica è del tutto inutile.

Guglielmo

Ecco, però come fai a dire che quella singola lettura sia random? Tutte le prove di Maubarzi infatti partono all'incirca dallo stesso valore.