Arduino - PV MPPT 太阳能充电器
组件和用品
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 |
必要的工具和机器
|
应用和在线服务
|
关于这个项目
市场上有许多充电控制器,但普通廉价的充电控制器在太阳能电池板的最大功率下使用效率不高。而那些有效率的却是非常昂贵的。
所以我决定让我自己的充电控制器变得高效和智能,以了解电池需求和太阳能条件。采取适当措施从太阳能中获取最大可用功率并将其非常有效地放入电池中。
如果您喜欢我的努力,请为本教程投票。
第 1 步:什么是 MPPT,我们为什么需要它?
我们的太阳能电池板很笨,不够聪明,无法了解电池状况。假设我们有一个 12v/100 瓦的太阳能电池板,它会根据制造商的不同提供 18V-21V 的输出,但电池的额定电压为 12v。在完全充电条件下,它们将为 13.6v,在完全放电时为 11.0v。现在让我们假设我们的电池以 13v 充电,面板以 100% 的工作效率提供 18v、5.5A(不可能有 100%,但让我们假设)。普通控制器有一个 PWM 电压调节器 ckt,可将电压降至 13.6,而没有任何电流增益。仅在夜间提供过充电保护和面板漏电流保护。
为了解决这个问题,我使用了 smps 降压转换器。这种转换器具有 90% 以上的效率。即使 90% 也被认为是穷人。
我们遇到的第二个问题是太阳能电池板的非线性输出。它们需要在特定电压下运行才能获得最大可用功率。他们的产出每天都在变化。
为了解决这个问题,使用了 MPPT 算法。 MPPT(最大功率点跟踪)顾名思义,该算法跟踪面板的最大可用功率,并改变输出参数以维持条件。
因此,通过使用 MPPT,我们的面板将产生最大可用功率,而降压转换器将有效地将这些电荷放入电池中。
第 2 步:MPPT 如何工作?
我不打算详细讨论这个,所以如果你想了解它,看看这个链接 - 什么是 MPPT?
在这个项目中,我还跟踪了输入 V-I 特性和输出 V-I。通过将输入 V-I 和输出 V-I 相乘,我们可以获得以瓦特为单位的功率。
假设我们在一天中的任何时间都有 17 V 5 A,即 17x5 =85 瓦特。同时我们的输出是 13 V 6A,即 13x6 =78 瓦。
现在MPPT将通过与以前的输入/输出功率相比将输出电压增加或减少到。
如果之前的输入功率为高,而输出电压低于当前,则输出电压将再次降低以恢复为高功率。如果输出电压高,则当前电压将增加到以前的水平。因此它一直围绕最大功率点振荡。这些振荡通过有效的 MPPT 算法被最小化。
第 3 步:在 Arduino 上实现 MPPT
这是这款充电器的大脑。以下是在单个代码块中调节输出和实现 MPPT 的 Arduino 代码。
// Iout =输出电流// Vout =输出电压// Vin =输入电压// Pin =输入功率,Pin_previous =最后输入功率// Vout_last =最后输出电压,Vout_sense =当前输出电压无效调节(float Iout, float Vin, float Vout) {
if((Vout>Vout_max) || (Iout>Iout_max) || ((Pin>Pin_previous &&Vout_senseVout_last ))) { if(duty_cycle>0) { duty_cycle -=1;模拟写入(buck_pin,duty_cycle); } else if ((VoutPin_previous &&Vout_sense>Vout_last) || (Pin占空比+=1;模拟写入(buck_pin,duty_cycle); Pin_previous =Pin; Vin_last =Vin;Vout_last =Vout;}
第 4 步:降压转换器
我使用 N 通道 mosfet 来制作降压转换器。通常人们选择 P 沟道 mosfet 用于高侧开关,如果他们出于相同目的选择 N 沟道 mosfet,则需要驱动器 IC 或自举 ckt。
但我修改了降压转换器 ckt 以使用 N 沟道 mosfet 进行低侧开关。我使用 N 通道是因为它们成本低、额定功率高且功耗低。本项目使用IRFz44n逻辑电平mosfet,可直接由Arduino PWM引脚驱动。
对于更高的负载电流,应使用晶体管在栅极施加 10V 电压,以使 mosfet 完全饱和并最大限度地降低功耗。我也是这样做的。
正如您在上面的 ckt 中看到的那样,我已将 mosfet 置于 -ve 电压上,因此将面板上的 +12v 用作接地。这种配置使我能够使用 N 沟道 mosfet 以最少的组件实现降压转换器。
但它也有一些缺点。由于您将两侧 -V 电压分开,因此您不再有共同的参考地。所以电压的测量非常棘手。
我已经在太阳能输入端子上连接了 Arduino,使用它的 -Ve 线作为 Arduino 的接地。我们可以根据我们的要求使用分压器 ckt 轻松测量此时的输入电压。但是我们不能那么容易地测量输出电压,因为我们没有共同点。
现在要做到这一点有一个技巧。我没有测量输出电容器两端的电压,而是测量了两条 -Ve 线之间的电压。使用太阳能 -Ve 作为 Arduino 的地,输出 -Ve 作为要测量的信号/电压。应从测量的输入电压中减去您通过此测量获得的值,您将获得输出电容器两端的实际输出电压。
Vout_sense_temp=Vout_sense_temp*0.92+float(raw_vout)*volt_factor*0.08; //测量输入接地和输出接地的电压。
Vout_sense=Vin_sense-Vout_sense_temp-diode_volt; //改变两个地之间的电压差为输出电压..
对于电流测量,我使用了 ACS-712 电流传感模块。它们由Arduino供电并连接到输入GND。
内部定时器被修改为在引脚 D6 处获得 62.5 Khz PWM,用于驱动 MOSFET。为此,将需要一个输出阻塞二极管来提供反向泄漏和反向极性保护,为此使用所需额定电流的肖特基二极管。电感值取决于频率和输出电流要求。您可以使用在线可用的降压转换器计算器或使用 100uH 5A-10A 负载。切勿超过电感器最大输出电流的 80%-90%。
第 5 步:最后润色
您还可以为充电器添加其他功能。我的有LCD显示参数和2个开关接受用户输入。
我会尽快更新最终代码并完成ckt图。
第 6 步:实际电路图、BOM 和代码
更新:
我已经上传了代码、bom 和电路。它和我的略有不同,因为它更容易制作。
Solar_charger_tutorial_code.ino
代码
- Solar_charger_tutorial_code.ino
Solar_charger_tutorial_code.inoArduino
///////////////////////////////////////////// //////////////////////////////////////////使用条款///// ////////////////////////////////////////////////// //////////////////////////////本软件“按原样”提供,不提供任何形式的明示保证或//暗示,包括但不限于适销性保证,//适用于特定目的和不侵权。在任何情况下,//作者或版权持有人均不对任何索赔、损害或其他//责任承担责任,无论是在合同诉讼、侵权行为或其他方面,源自、//来自软件或在//软件中使用或其他交易。////////////////////////////////////// ///////////////////////////////////////////////#include#include #include #define vin_pin A1#define vout_pin A0#define iout_pin A2#define iin_pin A3#define lm35 A4#define fan 5#define buck_pin 6#define menu 3#define button 2#define led 13#define charge_led A5#define light 4uint8_t auto_mode=1;float Pin=0,Pout=0,Pin_previous=0;float efficiency=0.0;int raw_vin=0, raw_vout=0, raw_iout =0,raw_iin=0, raw_lm35=0;float Vout_boost=14.5,Vout_max=15.0, Iout_max=5.0, Vout_float=13.5, Iout_min=0.00,Vin_thresold=10.0;float Iout_sense,Iin_sense,Vin_float_float_float_last_ins;;float Vin_sense;uint8_t duty_cycle =0;float volt_factor =0.05376; //更改此值以校准电压读数...String mode="";bool startup=true, lcd_stat=true,charge=true,mppt_init =true;unsigned int count=0;LiquidCrystal lcd(7, 8, 9, 10, 11, 12);void lcd_show(String data,int column, int row);void UI();void set_limits(int cmd,int temp);void mem_read();void mem_write();void mppt();无效设置(){ wdt_disable();看门狗设置(); // 把你的设置代码放在这里,运行一次:Serial.begin(115200);mem_read();pinMode(light,OUTPUT);pinMode(charge_led,OUTPUT);digitalWrite(charge_led,LOW);digitalWrite(light,HIGH);pinMode(led,OUTPUT);pinMode(fan,OUTPUT);pinMode(menu,INPUT);pinMode(button,INPUT);digitalWrite(menu,HIGH);digitalWrite(button,HIGH);TCCR0B =TCCR0B &0b11111000 | 0x01; / 将 pwm 设置为最大... 62.5 KhzanalogWrite(buck_pin,0);lcd.begin(16,2);lcd_show("Solar Charger",0,0);delay(64000);wdt_reset();delay(64000);wdt_reset();lcd_show("Vi Vb Ib ",0,0);//////////////////for(int i=0;i<10;i++) { raw_iout +=analogRead(iout_pin)-513;raw_iin +=analogRead(iin_pin)-513;raw_vin +=analogRead(vin_pin);raw_vout +=analogRead(vout_pin);raw_lm35 +=analogRead(lm35);delay(2); } raw_iout=raw_iout/10; raw_iin=raw_iin/10; raw_vout=raw_vout/10; raw_vin=raw_vin/10; Iout_sense=float(raw_iout)*5/1023/0.066; Iin_sense=float(raw_iin)*5/1023/0.066; Vout_sense_temp=float(raw_vout)*volt_factor; Vin_sense=float(raw_vin)*volt_factor; // heat_sink_temp =raw_lm35*0.48; // 0.0049*1000/10 // heat_sink_temp =heat_sink_temp-273.15; //取消注释如果使用LM235}//////////void watchdogSetup(void){cli(); // 禁用所有中断swdt_reset(); // 重置 WDT 定时器 // 进入看门狗配置模式:WDTCSR |=(1< Vout_max) || (Iout>Iout_max) || ((Pin>Pin_previous &&Vin_sense Vin_last))) { if(duty_cycle>0) { duty_cycle-=1;模拟写入(buck_pin,duty_cycle); } else if((Vout Pin_previous &&Vin_sense>Vin_last) || (Pin Iout_min+1){ charge =true; } ///////////// if((Vout>Vout_max) &&(Iout 80.0){ duty_cycle=0;模拟写入(buck_pin,duty_cycle); Serial.println("过热关机"); lcd_show("过热失败",0,1); wdt_reset(); for(int i=0;i<10;i++){ digitalWrite(led,HIGH);数字写入(charge_led,低);延迟(4000);数字写入(charge_led,HIGH);数字写入(LED,低);延迟(4000); } wdt_reset(); }其他{收费=真;数字写入(charge_led,HIGH);调节(Iout_sense,Vin_sense,Vout_sense);数字写入(LED,低); }}void soft_start() { for(int i=0;i<20;i++) {调节(Iout_sense, Vin_sense, Vout_sense);Serial.print("Vin=");Serial.println(Vin_sense);Serial.print ("Vout=");Serial.println(Vout_sense);Serial.print("Iout=");Serial.println(Iout_sense);Serial.print("Duty cycle=");Serial.println(duty_cycle);Serial .print("充电器模式:");Serial.println(mode);Serial.println("Soft Start Activated");延迟(32000); } 启动=假; mppt_init =false;}void lcd_show(字符串数据,整数列,整数行){ lcd.setCursor(列,行); if(data.length()>0) { for(int i=0;i 0) { String data =Serial.readString(); int temp =data.toInt(); int func=temp%10;温度=温度/10; set_limits(func,temp); } //// for(int i=0;i<10;i++) {raw_iout +=analogRead(iout_pin)-513;raw_iin +=analogRead(iin_pin)-513;raw_vin +=analogRead(vin_pin);raw_vout +=模拟读取(vout_pin);raw_lm35 +=模拟读取(lm35);延迟(1); } ////////// raw_iout=raw_iout/10; raw_iin=raw_iin/10; raw_vout=raw_vout/10; raw_vin=raw_vin/10; raw_lm35=raw_lm35/10; ///// Iout_sense=float(raw_iout)*5/1023/0.066; Iin_sense=float(raw_iin)*5/1023/0.066; Vin_sense=Vin_sense*0.92+float(raw_vin)*volt_factor*0.08; Vout_sense=Vout_sense*0.92+float(raw_vout)*volt_factor*0.08; //测量输出电压。 heat_sink_temp =heat_sink_temp*0.92 + float(raw_lm35)*0.48*0.08; // 0.0049*1000/10 ////////// if(Iout_sense<0.0){ Iout_sense=Iout_sense*(-1); } if(Iin_sense<0.0){ Iin_sense =Iin_sense*(-1); Pin =Vin_sense*Iin_sense; Pout =Vout_sense*Iout_sense;效率 =Pout*100/Pin;如果(效率<0.0){效率=0.0; }if(count>100) { Serial.print("heat_sink_temp ="); Serial.println(heat_sink_temp); Serial.print("Raw=");Serial.println(raw_iout); Serial.print("Vin=");Serial.println(Vin_sense); Serial.print("Iin=");Serial.println(Iin_sense); Serial.print("Vout=");Serial.println(Vout_sense); Serial.print("Iout=");Serial.println(Iout_sense); Serial.print("Duty cycle=");Serial.print(duty_cycle/2.55);Serial.println("%"); Serial.print("PV power =");Serial.println(Pin); Serial.print("输出功率 =");Serial.println(Pout); Serial.print("Efficiency =");Serial.print(efficiency);Serial.println("%"); Serial.print("转换器模式:");Serial.println(mode); if(lcd_stat){lcd_num(Iin_sense,0,1); lcd_show("T-",0,0); lcd_num(heat_sink_temp,2,0); lcd_show("E-",8,0); lcd_num(效率,10,0);lcd_show(“%”,15,0);液晶统计=假; } else{ lcd_num(Vin_sense,0,1); lcd_show(" ",15,0); if(charge){ lcd_show("Vi Vb-B Ib ",0,0); } else { lcd_show("Vi Vb-F Ib ",0,0); } lcd_stat=true; } lcd_num(Vout_sense,6,1); lcd_num(Iout_sense,12,1);数字写入(led,高);延迟(16000); count=0;}if(startup==false) { if(auto_mode==1){ auto_cutoff(Iout_sense,Vin_sense, Vout_sense); } else { digitalWrite(charge_led,HIGH);调节(Iout_sense,Vin_sense,Vout_sense); digitalWrite(led,~digitalRead(led)); }}/////////if(heat_sink_temp> 45.0){ digitalWrite(fan,HIGH);}else if(heat_sink_temp<37.0){ digitalWrite(fan,LOW);}count++;}
示意图
制造工艺