4x Multiplexed RTD Temperature sensor module
Updated 30 Nov 2010 : Trystan Lea
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.
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.
RTD Input stage
3x PT1000 RTD Temperature sensors.
3x 10k resistors
3x 100uF capacitors
1x CD4052 Multiplexer
1x LM324 opamp
1x 100k resistor
1x 10k potentiometer
2x 10k resistor
2x 56k resistors
1x 220k resistor
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
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.
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.
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.
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
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:
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?
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