Solar 0 W
Voltage: 0 V
Current: 0 A
Peak today: 46 W
Load 6 W
Inverter: On
Current: 0.5 A
Peak today: 34 W
Battery voltage: 11.96 V
Discharging at 0.5 A
9%
Generated this week: 0.61 KwH Generated last week: 1.58 KwH Used this week: 1.21 KwH Used last week: 2.17 KwH More ▼
Last updated 23:08:20
Graph:

Summary



This project started some time ago when I became interested in renewable energy and built a wind turbine, and since then has evolved into a self-sufficient solar energy system, reporting real energy data to the internet using a Raspberry Pi. The generator inside the 24 foot wind turbine itself was frequently problematic and so it is not currently generating. Instead, the system is currently comprised of 400 watts of solar power, which charge 2 x 24 amp-hour batteries during the day. These power the entire LED lighting fixtures inside the house throughout the night.

In the present summer months, the lights, inverter and Raspberry Pi consume approximately 380 watt-hours per day. The batteries, at full health and capacity, provide approximately 580 watt-hours. This is adequate for the current season, but come winter it is likely I shall have to improve the capacity and add more solar.

Although the system is relatively low power, the project as a whole has been a fantastic learning opportunity, and I hope that anyone fascinated by do-it-yourself renewable energy systems find the details here of great interest. My long term plan is to acquire at least 1Kw of solar panels, and perhaps have the excess energy redirected to an immersion heater when the batteries are charged. You'll find that almost everything was acquired on Ebay, and where possible I have included a price and a link to each piece of equipment required, as well as any useful web resources and source codes.

Generating power



At present, the system is powered by 4 x 100w monocrystalline solar panels. They are wired in pairs to achieve 40 volts at 10 amps (peak). The panels are located on the south side of the garage roof, bolted to the roof in a way that allows them to pivot. I intend to adjust the angle of the panels at least twice a year.



4 x 100w monocrystalline solar panels: £320 Link

Charging batteries



From the solar panels, the cable arrives at a board on which all of the electrical equipment is mounted. A 20 amp rotary switch seperates the solar panel from the charge controller and is used to cut the power whenever maintenance is required.

After experimenting with some of the cheaper charge controllers and project kits, I eventually decided that I should invest in something a bit more fancy if I wanted to preserve the health of the batteries and have a reliable system. I discovered the MPPT Tracer charge controllers by EpSolar, an affordable but fantastic product that suited my requirements and more. I was specifically excited to learn that these charge controllers have a communication port, which has made the real-time data monitoring aspect much easier than first envisaged. More information on this can be found below.

The battery bank currently consists of 2 x Ritar 12v 24ah lead acid batteries wired in parallel. These batteries were hooked up to a home made wind turbine with a shunt regulator for a while, but the turbine was problematic and as a result the batteries sat for a year being insufficiently charged. Because of this, their capacity isn't too great (which is why you'll see in the above graph that they struggle to sit above 13v on their own). Nonetheless, their capacity is sufficient in the summer months, but come winter they could do with being replaced.

The charge controller uses an MPPT charging algorith to track to best power point of the solar panels. During the bulk charge phase (when the sun comes up and the batteries are low) the charge controller converts the 40 volts from the solar panels into as many amps as possible. Once the batteries have reached the configured voltage of 14.6, they remain at this voltage (the constant charge phase) and draw less current as they become more charged. When the charge controller reaches its float charging phase, the batteries are kept at 13.8 volts until the sun goes down.



2 x Ritar 24ah lead acid batteries: £72 Link
Tracer2210A charge controller: £70 Link

Using the power



Connected to the load output of the charge controller is a 300w pure sine wave inverter, which converts the 12v DC from the batteries into 220v AC. From this the power goes onto a 4-way socket.

Inbetween the inverter and the 4 sockets is a backup relay which switches the sockets to mains power should the inverter ever fail or the batteries run flat. This is a simple DPDT 230v relay that I wired according to a simple guide at REUK.

Plugged into one of the 4 sockets is a cable that goes back towards the house, into the roof, and to the lighting circuit for the entire house. The backup relay ensures the sockets are always live, so the lights in the house never go out!

In order to be able to power all of the lights from just a 300w inverter, all the bulbs, 28 in total, have been replaced with low power LEDs. This reduced the overall power required for the lights from 1.3Kw to just 115w, a 91% reduction!



300w pure sine wave inverter: £60 Link
28 x LED SES, ES, GU10 bulbs: £40 Link
230v DPDT relay and enclosure: £9 Link

Getting real-time data



Fitted inside an enclosure is a Raspberry Pi Model B (the credit card sized computer) running Linux (Raspbian Jessie Lite 4.4). It is powered by the inverter itself with a 5v adapter and has internet access via an ethernet cable coming from the router in the house. There's no screen or keyboard attached to the Raspberry Pi, but instead it is accessed over the network via SSH, with a client such as puTTY. I am also able to access it from outside of the network using a Dynamic DNS service. These are easy to set up providing you have a router that supports one of these services. Remote SSH access is useful, because it means I can reboot or make changes to the datalogging program from any location.

The EpSolar Tracer2210A charge controller (including their BN range) has an RJ45 port which can be used to connect an optional monitor, or to Windows monitoring software. I was able to make the Raspberry Pi communicate with the charge controller using the pymodbus library and a cheap USB to RS485 adapter.

The program I have written (source) continually requests data from the charge controller (solar voltage, solar current, battery voltage, charge current) and posts them to a web address using the urllib2 library. The PHP webpage, hosted on my web server (source) checks the data, calculates the power being generated/consumed in watts, and inserts it into a MySQL database. This is repeated around the clock approximately 8 times per minute.

The minimal amount of code needed for retrieving data from a Tracer charge controller can be seen below. Please see the modbus protocol for a full list of registers.

					from pymodbus.client.sync import ModbusSerialClient as ModbusClient
					
					client = ModbusClient(method = 'rtu', port = '/dev/ttyUSB0', baudrate = 115200)
					client.connect()
					
					result = client.read_input_registers(0x3100,6,unit=1)
					solarVoltage = float(result.registers[0] / 100.0)
					solarCurrent = float(result.registers[1] / 100.0)
					batteryVoltage = float(result.registers[4] / 100.0)
					chargeCurrent = float(result.registers[5] / 100.0)
					
					# Do something with the data
					
					client.close()
As well as requesting data from the charge controller, my Raspberry Pi senses the load current manually using a 30 amp current sensor and an ADC (analog to digital converter). This was necessary because the load current data given by the charge controller itself was very eratic, which made it difficult to calculate power accurately. I can only assume this is because the Tracer was not designed to power a pure sinewave inverter directly. The current sensor connects to the ADC of the Raspberry Pi using 3 wires: 5v, ground, and signal. The signal wire connects to one of the analog inputs of the ADC, and the voltage received at that pin (between 2.5 and 5 volts) is used to determine the current flowing through the sensor (from 0 to 30 amps). This is achieved by mapping the analog reading (2.5 - 5v) to the known current range (0 - 30a)

If you wish to use an ADC to detect current, below is the minimal amount of code needed:

					from ABE_ADCPi import ADCPi
					from ABE_helpers import ABEHelpers
					
					def map(x, in_min, in_max, out_min, out_max):
						return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
						
					i2c_helper = ABEHelpers()
					bus = i2c_helper.get_smbus()
					adc = ADCPi(bus, 0x68, 0x69, 14)
					adc.set_conversion_mode(1)
					inputPin = 6
					
					# The below values were calibrated for my sensor
					inMin = 2.485
					inMax = 2.7
					outMin = 0.26
					outMax = 3.63
					
					loadCurrent = round(map(adc.read_voltage(inputPin), inMin, inMax, outMin, outMax), 1)
The input-output variables for this function need to be calibrated in each individual application, for the output of the sensors can vary somewhat due to temperature, nearby interference, cable resistance, etc. I calibrated this current sensor by observing its output whilst comparing it to the current reading on a multimeter.

Handling errors and connection loss



One of the more difficult (and ongoing) tasks is ensuring the datalogger is always running. There is always the possibility of the Raspberry Pi crashing, or the internet dropping. Below is a list of problems I encountered, and the solution I have implemented to reduce the effect:


Raspberry Pi Model B: £30 Link
Analog to Digital Converter: £15 Link
30cm x 20cm enclosure: £17 Link
30 amp current sensor: £4 Link
USB to RS485 Adapter: £3 Link

Displaying the data



The data at the top of this page is updated using an ajax request. Every few seconds, the script calls upon a PHP page (readings.php). This page retrieves the most recently added data from the database, and prints that data in JSON format. See the source to see how. The javascript in this page then interprets the individual pieces of data, and updates the appropriate parts of the webpage instantly.

Since the database is constantly being updated, the precise status of the system can be examined at any moment, as far back as the beginning. The graphs above are generated in real-time with a PHP library called jpgraph.

With the past data in the database, it is possible to calculate the Kilowatt-Hours generated/consumed over a period of time. To do this, a script (source) is ran every hour to examine the previous hour's data and calculate the energy generated/consumed in KwH. The script gets all of the power data from within an hour (solar watts, load watts) and splits them up into their corresponding minutes. It looks at each peice of data received within that minute (usually about 4) and takes an average. That average is divided by 60 (because it is a 60th of an hour) and then divided by 1000 (because we're calculating Kilowatts). After doing this for each minute of the hour, the final step is adding up all of those minutes, and the result is the KwH generated/consumed in that hour. This figure is then added into a seperate database just for energy per hour.

If all this has confused you, consider the following. Suppose the solar panels generated 20 watts for a whole hour. Each minute of that hour, they would have generated 0.0033 KwH -

    (20 / 60) / 1000 = 0.0033 KwH

In this scenario, each minute is the same, so we can multiply that by 60 to get the actual KwH -

    0.0033 * 60 = 0.198 KwH

Because the power readings are always changing, I take the closest average (solar watts, load watts) of each individual minute, and then add the minutes all up. These very calculations are done in this script. With all of the KwH calculations stored in the database, I can then use a MySQL query to determine how much energy has been produced over a certain period. This is precisely how the KwH information is obtained and displayed at the top of this page.

Webcam



The webcam was perhaps the easiest feature to implement. The Raspberry Pi comes with a camera port, so I just had to purchase a camera and a long enough ribbon cable, and fit it in a weatherproof enclosure. The camera fitted easily inside an 85x58x35mm transparent enclosure (image). I cut away a small amount of plastic for the ribbon cable to fit through, and made it waterproof with some sealant before screwing on the cover. The enclosure is attached to a simple bracket made out of two peices of angle aluminium, which is secured to some existing bolts on the roof of the garage (image). The ribbon cable, protected from the weather inside a rubber sleeve, comes down through a gap in the roof and connects to the Raspberry Pi.

A seperate python script is set to run every few minutes as a cron job, which takes an image and posts it to a PHP page on my web server. The minimum amount of code needed to achieve this can be seen below:

					import picamera
					import requests
					import time

					image = 'webcam.jpg'
					url = 'http://www.solarpoweredhome.co.uk/webcam.php'
					headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.52 Safari/536.5'}
					
					camera = picamera.PiCamera()
					time.sleep(2)
					camera.capture(image)
					camera.close()
					
					files = {'file': open(image, 'rb')}
					r = requests.post(url, files=files, headers=headers)

In the root cron table of the Raspberry Pi (sudo crontab -e), the following line is added to run the script every 5 minutes, in daylight hours only:

					*/5 4-22 * * * /usr/bin/python /home/pi/solar/croncamera.py

The PHP script that saves the posted image on the web server is also very simple:

					print_r($_FILES);
					$temp = $_FILES["file"]["tmp_name"];
					print move_uploaded_file($temp,"webcam.jpg");

With the image being updated on the server every few minutes, all that is left to do is update them automatically on the webpage. This is achieved by setting an interval with javascript to update the image source:
					setInterval(function(){
						$("#webcam").attr("src","webcam.jpg?" + new Date().getTime());
					},300000);