Friday, August 24, 2012

Battery Charger - PWM controlled.



This is my latest project I just completed. It is a multi-channel lead acid battery charger. It can be used for VRLA, gell cell and wet cell types. It is designed to charge battery jars with a nominal voltage between 4 and 12 volts. It will also work well with any battery type requiring a constant voltage float charge. It has built in limiting circuitry to keep each channel at or below 1.25 amps. The individual channels may be paralleled for higher current. Once the set voltage is adjusted and the channel is turned on, the charger will try to drive to the set voltage while automatically current limiting. As the set voltage is reached the current diminishes to a fractional amount that is required to "float" the battery at that setpoint. The system has automatic fault detection for over/undervoltage and battery disconnect as well as open cell detection and will automatically turn off the affected channel.

      The charger is built around a modular approach whereby the charger cicuitry is on small charger PCBs that connect to a main 24V supply and are driven via a PWM signal from a microcontroller. They also provide a voltage feedback to the microcontroller via ADC input. A 4x20 matrix serial lcd screen and 4 membrane type buttons are used for HMI. The microcontroller used is a Picaxe 20M2 mounted on a Kiwi Patch board. The power supply is by Mean Well and there is a cooling fan mounted left side to keep everything running cool.












symbol PWR1 = bit0
symbol PWR2 = bit1
symbol PWR3 = bit2
symbol PWR4 = bit3
symbol FLT1 = bit4
symbol FLT2 = bit5
symbol FLT3 = bit6
symbol FLT4 = bit7
symbol i= b1
symbol ADC =W1
symbol PWM1 = W2
symbol PWM2 = W3
symbol PWM3 = W4
symbol PWM4 = W5
symbol SP = W6
symbol SP2 = W7
symbol SP3 = W8
symbol eval = W9
symbol ADC1 = W10
symbol ADC2 = W11
symbol ADC3 = W12
symbol ADC4 = W13
rem temporary setpoints placed in NV memory-remove in final
'SP = 650
'write 10,word SP
'write 20,word SP
'write 30,word SP
'write 40,word SP
rem _______________________________________________________

pause 2000
hsersetup B9600_16,
'hserout 0,(" PWM Battery Charger Mike Bentley")
'pause 10000
setup:
hserout 0,(124,2,50,124,0,"# VOLT SETP STATE",124,24,0,124,25,50,"1",124,24,0,124,25,40,"2",124,24,0,124,25,30,"3",124,24,0,124,25,20,"4")

lcdloop:
s_w3 = ADC1
gosub vconvert
hserout 0,(124,24,18,124,25,50)
if s_w2 > 9 then
hserout 0,(#s_w1,".",#s_w2," ")
else
hserout 0,(#s_w1,".0",#s_w2," ")
endif
read 10,word SP2
s_w3 = SP2
gosub vconvert
hserout 0,(124,24,54)
if s_w2 > 9 then
hserout 0,(#s_w1,".",#s_w2," ")
else
hserout 0,(#s_w1,".0",#s_w2," ")
endif
if PWR1 = 1 then
hserout 0,(" ON ")
else
hserout 0,(" OFF")

endif
if s_w4 = 10 then
hserout 0,(" *")
else
hserout 0,(" ")

endif
'pause 400

s_w3 = ADC2
gosub vconvert
hserout 0,(124,24,18,124,25,40)
if s_w2 > 9 then
hserout 0,(#s_w1,".",#s_w2," ")
else
hserout 0,(#s_w1,".0",#s_w2," ")
endif
read 20,word SP2
s_w3 = SP2
gosub vconvert
hserout 0,(124,24,54)
if s_w2 > 9 then
hserout 0,(#s_w1,".",#s_w2," ")
else
hserout 0,(#s_w1,".0",#s_w2," ")
endif
if PWR2 = 1 then
hserout 0,(" ON ")
else
hserout 0,(" OFF")
endif
if s_w4 = 20 then
hserout 0,(" *")
else
hserout 0,(" ")

endif
'pause 400

s_w3 = ADC3
gosub vconvert
hserout 0,(124,24,18,124,25,30)
if s_w2 > 9 then
hserout 0,(#s_w1,".",#s_w2," ")
else
hserout 0,(#s_w1,".0",#s_w2," ")
endif
read 30,word SP2
s_w3 = SP2
gosub vconvert
hserout 0,(124,24,54)
if s_w2 > 9 then
hserout 0,(#s_w1,".",#s_w2," ")
else
hserout 0,(#s_w1,".0",#s_w2," ")
endif
if PWR3 = 1 then
hserout 0,(" ON ")
else
hserout 0,(" OFF")
endif
if s_w4 = 30 then
hserout 0,(" *")
else
hserout 0,(" ")

endif
'pause 400

s_w3 = ADC4
gosub vconvert
hserout 0,(124,24,18,124,25,20)
if s_w2 > 9 then
hserout 0,(#s_w1,".",#s_w2," ")
else
hserout 0,(#s_w1,".0",#s_w2," ")
endif
read 40,word SP2
s_w3 = SP2
gosub vconvert
hserout 0,(124,24,54)
if s_w2 > 9 then
hserout 0,(#s_w1,".",#s_w2," ")
else
hserout 0,(#s_w1,".0",#s_w2," ")
endif
if PWR4 = 1 then
hserout 0,(" ON ")
else
hserout 0,(" OFF")
endif
if s_w4 = 40 then
hserout 0,(" *")
else
hserout 0,(" ")

endif
pause 200
if s_w4 > 0 then
peek 28, word SP2
hserout 0,(124,24,18,124,25,10,"IMP ",#SP2," ")
else
hserout 0,(124,24,18,124,25,10," ")
endif
'pause 400
goto lcdloop

vconvert:
s_w1 = s_w3 * 21
s_w2 = s_w3 *25/100
s_w1 = s_w1 + s_w2/10
s_w2 = s_w1
s_w1 = s_w1/100
s_w3 = s_w1 * 100
s_w2 = s_w2 - s_w3
pause 200
return

start1:
'pause 3000
PWM1 = 1000
PWM2 = 1000
PWM3 = 1000
PWM4 = 1000
PWR1 = 1
PWR2 = 1
PWR3 = 1
PWR4 = 1
pwmout pwmdiv64,C.5,249,PWM1
pwmout pwmdiv64,C.3,249,PWM2
pwmout pwmdiv64,C.2,249,PWM3
pwmout pwmdiv64,B.1,249,PWM4

main1:
eval = 0
s_w5 = 0
s_w6 = 1000
read 10,word SP
for i = 1 to 15
readadc10 B.2,ADC
if ADC > s_w5 then
s_w5 = ADC
elseif ADC < s_w6 then
s_w6 = ADC
endif
eval = eval + ADC
next i
ADC1 = eval/15
eval = s_w5 - s_w6
if s_w4 = 10 then
poke 28, word eval
endif
'eval = eval + ADC
'next i
'ADC1 = eval/15
if SP > ADC1 then
eval = SP-ADC1
else
eval = 0
endif
if PWR1 = 0 then goto main2
if ADC1 < 200 or ADC1 > 800 or eval > 200 then
PWR1 = 0
FLT1 = 1
PWM1 = 1000
pwmduty C.5,1000
goto main2
endif
'sertxd (#PWM1,cr,lf)
if ADC1 = SP then
goto main2
endif
increase:
if ADC1 < SP then
if PWM1 > 0 then
PWM1 = PWM1 -1
endif
pwmduty C.5,PWM1
goto main2
endif
decrease:
if ADC1 > SP then
eval = ADC1 -SP
if eval > 20 then
PWM1 = PWM1 +2 max 1000
endif
PWM1 = PWM1 +1 max 1000
pwmduty C.5,PWM1
goto main2
endif

main2:
eval = 0
s_w5 = 0
s_w6 = 1000
read 20,word SP
for i = 1 to 15
readadc10 B.3,ADC
if ADC > s_w5 then
s_w5 = ADC
elseif ADC < s_w6 then
s_w6 = ADC
endif
eval = eval + ADC
next i
ADC2 = eval/15
eval = s_w5 - s_w6
if s_w4 = 20 then
poke 28, word eval
endif
'eval = eval + ADC
'next i
'ADC2 = eval/15
if SP > ADC2 then
eval = SP-ADC2
else
eval = 0
endif
if PWR2 = 0 then goto main3
if ADC2 < 200 or ADC2 > 800 or eval > 200 then
PWR2 = 0
FLT2 = 1
PWM2 = 1000
pwmduty C.3,1000
goto main3
endif
if ADC2 = SP then
goto main3
endif
increase2:
if ADC2 < SP then
if PWM2 > 0 then
PWM2 = PWM2 -1
endif
pwmduty C.3,PWM2
goto main3
endif
decrease2:
if ADC2 > SP then
eval = ADC2 -SP
if eval > 20 then
PWM2 = PWM2 +2 max 1000
endif
PWM2 = PWM2 +1 max 1000
pwmduty C.3,PWM2
goto main3
endif

main3:
eval = 0
s_w5 = 0
s_w6 = 1000
read 30,word SP
for i = 1 to 15
readadc10 B.4,ADC
if ADC > s_w5 then
s_w5 = ADC
elseif ADC < s_w6 then
s_w6 = ADC
endif
eval = eval + ADC
next i
ADC3 = eval/15
eval = s_w5 - s_w6
if s_w4 = 30 then
poke 28, word eval
endif
'eval = eval + ADC
'next i
'ADC3 = eval/15
if SP > ADC3 then
eval = SP-ADC3
else
eval = 0
endif
if PWR3 = 0 then goto main4
if ADC3 < 200 or ADC3 > 800 or eval > 200 then
PWR3 = 0
FLT3 = 1
PWM3 = 1000
pwmduty C.2,1000
goto main4
endif
if ADC3 = SP then
goto main4
endif
increase3:
if ADC3 < SP then
if PWM3 > 0 then
PWM3 = PWM3 -1
endif
pwmduty C.2,PWM3
goto main4
endif
decrease3:
if ADC3 > SP then
eval = ADC3 -SP
if eval > 20 then
PWM3 = PWM3 +2 max 1000
endif
PWM3 = PWM3 +1 max 1000
pwmduty C.2,PWM3
goto main4
endif

main4:
eval = 0
s_w5 = 0
s_w6 = 1000
read 40,word SP
for i = 1 to 15
readadc10 B.5,ADC
if ADC > s_w5 then
s_w5 = ADC
elseif ADC < s_w6 then
s_w6 = ADC
endif
eval = eval + ADC
next i
ADC4 = eval/15
eval = s_w5 - s_w6
if s_w4 = 40 then
poke 28, word eval
endif
'eval = eval + ADC
'next i
'ADC4 = eval/15
if SP > ADC4 then
eval = SP-ADC4
else
eval = 0
endif
if PWR4 = 0 then goto main1
if ADC4 < 200 or ADC4 > 800 or eval > 200 then
PWR4 = 0
FLT4 = 1
PWM4 = 1000
pwmduty B.1,1000
goto main1
endif
if ADC4 = SP then
goto main1
endif
increase4:
if ADC4 < SP then
if PWM4 > 0 then
PWM4 = PWM4 -1
endif
pwmduty B.1,PWM4
goto main1
endif
decrease4:
if ADC4 > SP then
eval = ADC4 -SP
if eval > 20 then
PWM4 = PWM4 +2 max 1000
endif
PWM4 = PWM4 +1 max 1000
pwmduty B.1,PWM4
goto main1
endif

start2:

buttonread:
if pinC.6 = 1 and pinB.0 = 0 then
s_w4 = s_w4 +10
if s_w4 = 50 then
s_w4 =0
endif
pause 300
endif

if pinC.4 = 1 and s_w4 > 0 then

read s_w4,word SP3
if SP3 < 700 then
inc SP3
write s_w4,word SP3
endif
pause 50
endif

if pinB.7 = 1 and s_w4 > 0 then

read s_w4,word SP3
if SP3 > 200 then
dec SP3
write s_w4,word SP3
endif
pause 50
endif

if pinB.0 = 1 then
select case s_w4
case 10
FLT1=0
PWR1=1
if pinC.6 = 1 then
PWM1 = 500
endif
case 20
FLT2=0
PWR2=1
if pinC.6 = 1 then
PWM2 = 500
endif
case 30
FLT3=0
PWR3=1
if pinC.6 = 1 then
PWM3 = 500
endif
case 40
FLT4=0
PWR4=1
if pinC.6 = 1 then
PWM4 = 500
endif
endselect
pause 200
endif
pause 50
goto buttonread


No comments:

Post a Comment