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) sensors.
It produces an analog voltage proportional to the probe temperature.
The module contains a multiplexer to enable using a maximum of four temperature probes.
RTD Temperature sensors change their resistance with temperature. The resistance change is converted to a voltage by a simple voltage divider. The output voltage 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 by a multiplexer.
Accuracy is maximized by using a difference amplifier to scale the output to the full range of the Arduino analog input.
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 type PT1000. Their resistance is 1000ohms at 0C. Another popular value is the PT100 which is 100ohms at 0C. The setup here can easily be modified for PT100's by changing the 10k resistor on the input stage voltage divider to a 1k resistor.
RTD temperature sensors have a fairly linear increase in resistance as their temperature increases (although not completely). The temperature at a given resistance is determined by a look-up table:
PT1000 resistance table
The changing resistance of the RTD can be converted to a voltage by placing the RTD in a simple voltage divider circuit with a constant voltage source and 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, thus 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 use 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 directly 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 to) 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: if V1 is set to 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. Using this reference voltage along with amplification of the 0.192V signal to 1.1V, the maximum voltage output 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, 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 went down noticeably from 100k to 10k but not noticeably lower at 1k, 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 sensor leads are often quite long and may act like aerials, which adds a lot of noise to the voltage signal coming in to the temperature sensing circuit. To get rid of the 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
By chance, while experimenting with reducing noise in the circuit, I tried adding a resistor on the output of the amplifier. Interestingly, the noise dropped by nearly 50% with resistances in the 100-220k range. Below 100k and above 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 make sense. At the moment, I'm not quite sure why this works but it does reduce the 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 the temperatures of the RTD sensors and prints the temperatures to the serial port 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);
(Thank you 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 three columns of values, 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 equal to your chosen minimum resistance. I found the easiest way to do this is to use a variable resistor and a multimeter.
3) Connect 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 the value being printed.
5) Adjust the voltage offset variable resistor until this value is between say 10 and 40. Note the value you have set it to and the corresponding minimum temperature that it corresponds 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 and/or tweak the offset voltage divider. I'm afraid this is a difficult calibration procedure.
Once you are happy with the maximum temperature and the minimum temperature note 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 coefficients 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 coefficients 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. The output should be temperature in degrees 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
I'm 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 that will creep up and need further investigation.
- 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 definitely recommend. It has a chapter on RTD temperature sensors and circuit suggestions in addition to other type of temperature sensors.
MICROCONTROLLER-BASED TEMPERATURE MONITORING AND CONTROL by Dogan Ibrahim