'------ Li-Ion Battery Management System Command Slave (Digital) Module ------- '------ Picbasic Pro Compiler version PIC12F683 - 071209 - V07 Beta ---------- '------ This code is for serial command slaves only and requires Master board V2 '------ & Master software V1.72 onwards. Please report any errors or problems. '------------------------------------------------------------------------------ '**************************** 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. '************************* Slave PIC12F683 Pinouts **************************** ' Top ' _____ '(+ Cell Supply) +Ve -1| ^ |8- -Ve (- Cell Supply) '(Slave Alive Out) Output 5 -2| 6 |7- Output 0 (Bypass Load Out) '(Slave Data Bus Out) Output 4 -3| 8 |6- Input 1 (RefAdc In 1.235V) '(Slave Data Bus In) Input 3 -4| 3 |5- Output 2 (Master Data Bus Out) ' ----- '************************ Slave Module Specification *************************** 'Supply/Cell Voltage 1.75 - 5.00V DC (Pic limits) 'Average Supply Current at 3.35v <1ma 'Voltage Ref LM 385 1.235V accuracy 1% 'Supply/Cell Voltage sensing maximum accuracy +/- 20mv 'Maximum balancing/bypass current with 15R resistor 333ma at 5.00V 'Maximum serial Bus data rate 9600 baud 'Maximum cell Capacity 650ah (65,000) (Limit of 16bit Word Master Variable) 'Maximum 256 Slave Modules per Master Module 'CPU Speed 31khz - 8mhz with internal resonator (Lower speed used for power saving) 'Permitted Working Cell Voltage Range 1.75 - 4.30V 'RefVADC should be 63200 but can be adjusted to compensate for variations. 'Note Slave Opto's are Sink driven therefore (Pic Output Low = Opto On, High = Opto Off) '******************************************************************************* '********************** Program Size 363 out of 2048 Words ********************* '******************************************************************************* '------------------------------ General configuration -------------------------- @ DEVICE PIC12F683,MCLR_OFF @ DEVICE PIC12F683,BOD_OFF @ DEVICE PIC12F683,PROTECT_OFF @ DEVICE PIC12F683,WDT_ON Define OSC 4 'Set processor speed to 4 Mhz INTCON = %10001000 'Internal oscillator OSCCON = %01100111 'Sets internal osc to 4 Mhz and stable CMCON0 = 7 'Comparators off GPIO = %00000000 'Outputs low TRISIO = %00001010 'Set Pins GPIO.1 & GPIO.3 as inputs ANSEL = %00110010 'AN1 Analog Input ADCON0 = %10000101 'Turns A/D on, A/D reads pin 6(AN1), right justify and Vref=Vdd 'Define ADCIN parameters Define ADC_BITS 10 'Set number of bits in result Define ADC_CLOCK 3 'Set clock source (3=rc) Define ADC_SAMPLEUS 50 'Set sampling time in uS include "modedefs.bas" 'Allows the use of the serin/serout command '******************************************************************************* 'Variables Constants and I/O definitions '------------------------ Variables 16bit -------------------------------------- CellV var Word 'Cell Voltage (16bit value) RefADC var Word 'Raw Adc input data variable range 0-1023 10bit CutInV var Word 'Balancing load/bypass cut in Voltage CutOutV var Word 'Balancing load/bypass cut out Voltage '----------------- Variables 8bit -------------------------------------------- VData var CellV.LowByte 'VData is low byte of Word Var CellV CountB var byte 'General 0-255 byte ADC loop counter variable Command var byte 'Serial data command byte 0-255 '------------------- Constants ----------------------------------------------- RefVADC con 63200 'Fixed Ref Voltage Calibration LM385 1.235v * 1023 * 100 / 2 = 63200 Delay con 5 'Data delay time in milliseconds DLow con 175 'Cell correction value 175 (1.75V) subtracted from CellVoltage DHigh con 430 'Cell correction value 430 (4.30V) (If Cell V>430 or <175 then error) CutInVD con 365 'Balancing load/bypass default cut in Voltage (Must match value set in Master) CutOutVD con 360 'Balancing load/bypass default cut out Voltage (Must match value set in Master) '-------------- Pins used for I/O and designations ------------------------- '---------------- Digital high/low Outputs ------------------------ Load var GPIO.0 '2W 15R load/bypass resistor & led indicator on Output 0 (pin 7) MasterBus var GPIO.2 'Master Data Bus Output Baud4800 on Output 2 (pin 5) SlaveBusIn var GPIO.3 'Slave Data Bus Input Baud4800 on Input 3 (pin 4) SlaveBusOut var GPIO.4 'Slave Data Bus Output Baud4800 on Output 4 & optional led indicator (pin 3) SlaveAlive var GPIO.5 'Slave Alive Toggle Test Ouput (Toggles high/low each time through main loop) '---------------- Analogue ADC Inputs ------------------------------ RefInput var GPIO.1 'LM385 1.235V RefAdc on Input 1 (pin 6) '******************************************************************************* Start: 'Main program start high SlaveBusOut 'Turn off interrupt signal for next Slave (SlaveBusOut) high MasterBus 'Turn off MasterBus Optocoupler (Reqd due to sink driven) low Load 'Turn off by-pass resistor CutInV = CutInVD 'Set default Balancing load/bypass cut in Voltage CutOutV = CutOutVD 'Set default Balancing load/bypass cut out Voltage Main: 'Main program loop label Toggle SlaveAlive 'Slave Alive Toggle Test Ouput (Toggles high/low each time through main loop) CellV = 0 'Set CellV word variable to 0 (Zero) for CountB = 1 to 10 '10x ADC Oversampling loop counter ADCON0.1 = 1 'Start ADC conversion while ADCON0.1 = 1 'Wait for ADC DONE wend RefADC.highbyte = ADRESH 'Move HIGH byte of result to RefADC.highbyte RefADC.lowbyte = ADRESL 'Move LOW byte of result to RefADC.lowbyte CellV = CellV + RefADC 'Add latest ADC reading to running total next CountB 'Repeat loop until 10 ADC readings obtained CellV = CellV / 10 'Calculate average ADC reading for last 10 readings CellV = RefVADC / CellV 'Calculate Cell Voltage from the average ADC LM385 VRef 1.235v reading CellV = CellV * 2 'Calculate Cell Voltage from the average ADC LM385 VRef 1.235v reading if CellV > CutInV then 'If Cell V > CutInV then high Load 'Turn on bypass resistor and bypass led endif if CellV < CutOutV then 'If Cell V < CutOutV then low Load 'Turn off bypass resistor and bypass led endif if SlaveBusIn = 0 then Main 'If no interrupt signal goto Main Loop1: if SlaveBusIn = 1 then Loop1 'Wait until interrupt signal (pin 4) is low before continuing serin SlaveBusIn,N9600,50,Main,Command 'Receive Command from previous Slave (Timeout 50ms) if Command = 0 then 'If command = 0 then send voltage data if CellV >DHigh or CellV 4.30V or V <1.75V set out of range (b0=0) VData = 0 'Set VData = 0 Cell error out of Voltage range condition else CellV = CellV - DLow 'Convert Word (CellV) data into Byte (VData) for output endif goto Transmit 'Goto Transmit to send data endif if Command = 1 then 'If command = 1 then increase Load CutInV CutInV = CutInV + 10 'Increase Load Cut in voltage by 10mv endif if Command = 2 then 'If command = 2 then decrease Load CutInV CutInV = CutInV - 10 'Decrease Load Cut in voltage by 10mv endif if Command = 3 then 'If command = 3 then increase Load CutOutV CutOutV = CutOutV + 10 'Increase Load Cut Out voltage by 10mv endif if Command = 4 then 'If command = 4 then decrease Load CutOutV CutOutV = CutOutV - 10 'Decrease Load Cut Out voltage by 10mv endif if Command = 5 then 'If command = 5 then set Slave defaults CutInV = CutInVD 'Set default Balancing load/bypass cut in Voltage CutOutV = CutOutVD 'Set default Balancing load/bypass cut out Voltage endif VData = Command 'Load VData with the current Command Transmit: 'This section transmits the commands and data on the two data buses Pause Delay 'Allow time for Master to be ready serout MasterBus,T9600,[VData] 'Send VData (b0) to Master at Baud9600 (MasterBusout) low SlaveBusOut 'Turn on interrupt signal for next Slave (SlaveBusOut) Pause Delay 'Allow time for next Slave to be ready high SlaveBusOut 'Turn off interrupt signal for next Slave (SlaveBusOut) Pause Delay 'Allow time for next Slave to be ready serout SlaveBusOut,T9600,[Command] 'Send Command Byte to next Slave goto Main 'Goto start of Main loop