Solar Water heater
WORK IN PROGRESS

some more notes to aid my memory
- not likely of interest to others but -

please email me if you do similar


Background

I am interested in solar electric power. But I calculated that a photovoltaic system offered to me by a local company would only pay back my investment after 130 years!
And due to regulations you cannot have a home made mains connected system :-(

I built a solar water heater some years ago with old radiators painted black in glass fronted boxes.
It worked well but was hard to keep full. Eventually the wooden frame went rotten.
So I looked into pressurised loop solar tube systems - some kits were £1500, but I found one for £500 from here

It came with 20 tubes, controller, expansion vessel, pumping station - good quality components.
But the company is just an importer and cannot offer technical support - learn the technology elsewhere.
You also need an existing tank, some pipes and fittings, thermal paste and a non return valve after the pump.

Objectives
1) Just out of interest - monitor the solar water heating system tank temperatures and the solar light level and display the results as a graph on a web page and also on a graphical display in the kitchen Sweex router box.
2) For my old system I fitted two hot water tanks in series. The system as delivered works for just one tank.
So build a controller to switch the system between tanks so I can get two tanks of hot water and have enough water (in summer) to provide water for cloudy days.

Method
Build electronics that via an i2c (long line) bus can be controlled by a Sweex router or NSLU2 (Slug) etc.

Circuit notes
1) I want to detect when the as-delivered controller feeds mains voltage to the auxiliary electric water heater and the water pump.
A CMOS gate in a CD4050 detects mains as picked up via the capacitance between two wires of a 15cm length of twin mains cable.
Resistor R is adjusted to get the switching level right. The pulse train created is changed to logic levels to feed an input pin of a PCF8574 8 port i2c chip.

2) A pin of the PCF8574 is set as output to drive a relay to switch mains to a two way water valve that sets which tank receives the hot water from the roof.

3) LM75 i2c thermometers are positioned on the tanks and the solar tube manifold on the roof. These connect to the local SDA/SCL lines above.

4) The master controller detects the tank temperatures with NTC resistor thermometers. I sourced a similar one from Farnell
(B57861S0103F45: SENSOR, MINIATURE< NTC, 10K)
for the bottom of the second (feeder) tank. The relay above connects the appropriate thermometer to the master controller - (not shown).

5) The solar light level is measured using a PV panel within a cheap garden night light unit. The voltage is measured across a load resistor to give some measure of photon power - on no load the volts stay at 3V. It gives about 1 volt across 1Kohm.

Software
i2c drivers for a Slug

/*
PCF8574_addr_byteout--read_to_ramdisk_slug.c
--------------------------------------------
Send address and byte to switch/read lines on 8 line port of i2c bus PCF8574
----------------------------------------------------------------------------
Save result to ramdisk file
---------------------------

1) send the i2c address
2) send byte as decimal to set the 8 port lines on or off
3) read the line states and save in /var/www/ramdisk/PCF8574_port_byte.dat

example-
use port line 0 as output to control a relay
detect the states of the lines 1 to 7
send <i2c address-byte> <255 for line 0 HI>or<254 for line 0 LO>
the read will report the state of all the lines

usage :- type with spaces but without the < >
<PCF8574_addr_byteout--read_to_ramdisk_slug> <decimal address> <decimal byte out 0-255>

*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/i2c-dev.h>
#define I2C_SLAVE 0x0703 /* Change slave address */

int i2c;
char filename[20];
unsigned long address;

int rc;
unsigned char data[1];
int byte; /* the 8 bit byte that represents the data present on the 8 wire port */

int main(int argc, char *argv[])
{
if (argc != 3) { /* error if we are not getting just 2 inputs after the program name */
fprintf(stderr, "usage: %s <address> <databyte>\n",argv[0]);
exit(1);
}

/* address is the first number after the program name */
address = atoi(argv[1]);
/* the byte to send out to the PC8574 is the second number*/
data[0] = atoi(argv[2]);

i2c = open("/dev/i2c-0",O_RDWR); /* open the device dev/i2c-0 */

rc=ioctl(i2c,I2C_SLAVE,address); /* set the i2c chip address */

write(i2c,data,1) ; /* send the byte */

read(i2c,data,1); /* now data(0) contains the byte of data on the 8 port lines*/

byte = data[0];

// printf("%d", byte); ( not used in this program)
/* BYTE value is 0-256 - print no return character - just the byte)*/

//save port byte to ramdisk
FILE *f;
f = fopen("/var/www/ramdisk/PCF8574_port_byte.dat","w");
fprintf(f, "%d", byte);
fclose(f);

i2c = close(i2c);
return(0);
}


/*
PCF8591_address_channel_Vout-ramdisk_slug.c
------------------------------
read the voltage on one A/D lines (0-3) and set the output voltage on the D/A pin
---------------------------------------------------------------------------------

1) send the i2c address
2) choose channel 0-3
3) send byte for D/A out
4) read channel volts as 5 x (byte_received)/255)
usage :- type with spaces but without the < >
<PCF8591_address_readvolts> <address as decimal> <channel 0-3> <D/A value as decimal 0-255>
(even if the D/A pin is unused type in any value 0-255)
4) save decimal byte to /var/www/ramdisk/AtoD.dat
*/

#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/i2c-dev.h>
#define I2C_SLAVE 0x0703 /* Change slave address */

int i2c;
int channel; /* line number 0-3 */
int V_out; /* value for the D/A out line */
unsigned char buf[1]; /* use to feed the i2c driver */
unsigned long address; /* i2c bus address */
int byte_in_0; /* the 8 bit byte that represents the voltage on the AD_line */
int AD_input; /* volts byte on chosen channel */

int rc;

int main(int argc, char** argv)
{
if (argc != 4) /* report error if we are not getting just 3 inputs after the program name */
{
printf("Error. usage: %s i2c_chip_address channel_to_read D/A_Vout(0-255)\n", argv[0]);
}

address = atoi(argv[1]); /* decimal address is the first number after the program name */
channel = atoi(argv[2]); /* choose A to D line to read 0-3 */
V_out = atoi(argv[3]); /* volts out as decimal 0-255 */

i2c = open("/dev/i2c-0",O_RDWR); /* open the device dev/i2c-0 */
rc=ioctl(i2c,I2C_SLAVE,address); /* set the i2c chip address */

channel = channel + 64; /* control register - enable the D/A output */
buf[0] = channel; /* A/D input line number is the first data byte sent */
buf[1] = V_out; /* D/A out value is the second data byte sent */
write(i2c,buf,2); /* we send 2 bytes <control register> <D/A value> */
read(i2c,buf,1); /* buf(0) contains the byte of data in the chip cache */
usleep (1000); /* do it again */
read(i2c,buf,1); /* buf(0) now contains the byte of data from the most recent analogue input*/
AD_input = buf[0];

 

//printf("%d", AD_input);
/*AD_line_x goes 0 to 255 as voltage input goes from 0 to supply voltage*/

//save AtoD byte to ramdisk
FILE *f;
f = fopen("/var/www/ramdisk/AtoD.dat","w");
fprintf(f, "%d", buf[0]);
fclose(f);

i2c = close(i2c);
return(0);
}
/* Sunspot 091108 - (Google/copy/paste c code - thanks to sources) */

solar_display.bas

The Debian Slug monitors the solar heater thermometers using solar_display.bas
It acts to pull together various scripts and other Blassic basic programs.
It does the following in a loop and saves the data every 2 minutes ready for the webpage graphical report

Clear the 4x20LCD03 screen every 2 minutes after a data save.
Run LM75-Deb-slug (72 to 77) to save five LM75 thermometer values to the Slug ramdisk as T72.txt etc
Run the ash script wget_bee_count.sh to grab the byte stored in the file bee_count.dat stored in the Kitchen Sweex website.
- this is normally displayed on the bee activity 128x64 display in the kitchen.
Get the T72.txt values and display them on the Slug LCD03 using print_word.bas
See if the a key on the key pad has been pressed using LCD03_keyboard_get_key_once.bas
(you have to hold the key down till there is a response - The Slug speaks the result using espeak)
Key 1 = (switch solar hot water to feed-tank) | Key 2 = (main tank) | Key # = (close this program)
Run solar-set_tank-read_pump_heater_lightlevel.bas to switch the PCF8574 to switch the relay that connects the tank-bottom NTC thermometers to the main control unit and also turn the motorised water valve that switches the solar hot water to either tank.
The PCF8574 also reads the status of the solar pump and the immersion heater by detecting whether their mains leads are live.
port_5_status.txt holds the solar pump status and
port_6_status.txt holds the immersion heater status. They are numbers like 430 etc in readiness for the web plot - a "square wave" shows the on/off status of pump and heater.
Save comma delimited data every 2 minutes in /var/www/solar_data/datafile where data file is a name like 20091129solar
Also every 2 minutes run make_page.bas to create the graphical page using "Canvas" that is seen from the browser.

Display the data on a web page

 

Sunspot Home