Overview
In this project we are going to build our own MPPT Solar Charge Controller using Arduino and by combining many active-passive electronics. MPPT means Maximum Power Point Tracking Controller. Most solar panels produce much higher voltage than is necessary to charge a 12V battery. A 12V charging panel will actually produce 16 to 18 volts, depending on conditions, but only about 14.6 volts is necessary to charge most 12V batteries. There most of the voltage is wasted. Using the MPPT Charging Technology, we can convert the excessive voltage to current, and hence we can increase the efficiency.
In this article, we will learn about Solar Power Charging Technology and go through MPPT Charging Technology. Later using the Arduino and many electronic components we will design the schematic and PCB for MPPT Charge Controller. Then by writing the Arduino C code, we can program the Arduino Nano to visualize all the charging parameters related to MPPT Solar Charge Controller on a 20×4 LCD Screen. The code has all the parameters and functions to measure Solar Panel Voltage, Current, Power, Battery Voltage, Charger state, SOC, PWM duty cycle, load status.
Later we can test the Charger the whole day and find out whether it is perfectly working or not. This design is suitable for a 50W solar panel to charge a commonly used 12V lead-acid battery. This article is very detailed with a lot of explanation and design methods involved which we shall discuss.
Bill of Materials
We will use the following components in our project to build an Arduino Based MPPT Solar Charge Controller.
| S.N. | Components | Quantity | Purchase Links |
|---|---|---|---|
| 1 | Arduino Nano | 1 | Amazon | AliExpress |
| 2 | 20x4 LCD Display | 1 | Amazon | AliExpress |
| 3 | ACS712 Current Sensor | 1 | Amazon | AliExpress |
| 4 | IR2104 IC | 1 | Amazon | AliExpress |
| 5 | MOSFET IRFZ44 | 4 | Amazon | AliExpress |
| 6 | Transistor 2N2222A | 1 | Amazon | AliExpress |
| 7 | Diode P6KE36CA | 1 | Amazon | AliExpress |
| 8 | Diode 1N4007 | 1 | Amazon | AliExpress |
| 9 | Diode 1N4148 | 2 | Amazon | AliExpress |
| 10 | Push Button Switch | 2 | Amazon | AliExpress |
| 11 | Resistor 100K | 1 | Amazon | AliExpress |
| 12 | Resistor 20K | 2 | Amazon | AliExpress |
| 13 | Resistor 470K | 1 | Amazon | AliExpress |
| 14 | Resistor 10K | 3 | Amazon | AliExpress |
| 15 | Resistor 1K | 1 | Amazon | AliExpress |
| 16 | Resistor 220Ω | 6 | Amazon | AliExpress |
| 17 | Capacitor 220uF | 1 | Amazon | AliExpress |
| 18 | Capacitor 10uF | 2 | Amazon | AliExpress |
| 19 | Capacitor 0.1uF | 6 | Amazon | AliExpress |
| 20 | Inductor 33uH | 1 | Amazon | AliExpress |
| 21 | Red LED | 1 | Amazon | AliExpress |
| 22 | Green LED | 1 | Amazon | AliExpress |
| 23 | Blue LED | 1 | Amazon | AliExpress |
| 24 | Solar Panel (12/24/36V) | 1 | Amazon | AliExpress |
| 25 | Lead Acid Battery 12V | 1 | Amazon | AliExpress |
| 26 | Terminal Blocks | 3 | Amazon | AliExpress |
| 27 | Female Headers | 2 Sets | Amazon | AliExpress |
| 28 | DC Jack | 1 | Amazon | AliExpress |
You can purchase all the components from the given links.
What is a Solar Charge Controller?
A solar charge controller is an electronic device that regulates the flow of electrical current from a solar panel to a battery or a bank of batteries.
It ensures that the battery is not overcharged or undercharged, which can damage the battery and reduce its overall lifespan. The solar charge controller also prevents the battery from discharging back through the solar panel at night. It is a critical component in a solar power system. The Solar Power can be measured using Pyranometer Sensor.
Types of Charge controller
Every solar panel system that has batteries needs a charge controller. Its purpose is to regulate and control the power coming from the solar panels to the batteries to prolong the health of the batteries.
There are three types of charge controllers:
- Simple on-off Controller (ON OFF)
- Pulse Width Modulation Controller (PWM)
- Maximum Power Point tracking controller (MPPT)
On-off controllers are very simple devices. All they do is detect the voltage of the battery bank and turn on or off the power.
Pulse width modulation controllers will charge a little bit faster than on-off controllers, and then they taper down the voltage as the battery gets full. When the battery is full, the controller switches to a float charging profile, which basically just keeps a trickle of current coming into the battery to keep it from discharging. PWM controllers will extend the life of a battery over simple on-off controllers.
Maximum Power Point Tracking Controllers (MPPT)
An MPPT (Maximum Power Point Tracking) charge controller is an electronic device that regulates the charging of batteries from solar panels by maximizing the amount of power from the solar panel that is stored in the battery. It does this by continuously adjusting the voltage and current of the solar panel to match the optimal charging voltage of the battery. This allows the battery to charge more quickly and efficiently, and can also increase the overall power output of a solar system.
Maximum PowerPoint tracking controllers are much more advanced and much more efficient than the two above-mentioned older types. These controllers are smart enough to be able to convert excess voltage into an additional current that normally would be wasted by a PWM controller.
Most solar panels produce much higher voltage than is necessary to charge a 12V battery, or 24 or 48 volts if you have that configuration. A 12V charging panel will actually produce 16 to 18 volts, depending on conditions, but only about 14.6 volts is necessary to charge most 12V batteries. So, the MPPT controller can convert those extra volts into more current, which will charge the battery faster and be much more efficient.
Advantages & Disadvantages of MPPT Solar Charge Controller
The MPPT controller can convert those extra volts into more current, which will charge the battery faster and be much more efficient. Another advantage of MPPT controllers is that they can handle much higher voltage configurations of solar panels to help minimize voltage drop or line losses. In other words, you can wire more solar panels in series in order to increase the input voltage, allowing you to run smaller gauge wires or travel much farther distances between panels and the charge controller without big losses. This benefit also allows you to run bigger panel arrays than you normally could with a PWM controller.
So if you’re grid-tied and you want to add some batteries in for backup power, MPPT is the only way you can do it. MPPT controllers are about 94% to 99% efficient, which can be as much as 30% more efficient than a similar PWM controller. However, they usually cost two to three times more than PWM. Because MPPT is still a new technology. They’re also usually much bigger than a PWM controller.
MPPT controllers are critical for off-grid solar panel systems in cold climates or areas with lots of cloud cover, as they can extract every bit of solar power that’s available. One of the only other drawbacks to MPPT is that they don’t work very well in low light conditions because they have a hard time finding that sweet spot of maximum power. Luckily, those conditions don’t last very long, and it more than makes up for it the rest of the day.
Designing of MPPT Solar Charge Controller using Arduino
Now let us design the MPPT Solar Charge Controller project using Arduino. A lot of calculations and complex algorithms is considered while designing this project.
This project is designed with reference taken from opengreenenergy and asmlektor design. We have modified the design according to our requirements.
Features & Specifications
The charge controller has the following features:
- Based on MPPT algorithm
- Multiple LED indication for the state of charge
- 20×4 character LCD display for displaying voltages, current, power, load state, etc
- Overvoltage / Lightning protection
- Short Circuit, Overload and Reverse Polarity protection
- Rated Voltage= 12V
- Maximum current = 5A
- Maximum load current =10A
- Input Voltage = Solar panel with Open circuit voltage from 12 to 25V
- Solar panel power = 50W
Schematic/Circuit Design
A solar panel will generate different voltages depending on different parameters like the quantity of sunlight, connected load & temperature of the solar panel.
The project consists of many steps and has a lot of design calculations involved. All the steps are explained in this section. Here is the complete schematic for this project.
As the sunlight quantity changes throughout the day. Hence, the voltage produced by the solar panel will constantly vary. Due to the varying voltage, the varying current is produced. The amount of current produced in Amps for any given voltage is determined by a graph called an IV curve which looks something like this.
In this graph, the blue line shows a solar panel voltage of 30V corresponding to a current of about 6.2A. The green line shows a Voltage of 35V corresponds to a current of 5A.
We know that, Power = V x I
In the above graph, there is a point where voltage is multiplied by its corresponding current will yield Maximum power. This maximum power is called Maximum Power Point Tracking (MPPT). You may also use Amps to Watt Calculator.
The Solar Panel used in our project has the following parameters defined as shown in the image below.
Design Considerations & Selecting Right Component
For a 50W Solar panel and a load of 12V lead-acid battery, we need to design a Buck Converter. The Buck converter in our case is designed using the Inductor, Capacitor, and MOSFETS. The switching frequency is inversely proportional to the size of the inductor and capacitor and directly proportional to the switching losses in MOSFETs.
Keeping these constraints into consideration the selected frequency is 50KHz. To achieve this frequency, we have used an inductor of 33uH and a Capacitor of 220uF. For the MOSFET part, we used IRFZ44N MOSFET as it is easily available. The IRFZ44N MOSFET Vds and Ids value have enough margin & low Rds(On) value. For driving the MOSFET, we need a MOSFET driver IC. The IR2104 Half-Bridge driver is best suited for this application. The IC takes the incoming PWM signal from the microcontroller and then drives two outputs for a High and a Low Side MOSFET.
Working of the Circuit
The Solar Panel voltage is fed as an input voltage. The buck converter is made up of the synchronous MOSFET switches Q4 and Q5 & the energy storage devices inductor L1 & capacitors C4 and C9. The inductor smooths the switching current and along with C4, it smooths the output voltage. Capacitors C3 & Resistor R4 are snubber networks, used to cut down on the ringing of the inductor voltage generated by the switching current in the inductor.
The MOSFET Q3 is added to allow the system to block the battery power from flowing back into the solar panels at night. Q3 turns on when Q4 is on from voltage through D2. R3 drains the voltage of the gate of Q3 so it turns off when Q4 turns off.
The IC IR2104 is a half-bridge MOSFET gate driver. It drives the high and low-side MOSFETs using the PWM signal from the Arduino Pin D6. The IR2104 can also be shut down with the control signal from the D5 Pin of Arduino on pin 3. D4 & C6 are part of the bootstrap circuit that generates the high side gate drive voltage for Q3 & Q4. The software keeps track of the PWM duty cycle and never allows 100% or always on. It caps the PWM duty cycle at 99.9% to keep the charge pump working.
There are two voltage divider circuits (R1, R2, and R7, R8) to measure the solar panel and battery voltages respectively. The output from the dividers feeds the voltage signal to Analog Pin A0 & A2 of Arduino.
The diode D3 is supposed to make the converter more efficient. The diodes D1 & D5 are TVS diodes used for overvoltage protection from the solar panel and load side. The MOSFET Q2 is used to control the load. The driver for this MOSFET consists of a 2N2222 transistor Q1 and resistors R5, and R6.
The current sensor ACS712 senses the current from the solar panel and feeds it to the Arduino analog pin A1. The 3 LEDs are connected to the digital pins of the microcontroller and serve as an output interface to display the charging state. The backlight switch is to control the backlight of the LCD display. If the user presses the switch then it will be on for 15 secs and again go off.
Hardware Assembly
Before soldering you should clear about the Power and Control Signal. Do not mix up between them. Otherwise, you will fry everything.
To assemble all the components as per the circuit diagram I used the Zero PCB or a Vero Board.
For our project, I used 24V Solar Panel. The Solar Panel is huge and can collect a large quantity of light. The Solar Panel is connected at the Input Terminal of the assembled circuit. Similarly a 12V, 7Ah Lead-Acid Battery is connected as a battery Terminal. The Load can output the required voltage. The Load can be directly connected to an Inverter or some battery-operated devices.
To power the Arduino Nano Board and some other part of the circuit, a 5V-9V DC Adapter can be used.
Arduino Source Code/Program
We can use Arduino IDE to write the MPPT Solar Charge Controller Project Code. The code has all the parameters and functions to measure Solar Panel Voltage, Current, Power, Battery Voltage, Charger state, SOC, PWM duty cycle, load status. The 20×4 LCD Display will show the real-time status of this parameters.
The code requires I2C LCD Library and also the TimerOne Library for compilation.
Copy the following code and upload it to the Arduino Nano Board.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 |
#include "TimerOne.h" #include <LiquidCrystal_I2C.h> #include <Wire.h> #define ENABLE_DATALOGGER 0 #define LOAD_ALGORITHM 1 #define SOL_AMPS_CHAN 1 #define SOL_VOLTS_CHAN 0 #define BAT_VOLTS_CHAN 2 #define AVG_NUM 8 // #define SOL_AMPS_SCALE 0.026393581 #define SOL_VOLTS_SCALE 0.029296875 #define BAT_VOLTS_SCALE 0.029296875 #define PWM_PIN 6 #define PWM_ENABLE_PIN 5 #define PWM_FULL 1023 #define PWM_MAX 100 #define PWM_MIN 60 #define PWM_START 90 #define PWM_INC 1 #define TRUE 1 #define FALSE 0 #define ON TRUE #define OFF FALSE #define TURN_ON_MOSFETS digitalWrite(PWM_ENABLE_PIN, HIGH) #define TURN_OFF_MOSFETS digitalWrite(PWM_ENABLE_PIN, LOW) #define ONE_SECOND 50000 #define LOW_SOL_WATTS 5.00 #define MIN_SOL_WATTS 0.10 #define MIN_BAT_VOLTS 11.00 #define MAX_BAT_VOLTS 14.10 #define BATT_FLOAT 13.60 #define HIGH_BAT_VOLTS 13.00 #define LVD 11.5 #define OFF_NUM 9 #define LED_YELLOW 12 #define LED_GREEN 11 #define LED_RED 10 #define LOAD_PIN 4 #define BACK_LIGHT_PIN 3 float AcsValue, ss = 0.0; byte battery_icons[6][8] = {{ 0b01110, 0b11011, 0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b11111, }, { 0b01110, 0b11011, 0b10001, 0b10001, 0b10001, 0b10001, 0b11111, 0b11111, }, { 0b01110, 0b11011, 0b10001, 0b10001, 0b10001, 0b11111, 0b11111, 0b11111, }, { 0b01110, 0b11011, 0b10001, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, }, { 0b01110, 0b11011, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, }, { 0b01110, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, } }; #define SOLAR_ICON 6 byte solar_icon[8] = { 0b11111, 0b10101, 0b11111, 0b10101, 0b11111, 0b10101, 0b11111, 0b00000 }; #define PWM_ICON 7 byte _PWM_icon[8] = { 0b11101, 0b10101, 0b10101, 0b10101, 0b10101, 0b10101, 0b10101, 0b10111, }; byte backslash_char[8] = { 0b10000, 0b10000, 0b01000, 0b01000, 0b00100, 0b00100, 0b00010, 0b00010, }; float sol_amps; float sol_volts; float bat_volts; float sol_watts; float old_sol_watts = 0; unsigned int seconds = 0; unsigned int prev_seconds = 0; unsigned int interrupt_counter = 0; unsigned long time = 0; int delta = PWM_INC; int pwm = 0; int back_light_pin_State = 0; boolean load_status = false; enum charger_mode {off, on, bulk, bat_float} charger_state; LiquidCrystal_I2C lcd(0x27, 20, 4); void setup() { pinMode(PWM_ENABLE_PIN, OUTPUT); TURN_OFF_MOSFETS; charger_state = off; lcd.init(); lcd.backlight(); for (int batchar = 0; batchar < 6; ++batchar) { lcd.createChar(batchar, battery_icons[batchar]); } lcd.createChar(PWM_ICON, _PWM_icon); lcd.createChar(SOLAR_ICON, solar_icon); lcd.createChar('\\', backslash_char); pinMode(LED_RED, OUTPUT); pinMode(LED_GREEN, OUTPUT); pinMode(LED_YELLOW, OUTPUT); Timer1.initialize(20); Timer1.pwm(PWM_PIN, 0); Timer1.attachInterrupt(callback); Serial.begin(9600); pwm = PWM_START; pinMode(BACK_LIGHT_PIN, INPUT); pinMode(LOAD_PIN, OUTPUT); digitalWrite(LOAD_PIN, LOW); digitalWrite(BACK_LIGHT_PIN, LOW); lcd.setCursor(0, 0); lcd.print("SOL"); lcd.setCursor(4, 0); lcd.write(SOLAR_ICON); lcd.setCursor(8, 0); lcd.print("BAT"); } void loop() { read_data(); run_charger(); print_data(); load_control(); led_output(); lcd_display(); } int read_adc(int channel) { int sum = 0; int temp; int i; for (i = 0; i < AVG_NUM; i++) { temp = analogRead(channel); sum += temp; delayMicroseconds(50); } return (sum / AVG_NUM); } float read_adccc() { int i; float AcsValue, ss = 0.0; for (i = 0; i < AVG_NUM; i++) { AcsValue = analogRead(A1); ss += mapf(AcsValue, 510, 580, 0.0, 5.0); delayMicroseconds(50); } Serial.println(AcsValue); Serial.println(ss / AVG_NUM); return (ss / AVG_NUM); } void read_data(void) { sol_amps = read_adccc(); sol_volts = read_adc(SOL_VOLTS_CHAN) * SOL_VOLTS_SCALE; bat_volts = read_adc(BAT_VOLTS_CHAN) * BAT_VOLTS_SCALE; sol_watts = sol_amps * sol_volts ; } void callback() { if (interrupt_counter++ > ONE_SECOND) { interrupt_counter = 0; seconds++; } } void set_pwm_duty(void) { if (pwm > PWM_MAX) { pwm = PWM_MAX; } else if (pwm < PWM_MIN) { pwm = PWM_MIN; } if (pwm < PWM_MAX) { Timer1.pwm(PWM_PIN, (PWM_FULL * (long)pwm / 100), 20); } else if (pwm == PWM_MAX) { Timer1.pwm(PWM_PIN, (PWM_FULL - 1), 20); } } void run_charger(void) { static int off_count = OFF_NUM; switch (charger_state) { case on: if (sol_watts < MIN_SOL_WATTS) { charger_state = off; off_count = OFF_NUM; TURN_OFF_MOSFETS; } else if (bat_volts > (BATT_FLOAT - 0.1)) { charger_state = bat_float; } else if (sol_watts < LOW_SOL_WATTS) { pwm = PWM_MAX; set_pwm_duty(); } else { pwm = ((bat_volts * 10) / (sol_volts / 10)) + 5; charger_state = bulk; } break; case bulk: if (sol_watts < MIN_SOL_WATTS) { charger_state = off; off_count = OFF_NUM; TURN_OFF_MOSFETS; } else if (bat_volts > BATT_FLOAT) { charger_state = bat_float; } else if (sol_watts < LOW_SOL_WATTS) { charger_state = on; TURN_ON_MOSFETS; } else { if (old_sol_watts >= sol_watts) { delta = -delta; } pwm += delta; old_sol_watts = sol_watts; set_pwm_duty(); } break; case bat_float: if (sol_watts < MIN_SOL_WATTS) { charger_state = off; off_count = OFF_NUM; TURN_OFF_MOSFETS; set_pwm_duty(); } else if (bat_volts > BATT_FLOAT) { TURN_OFF_MOSFETS; pwm = PWM_MAX; set_pwm_duty(); } else if (bat_volts < BATT_FLOAT) { pwm = PWM_MAX; set_pwm_duty(); TURN_ON_MOSFETS; if (bat_volts < (BATT_FLOAT - 0.1)) { charger_state = bulk; } } break; case off: TURN_OFF_MOSFETS; if (off_count > 0) { off_count--; } else if ((bat_volts > BATT_FLOAT) && (sol_volts > bat_volts)) { charger_state = bat_float; TURN_ON_MOSFETS; } else if ((bat_volts > MIN_BAT_VOLTS) && (bat_volts < BATT_FLOAT) && (sol_volts > bat_volts)) { charger_state = bulk; TURN_ON_MOSFETS; } break; default: TURN_OFF_MOSFETS; break; } } void load_control() { #if LOAD_ALGORITHM == 0 load_on(sol_watts < MIN_SOL_WATTS && bat_volts > LVD); #else load_on(sol_watts > MIN_SOL_WATTS && bat_volts > BATT_FLOAT); #endif } void load_on(boolean new_status) { if (load_status != new_status) { load_status = new_status; digitalWrite(LOAD_PIN, new_status ? HIGH : LOW); } } void print_data(void) { Serial.print(seconds, DEC); Serial.print(" "); Serial.print("Charging = "); if (charger_state == on) Serial.print("on "); else if (charger_state == off) Serial.print("off "); else if (charger_state == bulk) Serial.print("bulk "); else if (charger_state == bat_float) Serial.print("float"); Serial.print(" "); Serial.print("pwm = "); if (charger_state == off) Serial.print(0, DEC); else Serial.print(pwm, DEC); Serial.print(" "); Serial.print("Current (panel) = "); Serial.print(sol_amps); Serial.print(" "); Serial.print("Voltage (panel) = "); Serial.print(sol_volts); Serial.print(" "); Serial.print("Power (panel) = "); Serial.print(sol_volts); Serial.print(" "); Serial.print("Battery Voltage = "); Serial.print(bat_volts); Serial.print(" "); Serial.print("\n\r"); } void light_led(char pin) { static char last_lit; if (last_lit == pin) return; if (last_lit != 0) digitalWrite(last_lit, LOW); digitalWrite(pin, HIGH); last_lit = pin; } void led_output(void) { static char last_lit; if (bat_volts > 14.1 ) light_led(LED_YELLOW); else if (bat_volts > 11.9) light_led(LED_GREEN); else light_led(LED_RED); } void lcd_display() { static bool current_backlight_state = -1; back_light_pin_State = digitalRead(BACK_LIGHT_PIN); if (current_backlight_state != back_light_pin_State) { current_backlight_state = back_light_pin_State; if (back_light_pin_State == HIGH) lcd.backlight(); else lcd.noBacklight(); } if (back_light_pin_State == HIGH) { time = millis(); } lcd.setCursor(0, 1); lcd.print(sol_volts); lcd.print("V "); lcd.setCursor(0, 2); lcd.print(sol_amps); lcd.print("A"); lcd.setCursor(0, 3); lcd.print(sol_watts); lcd.print("W "); lcd.setCursor(8, 1); lcd.print(bat_volts); lcd.setCursor(8, 2); if (charger_state == on) lcd.print("on "); else if (charger_state == off) lcd.print("off "); else if (charger_state == bulk) lcd.print("bulk "); else if (charger_state == bat_float) { lcd.print(" "); lcd.setCursor(8, 2); lcd.print("float"); } int pct = 100.0 * (bat_volts - 11.3) / (12.7 - 11.3); if (pct < 0) pct = 0; else if (pct > 100) pct = 100; lcd.setCursor(12, 0); lcd.print((char)(pct * 5 / 100)); lcd.setCursor(8, 3); pct = pct - (pct % 10); lcd.print(pct); lcd.print("% "); lcd.setCursor(15, 0); lcd.print("PWM"); lcd.setCursor(19, 0); lcd.write(PWM_ICON); lcd.setCursor(15, 1); lcd.print(" "); lcd.setCursor(15, 1); if ( charger_state == off) lcd.print(0); else lcd.print(pwm); lcd.print("% "); lcd.setCursor(15, 2); lcd.print("Load"); lcd.setCursor(15, 3); if (load_status) { lcd.print("On "); } else { lcd.print("Off "); } spinner(); backLight_timer(); } void backLight_timer() { if ((millis() - time) <= 15000) lcd.backlight(); else lcd.noBacklight(); } void spinner(void) { static int cspinner; static char spinner_chars[] = { '*', '*', '*', ' ', ' '}; cspinner++; lcd.print(spinner_chars[cspinner % sizeof(spinner_chars)]); } float mapf(float x, float in_min, float in_max, float out_min, float out_max) { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } |
Testing the Arduino MPPT Solar Charge Controller
Now let us do the final testing of our Arduino MPPT Solar Charge Controller project and find out how efficient it is.
Initially you need to calibrate the ACS712 Current Sensor so that it can measure the current accurately. The ACS712 sensor reads the current value and converts it into a relevant voltage value. You can download the ACS712 Calibration Code if you wanna calibrate the sensor.
In case you are okay with the calibration then you can upload the main source code above. After uploading the code, the LCD will display the following parameters.
The LCD will display all the voltages as 0 as, we didn’t connect the Solar Panel, Load, Battery currently.
If we expose Solar Panel outside, it gives a voltage of almost 20V.
When we connect the Solar Panel to the input terminal of the circuit, the LCD will display the value of Solar panel voltage, Current and Power in the first column.
When we connect the Battery to the circuit, the LCD will display Battery Voltage, Charger state, and SOC in the 2nd column.
At last, we can connect any load to the load terminal for testing the status. The LCD will show the PWM duty cycle and load status on the 3rd column.
The Red, Green and Yellow LEDs are used to indicate the battery voltage level.
- Low Voltage — > Red led
- Normal Voltage –> Green Led
- Fully Charged –> Yellow Led
While testing we can notice that the voltage to the solar panel increases initially, if the output power increase, the voltage continually increases until the output power starts decreasing. Once the output power starts decreasing, the voltage to the solar panel decreases until it reaches maximum power. This process is continued until the MPPT is attained. This result is an oscillation of the output power around the MPP.
This is how you can design and develop your own MPPT Solar Charge Controller using Arduino. We can do a lot of modifications and design the circuit with additional features to increase efficiency with better results.
Video Tutorial & Guide
You can also follow some of our previous projects like:

























33 Comments
nice sir
Can you help the community and help with a proper parts list for the link added because the author has been out of contact the last few years:
https://www.instructables.com/DIY-1kW-MPPT-Solar-Charge-Controller/
But I love this project too. I just want to help project that died and I think it can help a lot of people.
We are currently buliding a Similar project with IoT Capability. Stay tuned, we will post it soon.
good
Can you teach us, how is the complete calculation so you can form the circuit?
Can I use 12V 20W solar panel instead of 24V?
VCC pin of IR2104 (Mosfet Driver) is not fed.
Hi Thanks, we have updated the schematic and PCB.
i would like to purchase ready project of ____MPPT Solar Charge Controller using Arduino with loaded program code and assembled components ………..what price ????? and how to proceed ?????
Is the R7 really 10K? Could it be 100k?
I want to purchase the simulation of this project. Is this possible?
I need to design and implement a MPPT charge controller for 3.7V lithium ion batteries. What should I modify? I await your response. Thank you so much. Greetings from Venezuela
This circuit is for 12V battery not for a 3.7V.
Keeping these constraints into consideration the selected frequency is 50KHz. To achieve this frequency, we have used an inductor of 33uH and a Capacitor of 220uF.
…
f = 1/(2pisqrt(33uH*220uF)) = 1.8679kHz ??
Hello, I have designed the same project but its not working. Did you do any changes in the code?
No changes
Everything is same.
what would be the possible reason for its not working?
Hi – what is the function of switch S1 ?
can you please share the design calculations.
Push button S1 sets D3 (pin 6) to HIGH. In the code pin 6 is called PWM_PIN and is used by timer1. But I don’t understand what it is exactly doing 🙁
I want to make project ..please could you contact with me
my whatsapp :+ 8801638585431
Hi.. i tried to build the circuit and facing the same issues that Deba168 faced. I could’nt find any difference between your circuits. can you please tell what modification you made from his circuit.
There was some issues in the schematic. It is updated now. Check the schematic again. The current schematic circuit is tested multiple times and works very well. Also a little modification in the code is made, which has also been updated.
Sorry to bother you sir, may I know where to get the latest modification of the schematic diagram and the code? I am trouble with the circuit so far. Thank you for your patience to reply me.
Hi.. thank you for your quick response. I will modify mine and check and will let you know.
Hi i have bought all of this components on 19/08/2023, i need now to buy another time all?
I have tried to compile new Sketch but i have this error:
C:\Users\Laboratorio\Documents\Arduino\solar_mppt\solar_mppt.ino:57:28: error: ‘BULK’ redeclared as different kind of symbol
enum ChargerMode {OFF, ON, BULK, BAT_FLOAT} chargerState;
^~~~
C:\Users\Laboratorio\Documents\Arduino\solar_mppt\solar_mppt.ino:39:12: note: previous declaration ‘const byte BULK’
const byte BULK = 0;
^~~~
exit status 1
Compilation error: ‘BULK’ redeclared as different kind of symbol
at one point you say:
“The code requires I2C LCD Library and also the TimerOne Library for compilation.”
But i dont see #include “TimerOne.h” in the code
Hi i have bought all of this components on 19/08/2023, i need now to buy components and PCB another time?
Kk thank you now compile fine, but i have bought all of this components and PCB on 19/08/2023, i need now buy components and PCB another time?
Thnak you
Use the schematic and assemble on the breadboard.
Now you have added a diode D4 to prevent reverse flow from battery, is there any need of MOSFET Q1, resistor R3 and diode D2 in the circuit.
Hello. Is it possible to request for the easyeda file for this project. We saw this project and decided to make it our basis for our own undergraduate thesis. I hope you see this message and thank you in advance for considering our request.
Hello sir I would like to contact you about this project. Please do respond.