#REM Li-Ion Battery Management System Master Module. By Peter Perkins Picaxe 28X1 - PIC16F886 - 120908 - www.150mpg.co.uk - V09 Video Beta **************************** General Information ****************************** The BMS modules carry no warranty or guarantee of any kind! They are used at your own risk, and I make no claims as to their suitability for a particular function. Prospective users must evaluate the system before using it, and no liability will be entertained by myself in any shape or form whatsoever. The modules and software have been produced at low cost for the benefit of the EV & electronic community. The software is available free via the internet. Users may modify or adapt the system as they see fit. If you are not fully competent to work on potentially lethal battery systems and high voltages, then do not experiment with or use this system. Be aware that vehicle modifications can lead to invalidated insurance and warranty issues. You the end user remain fully liable for any modifications made to your vehicle. ************************** Master Picaxe 28X1 Pinout ************************** Top _____ (Pic Reset) Reset -01| ^ |28- Output 7 (Drive Inhibit Out) (Current Sensor In) Adc 0 -02| |27- Output 6 (Charger Relay Out) (Spare Adc In) Adc 1 -03| |26- Output 5 (Video Display Out) (Spare Adc In) Adc 2 -04| |25- Output 4 (Controller Cutback Out) (Spare Adc In) Adc 3 -05| P |24- Output 3 (WatchDog Led Out) (Program In) Rxd -06| 2 |23- Output 2 (Slave Data Bus Out) (Program Out) Txd -07| 8 |22- Output 1 (Charger Cutback Out) (- Supply) Gnd -08| X |21- Output 0 (Audible Alarm Out) (Resonator In) Osc 1 -09| 1 |20- +Ve (+ Supply) (Resonator In) Osc 2 -10| |19- Gnd (- Supply) (Button A In) Input 0 -11| |18- Input 7 (Master Data Bus In) (Button B In) Input 1 -12| |17- Input 6 (Interlocks In) (Temp Sensors In) Input 2 -13| |16- Output c5 (Charging Led 2 Out) (Speed Sensor In) Input 3 -14| |15- Output c4 (Dash Led 1 Out) ----- ************************ Other IC's On Master Pcb ***************************** *********************** Watchdog Picaxe 08M Pinouts *************************** Top _____ (+ Supply) +Ve -1| ^ |8- Gnd (- Supply) (Program In) Rxd -2| 0 |7- Txd (Program Out) (Watchdog Led Out) Output 4 -3| 8 |6- Output 1 (Audible Alarm Out) (Pulse Count In) Input 3 -4| M |5- Output 2 (Master Reset Out) ----- ****************** SV2000 Serial to Composite Video IC ************************ Top _____ (Sync Out) Syn -1| ^ |8- +Ve (+ Supply) (Video Out) Vid -2| V |7- Nc (No Connection) (Serial Data In) Rxd 4 -3| I |6- Inv (Serial Data Invert Mode) (- Supply) Gnd 3 -4| D |5- Txd (No Connection) ----- ************************ Master Module Specification ************************** Board Supply Voltage 8.00-20.00V DC or as limited by 5.00V 78L05 regulator CPU Supply Voltage 5.00V CPU Speed 8mhz with internal resonator (Pic limit 20mhz with external res) Average Board Supply Current at 12.00v <100ma Maximum Serial Bus data rate 4800 baud (Picaxe 08M limit at 8mhz) Maximum Cell Capacity 65ah (65535) (Limit of 16bit Word Variable) Maximum Pack Voltage 650v (65535) (Limit of 16bit Word Variable) Maximum Charge/Discharge rate 100A (Allegro Current Sensor limit) Maximum 128 Slave Modules per Master Module (Pic Scratchpad Ram limit) Battery Pack Temp Sensor Range (0 to 127C) Composite Video Display data rate 9600 baud (SV2000 Serial to Video Chip) Composite RCA Video Monitor Output 1V 75ohm PAL/NTSC Charger relay output 5.00v at 500ma Opto Isolated Charger/Controller Cutback outputs max 25ma ******************************************************************************* ********************* Program Size 1437 out of 4096 Bytes ********************* ******************************************************************************* #ENDREM `Variables Constants and I/O definitions `Variables 16bit (Word) symbol FlagsWarnings= w0 ;w0 (b0,b1) = Flags and Warnings Word (b0,b1 bytes) (16 bits = 2 x 8bits) symbol CellVoltage = w1 ;w1 (b2,b3) = Cell Voltage 0-1023 10bit (0-5v) symbol PackVoltage = w2 ;w2 (b4,b5) = Calculated pack voltage (Voltage of all Cells added together) symbol Soc = w3 ;w3 (b6,b7) = Calculated pack capacity (Soc State of Charge) resolution 10ma symbol BatCurrent = w4 ;w4 (b8,b9) = Current Sensor ADC value 0-1023 10bit Approx 200ma resolution symbol DutyCycle = w5 ;w5 (b10,b11) = Charger & Controller HPWM Duty Cycle 0 - 100% (0-1023) (+/- 10 = 1%) symbol Charge = w6 ;w6 (b12,b13) = Accumulated Charge current for last minute symbol Discharge = w7 ;w7 (b14,b15) = Accumulated Discharge current for last minute symbol Speed = w8 ;w8 (b16,b17) = Vehicle calculated speed in mph/kph symbol Distance = w9 ;w9 (b18,b19) = Distance (feet) travelled accumulator (5280ft = 1 mile) symbol WhMile = w10 ;w10(b20,b21) = Watt Hours per mile (Power Consumed) symbol TempSoc = w11 ;w11(b22,b23) = Word var split into two bytes (Temp & Soc Counter) symbol CountW = w12 ;w12(b24,b25) = General 0-65535 16bit Word Counter/Local Variable (Note CountC & D) symbol CountX = w13 ;w13(b26,b27) = General 0-65535 16bit Word Counter/Local Variable (Note CountA & B) `Variables 8bit (Byte) symbol CountA = b27 ;b27 = General 0-255 8bit Byte Counter or General/Local Variable (Note CountX) symbol CountB = b26 ;b26 = General 0-255 8bit Byte Counter or General/Local Variable (Note CountX) symbol CountC = b25 ;b25 = General 0-255 8bit Byte Counter or General/Local Variable (Note CountW) symbol CountD = b24 ;b24 = General 0-255 8bit Byte Counter or General/Local Variable (Note CountW) symbol PackTemp = b23 ;b23 = Pack Temperature 1C resolution (0 to 127C) symbol SocCounter = b22 ;b22 = SocCounter increments each time current measured to calc av 1 min current symbol VoltageData = b2 ;b2 = Voltage data byte (8bit value) (Received from Slave via serial link) symbol Warnings = b1 ;b1 = Warnings Flags byte (To clear all warning flags set b1=0) `General Flags x8 1bit (b0) ;Note the 16 Bit flags use Byte variables (b0) & (b1) which in turn use Word (w0) symbol WatchFlag = bit0 ;bit0 = Watchdog Flag pulses dash led every other time through Main loop symbol PosNegFlag = bit1 ;bit1 = Pos/Neg Amps used to indicate Charge/Discharge (0=Charge+) (1=Discharge-) symbol ChargeFlag = bit2 ;bit2 = ChargeFlag indicates charging in progress (0=Not Charging) (1=Charging) symbol IlockFlag = bit3 ;bit3 = IlockFlag indicates readiness to drive (0=Ready) (1=Not Ready) Interlocks symbol Unused4 = bit4 ;bit4 = symbol Unused5 = bit5 ;bit5 = symbol Unused6 = bit6 ;bit6 = symbol Unused7 = bit7 ;bit7 = `Note to clear all eight warning flags below in one go set (Warnings or b1 to Zero) `Warning Flags x 8 1bit (b1) symbol Warn1 = bit8 ;bit8 = Warning Flag (Cell over AbsMax V) symbol Warn2 = bit9 ;bit9 = Warning Flag (Cell under AbsMin V) symbol Warn3 = bit10 ;bit10 = Warning Flag (Cell over Max V) symbol Warn4 = bit11 ;bit11 = Warning Flag (Cell under Min V) symbol Warn5 = bit12 ;bit12 = Warning Flag (Cell data serial transfer timeout error) symbol Warn6 = bit13 ;bit13 = Warning Flag (Battery Pack over AbsMax Temp) symbol Warn7 = bit14 ;bit14 = Warning Flag (Battery Pack over Max Temp) symbol Warn8 = bit15 ;bit15 = Warning Flag (Soc < SocMin = less than 10% remaining) `***** EEPROM Data Storage 0-255 bytes used for SOC, Odometer, Wh and other as yet undefined ideas! **** `Data Store Constants symbol SocStore = 0 ;Address in EEPROM at which SOC readings are stored each minute symbol DistStore = 2 ;Address in EEPROM at which Distance readings are stored symbol OdoStore = 4 ;Address in EEPROM at which Odometer readings are stored symbol WhStore = 6 ;Address in EEPROM at which WhMile readings are stored each minute `*** Special Compiler Variable Notes *** `Timer = Internal timer variable and set to 1 second ticks (t1s_8) `ptr = Scratchpad Ram Variable data pointer (Scratchpad is 128 bytes) `@ptrinc = Scratchpad Ram pointer with automatic increment after execution. `Constants symbol Cells = 5 ;Number of cells in the battery pack (5) (Max is 128 cells) symbol MaxPackVoltage = 19000 ;Maximum pack voltage = 190v (19,000 as 16 bit value) Res 10mv (Max 650v) symbol MinPackVoltage = 10000 ;Minimum pack voltage = 100v (10,000 as 16 bit value) Res 10mv symbol AbsMaxCellVoltage = 375 ;Absolute Maximum permitted cell voltage = (3.75V) (Alarm & Shutdown point) symbol MaxCellVoltage = 368 ;Normal Maximum permitted cell voltage = (3.65V) (Charger/Regen cutback point) symbol MinCellVoltage = 250 ;Normal Minimum permitted cell voltage = (2.50V) (Controller/Assist cutback point) symbol AbsMinCellVoltage = 230 ;Absolute Minimum permitted cell voltage = (2.30V) (Alarm & Shutdown point) symbol AbsMaxPackTemp = 55 ;Absolute Maximum permitted pack temperature = (55C) (Alarm & Shutdown point) symbol MaxPackTemp = 45 ;Maximum permitted pack temperature = (45C) (Warning & Cutback point) symbol CellCapacity = 40000 ;Nominal cell capacity = 40ah (40,000 as 16 bit value) Res 1ma (Max 65A) symbol SocMin = 4000 ;Minimum cell capacity = 4ah (4000 as 16 bit value) 10% of CellCapacity symbol Delay = 10 ;Interrupt and data delay in milliseconds (10ms) symbol DiscardLow = 175 ;Cell correction value 175 or 1.75V added to CellVoltage to recreate correct V symbol DiscardHigh = 430 ;Cell correction value 430 or 4.30V (Not currently used in Master Software) symbol TimeOut = 100 ;Serial Data Receive Timeout value 100ms symbol PwmFreq = 199 ;Frequency for HPWM outputs (199 = 5khz) (99 = 10khz) (49 = 20khz) symbol PulsePerMile = 455 ;Pulses from speed sensor per mile (4550) / 10 to fit into integer maths symbol MaxMainsChg = 15 ;Maximum permitted mains charging current in amps (15A) `BaudRate constants for 8mhz symbol Baud1200 = T600 ;Baud rate 1200 at 8mhz symbol Baud2400 = T1200 ;Baud rate 2400 at 8mhz symbol Baud4800 = T2400 ;Baud rate 4800 at 8mhz symbol Baud9600 = T4800 ;Baud rate 9600 at 8mhz (Note Baud9600 is reserved for the Video output chip) `Pins used for I/O and designations `*** Digital high/low Outputs on port b - Outputs 0-7 *** symbol Alarm = 0 ;Audible Alarm warning on Output 0 symbol ChargerPWM = 1 ;Charger Cutback PWM output on Output 1 (Opto conducts when cell V > 3.70V) symbol SlaveBus = 2 ;Slave Data Bus Output Baud4800 on Output 2 symbol WatchDogLed = 3 ;Watchdog flashing Green Led on Output 3 (Flashes every other program loop) symbol ControllerPWM = 4 ;Controller Cutback PWM Output on Output 4 (Opto conducts when cell V < 2.20V) symbol Video = 5 ;Dashboard Video display Baud4800 (9600) on Output 5 symbol ChargerOnOff = 6 ;Charger Relay On/Off control on Output 6 (5.00v Max 500ma) symbol DriveInhibit = 7 ;Drive inhibit Opto on Output 7 `*** Extra Digital high/low Outputs on port c 4-5 *** symbol Led1 = 4 ;Dashboard Alarm Led 1 on Output portc 4 symbol Led2 = 5 ;Dashboard Charging Led 2 on Output portc 5 `*** Digital high/low Inputs on port c - Inputs 0-3 & 6-7 *** symbol ButtonA = pin0 ;Dashboard A button on Input 0 symbol ButtonB = pin1 ;Dashboard B button on Input 1 symbol TempSensor = 2 ;I2C DS18B20 Battery Pack Temp Sensors on Input 2 (-55 to +125C) symbol SpeedSensor = 3 ;Speed Sensor 5.00V pulse counter input on Input 3 symbol Interlocks = pin6 ;Interlocks and additional safety switch inputs on Input 6 symbol MasterBus = 7 ;Master Data Bus Input Baud4800 on Input 7 `*** Analogue ADC Inputs *** symbol CurrentSensor = 0 ;Battery Current Sensor 0-5V ADC on Input 0 (+100 to -100A) 2.5v = 0 Amps ;************************************************************************************************************* `*** Program Eprom Data Storage 0-255 bytes used for LCD messages *** `*** Note Display is 16x9 and Messages should be broken up accordingly *** TABLE 0, (27,67) ; 0-1 bytes Store data in eprom table (Clear Screen Command Sequence) TABLE 2, ("*BMS Master V09*") ; 2-17 bytes Store data in eprom table TABLE 18, ("By Peter Perkins") ; 18-33 bytes Store data in eprom table TABLE 34, ("www.150mpg.co.uk") ; 34-50 bytes Store data in eprom table TABLE 51, (" ") ; 51-67 bytes Store data in eprom table `TABLE 68, (" ") ; 68-84 bytes Store data in eprom table `TABLE 85, (" ") ; 85-101 bytes Store data in eprom table `TABLE 102,(" ") ; 102-117 bytes Store data in eprom table `TABLE 118,(" *Pack Low Soc* ") ; 118-133 bytes Store data in eprom table `TABLE 134,(" Cell > AbsMaxV ") ; 134-150 bytes Store data in eprom table `TABLE 151,(" Cell < AbsMinV ") ; 151-167 bytes Store data in eprom table `TABLE 168,(" Cell > MaxV ") ; 168-184 bytes Store data in eprom table `TABLE 185,(" Cell < MinV ") ; 185-201 bytes Store data in eprom table `TABLE 202,("Cell Data Error!") ; 202-217 bytes Store data in eprom table `TABLE 218,(" Pack > AbsMaxT ") ; 218-233 bytes Store data in eprom table `TABLE 234,(" Pack > MaxT ") ; 234-250 bytes Store data in eprom table `TABLE 251,(" ") ; 251-255 bytes Store data in eprom table (End of table 255 bytes) ;************************************************************************************************************* Start: ;Initialise Program. Start Timer, Load Variables, Start Hardware PWM setfreq m8 ;Setfreq CPU Freq to 8mhz serout Video,Baud9600,(" ") ;Clear Display Buffer (Reset Display chip to receive data) for CountA = 0 to 50 ;Start a display loop readtable CountA,CountB ;Read value from data table serout Video,Baud9600,(CountB) ;Transmit data to Video Display next CountA ;Loop to next character pause 5000 ;Wait 2.5 Seconds (8mhz) read SocStore, WORD Soc ;Load last saved Soc reading from eeprom storage if Soc = 0 then ;Test if stored SOC is 0, if it is then reset SOC to CellCapacity Soc = CellCapacity ;Set Initial SOC (State of charge) to CellCapacity (40ah = 40,000) endif read DistStore, WORD Distance ;Load last saved Distance (Feet) reading from eeprom storage read WhStore, WORD WhMile ;Load last saved WhMile reading from eeprom storage settimer t1s_8 ;Set internal (timer) variable to 1 second ticks at 8mhz hpwm 0,0,%1100,PwmFreq,0 ;Start internal HPWM outputs 1 & 4 at 0% duty cycle serout Video,Baud9600,(27,67,27,70) ;Video Display Clear Screen Command Sequence ;************************************************************************************************************* ;************************************************************************************************************* MainLoop: ;Main program loop If WatchFlag = 0 then ;If WatchFlag = 0 then turn on Led high WatchDogLed ;Turn on Green Led WatchFlag = 1 ;Set WatchFlag to 1 else ;If WatchFlag = 1 then turn off led low WatchDogLed ;Turn off Green Led WatchFlag = 0 ;Set WatchFlag to 0 end if gosub CheckCells ;Gosub CheckCells routine to collect Cell V data gosub CheckTemp ;Gosub CheckTemp routine to evaluate battery pack temperature gosub CheckCurrent ;Gosub CheckCurrent routine to accumulate charge/discharge data ` gosub CheckInterlocks ;Gosub CheckInterlocks routine to evaluate readiness to drive ` gosub CheckSpeed ;Gosub CheckSpeed routine to calculate/speed distance if timer >59 then gosub CalcSoc ;if SocTimer > 59 (1 Minute has elapsed so Calculate Soc) gosub Display ;Gosub Display BMS Data on Video Monitor routine gosub Warning ;Gosub Warning Flags Routine and act on Warnings as reqd If ButtonA = 1 then gosub StartChg ;Gosub Start Charging Routine Warnings = 0 ;Reset Warnings Flags goto mainloop ;Goto main program loop ;************************************************************************************************************* ;************************************************************************************************************* CheckCells: ;Check Cells subroutine, receive data to calculate pack voltage ptr = 0 ;Reset Scratchpad pointer to 0 (Start of 128 byte Scratchpad Ram) high SlaveBus ;Turn on Message waiting signal (SlaveBus) pause Delay ;Hold Message waiting signal high until Slave has time to respond low SlaveBus ;Turn off Message waiting signal (SlaveBus) for CountB = 1 to Cells ;Start for/next loop to store cell data in 128 byte Scratchpad Ram serin [TimeOut,DataError],MasterBus,Baud4800,@ptrinc ;Receive Data on opto bus into Scratchpad Ram and inc pointer next CountB ;Increment for/next loop and move to next Cell PackVoltage = 0 ;Reset PackVoltage Total to zero = 0V ptr = 0 ;Reset Scratchpad pointer to 0 (Start of 128 byte Scratchpad Ram) for CountB = 1 to Cells ;Start for/next loop to calculate Pack voltage and check cell data/voltage CellVoltage = 0 ;Clear CellVoltage Variable VoltageData = @ptrinc ;Load VoltageData (b2) with value from Scratchpad Ram and inc data pointer CellVoltage = CellVoltage + DiscardLow ;CellVoltage (w1) = CellVoltage (w1) (1-255 0.01-2.55V) + (175 1.75V) ;Note (w1) is a 16 bit word variable made up of (b2) & (b3) byte variables if CellVoltage > AbsMaxCellVoltage then ;If cell V > AbsMaxCellVoltage then set Warning Flag Warn1 = 1 ;Set Warn1 Flag to 1 (Indicates Cell over AbsMax Voltage condition) endif if CellVoltage < AbsMinCellVoltage then ;If cell V < AbsMinCellVoltage then set Warning Flag Warn2 = 1 ;Set Warn2 Flag to 1 (Indicates Cell under AbsMin Voltage condition) endif if CellVoltage > MaxCellVoltage then ;If cell V > MaxCellVoltage then set Warning Flag Warn3 = 1 ;Set Warn3 Flag to 1 (Indicates Cell over Max Voltage condition) endif if CellVoltage < MinCellVoltage then ;If cell V < MinCellVoltage then set Warning Flag Warn4 = 1 ;Set Warn4 Flag to 1 (Indicates Cell under Min Voltage condition) endif PackVoltage = PackVoltage + CellVoltage ;Add Cell voltage to accumulated Pack voltage next CountB ;Increment for/next loop and move to next cell return ;Return to main program loop DataError: ;Serial Slave Data Receive TimeOut error routine. ;If no Data received within (TimeOut = 100ms) then execution jumps here Warn5 = 1 ;Set Warn5 Flag to 1 (Indicates Cell Data Timeout Error) return ;Return to main program loop ;************************************************************************************************************** CheckTemp: ;Check Battery Pack temperature routine readtemp TempSensor, PackTemp ;Read Battery Pack temperature into variable (PackTemp) (+127C to -127C) if PackTemp > 127 then ;Test for Value >127 = Temp <0C PackTemp = 0 ;Set Temp to 0C if less than 0C endif if PackTemp > AbsMaxPackTemp then ;If PackTemp > AbsMaxPackTemp set Warning Flag Warn6 = 1 ;Set Warn6 Flag to 1 (Indicates Pack over AbsMax Temp condition) endif if PackTemp > MaxPackTemp then ;If PackTemp > MaxPackTemp set Warning Flag Warn7 = 1 ;Set Warn7 Flag to 1 (Indicates Pack over Max Temp condition) endif return ;Return to main program loop ;************************************************************************************************************** CheckInterlocks: ;Check Interlocks Routine for readiness to drive If Interlocks = 1 then ;If Interlocks pin = 1 (High) then set IlockFlag IlockFlag = 1 ;Set IlockFlag to 1 (Indicates Interlock Set condition = Not ready to drive) High DriveInhibit ;Set Drive Inhibit output high to disable controller (Prevent Driving) else IlockFlag = 0 ;Set IlockFlag to 0 (Indicates Interlock Clear condition = Ready to drive) Low DriveInhibit ;Set Drive Inhibit output low to enable controller (Allow Driving) endif return ;Return to main program loop ;************************************************************************************************************** CheckCurrent: ;Accumulate (Current in Amps) charge/discharge data readadc10 CurrentSensor, BatCurrent ;Read present charge/discharge current (0-1023 10bit)(-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 PosNegFlag = 0 ;Set display indicator flag to (0 = +) 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 PosNegFlag = 1 ;Set display indicator flag to (1 = -) Display Ascii Character (45 Decimal) goto ExitCurrent endif ExitCurrent: inc SocCounter ;SocCounter = SocCounter + 1 return ;Return to main program loop ;************************************************************************************************************** CheckSpeed: CountW = 0 ;Set Local Variable CountW to 0 (Zero) Count SpeedSensor,250,CountW ;Measure speed by counting VSS pulses for 250ms (Vehicle Speed Sensor) Speed = CountW * 1440 / PulsePerMile ;Calculate Speed in mph CountW = CountW * 2112 / PulsePerMile ;Calculate Feet travelled in last second Distance = Distance + CountW ;Add distance travelled in last second to running total If Distance >= 5280 then ;5280ft per mile / Tyre circumference 5.8ft = 910 revs per mile read OdoStore, WORD CountW ;Load last saved Odometer (Mile) reading from eeprom storage inc CountW ;Increment Odometer by 1 mile write OdoStore, WORD CountW ;Write current Odometer reading to eeprom for storage when Master Off Distance = Distance - 5280 ;Subtract (5280ft 1mile) from Distance and start accumulating again endif return ;Return to main program loop ;************************************************************************************************************** CalcSoc: ;Use 1 min accumulated sensor current data to calculate Soc if Charge > 0 then ;If no Charge in last minute jump over Charge calculations Charge = Charge / SocCounter ;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 / SocCounter ;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 write SocStore, WORD Soc ;Write Soc reading to eeprom for storage when Master Off write DistStore, WORD Distance ;Write Distance reading to eeprom for storage when Master Off write WhStore, WORD WhMile ;Write WhMile reading to eeprom for storage when Master Off if Soc < SocMin then ;If Soc < SocMin then less than 10% capacity remaining warn8 = 1 ;Set Warn8 Flag to 1 (Indicates Pack < 10% capacity remaining) else warn8 = 0 ;Set Warn8 Flag to 0 (Indicates Pack > 10% capacity remaining) endif SocCounter = 0 ;Reset SocCounter to 0 settimer t1s_8 ;Reset internal (timer) variable to 1 second ticks at 8mhz timer = 0 ;Reset timer variable to 0 (Start another 1 minute timing loop) return ;Return to main program loop ;************************************************************************************************************** Warning: ;Warnings/Alarms turns on led/audible alarms and turns down charger etc ;Action taken depends on Warning Flags (8 different warnings max!) If Warn1 = 1 then ;bit8 = Warning Flag 1 (Cell over AbsMax V) high DriveInhibit ;Set drive inhibit opto output high high Alarm ;Activate audible alarm high portc led1 ;Activate dash Led1 low ChargerOnOff ;Turn off Charger main relay serout Video,Baud9600,("*Cell > AbsMaxV*") ;Video Display else low DriveInhibit ;Set drive inhibit opto output low low Alarm ;Deactivate audible alarm low portc led1 ;Deactivate dash Led1 endif If Warn2 = 1 then ;bit9 = Warning Flag (Cell under AbsMin V) high DriveInhibit ;Set drive inhibit opto output high high Alarm ;Activate audible alarm high portc led1 ;Activate dash Led1 serout Video,Baud9600,("*Cell < AbsMinV*") ;Video Display else low DriveInhibit ;Set drive inhibit opto output low low Alarm ;Deactivate audible alarm low portc led1 ;Deactivate dash Led1 endif If Warn3 = 1 then ;bit10 = Warning Flag (Cell over Max V) if DutyCycle <= 1013 then ;Check to see if DutyCyle <= 1013 and can be Incremented (Max 1023) DutyCycle = DutyCycle + 10 ;Increment DutyCycle by 10 to increase opto conduction by 1% endif high portc led1 ;Activate dash Led1 serout Video,Baud9600,("Cells Balancing!") ;Video Display else low portc led1 ;Deactivate dash Led1 endif If Warn4 = 1 then ;bit11 = Warning Flag (Cell under Min V) high portc led1 ;Activate dash Led1 serout Video,Baud9600,("**Cell < MinV** ") ;Video Display else low portc led1 ;Deactivate dash Led1 endif If Warn5 = 1 then ;bit12 = Warning Flag (Cell data serial transfer timeout error) high portc led1 ;Activate dash Led1 serout Video,Baud9600,("Cell Data Error!") ;Video Display else low portc led1 ;Deactivate dash Led1 endif If Warn6 = 1 then ;bit13 = Warning Flag 6 (Battery Pack over Abs Max Temp) high DriveInhibit ;Set drive inhibit opto output high high Alarm ;Activate audible alarm high portc led1 ;Activate dash Led1 low ChargerOnOff ;Turn off Charger main relay serout Video,Baud9600,("Cell>AbsMaxTemp") ;Video Display else low DriveInhibit ;Set drive inhibit opto output low low Alarm ;Deactivate audible alarm low portc led1 ;Deactivate dash Led1 endif If Warn7 = 1 then ;bit14 = Warning Flag (Battery Pack over Max Temp) high portc led1 ;Activate dash Led1 serout Video,Baud9600,("Cell > Max Temp") ;Video Display else low portc led1 ;Deactivate dash Led1 endif If Warn8 = 1 then ;bit15 = Warning Flag (Battery Pack < 10% capacity remaining) high portc led1 ;Activate dash Led1 serout Video,Baud9600,("*Soc < 10% Left*") ;Video Display else low portc led1 ;Deactivate dash Led1 endif If Warnings = 0 then serout Video,Baud9600,(27,83,0,9,"System Nominal! ") endif hpwmduty DutyCycle ;Set updated HPWM Charger/Controller DutyCycle to adjust output/limit return ;Return to main program loop ;************************************************************************************************************** ;************************************************************************************************************** Display: ;General and Extended Cell BMS Data Display Routines serout Video,Baud9600,(27,72) ;Video Display - (Cusror Home Command Sequence) If ButtonB = 1 then DisplayB ;Goto Display Extended Cell BMS Data DisplayA: ;Display General Parameters on Dashboard Lcd or Video Screen if PosNegFlag = 0 then ;Check Amps (+/-) Display flag and set character to display CountB = 43 ;Set Character (+) to be displayed if charging else CountB = 45 ;Set Character (-) to be displayed if discharging endif CellVoltage = PackVoltage / Cells ;Average Cell Voltage = Total Pack Voltage / Number of Cells (50) serout Video,Baud9600,("** BMS Master **") serout Video,Baud9600,("Current ",CountB,#BatCurrent,"A ",10,13) serout Video,Baud9600,("Temp ",#PackTemp,"C ",10,13) CountW = PackVoltage / 100 CountX = PackVoltage // 100 CountX = CountX / 10 serout Video,Baud9600,("Voltage ",#CountW,".",#CountX,"V ",10,13) CountW = CellVoltage / 100 CountX = CellVoltage // 100 serout Video,Baud9600,("Average ",#CountW,".",#CountX,"V ",10,13) CountW = Soc / 1000 CountX = Soc // 1000 CountX = CountX / 100 serout Video,Baud9600,("Capacity ",#CountW,".",#CountX,"Ah",10,13) serout Video,Baud9600,("Speed ",#Speed," Mph ",10,10,13) return ;Return to main program loop ;************************************************************************************************************** DisplayB: ;Display Extended Cell BMS Data ptr = 0 ;Reset Scratchpad pointer to 0 (Start of 128 byte Scratchpad Ram) CountC = 0 ;Reset CountC to 0 (Used to accumulate highest Cell V) CountD = 255 ;Reset CountD to 255 (Used to accumulate lowest Cell V) serout Video,Baud9600,(27,67) ;Video Display Clear Screen Command Sequence for CountA = 1 to Cells ;Start for/next loop to read cell data from 128 byte Scratchpad Ram CellVoltage = 0 ;Clear CellVoltage Variable VoltageData = @ptrinc ;Load VoltageData (b2) with value from Scratchpad Ram and inc data pointer if CountC < VoltageData then ;If VoltageData > CountC then (If Current Cell > Highest Cell) CountC = VoltageData ;CountC = VoltageData (Store Current Cell V in CountC) endif if CountD > VoltageData then ;If VoltageData < CountD then (If Current Cell < Lowest Cell) CountD = VoltageData ;CountD = VoltageData (Store Current Cell V in CountD) endif CellVoltage = CellVoltage + DiscardLow ;CellVoltage (w1) = CellVoltage (w1) (1-255 0.01-2.55V) + (175 1.75V) serout Video,Baud9600,("Cell ",#CountA," ",#CellVoltage," V ",10,13) ;Video Display with Line Feed pause 1000 ;Pause for half a second at 8mhz Loop1: If ButtonB = 0 then Loop1 ;If Button B is not pressed goto Loop1 next CountA ;Increment for/next loop and move to next cell CountX = CountC + DiscardLow ;Highest Cell V Correction factor serout Video,Baud9600,(10,"Highest ",#CountX," V ",10,13) ;Video Display with Line Feed CountX = CountD + DiscardLow ;Lowest Cell V Correction factor serout Video,Baud9600,(13,"Lowest ",#CountX," V ",10,10,13) ;Video Display with Line Feed pause 2000 ;Pause for one second serout Video,Baud9600,("Press A to Exit ") ;Video Display with Line Feed Loop2: If ButtonA = 0 then Loop2 ;If Button A is not pressed goto Loop2 serout Video,Baud9600,(27,67) return ;Return to main program loop ;************************************************************************************************************** ;************************************************************************************************************** StartChg: ;Start Charging Cycle Routine If Warnings>0 then ;If Warnings >0 means an error flag is set & charge start is aborted serout Video,Baud9600,(27,83,0,9,"Error Can't Chg!") ;Show error message pause 2000 ;Pause for one second at 8mhz return ;Return to main loop, charging aborted due to error flag set endif DutyCycle = 0 ;Allow charger to start at maximum output Set PWM to 0% hpwmduty DutyCycle ;Set updated HPWM Charger/Controller DutyCycle to adjust output/limit ChargeFlag = 1 ;Set ChargeFlag to 1 indicates Charging in progress high ChargerOnOff ;Turn on Charger main relay high portc led2 ;Activate dash Led2 Mains Charging Indicator return ;Return to main program loop