Go Down

Topic: Strange results from TMP36 Thermistor (Read 1 time) previous topic - next topic

Wawa

Two consecutive A/D readings are sometimes done to clear the A/D from a possible ghost charge from a previous reading. The line you're referring to is a dummy read before the real readings in the for loop.
Leo..

vagulus

Thanks.  That's what I suspected.  Pity there is no Serial.purge(A0); command to clarify what the programmer is trying to do.  :)
"Answers are easy;
               it's asking the right questions
                                                      which is hard."
 The Doctor (Dr Who: The Face of Evil (1977))

Wawa

#17
Jan 14, 2018, 03:23 am Last Edit: Jan 14, 2018, 03:25 am by Wawa
A dummy read is to pre-charge the A/D sample cap to the value that is expected next.
Not to set the A/D value to zero.
Leo..

vagulus

"Answers are easy;
               it's asking the right questions
                                                      which is hard."
 The Doctor (Dr Who: The Face of Evil (1977))

vagulus

#19
Jan 14, 2018, 04:05 am Last Edit: Jan 14, 2018, 04:12 am by vagulus
I am still trying to get as accurate a temperature reading as possible from the TMP36.  The current configuration is

and the circuit is

and the code is
Code: [Select]

/*
-- filename   : usingTMP36temperatureSensor.ino
--
-- purpose    : demonstrate the interpretation of data from a TMP36
--               temperature sensor
--
-- derivation : https://learn.adafruit.com/tmp36-temperature-sensor/using-a-temp-sensor
--
-- version    : 0
--
-- date       : January 10, 2018
--
-- copyright  : this code is in the public domain
--
1234567890123456789012345678901234567890123456789012345678901234567890
_________1         2         3         4         5         6         7
*/

// general constants
// we tie 3.3V to ARef
#define AREF_VOLTAGE 3.27
//the analog pin the TMP36's Vout
#define SENSOR_PIN A0
// debug info switch
#define DEBUG true
// zero degree celsius voltage offset
#define OFFSET 0.53


// general variables
// the analog reading from the sensor
int sensorInput;
// voltage
float voltage;
// temperature in Celsius
float temperatureC;
// temperature in Fahreinheit
float temperatureF;



/*==========================================*/


void setup()
{
 // send debugging information via the Serial monitor
 Serial.begin(9600);

 // tell 'em who we are, man!
 Serial.println("usingTMP36temperatureSensor.ino");
 Serial.println();

 // initialize for output to PLX-DAQ
 if (!DEBUG)
 {
 Serial.println("CLEARDATA");
 Serial.println
 ("LABEL,Current Time,Raw Data,Voltage,Celsius,Fahreinheit");
 }

 // read into SENSOR_PIN
 pinMode(SENSOR_PIN, INPUT);

 // set the aref to something other than the UNO
 analogReference(EXTERNAL);
}  // end setup()


/*==========================================*/


void loop()
{
 // zero sensorInput
 sensorInput = 0;

 // get averaged reading from the sensor and show it
 for (int count = 0; count <= 31; count++)
 {
 sensorInput += analogRead(SENSOR_PIN);
 }
 sensorInput /= 32;
 if (DEBUG)
 {
 Serial.print("Sensor Input = ");
 Serial.print(sensorInput);
 }

 // converting that reading to voltage, which is based off
 //  the reference voltage and show it
 voltage = sensorInput * AREF_VOLTAGE / 1024.0;

 if (DEBUG)
 {
 Serial.print(" which equates to ");
 Serial.print(voltage, 4);
 Serial.println(" volts");
 }

 // convert from 10 mv per degree with 500 mV offset
 // ( TMP36 outputs 0.5volt at zero Celcius)
 //  to degrees ((voltage - 500 mV) times 100)
 //  and show it
 temperatureC = (voltage - OFFSET) * 100;
 if (DEBUG)
 {
 Serial.print(temperatureC, 1);
 Serial.println(" degrees C");
 }

 // now convert to Fahrenheit and show it
 temperatureF = (temperatureC * 9.0 / 5.0) + 32.0;
 if (DEBUG)
 {
 Serial.print(temperatureF, 1);
 Serial.println(" degrees F");
 Serial.println();
 //Serial.println();
 }

 // export the data to PLX-DAQ
 if (!DEBUG)
 {
 Serial.print("DATA,TIME,");
 Serial.print(sensorInput);
 Serial.print(',');
 Serial.print(voltage, 4);
 Serial.print(',');
 Serial.print(temperatureC, 1);
 Serial.print(',');
 Serial.println(temperatureF, 1);
 }

 // take a breather
 delay(3000); // (900000);
}


As you'll see in line 66 I am using EXTERNAL analog reference  which is defined in line 21 as 3.27 V.

No, studying Fig 6 0n page 5 of the TMP36 Datasheet I noticed that the Vout (at 3 V Vin) for the TMP36 at 0 degrees Celsius is a little more that 0.5.

so I cast a TMP36 in ice and tweaked the offset to a value of 0.53 (line 27) which gave a temperature reading of zero degrees Celsius.  Dipping the TMP36 in hot water less than a minute from boiling in the kettle gave me a reading of 98 degrees Celsius, so I decided the offset must be somewhere near right.  What can possibly go wrong?

Running my program gives me a temperature of 25.9 C when my store-bought desktop thermometer (yesterday) tells me it's 27.9 C.

Who do I trust, and how do I adjust my program?

"Answers are easy;
               it's asking the right questions
                                                      which is hard."
 The Doctor (Dr Who: The Face of Evil (1977))

Wawa

I see you're using two supplies. USB and breadboard.
There could be some ground voltage difference between the two.
You should use only power/ground from the Arduino.

The graph probably has a drawing error.
Specs of the TMP36 are 750mV@25C (calibration point) and 10mV per degree C from there.

0 degrees C readout not only depends on offset, but also on gain (AREF_VOLTAGE).
Simply tweaking offset to 0.53volt could shift the whole temp range by three degrees.

Water boils at 100C only at sea level, and at a certain atmospheric pressure.
Leo..


vagulus

I see you're using two supplies. USB and breadboard.
There could be some ground voltage difference between the two.
The breadboard and the UNO are wired to have common ground.  My knowledge of electronics is virtually nil, but I was thinking that such wiring would eliminate any difference.  Is that right?

You should use only power/ground from the Arduino.
I have found in the past (working with RF communication using the nRF24L01 breakout) that the power output from an Arduino is (to be nice) erratic.  Hence providing a stabilized Vin to the sensor.

The Red Wings regulator is not perfect (NB the 3.27 V AREF) but is appears to be stable.

The graph probably has a drawing error.
Specs of the TMP36 are 750mV@25C (calibration point) and 10mV per degree C from there.
If you take a close look at that graph it shows 755 mV @ 25 C for 3 V AREF - that's according to my tradesman's eye - so it would still need calibrating.  Trouble is, I do not have the laboratory facilities to provide 25 C ambient to the sensor.  That's why I went for 0 and 100 C.

0 degrees C readout not only depends on offset, but also on gain (AREF_VOLTAGE).
Simply tweaking offset to 0.53volt could shift the whole temp range by three degrees.
My point is that the range needed shifting.

Water boils at 100C only at sea level, and at a certain atmospheric pressure.
FTR: I'd be less that 15 m above sea level and QNH in the city (40 min wal;k away) is 1011.1 hPa.  The boiling point of water here would be pretty close to 100 C - closer than a lot of the other variables we work with  :smiley-wink: .

I am forced to the conclusion that the calibrated TMP36 is likely more accurate than the off-the-shelf, made-in-asia thermometer I bought yesterday - it just doesn't look as pretty.  Do you agree?

You note that the code does not include some adjustment (tweaking) value like 0.1074 or whatever.  I am thinking that, it the derived temperature is right at 0 C and (about) 100 C it should be correct in between.  Do you agree?

Cheers
"Answers are easy;
               it's asking the right questions
                                                      which is hard."
 The Doctor (Dr Who: The Face of Evil (1977))

Wawa

#22
Jan 14, 2018, 09:16 am Last Edit: Jan 14, 2018, 09:18 am by Wawa
The breadboard and the UNO are wired to have common ground.  My knowledge of electronics is virtually nil, but I was thinking that such wiring would eliminate any difference.
But the USB connector is connected to a laptop or PC that might be connected to mains power ground.
Same for the breadboard supply. Mains ground could be a second ground path.
A clean ground between sensor and Arduino might be more important than a clean 3.3volt supply.

You can check if sensor output voltage and Arduino temp readout matches, with a DMM set to 2volt DC.
750mV is 25C, and every degree is 10mV difference.
You rely on factory calibration of the TMP36 (+/- 0.5C) if you calibrate your sketch this way.

I hope you still remember the last line of post#9.
Leo..

vagulus

But the USB connector is connected to a laptop or PC that might be connected to mains power ground.
Same for the breadboard supply. Mains ground could be a second ground path.
A clean ground between sensor and Arduino might be more important than a clean 3.3volt supply.
This is where my understanding of electronics caves in!  >:(   Surely everything goes back to Earth (i.e. the planet) in the end.  Both the Red Wing and the UNO have power supplies earthed to Earth, and they are commonly linked earth to earth.  I don't understand what you mean by a clean ground between sensor and Arduino much less a second ground path.

Are you saying to avoid more than one mains power input.  Since I need the setup connected to my PC so I can record the readings this would mean powering the whole system from USB via the UNO.  I had a nasty experience relating to relying on the UNO power outputs - they can fluctuate under the load of driving one LED!  That's why I went to the Red Wing - it may be out a little bit but it is steady at 3.27 V.

BTW: my DMM gives me Vout from the TMP36 as 0.740-0.750 V.
(0.750 - 0.5) * 100 = 25 degrees Celsius.  The temperature here at the moment is 29.2 Celsius.

I'm getting confusder and confusder  :-\
I'll knock off, have dinner, and sleep on it.  I'll get back to it in the morning.

I hope you still remember the last line of post#9.
Yes.  If at first you don't succeed, get a better widget!  :)
"Answers are easy;
               it's asking the right questions
                                                      which is hard."
 The Doctor (Dr Who: The Face of Evil (1977))

vagulus

In Post #23 I wrote

Surely everything goes back to Earth (i.e. the planet) in the end.  Both the Red Wing and the UNO have power supplies earthed to Earth, and they are commonly linked earth to earth.  I don't understand what you mean by a clean ground between sensor and Arduino much less a second ground path.
Can someone please clarify this?  
I have always worked on the principle that an earth is an earth is an earth.  Have I been deluding myself all these years?
"Answers are easy;
               it's asking the right questions
                                                      which is hard."
 The Doctor (Dr Who: The Face of Evil (1977))

Wawa

I don't think I mentioned 'earth', only 'ground'.

Two ground paths can make a groundloop (Google it).
Leo..

vagulus

I Googled groundloop and, okay, this phenomenon exists, but there doesn't seem to be much you can do about it except be aware.

My background case for this experimentation is some sort of plant with sensors all over.  It would be impossible to supply Vin to all sensors from my UNO so they have to have an alternative (external) power supply.  That means that the sensors are grounded (:smiley-wink:) to their power supply and to the UNO.  The condition for possible groundloop exists.

What can I do about that?
"Answers are easy;
               it's asking the right questions
                                                      which is hard."
 The Doctor (Dr Who: The Face of Evil (1977))

Wawa

What can I do about that?
Analogue sensors are sensitive to ground voltage differences.
Switch to digital sensors.
Leo..

vagulus

#28
Jan 15, 2018, 03:44 am Last Edit: Jan 15, 2018, 03:45 am by vagulus
CHANGE OF APPROACH

+  I kept the external power supply to the sensor
+  I did not use AREF


In one of the iterations of this experiment I used analogReference(INTERNAL) which gives an analog reference point of 1.1 V.  This would require Vin to the TMP36 at 1.1 V also, and I don't have a power supply to do that.  My solution was to use analogReference(DEFAULT) which gives AREF ar 5.0 V.  This I can match with the Red Wings regulator.  This resulted in this setup

and this circuit


With the TMP36 in ice water the output from this code
Code: [Select]

/*
-- filename   : nonAREFtmp36reader.ino
--
-- purpose    : demonstrate the interpretation of data from a TMP36
--               temperature sensor
--
-- derivation : https://learn.adafruit.com/tmp36-temperature-sensor/using-a-temp-sensor
--            : correspondence on Arduino Forum
--            : http://forum.arduino.cc/index.php?topic=522128.new#new
--
-- version    : 0
--
-- date       : January 15, 2018
--
-- copyright  : this code is in the public domain
--
1234567890123456789012345678901234567890123456789012345678901234567890
_________1         2         3         4         5         6         7
*/

// general constants
//the analog socket to the TMP36's Vout
#define SENSOR_PIN A0
// debug info switch
#define DEBUG true
// define time between temperature checks
#define INTERVAL 900000


// general variables
// the analog reading from the sensor
int sensorInput;
// voltage
float voltage;
// temperature in Celsius
float temperatureC;
// temperature in Fahreinheit
float temperatureF;


/*==========================================*/


void setup()
{
 // send debugging information via the Serial monitor
 Serial.begin(9600);

 // tell 'em who we are, man!
 Serial.println("nonAREFtmp36reader.ino");
 Serial.println();

 // initialize for output to PLX-DAQ
 if (!DEBUG)
 {
 Serial.println("CLEARDATA");
 Serial.println
 ("LABEL,Current Time,Raw Data,Voltage,Celsius,Fahreinheit");
 }

 // set the aref to something other than the UNO
 analogReference(DEFAULT);
}  // end setup()


/*==========================================*/


void loop()
{
 // zero sensorInput
 sensorInput = 0;

 // get averaged reading from the sensor
 //  and show it
 for (int count = 0; count <= 31; count++)
 {
 delay(50);
 sensorInput += analogRead(SENSOR_PIN);
 }
 sensorInput /= 32;
 if (DEBUG)
 {
 Serial.print("Sensor Input = ");
 Serial.print(sensorInput);
 }


 // convert that reading to voltage, which is based on
 //  the reference voltage
 //  and show it
 voltage = (sensorInput * 5.0 / 1024.0);
 if (DEBUG)
 {
 Serial.print(" which equates to ");
 Serial.print(voltage, 4);
 Serial.println(" volts");
 }


 // convert from 10 mv per degree with offset
 //  and show it
 temperatureC = (voltage - 0.5) * 100;
 if (DEBUG)
 {
 Serial.print(temperatureC, 1);
 Serial.println(" degrees C");
 }


 // convert to Fahrenheit
 //  and show it
 temperatureF = (temperatureC * 9.0 / 5.0) + 32.0;
 if (DEBUG)
 {
 Serial.print(temperatureF, 1);
 Serial.println(" degrees F");
 Serial.println();
 //Serial.println();
 }


 // export the data to PLX-DAQ
 if (!DEBUG)
 {
 Serial.print("DATA,TIME,");
 Serial.print(sensorInput);
 Serial.print(',');
 Serial.print(voltage, 4);
 Serial.print(',');
 Serial.print(temperatureC, 1);
 Serial.print(',');
 Serial.println(temperatureF, 1);
 }


 // take a breather
 if (DEBUG)
 {
 delay(3000);
 }
 else
 {
 delay(INTERVAL);
 }
}

was
Code: [Select]

Sensor Input = 103 which equates to 0.5029 volts
0.3 degrees C
32.5 degrees F

Sensor Input = 104 which equates to 0.5078 volts
0.8 degrees C
33.4 degrees F

Sensor Input = 103 which equates to 0.5029 volts
0.3 degrees C
32.5 degrees F

Sensor Input = 102 which equates to 0.4980 volts
-0.2 degrees C
31.6 degrees F

Sensor Input = 102 which equates to 0.4980 volts
-0.2 degrees C
31.6 degrees F

Sensor Input = 102 which equates to 0.4980 volts
-0.2 degrees C
31.6 degrees F

Sensor Input = 103 which equates to 0.5029 volts
0.3 degrees C
32.5 degrees F

Sensor Input = 104 which equates to 0.5078 volts
0.8 degrees C
33.4 degrees F

Sensor Input = 103 which equates to 0.5029 volts
0.3 degrees C
32.5 degrees F

Sensor Input = 102 which equates to 0.4980 volts
-0.2 degrees C
31.6 degrees F

Sensor Input = 103 which equates to 0.5029 volts
0.3 degrees C
32.5 degrees F

Sensor Input = 103 which equates to 0.5029 volts
0.3 degrees C
32.5 degrees F


which is within the accuracy range given in the TMP36 Datasheet (+/- 2 C).  I tried creating an adjustment factor but there was no improvement in accuracy.

It might seem, after all this time, that a lot of time and effort was wasted.  After all, this solution is a simple plug-and-play solution.  I don't think it was wasted.  I learnt a lot, which was the real object of the exercise.

My thanks to Wawa and others who contributed.  Your efforts are much appreciated.
"Answers are easy;
               it's asking the right questions
                                                      which is hard."
 The Doctor (Dr Who: The Face of Evil (1977))

Wawa

#29
Jan 15, 2018, 05:44 am Last Edit: Jan 15, 2018, 05:50 am by Wawa
In one of the iterations of this experiment I used analogReference(INTERNAL) which gives an analog reference point of 1.1 V.

This would require Vin to the TMP36 at 1.1 V also, and I don't have a power supply to do that.
1) Yes, told you that would give a higher (0.1C) resolution.

2) No... You POWER the sensor with 3.3volt or 5volt, and it outputs a voltage according to the temp.
It is better to POWER the sensor with the potentially cleaner 3.3volt from the Arduino than 5volt from the Arduino. This was mentioned in the comments of the sketch I gave you in post#5.

But I'm glad you have it working. Powering the sensor from the breadboard supply is just not needed.
Leo..

Go Up