DIY Solar Panel Monitoring System - V1.0

28,529

343

16

Introduction: DIY Solar Panel Monitoring System - V1.0

About: I am a DIY hobbyist by passion and Power Engineer by profession. Most of my works are related to Solar Energy and Arduino. Apart from Electronics I love 3D printing, Woodworking and to make crafts from used …

A few months back, I have installed a small-scale Off-Grid Solar System. I am always very curious to see the performance of my solar PV system, and the good news is that the charge controller that I am using has its own local display for monitoring. But, I am badly missing the remote monitoring facility. So, I have decided to make my own monitoring system which must have both local and remote monitoring facilities.

Why We Need Monitoring?

1. It gives clear information about various solar parameters, extracted energy, fault detection, historical analysis of the solar plant, and associated energy loss.

2. You can easily measure your solar production and the saving on your monthly electricity bill.

3. You can track all the important parameters of the solar PV system in real-time from your smartphone.

In this Instructables, I will show you I have made a simple Solar Monitoring System by using an ESP32 development board and ACS723 current sensor.

Specification:

1. Input Voltage - 0- 24V ( Can be extended up to 50V )

2. Input Current: 0 -15A

3. Solar Panel Rating - 250W (12V ) / 500W ( 24V )

Visit my newly created personal Blog: https://www.opengreenenergy.com

Full Video Tutorial:

Supplies

Components Used:

1. ESP32 Board - 30 pins ( Banggood / Aliexpress )

2. ACS723 Sensor ( LCSC )

3. OLED Display ( Amazon / Banggood )

4. Resistors ( Amazon / Banggood )

5. Ceramic Capacitors ( Amazon / Banggood )

6. XL7015 Buck Converter Module ( Amazon )

7. Temperature Sensor ( Amazon / Banggood )

8. Screw Terminal 3P- 3.5mm pitch ( LCSC )

9. Screw Terminal 2P - 9.52mm pitch (LCSC )

10. Header Pins ( Amazon / Banggood )

11. Jumper Wires M-F ( Amazon )

12. PCB

13. Soldering Flux ( Banggood )

14. Soldering Paste ( Banggood )

Tools Used:

1. Soldering Iron ( Amazon / Banggood )

2. Nipper ( Amazon / Banggood)

3. Wire Stripper ( Amazon / Banggood)

4. 3D Printer ( Amazon / Banggood)

Step 1: How It Works?

The Solar panel voltage and current are sensed by voltage and current sensor respectively. Here, a voltage divider network is used to measure the solar panel voltage, and the AC723 hall effect current sensor is used to measure the solar panel current. Similarly, the ambient temperature is sensed by the DS18B20 temperature sensor.

The raw sensor data from all the sensors are processed by an ESP32 board and do all the necessary maths to calculate the power, energy. The processed data then send to an OLED display for local monitoring and also to the cloud for remote monitoring. The remote monitoring is done through the Blynk app installed on a Smartphone.

Step 2: Measuring Voltage

The solar panel voltage is sensed by a voltage divider network consists of two resistors R1=47k and R2=6.8k. The output from the R1and R2 is connected to ESP32 analog pin GPIO pin 34. The output from the voltage divider is smoothed out by using a ceramic capacitor C1.

Voltage Measurement :

ESP32’s analog inputs can be used to measure DC voltage between 0 and 3.3V. The solar panel that I have considered can generate 24V ( Open Circuit Voltage). To read this voltage we have to step don the voltage which can be done by using a voltage divider network.

For a voltage divider circuit

Vout = R2/(R1+R2) x Vin

Vin = (R1+R2)/R2 x Vout

The analogRead() function reads the voltage and converts it to a number between 0 and 4095

Calibration :

We’re going to read the output value with one of the analog inputs of Arduino and its analogRead() function. That function outputs a value between 0 and 4095 that is 3.3/4095 for each increment

Vin = Vout*(R1+R2)/R2 ; R1=47k and R2=6.8k

Vin= ADC count * ( 3.3/4095 ) * ( ( 47+6.8) / 6.8 ) Volt

You can use solar panel with higher voltage by selecting the appropriate resistors R1 and R2.

To select the voltage divider resistance values, you can use this online calculator.

Step 3: Measuring Current

For current measurement, I used a Hall Effect current sensor ACS 723 -20AUvariant. There are other variants of ACS723 Sensor based on the range of its current sensing. The ACS712 sensor reads the current value and converts it into a relevant voltage value, The value that links the two measurements is Sensitivity. The output sensitivity can be obtained from the datasheet. As per the datasheet, the sensitivity is 200mV / A

Calibration:

analog read value = analogRead(Pin);

ADCVoltage = (3.3/4095)*analog read value

Current in amp = ( ADCVoltage – Offset Voltage ) / sensitivity

As per data sheets offset voltage is 0.1 * Vcc ( 0.5V ) and sensitivity is 200mV/A

Note: The output from the ACS723 is stepdown by a voltage divider network consists of R4 and R5.

Step 4: Measuring Temperature

I have used an external DS18B20 probe for measuring the ambient temperature. It uses a one-wire protocol to communicate with the microcontroller. One-wire devices need a pull-up resistor connected to their signal line to be properly read by your board. Here, I have used a 4.7K resistor ( R6 ) as a pull-up resistor.

It can be hooked up to the PCB through the 3pin screw terminal.

To interface with the DS18B20 temperature sensor, you need to install the One Wire library and the Dallas Temperature library. You can read this article for more details on the DS18B20 sensor.

The connection is as follows:

Red Wire -> Vcc

Yellow Wire -> DATA

Black Wire -> GND

All the above are clearly labeled on the PCB for avoiding any confusion.

Step 5: Interfacing OLED Display

To display the solar panel parameters locally, I have used a 0.96" OLED display. It has a 128 x 64 resolution and uses an I2C bus to communicate with the ESP32. Two pins SCL (GPIO22), SDA (GPIO21) in ESP32 are used for communication.

I am using the Adafruit_SSD1306 library to display the parameters. First, you have to download the Adafruit_SSD1306. Then installed it.

The connections should be as follows:

ESP32 - ->OLED

3.3V --->VCC

GND -->GND

GPIO21----> SDA

GPIO22----> SCL

Step 6: PCB Design

I have drawn the schematic by using EasyEDA online software and then designed a custom PCB for this project. The PCB is designed for mounting the different modules instead of using a lot of components. I have ordered my PCB from JLCPCB and received it within 7 days.

You can download the Gerber files attached below.

Step 7: PCB Assembly

For Soldering, you will need a decent Soldering Iron, Solder, Nipper, and a multimeter. It is good practice to solder the components according to their height. Solder the lesser height components first.

You can follow the following steps to solder the components :

1. Push the component legs through their holes, and turn the PCB on its back.

2. Hold the tip of the soldering iron to the junction of the pad and the leg of the component.

3. Feed solder into the joint so that it flows all around the lead and covers the pad.

Once it has flowed all around, move the tip away.

Step 8: Soldering the ACS723

In the entire PCB, the lesser height component is the current sensor ACS723 which is the only SMT component used in this project.

First, apply soldering flux on all 8 pads and then apply a small amount of solder to the corner pads. Place and align the diode chip using tweezers. Hold the chip in place while touching the pads with the tip of the soldering iron so that the solder melts the pin and the pad together.

Be sure the dot symbol on the PCB and the ACS723 IC is matching together. The dot symbol represents pin number -1.

Now apply solder to all the pads, and you are done. If you mess up during the soldering, you can remove the extra solder by using a desoldering wick.

You can read this tutorial if you are new to soldering SMD components by using a soldering iron.

Step 9: 3D Printed Enclosure

To give a nice commercial product look, I have designed an enclosure for this project by using Autodesk Fusion 360. The dimensions of all the components and PCB mounting holes are measured by a vernier caliper then the same were considered during the design.

The enclosure has two parts: 1. Main Body 2. Top Lid The

The main body is basically designed to keep the PCB board. The top lid is to cover up the main body opening and mounting the OLED display.

I used my Creality CR-10 printer and 1.75 mm green PLA filament to print the parts. It took me about 6 hours to print the main body and around 2 hours to print the top lid.
My settings are:

Print Speed : 60 mm/s

Layer height: 0.2mm ( 0.3 also works well)

Fill Density: 20%

Extruder Temperature: 200 deg C

Bed Temp: 60 deg C

Download the STL files from Thingiverse

Step 10: Assemble the 3D Printed Enclosure

The PCB can be mounted on the 4 standoffs in the 3D printed enclosure. You can directly secure the PCB by using 4 x M3 screws or you may install threaded thermal inserts for more reliability. Here I have used thermal inserts on each standoff.

After mounting the PCB onto the main body, we can move to install the OLED display. The OLED display can be mounted on the backside of the top lid by using hot glue or strong adhesive tape.

Connect the jumper wires from the OLED display to the PCB OLED port. The header pins on the PCB are clearly labeled.

Insert the temperature sensor cable into the hole given on the right side of the enclosure. Then connect the wires to the screw terminal.

Now close the top lid by using 4 x M3 screws.

To make the enclosure more attractive, I have stuck an Instructables sticker on the top lid.

Step 11: Software and Libraries

To use the ESP32 board with the Arduino library, you'll have to use the Arduino IDE with ESP32 board support. If you haven't already done that yet, you can easily install ESP32 Board support to your Arduino IDE by following this tutorial by Sparkfun.

Install the Libraries:

Before uploading the code install the following libraries :

1. ESP32

2. Blynk

3. Adafruit_SSD1306

4. One Wire

5. Dallas Temperature

How to Install the Libraries?

You can read this tutorial by Sparkfun to install the Arduino libraries.

Step 12: Interfacing With Blynk App

Blynk is the most popular Internet of Things platform for connecting any hardware to the cloud, designing apps to control them, and managing your deployed products at scale. With Blynk Library you can connect over 400 hardware models including ESP8266, ESP32, NodeMCU & Arduino to the Blynk Cloud.

Step-1:

Download the Blynk app

1. For Android

2. For iPhone

Step-2:

Get the Auth Token In order to connect the Blynk App and your hardware, you need an Auth Token.

1. Create a new account in the Blynk App.

2. Press the QR icon on the top menu bar. Create a clone of this Project by scanning the QR code shown above. Once it detected successfully, the whole project will be on your phone immediately. I've made the Sol Weather Station app. You are welcome to try it out!

To start using it:

1. Download Blynk App: http://j.mp/blynk_Android or http://j.mp/blynk_Android

2. Touch the QR-code icon and point the camera to the code below, enjoy my app!

3. After the project was created, we will send you Auth Token over email.

4. Check your email inbox and find the Auth Token.

Step-3:

Preparing Arduino IDE for Wemos BoardTo upload the Arduino code to Wemos board, you have to follow this Instructables

Step-4:

After installing the above libraries, paste the Arduino code given below.
Enter the auth code from step-1,ssid, and password of your router.

Then upload the code.

//======================================================================================//
//                                                                                      //
//                 Solar Panel Energy Monitoring V1.0 Firmware                          //
//                                                                                      //
//             Developed by Debasish Dutta, Last Update: 06.05.2021                     //                 
//                                                                                      //
//======================================================================================// 
    
    #include <Adafruit_GFX.h>
    #include <Adafruit_SSD1306.h>
    #include <DallasTemperature.h> 
    #include <OneWire.h>   
    #include "Wire.h"    
    #include <WiFi.h>          
    #define BLYNK_PRINT Serial
    #include <BlynkSimpleEsp32.h>
    
    #define SCREEN_WIDTH 128 // OLED display width, in pixels
    #define SCREEN_HEIGHT 64 // OLED display height, in pixels
    #define INPUT_VOLTAGE_SENSE_PIN 34
    #define INPUT_CURRENT_SENSE_PIN 35
    #define TEMP_SENSE_PIN 4
    #define VOLTAGE_SCALE  7.911 // R1+R2 / R2 // ( 47K + 6.8K ) / 6.8K
    #define CURRENT_SCALE  1.5 // R4+R5 / R5 // ( 1K + 2K ) / 2K
    
    double mVperAmp = 200; //Sensityvit of the sensor //  use 100 for 20A Module and 66 for 30A Module
    double ACSoffset = 514; // Ideally it should be ( 0.1 x Vcc ) // measured value is 514mV
    unsigned long last_time =0;
    unsigned long current_time =0;
    float power =0 ; // Power in Watt
    float energy =0 ; // Emergy in Watt-Hour
    float tempC=0; // temperaure in Celcius
    //float tempF = 0; temperature in F
    float saving=0; // cost saving  
   
    
     WiFiClient client;
    // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
    Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
    // GPIO where the DS18B20 is connected to
    const int oneWireBus = 2;    
    // Setup a oneWire instance to communicate with any OneWire devices
    OneWire oneWire(TEMP_SENSE_PIN);
    DallasTemperature sensors(&oneWire);
    
//========================= Variables for wifi server setup =============================
     
  // Your WiFi credentials.
  // Set password to "" for open networks.
  char ssid[] = "XXXX"; // WiFi Router ssid
  char pass[] = "XXXX"; // WiFi Router password
  
  // copy it from the mail received from Blynk
  char auth[] = "XXXX";  
  
//========================= Setup Function ================================================ 
    
void setup() {
  Serial.begin(115200);
  Blynk.begin(auth, ssid, pass);
  sensors.begin();
  
  
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { 
    Serial.println(F("SSD1306 allocation failed"));
    for (;;);
  }  
  display.clearDisplay();  
  display.setTextColor(WHITE);
  display.display();  
  delay(500);
}

//========================= Loop Function ================================================ 
    

void loop()
{
 
  // read voltage and current
  float voltage = abs( return_voltage_value(INPUT_VOLTAGE_SENSE_PIN)) ;
  float current = abs( return_current_value(INPUT_CURRENT_SENSE_PIN)) ;

 // read temperature from DS18B20
  sensors.requestTemperatures(); // get temperatures
  tempC = sensors.getTempCByIndex(0);
  //tempF = sensors.getTempFByIndex(0); 

  // Calculate power and energy
  power = current * voltage ; // calculate power in Watt
  last_time = current_time;
  current_time = millis();    
  energy = energy +  power *(( current_time -last_time) /3600000.0) ; // calculate power in Watt-Hour // 1 Hour = 60mins x 60 Secs x 1000 Milli Secs

  saving = 6.5 * ( energy /1000 ); // 6.5 is cost per kWh // used just for example
  

  // ================= Display Data on Serial Monitor ================================================ 
  
 /* Serial.print("Voltage: ");
  Serial.println(voltage);
  Serial.print("Current: ");
  Serial.println(current);
  Serial.print("Power: ");
  Serial.println(power);
  Serial.print("Energy: ");
  Serial.println(energy);
  Serial.print("Temp: ");
  Serial.println(tempC);
  Serial.println(voltage);
  delay(1000);
*/
// ================= Display Data on OLED Display ================================================

  // Display Solar Panel Voltage 
  display.setTextSize(1);
  display.clearDisplay();
  display.setCursor(10, 10);
  display.print(voltage,1);
  display.print(" V");

  // Display Solar Panel Current 
  
  display.setCursor(70, 10);

  if (current >0 && current < 1 )
  {
   display.print(current*1000,0);
   display.print(" mA");
  }
  else
  {
  display.print(current,2);  
  display.print(" A");
  }

 // Display Solar Panel Power in Watt

  display.setTextSize(2);
  display.setCursor(10,25);
  display.print(power);
  display.print(" W");

 // Display Energy Generated by the Solar Panel 
  display.setCursor(10,45);
  
  if ( energy >= 1000 )
  {
   display.print(energy/1000,3);
   display.print(" kWh");
  }
  else
  {
  display.print(energy,1);  
  display.print(" Wh");
  }
  display.display();
  display.clearDisplay();
  
  
// ================= Display Data on Blynk App ================================================
   Blynk.run();  
   Blynk.virtualWrite(0, voltage ); // virtual pin 0
   Blynk.virtualWrite(1, current ); // virtual pin 1 
   Blynk.virtualWrite(2, power);    // virtual pin 2
   Blynk.virtualWrite(3,energy/1000);// virtual pin 3
   Blynk.virtualWrite(4,tempC );    // virtual pin 4   
   Blynk.virtualWrite(5,saving);    // virtual pin 4  
   //delay(1000);
}

//========================= Function to Calculate Solar Panel Voltage ===================================
  
double return_voltage_value(int pin_no)
{
  double tmp = 0;
  double ADCVoltage = 0;
  double inputVoltage = 0;
  double avg = 0;
  for (int i = 0; i < 100; i++)
  {
    tmp = tmp + analogRead(pin_no);
  }
  avg = tmp / 100;
  ADCVoltage = ((avg * 3.3) / (4095)) + 0.184 ; // 0.184 is offset adjust by heat and try
  inputVoltage = ADCVoltage * VOLTAGE_SCALE; 
  return inputVoltage;
}


//========================= Function to Calculate Solar Panel Current ===================================

double return_current_value(int pin_no)
{
  double tmp = 0;
  double avg = 0;
  double ADCVoltage = 0;
  double Amps = 0;
  for (int z = 0; z < 150; z++)
  {
    tmp = tmp + analogRead(pin_no);
  }
  avg = tmp / 150;
  ADCVoltage = ((avg*3331) / 4095); // Gets you mV
  Amps = ((ADCVoltage * CURRENT_SCALE - ACSoffset ) / mVperAmp); // 1.5 is the scaling for voltage divider
  return Amps;
}<br>

Step 13: Field Testing

Now our device is ready for real field testing. The connection shall be as follows:

1. Connect the negative terminal of the load to the negative terminal of the output screw terminal and then the positive terminal to the output positive terminal. Here I have connected the out terminal to my charge controller solar input terminal.

2. Connect the Solar panel negative terminal to the negative terminal of the Input screw terminal and positive to the input positive terminal.

The Input and Output screw terminals can be used for wire sizes from 26 - 10AWG.

You can refer to the above wiring diagram for better understanding.

Note: Be sure you are connecting to the right polarity, otherwise you will see the magic smoke. The circuit doesn't have reverse polarity protection.

After all the connections, you will see your solar panel parameters displayed on the OLED display. You can check it from your smartphone by opening the Blynk App.

Future Goal:Implementation of MQTT and Home Assistant

Thanks for reading my Instructable.
If you like my project, don't forget to share it. Comments and feedback are always welcome.

Be the First to Share

    Recommendations

    • Arduino Contest

      Arduino Contest
    • Box Challenge

      Box Challenge
    • Barbecue Speed Challenge

      Barbecue Speed Challenge

    16 Comments

    0
    ChiefInstructor
    ChiefInstructor

    20 days ago

    Excellent write-up. Well done. Very impressed with all the levels of detail to make this work.

    0
    Krejstrup
    Krejstrup

    27 days ago

    I have a suggestion of a different current sensing IC. There's a superb IC called INA260 that can measure current up to 15A and 36V. The data is read via I2C and hence you don't have to read out any analog signal, neither do any calibrations at all. All calibrations are done in manufacturing.
    The current sensing is done by internal shunt, but there is not much loss in power since the resistor is quite low.
    You can either buy the IC separately or as a module. The shunt is a bit heat sensitive if you hand solder the SMD (I've destroy'd two IC's by overheating them). So the module is an easy way of just plug it into the PCB:
    https://www.adafruit.com/product/4226

    Really nice project!!

    0
    marioo220
    marioo220

    4 weeks ago

    Great design and workmanship!

    0
    gswanepoel
    gswanepoel

    4 weeks ago

    Very impressive.

    0
    kanouti
    kanouti

    4 weeks ago

    How do you manage the non-linearity of the ESP32’s ADC when measuring the voltage?

    0
    Gr975
    Gr975

    4 weeks ago

    Harika olmuş paylaşım için teşekkürler

    2
    Thorigol
    Thorigol

    4 weeks ago

    Nice project, but I would make a suggestion. It is not a great idea to have all the current from the panel(s) flow through your box as it becomes a single point of failure and can generate heat if your circuit board traces are not very thick or a connection should become loose or oxidized.
    A much better solution is to use a non-invasive current sensor such as SCT-013-030/015 Non-invasive AC Current Sensor Split Core Current Transformer. This way your system only has low currents to deal with. These are easy to read with Arduino analog pins and a small network per https://learn.openenergymonitor.org/electricity-monitoring/ct-sensors/interface-with-arduino

    IMG_2544.jpg
    0
    calistusokwudili
    calistusokwudili

    4 weeks ago

    How would you connect it if you had a large solar system, 10kva - 36 panels?

    0
    bldrkamal
    bldrkamal

    5 weeks ago

    Nice work.

    1
    cucogoyo
    cucogoyo

    4 weeks ago

    I have a doubt, you set the Buck Converter XL7015 to 5v but the ESP 32 resis that 5v? and if is this true wich pin you use too. Thnx for the infromation and the proyect looks amazing

    0
    opengreenenergy
    opengreenenergy

    Reply 4 weeks ago

    I have applied 5V to the Vin pin of the ESP32 dev board. The onboard voltage regulator step down the voltage to 3.3V for operating the ESP32 chip.

    3
    jessyratfink
    jessyratfink

    5 weeks ago

    Fantastic work as always :D