Solar hot water controller v1.0

A little more info on the blog post here too.

A brief introduction

In many solar hot water systems (systems that don't thermo-syphon) a pump is needed to circulate the water in between the solar hot water collector  (evacuated tube or flat plate) and the solar hot water cylinder resulting in the transfer of heat from the collector to the water in the hot water cylinder.

The pump must only turn on when the water in the collector is hotter than the water in the cylinder and so to control the pump a solar hot water controller is needed. The controller measures the temperature at the collector and the bottom of the solar hot water cylinder and when the temperature difference is more than a set amount (say 7-10C) it turns the circulating pump on transfering heat from the collector to the cylinder, when the temperature difference then drops to around (3C-5C) it turns the pump off.  

Left: the solar hot water collector, the temperature sensor is in the manifold.

Right: the solar hot water cylinder, the temperature sensor at the bottom is used to calculate the temperature difference with the collector.

We have a navitron solar hot water system installed on our house (see the pictures above). The installed controller was a DeltaSol BS3 which is a nice controller but it doesn't come with datalogging, a datalogging version is available but its another £150-190 and I fancied the challenge of building one myself, and doing so opens up some interesting possibilities with using the data. This page details version 1.0 of the design.

The main requirements for the build is that it:

Could be a direct replacement of the DeltaSol BS3  by:

  • using the same PT1000 RTD sensors used by the DeltaSol controller so that I could avoid rewiring the sensors.
  • having 3 RTD inputs one for the collector, one for the bottom of the hot water cylinder and one for the top of the hot water cylinder.
  • being able to witch on and off the 230V circulation pump.
  • give as acurate as possible temperature readings, the deltaSol controller gives an accuracy of around 0.1C. With the circuit below and the arduino 10 bit ADC it is not quite possible to do that. But software based averaging and smoothing does seem to improve things and bring it quite close... 

As well as the above it needs to be able to output temperature and pump state data so that it can be used to gain useful information. Data should be able to be logged out to serial and/or any combination of LCD displays, Ethernet and USB stick data logging...

An interesting aspect will be the possibility of sharing the same arduino for the solar hot water controller with the mains AC energy monitor, which both reduces the cost compared with buying each one separately

and also allows interesting things to be done with the data, like for a start tagging the energy monitor graph with pump on and off state.

Design 1.0

Picture: the solar water controller in its current breadboarded form.

The diagram below shows the main parts of the solar hot water controller. Temperature is measured with RTD sensors that 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 3 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. The Arduino analog input consisting of a 10bit ADC converts the analog voltage output of the difference amplifier in to the digital world were it is converted into a temperature value and used to control  the pump relay and give useful information.

Component list

1x Arduino

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

Pump control stage

1x 5V Relay

1x 2N2222 transistor

1x 1N4004 diode

1x 10k resistor

Circuit schematic

Download: jpg : kicad

Detailed design

Temperature sensing

RTD Temperature sensor

RTD temperature sensors ( resistive temperature detectors) change their resistance with temperature. 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. 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 3 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 most effective at getting rid of most of the noise.

Pump relay circuit

The solar hot water circulation pump requires: 230V. There are 5V relays available that can run straight off the Arduino and switch 230V. I followed the circuit on the arduino website here: relays.pdf

Running the 5V relay off the arduino can cause interference with the temperature sensing circuit, I get a 0.05-0.1C temperature shift when the relay switches on and off. When I first built the circuit the shift was around 1.5C by cleaning up the circuit layout and making sure the ground path is really good I managed to reduce the interference to 0.05-0.1C, which is still a pain but is acceptable for me at the moment. The interference can be removed completely (as far as I can tell) by powering the relay off a seperate power supply but this adds complexity and extra components. One thing I haven't tried yet is powering the RTD voltage divider off the 3.3V supply on the arduino, which may have the same effect as powering the relay off a seperate supply. I will update once I get a chance to try it out.

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...?

That I think completes the hardware side of things, now on to:

Software

The Arduino sketch reads in the temperatures of the RTD sensors, controls the pump, and prints out the temperatures to serial for logging. I've created a RTD temperature sensor library to hopefully make the make the main sketch less cluttered. For example to get the temperature of the collector sensor:

COL = collector.getTemperature();

Download RTDsensor library: RTDSensor.tar.gz

Download the Arduino sketch: SolarSketch.tar.gz

Copy the library to your Arduino/Libraries folder and 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 collector(2,4,5,0,0, m, c);

MultiplexedRTDSensor collector(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:

COL = collector.getTemperature(); 

can be replaced with: 

COL = collector.getTemperatureSmooth(number of samples to average, number of averaged samples to smooth);

try COL = collector.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:

Example graph of collector and cylinder bottom temperature (kst), it was a sunny day :)

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! :)

  • What is the role of ground path in causing output jumps from the relay?
  • How acceptable and accurate is software based smoothing and averaging? what is the theory behind this?
  • How can the effect of the relay on temperature readings be minimized?
  • Should calibration be done against the lookup table?
  • Exactly how accurate is it without lookup table calibration?

Safety

Arduino sketck needs to be changed to include a check for when the cylinder reaches a maximum temperature and then to turn the circulation pump off, to stop the solar collector from continuously adding more heat, the collector can reach temperatures of up to 250C. If the hot water cylinder is unvented, the cylinder can explode which needless to say very dangerous.

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