Solar Panel Monitoring

Software for Arduino Yun (AVR side)

Writing a program for the Arduino was a new experience for me. Spoiled by Windows/Linux and even Android which have basically no memory limit I run very soon into problems with the very limited code and variable space on the Arduino boards. The Arduino Yun offers only 28,627 bytes for code and 2560 bytes for global variables.

What I learned fast was that I can use up the code memory up to 99.9%, but if I use more than 60% of the memory for global variables the sketch was no longer working reliable. I think the underlaying code (bootloader, …) requires some free space int global variables memory.

So I had to optimize my code and limit usage of global variables as much as possible.

For the code itself, I split the Arduino sketch into several files. I tried to comment the code as good as possible, so it should be self explanatory.

The names of the files follow a specific scheme. The compiler for the sketch requires that sub-functions used must be declared before they are used. So the file names are SKETCHNAME_index_MODUL. With the index I get the files to be compiled in the correct sequence.


In the first part all the external files necessary for the different functions are included.

Calibration values:

These values are crucial for the measurements. These values are depending on the CT sensors used, tolerances of the used resistors and capacitors and other things. To get these values correct, I stepped several times through the calibration guide of OpenEnergyMonitor building block Calibration Procedure. Until you have the correct values here all your measurements will be more or less CRAP! To make the calibration possible without writing a special script I included a “calibration mode” into the Android application. When the calibration mode is activated the Android applications pulls data from the Arduino every 10 seconds and displays details about the power factor, real and apparent power and measured voltage. The calibration values can then be changed until the values are as expected (e.g. power factor close to 1.o).

The other global variables are well commented.


This modul contains 2 functions used to store the recorded values.

String getTimeStamp() returns the current date and time of the system. To get it we use the “bridge” function “.run” to run a command on the Linux side and receive the output over the “bridge“.

This part starts the date command on a Linux shell with the parameters +%y,%m,%d,%H:%M. If you start this on a Linux shell it will return 15,08,21,18:29 . This output is captured by the following code and returned as String to the calling function:

The possibility to start commands and scripts on a Linux shell extends the capabilities of the Arduino board. Instead of the problems to add complex functions into the limited program space of the AVR controller they can be delegated to the Linux part.

void saveData () uses the “bridge” functions as well to write the collected data into a database, send it to an cloud web service and store it for easy access on the Linux side.

The measurements are done every second, but the values are stored only every minute. The measured values are stored in an accumulator. The code part

calculates the average of the measurements done since the last saving of values.

The code part

stores the measured values on the Linux processor using a Key/Value structure. These structure can be retrieved as a JSON string by simple calling “http://IPADDRESS//data/get”. (IPADDRESS is the IP address assigned to the Arduino Yun). The data looks like:

You can see the data we put with the above code part in this JSON string.

The L, S and C value is updated every minute and used to update the UI in the Android app. The c, cv, cr, .. values are updated after every measurement cycle (~1s) and can be used during the calibration mode. They are as well shown on the UI of the Android app.

The next code part

uses the “bridge” function “.runShellCommand” to write the measured values into the Sqlite database. From there they can be retrieved over the local network with the query.php script.

And the last code part

uses as well the “bridge” function “.runShellCommand” to send the data to a cloud web service. This cloud web service offers (at the moment for free) the possibility to store sensor data and visualize them on the web. Check their service, they are powered by OpenEnergyMonitor!

One of the visualization options of emoncms


This modul handles the light sensor. The communication with the light sensor is done within the Adafruit_Sensor and Adafruit_TSL2561_U libraries. These libraries are available as open source from Adafruit, the manufacturer of the light sensor module.

void configureSensor () initiates the auto range function of the light sensor and sets it integration time to the highest value.

void readLux () initiates a measurement on the light sensor module. To adapt to different light intensities it is necessary to adapt the integration time of the sensor. Initially the sensor is set to the highest integration time which is the best in low light situations. But if the light gets brighter, the sensor will saturate and it is necessary to switch to a shorter integration time. The sensor offers 3 different integration times. The code part

reads a value from the sensor. If the sensor delivers a value, the code switches to a higher integration time.

But if the sensor is already saturated, we lower the integration time and try again to read from the sensor

This loop is  repeated  5 times to adapt to  changing light situations.


This modul contains the CT sensor measurement routines. The direct measurement of current and voltage is done by the emonLib library. EmonLib is an open source library provided by OpenEnergyMonitor.

void getCTValues (int index) calls emonLib to initiate the measurement of current, voltage and calculation of power and power factor. The parameter index determines the sensor that should be read. index = 0 starts a measurement of the CT sensor attached to the solar panel wire, 1 starts a measurement of the CT sensor attached to the main power line.

The collected values are then stored in an accumulator. At the moment the system is able to make a measurement around every second.  The values stored in the accumulator are used to calculate an average value before saving the values in the database, which is done every 60 seconds.

At night the solar panel is not producing power, but it is using a small standby current. We eliminate this standby current with the code

This way we make sure that we do not record a not existing power production during night.

The measured values are then saved on the Linux side with the “Bridge.put” function as a Key/Value structure. The keys are created by using the prefix s for values from the solar sensor and the prefix c for values from the main line sensor.


This is the programs main loop. It is running all the time. Inside the loop we use the millis() function to initiate measurements and saving of values in specific frequencies.

At the moment the measurement is initiated every second. This is possible because the light sensor is not used yet. Once the light sensor is attached the frequency of the measurement has to be reduced, as the routine for the light measurement can take more than 2 seconds worst case.

This code calls the measurement functions for the CT sensors and the light sensor. The measurement cycle is visualized by an LED mounted on the sensor connection shield.

The following code calls the function to save the values into the database every minute:

And finally we have a code part to communicate directly over the local network with a PC or Android device. When I started with the application, I tried to have all communication handled within this Arduino code, but due to the memory limitations I realized that this was not possible. So at the end there is only one function left here. As most communication parts are delegated directly to the Linux part of the Arduino board only the status report function is handled here.

The status can be request by any browser or application by simply calling http://IPADDRESS/arduino/e

The response is

F is the measurement frequency, V is the voltage calibration value, C1 and C2 are the CT sensor calibration values.

This function will be used by the Android application to find the Arduino device on the local network.


This routine is called once after a reset of the Arduino board. It contains the initialization routines for the network communication and the sensors

1 – setting the port for the activity LED

2 – initializing the network communication and access to the Linux file system.

3 – initialization of the light and CT sensors

4 – Initialization of the timer and the watchdog

Regarding the watchdog, you can see

frequently in the source code. With using the watchdog I make sure that when the program gets stuck anywhere that latest after 8 seconds a reset of the Arduino board is initiated. This makes sure that the program can run unattended for a long time.

This ends the short description of the Arduino source code. To see all details, check out my repository on Github where you can find the full source code.

It is nice to see the collected data on a website, but I wanted to see the data as well on my Android gadgets. Learn how the Android application works on the next page.


Leave a Reply

Your email address will not be published. Required fields are marked *

Free Link Directory