`Battery Management System SOC Calculation Test Module by Peter Perkins `Picaxe 28X1 PIC16F886 - V1.00 - 180708 - peter@solarvan.gotadsl.co.uk `********************* General Information ************************** `This test module uses the Picaxe interpreter/compiler to simulate `the SOC state of charge calculation of the BMS Master Module. `Set the Picaxe editor to show the AXE033 LCD display from the `VIEW, OPTIONS, SIMULATION TAB, OUTPUT 5 `When running use the GENERIC ADC button to adjust the ADC input. `Do not exceed 1023 on the ADC input or the routine will not work `Do not exceed 65A average charge or discharge over a minute period `or the routine will give unpredictable results due to integer maths `overflows. The Honda Insight Car I am designing this system for `should not allow the average to be exceeded so I have retained the `65A average limit to improve accuracy `The current sensor I'm using is an Allegro ACS754SCB-100-PFF `-100A to +100A Fully isolated Hall effect device. `******************************************************************** `Variables Constants and I/O definitions `Variables 16bit symbol Camps = w1 ;(Camps) Test variable used only in this Demo symbol Soc = w2 ;w2 = Calculated pack capacity (Soc State of Charge) resolution 10ma symbol BatCurrent = w3 ;w3 = Current Sensor ADC value 0-1024 10bit Approx 200ma resolution symbol Damps = w4 ;(Damps) Test variable used only in this Demo symbol Charge = w5 ;w5 = Accumulated Charge current for last minute symbol Discharge = w6 ;w6 = Accumulated Discharge current for last minute `Variables 8bit symbol Counter = b27 ;b27 = General 0-255 byte counter variable symbol SocTimer = b23 ;b23 = SocTimer increments each time current measured until reaches 60 (1 min) symbol PosNeg = b22 ;b22 = Positive/Negative Amps used for LCD display to indicate Charge/Discharge `Special Compiler Variable Notes ` Timer = Internal timer variable and set to 1 second ticks (t1s_4) `Constants symbol CurrentSensor = 0 ;Battery Current Sensor 0-5V ADC on Input 0 (+100 to -100A) 2.5v = 0 Amps symbol CellCapacity = 40000 ;Nominal cell capacity = 40ah (40,000 as 16 bit value) Res 1ma (Max 65A) symbol Lcd = 5 ;Dashboard Lcd display on Output 5 (2400 baud) ;************************************************************************************************************* `Main program loop executed once a second. Start: settimer t1s_4 ;Set internal (timer) variable to 1 second ticks at 4mhz Soc = CellCapacity ;Set Initial SOC (State of charge) to CellCapacity (40ah = 40,000) Main: If timer >0 then gosub CheckCurrent ;Gosub CheckCurrent routine to accumulate 1 second charge/discharge data ;Display Parameters on Dashboard Lcd serout Lcd,N2400,(254,128,"Chg ",#Charge," Dis ",#Discharge," ") serout Lcd,N2400,(254,192,"C ",#Soc," A ",PosNeg,#BatCurrent," T ",#SocTimer," ") if SocTimer >59 then gosub CalculateSoc ;if SocTimer > 59 (1 Minute has elapsed so Calculate Soc) goto main ;Goto main program loop ;************************************************************************************************************** CheckCurrent: ;Accumulate second by second (Current in Amps) charge/discharge data readadc10 CurrentSensor, BatCurrent ;Read present charge/discharge current (0-1023 10bit) ;Specified sensor range is (-100A to +100A 0-5V) if BatCurrent >512 then ;If BatCurrent is >512 means system is Charging BatCurrent = BatCurrent - 512 ;Subtract sensor offset to get a positive number (0-512 = 0-100A+) BatCurrent = BatCurrent * 100 / 512 ;Convert sensor charge rate to charge rate in Amps Charge = Charge + BatCurrent ;Add Latest sensor Current reading to running 1 minute Charge total PosNeg = 43 ;Set LCD indicator to (+) Display Ascii Character (43 Decimal) goto ExitCurrent endif if BatCurrent <512 then ;If BatCurrent is <512 means system is Discharging BatCurrent = 512 - BatCurrent ;Subtract sensor offset to get a positive number (0-512 = 0-100A-) BatCurrent = BatCurrent * 100 / 512 ;Convert sensor charge rate to charge rate in Amps Discharge = Discharge + BatCurrent ;Add Latest sensor Current reading to running 1 minute Discharge total PosNeg = 45 ;Set LCD indicator to (-) Display Ascii Character (45 Decimal) goto ExitCurrent endif ExitCurrent: inc SocTimer ;SocTimer = SocTimer + 1 (When reaches 60 = 1 minute elapsed) settimer t1s_4 ;Reset internal (timer) variable to 1 second ticks at 4mhz return ;Return to main program loop ;************************************************************************************************************** CalculateSoc: ;Use 1 min accumulated sensor current data to calculate Soc ;Note max 1 min average charge or discharge rate is 65,000 (65A) ;This is due to the limit imposed by the 16bit integer maths if Charge > 0 then ;If no Charge in last minute jump over Charge calculations Charge = Charge / 60 ;Calculate average sensor charge rate for last minute ;REM Charge = Charge * 100 / 6 ;This line may be needed with values that exceed 65,000 integer maths Charge = Charge * 1000 / 60 ;Calculate Amount of power/current added in last minute Soc = Soc + Charge ;Add amount of power generated in last minute to (Soc) PackCapacity Charge = 0 ;Reset Charge Counter to 0 endif if Discharge > 0 then ;If no Discharge in last minute jump over Discharge calculations Discharge = Discharge / 60 ;Calculate average sensor discharge rate for last minute ;REM Discharge = Discharge * 100 / 6 ;This line may be needed with values that exceed 65,000 integer maths Discharge = Discharge * 1000 / 60 ;Calculate Amount of power/current used in last minute Soc = Soc - Discharge ;Subtract amount of power used in last minute from (Soc) PackCapacity Discharge = 0 ;Reset Discharge Counter to 0 endif SocTimer = 0 ;Reset SocTimer to 0 return ;Return to main program loop