-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathPWMChargeController
More file actions
405 lines (369 loc) · 11.5 KB
/
PWMChargeController
File metadata and controls
405 lines (369 loc) · 11.5 KB
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
#include <Wire.h>
#include <LiquidCrystal.h>
#define SOL_ADC A0 // Solar panel side voltage divider is connected to pin A0
#define BAT_ADC A1 // Battery side voltage divider is connected to pin A1
#define CURRENT_ADC A2 // ACS 712 current sensor is connected to pin A2
#define TEMP_ADC A5 // LM 35 Temperature is connected to pin A3
#define AVG_NUM 150 // number of iterations of the adc routine to average the adc readings
#define BAT_MIN 10.5 // minimum battery voltage for 12V system
#define BAT_MAX 15.0 // maximum battery voltage for 12V system
#define BULK_CH_SP 14.4 // bulk charge set point for sealed lead acid battery // flooded type set it to 14.6V
#define FLOAT_CH_SP 13.6 //float charge set point for lead acid battery
#define LVD 11.5 //Low voltage disconnect setting for a 12V system
#define PWM_PIN 3 // pin-3 is used to control the charging MOSFET //the default frequency is 490.20Hz
#define LOAD_PIN 2 // pin-2 is used to control the load
//#define BAT_RED_LED 5
//#define BAT_GREEN_LED 6
//#define BAT_BLUE_LED 7
//#define LOAD_RED_LED 8
//#define LOAD_GREEN_LED 9
LiquidCrystal lcd(12, 11, 10, 4, 5, 6, 7);
byte solar[8] = //icon for solar panel
{
0b11111,0b10101,0b11111,0b10101,0b11111,0b10101,0b11111,0b00000
};
byte battery[8] = //icon for battery
{
0b01110,0b11011,0b10001,0b10001,0b10001,0b10001,0b10001,0b11111
};
byte energy[8] = // icon for power
{
0b00010,0b00100,0b01000,0b11111,0b00010,0b00100,0b01000,0b00000
};
/*byte alarm[8] = // icon for alarm
{
0b00000,0b00100,0b01110,0b01110,0b01110,0b11111,0b00000,0b00100
};*/
byte temp[8] = //icon for termometer
{
0b00100,0b01010,0b01010,0b01110,0b01110,0b11111,0b11111,0b01110
};
byte charge[8] = // icon for battery charge
{
0b01010,0b11111,0b10001,0b10001,0b10001,0b01110,0b00100,0b00100,
};
byte not_charge[8]=
{
0b00000,0b10001,0b01010,0b00100,0b01010,0b10001,0b00000,0b00000,
};
float solar_volt=0;
float bat_volt=0;
float load_current=0;
int temperature=0;
int temp_change=0;
int Vo;
float R1 = 7100;
float logR2, R2, T, Tc, Tf;
float c1 = 1.009249522e-03, c2 = 2.378405444e-04, c3 = 2.019202697e-07;
float system_volt=0;
float bulk_charge_sp=0;
float float_charge_sp=0;
float charge_status=0;
float load_status=0;
float error=0;
float Ep=0;
int duty =0;
float lvd;
float msec=0;
float last_msec=0;
float elasped_msec=0;
float elasped_time=0;
float ampSecs = 0;
float ampHours=0;
float watts=0;
float wattSecs = 0;
float wattHours=0;
int backLight = 13; // pin 13 will control the backlight
int charged_percent = 0;
void setup()
{
Serial.begin(9600);
// pinMode(BAT_RED_LED,OUTPUT);
// pinMode(BAT_GREEN_LED,OUTPUT);
// pinMode(BAT_BLUE_LED,OUTPUT);
// pinMode(LOAD_RED_LED ,OUTPUT);
// pinMode(LOAD_GREEN_LED,OUTPUT);
pinMode(PWM_PIN,OUTPUT);
pinMode(LOAD_PIN,OUTPUT);
digitalWrite(PWM_PIN,LOW); // default value of pwm duty cycle
digitalWrite(LOAD_PIN,LOW); // default load state is OFF
pinMode(backLight, OUTPUT); //set pin 13 as output
analogWrite(backLight, 150); //controls the backlight intensity 0-255
lcd.begin(16,2); // columns, rows. size of display
lcd.clear(); // clear the screen
}
void loop(){
lcd.setCursor(16,1); // set the cursor outside the display count
lcd.print(" "); // print empty character
Vo = analogRead(TEMP_ADC);
R2 = R1 * (1023.0 / (float)Vo - 1.0);
logR2 = log(R2);
T = (1.0 / (c1 + c2*logR2 + c3*logR2*logR2*logR2));
Tc = T - 277.15;
Tf = (Tc * 9.0)/ 5.0 + 32.0;
read_data(); // read different sensors data from analog pin of arduino
system_voltage(); // detect the system voltage according to battery voltage
setpoint(); // decide the charge set point according to system voltage
charge_cycle(); // pwm charging of battery
power(); // calculate the load power and energy
load_control(); //control the load
//led_indication(); // led indica
print_data(); // print in serial monitor
lcd_display(); // lcd display
charged_percent = bat_volt*10;
charged_percent = map(bat_volt*10, 30 , 62, 0, 100);
}
int read_adc(int adc_parameter){
int sum = 0;
int sample ;
for (int i=0; i<AVG_NUM; i++)
{ // loop through reading raw adc values AVG_NUM number of times
sample = analogRead(adc_parameter); // read the input pin
sum += sample; // store sum for averaging
delay(2); // pauses for
}
return(sum / AVG_NUM); // divide sum by AVG_NUM to get average and return it
}
void read_data(void) {
// 5V = ADC value 1024 => 1 ADC value = (5/1024)Volt= 0.0048828Volt
// Vout=Vin*R2/(R1+R2) => Vin = Vout*(R1+R2)/R2 R1=100 and R2=20
solar_volt = read_adc(SOL_ADC)*0.0048828*(120/20);
bat_volt = read_adc(BAT_ADC)*0.0048828*(120/20);
load_current = (read_adc(CURRENT_ADC)*0.0048828 -25);
temperature = Tc;
}
void power(void){
msec = millis();
elasped_msec = msec - last_msec; //Calculate how long has past since last call of this function
elasped_time = elasped_msec / 1000.0; // 1sec=1000 msec
watts = load_current * bat_volt; //Watts now
ampSecs = (load_current*elasped_time); //AmpSecs since last measurement
wattSecs = ampSecs * bat_volt; //WattSecs since last measurement
ampHours = ampHours + ampSecs/3600; // 1 hour=3600sec //Total ampHours since program started
wattHours = wattHours + wattSecs/3600; // 1 hour=3600sec //Total wattHours since program started
last_msec = msec; //Store 'now' for next time
}
void print_data(void) {
delay(100);
Serial.print("Solar Panel Voltage: ");
Serial.print(solar_volt);
Serial.println("V");
Serial.print("Battery Voltage: ");
Serial.print(bat_volt);
Serial.println("V");
Serial.print("Syestem Voltage: ");
Serial.print(system_volt);
Serial.println("V");
Serial.print("Charge Set Point:");
Serial.println(bulk_charge_sp);
Serial.print("Temperature:");
Serial.print(temperature);
Serial.println("C");
Serial.print("Load Current: ");
Serial.print(load_current);
Serial.println("A");
Serial.print("Power: ");
Serial.print(watts);
Serial.println("W");
Serial.print("Energy: ");
Serial.print(wattHours);
Serial.println("WH");
Serial.print("Duty Cycle :");
if (charge_status==1)
{
Serial.println("99%");
Serial.println("BULK CHARGING");
}else if (charge_status==2)
{
Serial.print(Ep);
Serial.println("%");
Serial.println("FLOAT CHARGING");
}else{
Serial.println("0%");
Serial.println("NOT CHARGING");
}
if(load_status==1){
Serial.println("LOAD IS CONNECTED");
}else{
Serial.println("LOAD IS DISCONNECTED");
}
Serial.println("***************************");
}
void system_voltage(void){
if ((bat_volt >BAT_MIN) && (bat_volt < BAT_MAX)){
system_volt = 12;
}
else if ((bat_volt > BAT_MIN/2 ) && (bat_volt < BAT_MAX/2)){
system_volt = 6;
}
}
void setpoint(void){
temp_change = temperature-22.0; // 22deg cel is taken as standard room temperature
// temperature compensation = -5mv/degC/Cell
// If temperature is above the room temp ;Charge set point should reduced
// If temperature is bellow the room temp ;Charge set point should increased
if(system_volt ==12)
{
bulk_charge_sp = BULK_CH_SP-(0.030*temp_change) ;
float_charge_sp=FLOAT_CH_SP-(0.030*temp_change) ;
lvd =LVD;
}
else if(system_volt ==6)
{
bulk_charge_sp = (BULK_CH_SP/2)-(0.015*temp_change) ;
float_charge_sp= (FLOAT_CH_SP/2)-(0.015*temp_change) ;
lvd=LVD/2;
}
}
void charge_cycle(void){
if (solar_volt > bat_volt && bat_volt <= bulk_charge_sp)
{
if (bat_volt <= float_charge_sp) // charging start
{
charge_status = 1; // indicate the charger is in BULK mode
duty= 252.45;
analogWrite(PWM_PIN,duty); // 99 % duty cycle // rapid charging
}
else if (bat_volt > float_charge_sp && bat_volt <= bulk_charge_sp){
charge_status = 2; // indicate the charger is in FLOAT mode
error = (bulk_charge_sp - bat_volt); // duty cycle reduced when the battery voltage approaches the charge set point
Ep = error *100 ; //Ep= error* Kp // Assume Kp=100
if(Ep < 0)
{
Ep=0;
}else if(Ep>100){
Ep=100;
}else if(Ep>0 && Ep <=100){
duty = (Ep*255)/100;
}
analogWrite(PWM_PIN,duty);
}
}else{
charge_status=0; // indicate the charger is OFF
duty=0;
analogWrite(PWM_PIN,duty);
}
}
void load_control(){
if (solar_volt < 5 ) // load will on when night
{
if(bat_volt >lvd){
load_status=1;
digitalWrite(LOAD_PIN, HIGH); // load is ON
}else if(bat_volt < lvd){
load_status=0;
digitalWrite(LOAD_PIN, LOW); //load is OFF
}
}else{
load_status=0;
digitalWrite(LOAD_PIN, LOW);
}
}
//void led_indication(void){
// battery_led(); //Battery status led indication
// load_led(); //Load led indication
//}
//void battery_led(void){
// if( (bat_volt > system_volt) && ( bat_volt <bulk_charge_sp)){
// leds_off_all();
// digitalWrite(BAT_GREEN_LED,LOW); // battery voltage is healthy
// }
// else if(bat_volt >= bulk_charge_sp) {
// leds_off_all();
// digitalWrite(BAT_BLUE_LED,LOW); //battery is fully charged
// }
// else if(bat_volt < system_volt){
// leds_off_all();
// digitalWrite(BAT_RED_LED,LOW); // battery voltage low
// }
//}
//void load_led(){
// if(load_status==1){
// digitalWrite(LOAD_GREEN_LED,HIGH);
// }
// else if(load_status==0){
// digitalWrite(LOAD_RED_LED,HIGH);
// }
//}
//void leds_off_all(void)
//{
// digitalWrite(BAT_RED_LED,HIGH);
// digitalWrite(BAT_GREEN_LED,HIGH);
// digitalWrite(BAT_BLUE_LED,HIGH);
// digitalWrite(LOAD_RED_LED, LOW);
// digitalWrite(LOAD_GREEN_LED, LOW);
//}
void lcd_display(){
lcd.setCursor(0,0); // set the cursor at 1st col and 1st row
lcd.print("SOL:");
lcd.print(solar_volt);
lcd.print(" BAT:");
lcd.print(bat_volt);
lcd.setCursor(1,1); // set the cursor at 1st col and 2nd row
delay(500);
if (charge_status == 0)
{
lcd.print("Fully Charged ");
}
// LCD will show the %charged during charging period only
if (charge_status == 1)
{
lcd.print(charged_percent);
lcd.print("% Charged BM");
}
if (charge_status == 2)
{
lcd.print(charged_percent);
lcd.print("% Charged FM");
}
// LCD will alart when battery is dead by displaying the message "BATTERY IS DEAD!!"
else if (bat_volt < 3)
{
lcd.print("BATTERY IS DEAD!!");
}
if (bat_volt < 3.2 && bat_volt > 3)
// seecond restriction is given for indicating battery is dead
// if you omit the (bat_volt > 6) when ever battery is dead also display bat discharged
{
lcd.setCursor(1,1);
lcd.print("BAT DISCHARGED..");
}
/*
lcd.setCursor(0, 0);
lcd.write(1);
lcd.setCursor(2, 0);
lcd.print(solar_volt);
lcd.print("V");
lcd.setCursor(14, 0);
lcd.write(5);
lcd.setCursor(16, 0);
lcd.print(temperature);
lcd.write(0b11011111);
lcd.print("C");
lcd.setCursor(0,1);
lcd.write(2);
lcd.setCursor(2, 1);
lcd.print(bat_volt);
lcd.print("V");
lcd.setCursor(14, 1);
lcd.write(2);
if((charge_status==1) | (charge_status== 2)){
lcd.write(6);
}
else{
lcd.write(7);
}
lcd.setCursor(0,2);
lcd.write(3);
lcd.setCursor(2,2);
lcd.print(load_current);
lcd.print("A");
lcd.setCursor(13,2);
lcd.print(watts);
lcd.print("W");
lcd.setCursor(0,3);
lcd.print("Energy:");
lcd.print(wattHours);
lcd.print("WH");
*/
}