Arduino Solar Charge Controller + Output Control and Data Logging Online With Xbee WiFi

Introduction: Arduino Solar Charge Controller + Output Control and Data Logging Online With Xbee WiFi

A while back I started working on a solar charge controller, it was based on a PIC microcontroller, a 20x4 characters display and the code was written in Assembly language. It did work well and was still working when I decided I wanted to add more to this controller.

My new controller uses a standalone ATMega328P, and a 1.8" tft screen from Saintsmart. I wrote the code with the arduino IDE and uploaded ( many many times ;-) ) straight onto the board with the standalone uP. I had a lot of solar cells at home so I decided to build my own solar panel to go with it. Not sure of the achieved wattage, it is not so great but it still gives 23 to 24 volts when it is not connected.

This new controller has a button that allows you to turn ON or OFF an output, where the voltage from the battery is applied and where you can connect anything like LED lights, power inverter or any other devices. Maximum output is 20 Amps for this design.

The features of this new controller are:

- Possibility to charge 6V, or 12V types batteries. (24V included in software but needs a small modification on the electronic side)

- Automatic detection of the type of battery connected.

- Push button to turn ON and OFF the output stage of the controller.

- Push button to display different information on the screen like total charge time, number of charging days, min and max battery voltages recorder, temperature, LUX values outside, maximum charging current and Watts as well as maximum output currents and Watts.

- All these values are saved to the EEPROM once a day when the ambient light goes down and are reloaded at start up.

- Possibility to erase the EEPROM and start with fresh readings, as well as possibility to delete the total charging time and days.

- The temperature of the battery is used in the software to reduce the charging values if it goes above 25° or raise them if it is lower than 25°.

- Information is sent to the IoT (Internet of Things) once every 5 minutes to be able to keep an eye on how things are going when I am not at home. Check out my channel to see what it looks like and what information is sent over by the controller.

- Automatic disconnection of the load connected to protect the battery and prevent over-discharging.

- Bulk charge, followed by 1h of constant voltage charge followed by float charge.

- Maximum charging current supported by the controller is 10 Amps, maximum output current is 20 Amps.

- Maximum solar voltage input is 30V in this configuration.(limited by the 7805 maximum input voltage)

- Current consumption while on standby and not charging the battery is <10 mA.

Step 1: Build One Yourself, What You Need

If you wish to build one of these controller yourself then here is the list of material and all the steps needed.

I wont show the build of the solar panel here as this instructable focuses on the solar charge controller.

I have kept the fuses off the board, this is why nothing will appear on this list. I have a 10Amp fuse on the solar panel wires and a 25Amps fuse on the output wires.

Material needed:

1x prototyping board

1x ATMega328P (28pins through hole)

1x 16MHz oscillator

2x 22pF capacitors

1x 1000uF 100V electrolitic capacitor

1x 220uF 16V electrolitic capacitor

1x 100nF capacitor

1x 10nF capacitor

5x 1uF ceramic capacitor

1x 82 Ohm resistor

6x 100 Ohm 1% resistors

4x 1 kOhm resistors

4x 2.2 kOhm resistors

4x 10 kOhm resistors

2x 5 mOhm resistors (3W minimum)

2x IN4007 diodes

1x Power diode MBR1045

2x STB80PF55 P-chanel MOSFETS

2x 2N2222 NPN transistors

1x reset push button

1x LM35 temperature sensor

1x LDR light sensor

2x 25 kOhm 10 turns potentiometers

2x 100 kOhm 10 turns potentiometers

3x 2pins 20Amps screw terminals

1x 6pins 20Amps screw terminals

2x LT6105 current sense amplifiers

2x adapters for MSOP to DIP packages (8pins)

1x 7pins male headers

2x 6pins male headers

1x 4pins male headers

1x 3pins male headers

1x 2pins male headers

1x 7805 (TO220 package) 5V regulator

1x Xbee Wifi + shield or interface ( I used the shield from Sparkfun as I had one handy)

1x 1.8" tft screen from Saintsmart

2x panel push-buttons

1x panel ON - OFF selector switch

heatsinks for the MOSFETS diode and the 7805 (it tends to get warmish at times)

And of course the usual soldering iron, hookup wires, drill and drill bits to cut tracks and make mounting holes.

Step 2: Soldering the Main Board + Sketch and Libraries

Start by soldering the main board. There is a picture of the way I wired my prototype board to help.

I made the drawing using Black Board software. You can use it as a guide or just make up your own layout.

There is also the schematics of the controller attached, to refer to for resistors values etc if needed.

Once done, you can download the sketch I made up for the controller and there is a few libraries that you might not already have installed that you ll need to install.

They are:

Adafruit_GFX.h ; download here if needed

Adafruit_ST7735.h ; download here if needed

EEPROMex.h ; download here if needed

Step 3: Thingspeak Website and Setting Up the Xbee

The data collected by the charge controller is pushed onto a website called Thingspeak. This is where I can log in and check on my charge controller when I am not at home. You can access it here to create an account and setup your own channel. If you don't want this feature on your charge controller you can just comment out the xbee() in the main loop section of the program and it will not take care of this while running.

If you do want to be able to check on your controller on the internet then you will have to create your own channel. Once you have created it, you will be given an API key. This key is important and will be needed in the arduino code so keep it handy. You can then setup the channel, There is 8 fields of data that are sent from the charge controller, so in your channel under the "channel settings" tab, enter the information as follow for the fields.

field 1 -- solar voltage

field 2 -- battery voltage

field 3 -- charge current

field 4 -- charge PWM

field 5 -- output current

field 6 -- battery charged

field 7 -- temperature

field 8 -- luminosity

My code for the charge controller does not create a connection for the Xbee every time it needs to send data. I have already programmed my Xbee with my personal WiFi settings using the X-CTU software.
There are some good tutorials on the internet on how to connect your Xbee and communicate with it using X-CTU. This one is very good and will get you on your way.

Follow the tutorial to get the Xbee connected to your personal WiFi network.

Once done there is a few parameters that we will change into the Xbee to get it setup to connect onto the Thingspeak website as this is where all the data will be sent.

Change or check the following settings:

- IP protocol needs to be set to "1-TCP"

- DL- destination IP address needs to be set to ""

- DE- destination port needs to be set to "50"

Once these settings have been changed, press the "write" button to store these settings into your Xbee.

You have now successfully setup your Xbee to push data onto your channel at Thingspeak.

Next, open the "Solar_charge_controller" sketch and look for line n° 1150

The line should be: xb.print(F("key=YOUR_API_KEY_HERE"));

Delete the parts which says YOUR_API_KEY_HERE and replace it with your own personal API key that you received when you created your channel on Thingspeak. Make sure you don't delete key= because it will not work without it.

Step 4: Powering Up and Loading the Code

Once the board is all done, it is time to power it up and load the code into the micro-controller. I forgot to add that this ATMega328P was already bootloaded so all I need to do is load up the program onto it.

There is some pretty good tutorials out on the internet on how to setup and program a standalone ATMega if someone needs more information.

  1. - In the case of this board, first thing you need to do is to load the Arduino ISP example sketch onto your arduino board.

2. - In the second picture I commented to show which header is used for programming and which pins is pin number 1.

3. - Wire your arduino to your board this way.

Arduino pin 10 -- board header pin 5

Arduino pin 11 -- board header pin 1

Arduino pin 12 -- board header pin 2

Arduino pin 13 -- board header pin 3

Arduino +5V -- board header pin 4

Arduino GND -- board header pin 6

4. - Open the "solar_charge_controller" sketch, make sure the type of board is set to Arduino UNO and select "Arduino as ISP" in the programmer section in the "tools" menu of your arduino IDE. Try to compile the sketch (ctrl + r) to make sure it doesn't return any error.

5. - Once it is all looking good, press and hold the SHIFT button on your keyboard and click onto the upload button arrow in your arduino IDE and if everything is working fine, you should see the little Rx Tx lights on your arduino board start to blink. (It takes a fair bit of time for the sketch to upload).

Once done you can remove the programming wires from the header.

Step 5: Connecting the Different Sensors and Cables to the Board

After mounting the board in its final place we need to connect the screen, Xbee, switches and sensors to it.

On the picture of the prototype board I have commented on what header is for what device and where to find pin 1.

You can also refer to the schematics to find the headers pin numbers.

Connection for the Xbee: (from the board to the Xbee shield)

Header pin 1 goes to Shield pin 3

Header pin 2 goes to Shield pin 2

Header pin 3 goes to shield pin +5V

Header pin 4 goes to shield pin GND

Connection for the tft screen: (from the board to the tft screen)

Header pin 1 goes to screen pin Vcc

Header pin 2 goes to screen pin GND (the screen works as well when it is not connected, saves a bit of power)

Header pin 3 goes to screen pin RES

Header pin 4 goes to screen pin RS/DC

Header pin 5 goes to screen pin CS

Header pin 6 goes to screen pin SDA

Header pin 7 goes to screen pin SCL

Connection for the buttons and switch: (from the board to the buttons and switch)

Header pin 1 goes to ON - OFF switch on 1 side

Header pin 2 goes to ON - OFF switch on the other side

- From this pin of the ON _ OFF switch run a wire to the + of the OUTPUT button light

Header pin 3 goes to the GND of the OUTPUT button light (not connected in my setup)

Header pin 4 goes to the DATA button on 1 side

- From this pin of the DATA button run a wire to the 1st side of the OUTPUT button

Header pin 5 goes to the DATA button on the other side

Header pin 6 goes to the OUTPUT button on the other side

Connection for the LM35 temperature sensor: (from the board to the sensor)

Header pin 1 goes to the LM35 pin +

Header pin 2 goes to the LM35 pin GND

Header pin 3 goes to the LM35 pin Vout

For the LDR sensor, it doesnt matter which way you connect the sensor to the header so just connect it the way you want.

Step 6: Know Your Controller's Functionality

The purpose of the ON - OFF switch is that you can let your system shut down at night when the Solar panel voltage is too low to keep it powered up. I personally keep it ON all the time.

When the controller is not charging, it will circle and display different values saved in.

You will probably notice that the values displayed are strange at first, this is because we need to erase the EEPROM to start fresh and write to it some nice and easy numbers.

The data button serves 2 functions. When pressed normally (0.5sec or so) while the battery is charging, It will temporarily remove the Charge time and charge state and display the max and min values that normally circle when the battery is not charging.

When pressed for more than 2 seconds, it will erase the max and min values stored. Once this is done it will ask you if you want to reset the total charge time as well (message will stay 2.5 seconds on the screen). If, while this message is displayed, you press the data button again, these values will be zeroed too. You want to do that too now to get rid of the 255's and NaN displayed in there at the moment.

The values displayed will be: Total charging time, Number of days of charge (or number of charge cycles), max solar voltage, min and max battery voltages max charge current and watts, max output current and watts, actual luminosity and actual battery temperature. For every press of the data button, the value displayed will change. This display mode will resume after 10 seconds if there is no further presses on the button.

Having a pretty small and poor solar panel connected I noticed I was having issues with the Xbee powering up and sometimes not connecting to my WiFi when I left the ON - OFF switch on OFF, so I added a piece of code preventing the program to startup for as long as the Solar Voltage haven't reached 8V.

The cycle time displayed on the screen was put on there when I was cleaning up my code a bit and try to make the loop faster, specially when charging the battery. It varies from 20ms to 30ms according to the charge state of the battery. It will go up more every now and then when other actions are performed like screen refresh etc. Again, if you do not wish to have this information displayed on your controller, just comment out the loop_time() line in the main loop section of the program and reload your code.

The PWM value is displayed next to the charge current to see at what duty cycle the MOSFET is working 0 being always off and 255 being always on. It will vary a lot depending on what kind of Solar Panel Wattage you have connected to the system. The bigger the panel the smaller the PWM value will tend to be.

In BULK CHARGE mode, the full power is tranferred to the battery until it reaches 14.6V (at 25°C). When it reaches it, the charge mode changes to CONSTANT VOLTAGE for 1h. It will keep the battery voltage at this value by increasing or decreasing the PWM value to the charge MOSFET. After that, the battery goes into FLOAT CHARGE mode, where the controller will keep the battery voltage at 13.6V (at 25°) by again varying the PWM value.

Step 7: Power Side Connections, Power Up and Settings

If it is a sunny day and the sun is out there on your panel, I recommend covering it up and not wiring it straight away. We have some testing and setting to do first. Make sure the ON - OFF switch is on the OFF position.

First connect your battery + and GND to their respective terminals.

Once connected, flick the ON - OFF switch to ON and your board should power up. You should be able to see the Xbee red LED is turned ON and the screen should be ON as well. After a few seconds the green LED DIO5 on the Xbee should start flashing at around 3 Hz, which indicates that your Xbee is connected to your WiFi network.

We will start by setting up the battery voltage. Using a voltmeter, measure precisely the battery voltage on your battery terminals. Now, using the potentiometer on the board, screw it in or out until the battery voltage displayed on the screen matches the one you can read on your voltmeter

Once it is ok, use a piece of wire and make a bridge between the battery + terminal to the solar panel + terminal. You will now see a solar voltage value displayed on the screen. Using the potentiometer for the solar voltage adjustment on the board, screw it in or out until the voltage displayed on the screen is equal to your battery voltage on the display.

Both your voltages are now set properly. Turn the ON - OFF switch off. Disconnect the battery + wire and as well the bridge you made earlier to the solar panel +. Connect the positive pin of an ammeter to the battery + terminal and connect the negative pin of the ammeter on the positive terminal of your battery.

Connect your solar panel to the board. Positive wired to the Solar panel + terminal and negative to the GND terminal of the board.

Turn the ON - OFF switch back ON. You can now uncover your solar panel and check the screen. The minimum voltage from the solar panel needs to raise to 18V before the charge cycle can begin.

Once the battery is charging, Read your ammeter and set the potentiometer for the charge current to have the correct current displayed on the screen.

Cover your solar panel again, flick the switch OFF and disconnect your ammeter. You can then reconnect your battery positive wire on the board terminal.

Last we will setup the output current potentiometer. Put your ammeter the exact same way as for the charging current but this time on the output terminal and connected to the positive side of any load you will connect to the system. (LED lights, fans, etc etc).

Flick the switch ON, uncover your solar panel and then press the output button. The output state on the display should say --Active--.

Set the output current adjustment potentiometer to have the correct value displayed on the screen in regards to the readings of your ammeter.

Step 8: Conclusion and Going Further

This controller has now been running nicely for a few months and is going well. I am open to any remarks or comments on any design faults or any improvements or ideas I could add onto this project.

Code wise it is very hard as this sketch uses nearly the full capacity of the ATMega328P at nearly 32'000 octets and any changes means that I have to tweak and change as many things around to minimize code space, I did manage to change the battery charging Watts display into Watts hours but I am still running some tests so I will update the instructable once I am happy with it and post the new code as well.

As some of you will be able to tell, I am not the king at writing code and there must definitely be some much better and easier way to get the same result but as I said just above, feel free to comment and give me any advice as possible. Learning is a never-ending thing.

I have tested the charge algorithm by simulating a solar panel voltage with my bench-top power supply and it does not perform too bad at all, I am pretty happy with the results, tracking nicely and reacting reasonably quickly to any sudden changes in supply or sudden current drains when the outputs turns ON or OFF etc.

Thanks for reading and for your time, hope you all have fun piecing one of these controller together for yourselves.

I will be entering this instructable in the make energy contest so if you like it don't hesitate to drop a vote for me.

Step 9: UPDATE: New Code Running With Watts Hours Display and Total Watts Hours Counter

As I previously said, there is an updated piece of code which is now displaying the Watts hours for the battery charging.

It will display the Watts hours and keep the display with the total value of Watts hours when the battery stopped charging, When the next charge cycle begins, the value will start again from 0.

The total amount of Watts hours, regardless of the charge cycles, will be stored and displayed when circling through the max and min values with the data button.

It can be zeroed the same way as zeroing the other min and max values.

MAKE ENERGY: A US-Mexico Innovation Challenge

Participated in the
MAKE ENERGY: A US-Mexico Innovation Challenge

Be the First to Share


    • Puzzles Challenge

      Puzzles Challenge
    • CNC and 3D Printing Contest

      CNC and 3D Printing Contest
    • Rice & Grains Challenge

      Rice & Grains Challenge



    1 year ago

    Beautiful! You can take it one step further and create a custom pcb. I'll definitely try to build this charger. Thanks and keep it up.


    4 years ago

    Great project, what changes would be required for a 24v setup?


    Reply 3 years ago


    As long as your mosfets can handle 24V, all is ok on this side.
    You might just want to recalculate the resistor dividers for the measure of the voltages.


    6 years ago

    This is truly awesome. I am working on a project to bring solar power to a poor school. I have coding experience, but no experience with the Arduino IDE or microcontrollers.

    Would anyone be able/willing to briefly coach me on what microcontroller and software tweaks I can use to convert this awesome instructable to function with a solar energy system of approxiamately 36 250-watt panels attached to a 24V 8000AH battery bank?


    Reply 6 years ago

    Hello, thank you ;-)

    This is a lot of panel and quite a big battery bank. I don't think a project like this one is really the best option. This is more of a hobby project and is by far not the most efficient way to maximise power out of a solar system. It is mainly designed for a hobby use of a couple hundred watts maximum.


    Reply 6 years ago

    OK. Understood. ty so much for your swift response!


    hi i am totally new to this thing and i want to make my own charge controller i have seen many but ur design is best i have 4 solar panels 2,2 are connected in series and my battries is 24 volt can u please help me how to make for 24 volt system with maxim current i shall be very thank ful to u brother


    Reply 6 years ago

    Hi, thank you for the nice words. I am so sorry I have not seen your comment earlier.

    24V battery is already included in the software, it will detect it at power up.

    All the specs depend on what kind of panels you have.


    7 years ago on Introduction

    you are a boss! to create this extremely desirable charge controller. I wish i had the skills.


    Reply 7 years ago on Introduction


    Thank you for your comment, wish I was the boss! You should try and build one for yourself, I am happy to help further if I can and something is not clear.



    Reply 7 years ago on Introduction

    Hey with your skills you can run your own business. In my book you are the boss!


    Reply 7 years ago on Introduction


    Sorry for my late answer. Mabye i can find a schematic drawing somewhere and a piece of code but not sure. Where would you like that posted?


    Reply 7 years ago on Introduction

    Yes of course, you will have to modify the line of code which does the calculation of the current according to your maximum desired current.

    I briefly checked the datasheet and it says it outputs 66 to 185mV / A, so that mean if you want to mesure 10A it will give you 1.85V (taking 185mV/A range)

    1.85V with the Arduino analog reference set at 5V will be (1.85 /(5/1023) = 378.88

    1023/378.88 = 2.7

    So you need to change the lines:

    charge_Current= read_pin(CHARGE_C);

    output_Current = read_pin(OUTPUT_C);


    charge_Current = read_pin(CHARGE_C)*2.7;

    output_Current = read_pin(OUTPUT_C)*2.7;

    and it will be ok.


    Reply 7 years ago

    thanks. can u design also MPPT solar charge controller with TFT display and uses ACS712 for current sensor. please post also and the code. thanks and more power