Solar 0 W
Voltage: 14.38 V
Current: 0 A
Peak today: 216 W
Load 0 W
Inverter: Off
Current: 0 A
Peak today: 103 W
Battery voltage: 13.27 V

100%
Generated this week: 1.28 KwH Generated last week: 2.84 KwH Used this week: 0.62 KwH Used last week: 2.43 KwH More ▼
Last updated 20:12:24
Graph:

Now

20:00

19:00

18:00

17:00

16:00

15:00

14:00

13:00

12:00

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 110 amp-hour batteries during the day. These power the entire LED lighting fixtures inside the house 24 / 7.

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 the garage roof, bolted into brackets in a way that allows them to pivot. They are currently raised approximately 40 degrees which is a suitable angle for both the winter and summer months.



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 12v 110ah lead acid leisure batteries wired in parallel. The charge controller uses an MPPT charging algorithm 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.4, 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.

After some research, I learned that it was advisable not to let the batteries fall below a 50% state of charge. In light of this, the controller has been set to cut power to the inverter once the batteries reach 12.1v.



2 x 110ah lead acid leisure batteries: £140 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 230v 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 to light the house from 1.3Kw to just 115w, a 91% reduction!



Mercury 300w pure sine wave inverter: £70 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 batteries with a 12-5v USB 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.

I used one of these USB to RS485 adapters. After cutting the end from an old ethernet cable, I attached the blue and blue-white wires to the adapter (RJ45 pins 4 and 5).



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.

* After experiencing persistent issues with the current sensor I am now taking load current directly from the charge controller until I can find a better way. If you've figured out how to measure DC current accurately with a Raspberry Pi, please let me know!

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);