How to connect a solar panel to a Raspberry Pi
Introduction
This tutorial will show you how to connect a Raspberry Pi to a small solar panel (cell) and get the measured voltage and current from that solar panel. Lastly I will briefly touch on how you can send this data to a website. This is not about charging or powering the Pi from the solar panel/cell.
I believe this is technically a solar cell but for the sake of this tutorial I’ll call it a solar panel.
Hardware requirements:
- Raspberry Pi
- Breadboard
- Some resistors
- Solar panel/cell
- ADC MCP3008
- Breadboard wire
Software requirements:
- Raspbian Stretch / other Raspberry Pi OS
- Python
Connect your Raspberry Pi to your home network
If you’re doing this with your Raspberry Pi connected to a monitor/keyboard/mouse then you can skip this part. You should be staring at a terminal. Skip to Setting up the Raspberry Pi
I am assuming that your Raspberry Pi is already connected to your local network (WiFi or Ethernet) so that you can access it remotely (SSH) to write commands.
I’m also assuming that you’re working with the Pi in a headless setup (no monitor/keyboard) but remotely accessing it by SSH.
Find your Raspberry Pi’s IP address
Depending on what your computer’s operating system is eg. Windows or Linux you will need to get to a terminal and use a specific command to scan your home network for connected devices. Then figure out which one is the Raspberry Pi.
You can eliminate your own computer by checking on the terminal by typing in ipconfig (for Windows) or ifconfig for Linux. The IP address(IPv4) you’re looking for starts with 192.
You can then try to connect to an ip using an SSH client like PuTTY on Windows or just the command line in Linux. By default the user is pi@ip-address and password is raspberry.
Analog to digital
Why can’t you just plug a solar panel directly into a Raspberry Pi? The Raspberry Pi has no analog GPIO pins unlike say an Arduino that has analog pins. So in order to connect the Raspberry Pi to an analog source like a solar panel’s voltage output, you need what is called an ADC (analog-to-digital converter). In this tutorial I’m using the MCP3008 which Adafruit wrote a great tutorial on.
Setting up the Raspberry Pi
There are a couple of things that you need to do in order for the Raspberry Pi to interface with the MCP3008.
Is Python installed on your Raspberry Pi?
Check by using the terminal. Type in:
python -V
You should see something like this with your version number.
If it’s not installed, install python using:
sudo apt-get install python
Update: 09/03/2020
Please note this MCP3008 library is deprecated however as of today it still works. The alternative is the Circuit Python library which I have not used.
Install the MCP3008 library from Adafruit — this tutorial uses the deprecated version
I’m using the first set of steps, I tried the pip method before and had problems.
sudo apt-get install git build-essential python-dev
cd ~
git clone https://github.com/adafruit/Adafruit_Python_MCP3008.git
cd Adafruit_Python_MCP3008
sudo python setup.py install
You can copy all of that and paste it into the terminal. I do it 1 line at a time.
After that is installed, you can then use Adafruit’s modules like simpletest.py to view the analog data being measured by the ADC in real time. We’ll come back to that after we wire the MCP3008 to the Raspberry Pi.
Connecting the Raspberry Pi to the MCP3008
The most important thing to figure out is the proper orientation of the Raspberry Pi’s GPIO pins so you don’t make the mistake of connecting to the wrong GPIO pins. Find a good GPIO pin out of a Raspberry Pi such as the one linked below.
https://www.jameco.com/Jameco/workshop/circuitnotes/raspberry_pi_circuit_note_fig2.jpg
Please note: pay attention to the pin out diagram. The numbers in the circle are not the GPIO pin numbers. These are just going from left to right top to bottom(when the GPIO pins are oriented vertically). The actual GPIO pin numbers are in the colored rectangles on the left/right sides of the circled numbers. For example: GPIO pin 18 is 6 pins from the left on the top row or it is circled-number 12.
First you’ll want to take your ADC and put in the middle of your bread board, so it’s separated in half as shown below:
The entire left side of the MCP3008 is for input (what you’re measuring) note that the top of the MCP3008 is the part that has the half-circle cutout.
Adafruit’s tutorial has a great image on the MCP3008’s pinout. I will create a wiring diagram and post it below. Please note: the MCP3008 pinout on Adafruit’s page does not match the Software SPI order from top to bottom. In particular after AGND, CLK should follow but is replaced with DGND. So focus on the MCP3008 pinout. I made sure to get this right on my own diagram below:
You should have something like this when you’re done:
I used wires to connect the Resistor to the board because to get to the low Ohm count, I would have to parallel wire a few large Ohm count resistors such as 220 Ohm or 100 Ohm eg. 4x 100 Ohm resistors in parallel equals 25 Ohms.
For ambient lighting (from a light bulb) you won’t get much power so you don’t want too low of a resistance (Ohms) I used a 1K Ohm resistor. Without this resistor the measured analog value is in the 700’s. For testing you don’t need the resistor but the load helps report a stable analog value. With that 1K Ohm resistor the 700-ish voltage value will drop to below 50.
With regard to the real sun, I personally have been using 25 Ohms (4x 100 Ohm resistors in parallel). The sun produces more power than a light bulb(obviously).
Getting the analog value from ADC to Raspberry Pi
With the wiring done. Navigate to the simpletest.py module that you downloaded(cloned) into your Raspberry Pi from the previous steps above.
On the terminal communicating between your computer and the Raspberry Pi you should be in the Adafruit_Python_MCP3008 directory.
If not you can get there by typing in:
cd ~/Adafruit_Python_MCP3008
Then you can navigate to the simpletest.py module which is in the /examples/ folder which is in the current folder (Adafruit_Python_MCP3008)
cd ~/Adafruit_Python_MCP3008/examples
Then you can run the simpletest.py module which outputs the measured values from the 8 channels. Notice since the other 7 values are not connected to anything they’re jumping all over the place.
Run the simpletest.py module by typing in:
python simpletest.py
You should see something like this appear: Channel 0 is the first pin(top left) on the MCP3008 which has the solar panel plugged into it. The solar panel is connected parallel to the 1K Ohm resistor as shown in the diagram above.
You can see in the Gif the values(for Channel 0 — left most column) they’re constant then will drop to 1 for a bit, then go back up again, that’s me putting my hand over the solar cell.
This sampling is a little slow it’s every half second.
Compute power (Volts times Amps)
First you should know that the analog values measured/displayed above are related to the reference voltage (VDD) which I set to 5V in my diagram.
You need to determine the multiplication variable that is based on the analog steps eg. 0 to 1023. Take the 5V reference voltage and divide it by 1024 this is your multiplication variable.
I’d say from the GIF above showing the live data, channel 0 was mostly in the 30’s. So we’ll say we measured 33 in analog from the ADC.
We multiply the 33 with the multiplication variable from 5V / 1024 = ~0.0049. So the measured voltage from the ADC of the solar panel is 33 * 0.0049 or ~0.16V
To calculate the power, you use the 1K Ohm resistance with the V = IR formual to get the current being produced by the solar panel.
0.16V = I * 1000
So the current I is ~ 0.00016A or 0.16mA
Here it is confirmed with the multimeter
Then with W = AV the power produced by the solar panel is ~ 0.0000256W or 0.0256mW
You can confirm the ADC-determined voltage as well. It won’t be an exact match but it should be close.
It’s pretty darn close! Granted the added load from the multimeter can change it to some degree, I can’t say exactly how much.
For reference you can measure the voltage being produced right now from ambient light with a multimeter (if you have one). You can see here that from the ambient light (a light bulb) the solar panel is producing ~3.6V of course this is probably almost no load, whatever the internal load is on the multimeter.
Grabbing the data programmatically and send to a web endpoint
So pretty much what you’ll do here is take parts from the simpletest.py script, primarily the imported dependencies, the SPI pin setup and the part to actually read the pin.
Then you can programmatically trigger this scripts say with a CRON job (scheduled event) and send it as a POST request to a server endpoint.
Here is a basic script based on simpletest.py that when executed grabs the measured voltage, computes current and power, then sends those values to a server endpoint.
For this part, you will need to install pip to install the requests module if you want to do this POST test, if you know how to write web endpoints/do this yourself then you don’t need to do this.
sudo apt-get install python-pip
pip install requests
You can create a file in the current folder that you’re in on the Raspberry Pi with:
touch grab-solar-data-send.py
Open that file with the nano editor using:
nano grab-solar-data-send.py
I made a gist of the code here. Copy all of this and paste it into the editor/command line editor(nano). Right-click in nano and paste.
Paste it into that file, and then run it using:
python grab-solar-data-send.py
You should see something like this:
Of course I didn’t trim the strings/round or anything like that.
Send to a server
For this optional example, I will use this website I found called postestserver, this is the second version. On this site you can create a test endpoint that will receive your post request.
Wow this is a cool service.
This is the post request code I used with Python.
requests.post(‘http://ptsv2.com/t/0436952175/post', data = { ‘analog_value’: analog_val, ‘computed_voltage’: computed_voltage, ‘computed_current’: computed_current, ‘computed_power’: computed_power})
You can see the received data form the POST request form the Raspberry Pi here:
And that’s it. Hope this is helpful.