4x Multiplexed RTD Temperature sensor module

Updated 30 Nov 2010 : Trystan Lea

Description

This module can be used to measure temperature using RTD (resistive temperature detectors) temperature sensors.

It produces an analog voltage that is proportional the temperature of the probe.

The module contains a multiplexer to enable measurement of up to 4 temperature probes.

Design

RTD Temperature sensors change their resistance with temperature. The resistance change is converted to a voltage change with a simple voltage divider. The output of which passes through a low pass filter to remove any unwanted high frequency noise components.

In order to use only one amplifier circuit and one arduino analog input the temperature sensing input stages are selected sequentially using a multiplexer.

The difference amplifier then takes the output voltage of the selected input stage and converts it to a voltage that uses the full range of the arduino analog input maximizing accuracy.

Component list

RTD Input stage

3x PT1000 RTD Temperature sensors.

3x 10k resistors

3x 100uF capacitors

Multiplexer stage

1x CD4052 Multiplexer

Amplifier stage

1x LM324 opamp

1x 100k resistor

1x 10k potentiometer

2x 10k resistor

2x 56k resistors

1x 220k resistor

Circuit schematic

Download png : kiCad

Detailed design

Temperature sensing

RTD Temperature sensor

The RTD sensors I'm using are PT1000 sensors: their resistance is 1000ohms at 0C, another popular value is the PT100 which is 100ohms at 0C, the setup here can be easily modified for PT100's just change the 10k resistor on the input stage voltage divider for a 1k resistor.

RTD temperature sensors have a fairly linear increase in resistance to temperature increase (although not completely). The temperature at a given resistance is given by a look-up table:

PT1000 resistance table

C Ohms

C Ohms
-10 961   55 1213
-5 980   60 1232
0 1000   65 1252
5 1019   70 1271
10 1039   75 1290
15 1058   80 1309
20 1078   85 1328
25 1097   9 1347
30 1117   95 1366
35 1136   100 1385
40 1155   105 1404
45 1175   110 1423
50 1194   115 1442

The changing resistance of the RTD can be converted into a changing voltage by placing the RTD in a simple voltage divider circuit with a constant voltage source and then measuring the voltage across the RTD. As in the following schematic:

The resistance of the RTD can be found from the output voltage of the voltage divider by the following equation:

RTD Resistance = Vout *R / (Vcc - Vout)    rearranged for   Vout = Vcc*RTD / (RTD + R)

The considerations when choosing R are:

  • Increasing R minimizes self heating of the RTD: minimizing error.
  • Increasing R decreases the magnitude of the voltage change per degree: decreasing signal to noise ratio.
  • Increasing R increases noise caused by the resistors: decreasing the signal to noise ratio.

So to choose R we need to balance these considerations. I decided to go with a 10k resistor.

With a supply voltage of 5V and R =10k, the voltage out at -10C will be 0.438V and at 115C will be 0.630V. This voltage can be measured straight by the Arduino analog inputs, however with default settings the accuracy will not be great. The arduino ADC with the default ADC reference voltage of 5V divides 0 to 5V in to 1023 divisions, 0.438V to 0.630V therefore has 39 divisions and 125C range divided by 39 is equal to an accuracy of about 3.2C. However by using the full Arduino ADC range we can do much better, the best accuracy achievable would be 125C / 1023 = 0.122C.

To use the full range of the ADC the voltage output from the temperature measurement circuit needs to be 0V at -10C and the arduino ADC reference voltage (what ever it is set too) at 115C.

Obtaining 0V at minimum temperature

The voltage at -10C is 0.438V so a circuit is needed to subtract 0.438V from the voltage output of the RTD input stage. This can be done with a difference amplifier.

The difference amplifier

The voltage output of the difference amplifier above is given by the following equation:

From the equation we can see that if V1 is set to be 0.438V and V2 to be the output of the RTD input stage then at -10C (V2 = 0.438V) the output of the difference amplifier will be 0V. 

A fixed V1 can be obtained with a voltage divider and a voltage follower to prevent the amplifier circuit from loading the voltage divider in a way that changes the desired fixed voltage. The output of the RTD input stage also needs a voltage follower for the same reason.

Matching maximum voltage out with arduino ADC reference voltage

With no amplification from the amplifier the voltage at 115C will be 0.630V - 0.438V = 0.192V. The Arduino ADC reference voltage could be set to 0.192V with a simple voltage divider, giving full accuracy. Or alternatively it could be amplified to match the internal ADC reference voltage:

1.1V Internal ADC reference voltage

The default internal ADC reference voltage is 5V. However many amplifiers will not amplify up to their supply voltage. I'm using the LM324 opamp which has a maximum output voltage of its supply: 5V - 1.5V = 3.5V and so 1.5V of the ADC range would be wasted if the ADC reference voltage was set to 5V. The ADC reference voltage could be set to 3.5V, however this would require the added reference voltage voltage divider. Luckily the Arduino has a 1.1V internal ADC reference voltage that can be selected from the arduino sketch and so using this reference voltage along with amplification of the 0.192V signal to 1.1V the maximum voltage out can be matched with the ADC reference voltage without the need for extra components.

Amplification

Amplifying 0.192V to 1.1V requires a gain of 5.7 times. The gain of the difference amplifier is given by RB / RA, and the main considerations when choosing RB and RA are:

  • RB / RA needs to be equal or as close to 5.7 as possible.
  • Larger magnitude resistors increases noise.
  • Larger magnitude resistors decreases power consumption.

Again here it is a matter of balance between noise and power consumption. I tried a combination of different resistors here: 100k / 560k, 10k / 56k and 1k / 5.6k. The noise when't down noticably from 100k to 10k but not noticably lower at 1k and so I decided to go with RA=10k and RB=56k.

Multiplexer

In order to save the effort and cost of building multiple amplifier circuits one for each RTD sensor a multiplexer can be used to select each sensor sequentially allowing 4 sensors to share one opamp. The multiplexer I used is a 4052 chip. The inputs can be selected with two digital control lines A and B.

A B Input pin
0 0 1 (0y)
1 0 5 (1y)
0 1 2 (2y)
1 1 4 (3y)

Low pass filter

The RTD sensors leads are often quite long and may span across the house, they act like arials, soaking up a lot of electromagnetic waves, which adds a lot of noise to the voltage signal coming in to the temperature sensing circuit. To get rid of this noise a capacitor can be connected in parallel with the RTD sensor. The capacitor acts as a low pass filter. I found a 100uF capacitor to be effective enough at getting rid of most of the noise.

220k output resistor

On an off chance while experimenting with reducing noise in the circuit, I tried adding a resistor on the output of the amplifier, interestingly the noise almost halved with resistances around the 100-220k range. Below 100k and above around 470k the noise would increase. The datasheet for the Atmel 328 states that the output impedance of circuits connected to the analog inputs should be 10k or less, so this doesn't quite add up, at the moment I'm not quite sure why this works but it does reduce noise significantly. The datasheet does state that the time for an analog read increases with higher impedance, so maybe it is some kind of averaging affect over the read time...?

Connecting the module to the Arduino

connection diagram

The example Arduino sketch below reads in the temperatures of the RTD sensors and prints out the temperatures to serial for logging. The RTD temperature sensor library hopefully makes the main sketch less cluttered. For example to get the temperature of the collector sensor:

temperature = sensorName.getTemperature();

Download RTDsensor library: RTDSensorLib.tar.gz 

Download the Arduino sketch: RTDModuleExample.tar.gz

Browse software in repository : software repository

1) Copy the library to your Arduino/Libraries folder

2) Open the example sketch in the arduino IDE and reset the current calibration:

rtd.calibration(0, 0.120270927, -15.066198679);

needs to be

rtd.calibration(0, 1.0, 1.0);

(Thankyou to Justin for the observation)

3) compile+upload the Sketch to the Arduino.

If you now go to the Arduino Serial monitor you should see values outputed like so:

1023.0 1023.0 1023.0

At this point the program is not calibrated, the output corresponds to the ADC value. So to see temperature values the next step is:

Calibration

Calibrating the minimum

1) Choose the minimum temperature to be measured and find the resistance of the RTD at this temperature. For example if a minimum of -10C is chosen from the lookup table the resistance should be 960Ohms.

2) Holding the RTD at a certain temperature for calibration is quite a challenge so to make things easier create a resistor at your chosen minimum resistance. I found that the easiest way to do this is to use a variable resistor and a multimeter.

3) Connect up your 'minimum' resistance to one of the 3 RTD inputs. 

4) With the arduino connected to the computer, go to the arduino serial monitor and check what value is being printed.

5) Adjust the voltage offset variable resistor until this value is between say 10 and 40. Note down the value you have set it to and the corresponding minimum temperature that it correspond to. For example:

-10C corresponds to 30

Calibrating the maximum

While watching the arduino serial monitor, increase the resistance of the 'RTD' variable resistor on the input until the value on the serial monitor hits 1023. 

Measure the resistance at this point with a multimeter and find the corresponding temperature. If the temperature is not close to your desired maximum. Either change the gain of the opamp by changing resistor RA and RB or/and tweak the offset voltage divider. I'm afraid this is a bit of a fiddly calibration procedure.

Once you are happy with the maximum temperature and the minimum temperature note down the temperatures and serial output readouts, for example:

-10C corresponds to 30

115C corresponds to 1010

Using the equation for a straight line the calibration coeficients can now be found:

y = mx + c

-10 = m * 30 + c

115 = m * 1010 + c

m = (y1 - y2) / (x1 - x2)

m = (-10 - 115) / (30 - 1010) = 0.128

c = -10 - 0.128 * 30 = -13.84

Place these calibration coeficients in the arduino sketch, for example:

MultiplexedRTDSensor sensorName(2,4,5,0,0, m, c);

MultiplexedRTDSensor sensorName(2,4,5,0,0, 0.128, -13.84);

upload the new sketch to the Arduino. Hopefully now the output should be temperature in C. The calibration procedure is best repeated for each sensor to maximise accuracy, this time however none of the resistors should need changing.

With all that done the solar hot water controller should now be functional, try experimenting with the temperature differences that turn the pump on and off. Graphing can be done with KST and the standard deviation can be found with KST too which gives an indication of the noise present. I managed to get a standard deviation of about 0.03 - 0.07C and a resolution of about 0.13C.

Another thing to experiment with is using software based averaging and smoothing, the command:

temperature = sensorName.getTemperature(); 

can be replaced with: 

temperature = sensorName.getTemperatureSmooth(number of samples to average, number of averaged samples to smooth);

try temperature = sensorName.getTemperatureSmooth(100,4); 

Smoothing appears to increase the resolution significantly to below 0.1C but I'm not sure of the theory behind this, and so it would be a good thing to investigate further:

Further development questions

Im learning while doing this project so there are a few questions that I currently have that need further investigation, I have listed those below. I'm also sure there will be countless things I don't yet know about that will creep up and need further investigation, as these things are! :)

  • How acceptable and accurate is software based smoothing and averaging? what is the theory behind this?
  • Should calibration be done against the lookup table?
  • Exactly how accurate is it without lookup table calibration?

Further reading

Found a really good book on microcontroller based temperature measurement that I would definetly recommend. It has a great chapter on RTD temperature sensors and circuit suggestions, in addition to all the other type of temperature sensors.

MICROCONTROLLER-BASED TEMPERATURE MONITORING AND CONTROL by Dogan Ibrahim

José Machado's picture

Re: RTD temperature sensing

Hello
I am really a begginer regarding electronics.
Can you please direct me to somewhere where I can the connections to the chip itself ?
I cannot make the relation from the schmatics to the physical chip.
Thanks in advance and congrats for your project.
José from Portugal

manoncloud9's picture

Re: RTD temperature sensing

Please forgive me for such a silly question but as many others are new to this, so am I.  I've installed the IDE and downloaded the library and sketch for this project and when I try to compile it, I get the following:

RTDModuleExample.cpp: In function 'void setup()':

RTDModuleExample:31: error: 'INTERNAL' was not declared in this scope

The library (RTDModule) appears in the Sketch->Import Library menu and I've been able to compile other sketches without a problem.  Have I missed something in the setup?  I've installed the platform on both a Mac OSX and Windows machine and get the same results.  Any recommendations?

Thanks in advance for your patience and any assistance!

 

manoncloud9's picture

Re: RTD temperature sensing

OK... I thought I had researched the problem thoroughly before posting a question only to find the answer this morning.  I'm using the latest release of the development platform and found in the release notes the following:

Replacing INTERNAL analog reference with INTERNAL1V1 AND INTERNAL2V56 on
  the Arduino Mega.  http://code.google.com/p/arduino/issues/detail?id=194

I hope this helps anyone else that may run across the same issue.  Sorry for cluttering up this venue.
Esso Imo's picture

Re: RTD temperature sensing

What exactly is the permitted lenght for the wires to use 2-wire RTD configuration ?? (can't find the answer on the web)

and if it's too long, can't i compensate for it in the programming if i know the value of the error in readings ??

or should i just go ahead with the 3-wire configuration ??

TrystanLea's picture

Re: RTD temperature sensing

Im not entirely sure about this but I think it depends on your calibration method. If you'r calibrating through component values then you need to be able to take into account the resistance of the wires accurately if using 2-wires, with 3 wires its not so critical. My setup is 2-wire and I have lengths of +15m, I calibrated by sticking the RTD's in a pan of water that I knew the temperature of accurately and so could calibrate accordingly.

Guest's picture

Re: RTD temperature sensing

Please need some help.
When compiling the sketch I get the error "undefined reference to 'RTDModule::calibration(int, double, double)'.
Can you tell me what I am doing wrong?
Thanks
Bertus

TrystanLea's picture

Re: RTD temperature sensing

 Hello Bertus. Did you install the library and restart the arduino IDE?

Guest's picture

Re: RTD temperature sensing

Thank you TrystanLea.
Thank you for responding to my question.
I found my mistake. Like I said I am totally new and in figuring out how the pragrams work I copied the files for one directory to another quite a few times. I extracted them again and after pasting in their proper directories they work. my circuit is still not working but the sketch compiles and uploads. If I can ask another question, can you please tell me if its possible to modify this sketch to run directly from Processing because I am running my Arduino with Firmata so I can't upload the Arduino sketch without removing the Firmata sketch.

Marais's picture

Re: RTD temperature sensing

Hi, I'm a complete amateur when it comes to the circuit design. I want to build an Arduino circuit for temp sensing with the 3 wire configuration. I've looked around and found some circuits to drive the Pt100 sensor. The explanations note that the excitation current at the Pt100 should ideally be < 1mA to prevent self heating. What would the current be in your design (assume Pt100 and R=1K) if I use the 5V from USB that powers the Arduino as Vcc?

Could this circuit be adapted to a 3 wire design? The leads to the probe I must use is very long but its already set up as a 3 wire design.
I found this with a schematic for 3 wires (you probably know this already)
http://dev.emcelettronica.com/howto-measure-rtd-resistance-temperature-d...

Thanks