Battery Management for 12V System
This module is part of the original MMBasic library. It is reproduced here with kind permission of Hugh Buckle and Geoff Graham. Be aware it may reference functionality which has changed or is deprecated in the latest versions of MMBasic.
'
' Battery Management Program for Caravan 12V System
' Copyright Doug Pankhurst May 2013
' Written for MMBasic V4.3a, copyright Geoff Graham 2012 '
'
' File Version: 2.04 May 2013
'
This is an updated (Mark II ) version of a program first submitted in May 2012. Lots of comments and it only JUST fits into a CMM running in 8 colour mode - I have intentionally made it verbose and not optimisedto allow easy reading.
This program monitors a 12V Battery System, monitoring the battery voltage, the solar panel voltage and the amount of charge supplied into and out of the battery via current shunt ICs. The charge/discharge state of the battery is given by comparing current in versus current out.
It also estimates time to 30% capacity based on battery voltage and current discharge rate and provides a warning.
Real time data is displayed on VGA display as well as historical data recorded to a log file on the SD card for later analysis.
It utilises a range of subroutines and defined funtions based on software and ideas from Doug Pankhurst, Geoff Graham, Tom Pankhurst, and also from programs provided in the MMBASIC Software library, authors unknown. This code is free for anyone to use or modify as long as they acknowledge it's source and credit the contributors above.
Physical configuration: Uses a CG Colourmax 2 as the hardware platform and an Arduino blank shield populated with voltage dividers for battery and solar voltages and Allegro ACS758 current sensors for input (charging) current and load current. Battery charge/discharge current is calculated by subtracting load current from charging current.
The 11.8V to 14.4V from the caravan battery system (depending on whether charging or driving load) is fed into an LM317 variable voltage regulator to provide regulated 8.5V to the CGCMM.
WARNING: The Allegro current sensors have VERY fragile leads so they need to be physically stabilised. The units I used were unidirectional and had an offset around 600mV and a 60mV/amp capacity.
A general synopsis of the program:
- Disable interrupts;
- Define and initialise variables and constants;
- Initialise display with static data; initialize 1 minute arrays to allow averaging;
- Enter main loop; wait for interrupt ( which sets NewData flag) then handle 2 second, 1 minute, 1 hour and end of day (6AM) occurrences;
- Start main loop, waiting for (set by interrupt routine);
- Cycle through 2 second, 1 minute, 1 hour and End-of-Day processing with initial data and display initial readings
- 2 second routine processes all instantaneous readings from interrupt routines - battery voltage, solar array voltage, input current from both solar controller and/or 240VAC battery charger
- 1 minute routine averages 30 two second readings, then pushes the averages into an array, also writes out running graph
- 1 hour routine takes array data and writes out to files in .CSV format
- EOD ( at 6AM ) closes log file and creates a new log file;
- Interrupt provides battery volts, solar volts, input current and load current.
Global Variables: These are here just for explanatory purposes - they are defined in the program proper. The initialised values are to simplify averaging and also represent typical values.
BVolts : Battery Voltage read from Pin A0. Read as 1/6th of real voltage via 6:1 resistive divider. BVArray(29) : Battery Volts 30 element array - 1 each 2 secs. BatCharge : Battery state of charge as a percentage where 12.75V or higher is 100%, down to 12.05V, being 35% - danger level. AverageBV : Average battery voltage over last 60 seconds. BVAArray(59) : 1 hours worth of minute average battery volts. DeltaBV : Battery voltage variation over 60 seconds. The difference between the first and the last used to calculate the "Time to 30% discharge point". Time2Discharge : Time to 30% discharge. SVolts : Solar Array voltage from Pin A1. Read as 1/10th of real voltage by 10:1 resistive divider. SVArray(29) : Solar Volts 30 element array - 1 each 2 secs. AverageSV : Average Solar Panel volts over last 60 seconds. SVAArray(59) : 1 hours worth of minute average solar volts. InputCurrent : Charging current into battery/load read from Pin A2 2.5V reading = 50mA across the shunt, which = 50A through shunt. This can be both battery charging current and load current. ICArray(29) : Input Current 30 element array. AverageIC : Average input (generator) current over last 60 seconds. ICAArray(59) : array with 1 hours worth of minute average input currents. LoadCurrent : Load current of caravan - can be supplied from the batteries and the charging systems (solar, AC Mains or generator). Pin A3. LCArray(29) : Load Current 60 element array. AverageLC : Average load current over last 60 seconds. LCAArray(59) : array to hold 1 hours worth of average load currents. BatCurrent : A calculated value; if positive, = a charging current to the battery; if negative, = a discharge current from the battery. AverageBC : Average charge/discharge current over last min calculated by AverageLC-AverageIC. InputCurrentAH : Input current as an amp hour calculated value - this is an accumulating value over 24 hours. PreviousICAH : yesterdays Input Current AHs. LoadCurrentAH : Load current as an amp hour calculated value - this is an accumulating value over 24 hours. PreviousLCAH : yesterdays Load Current AHs. BatCurrentAH : Bat charge (+value) or discharge (-value) as an amp hour calculated value - accumulating value over 24 hours. PreviousBCAH : yesterdays Bat Current AHs. LogArray$ : String to use for plugging into log array NewDataFlag : Two second flag - set every 2 seconds by the interrupt routine when new voltage and current values are collected. MinFlag : Minute flag - set once every min at 00 seconds by sec interrupt process and cleared by min processing code. HourFlag : Hour Flag - set on the hour to enable writing the 60 average readings in the log array to be written to file EODFlag : End of Day Flag - set at 6AM to enable daily log file to be closed and new log file created by LogFileCreate subroutine
CVBM204.BAS:
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Battery Management Program for Caravan 12V System ' ' Copyright Doug Pankhurst May 2012 ' ' Written for MMBasic V4.3a, copyright Geoff Graham 2012 ' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' File Version: 2.04 May 2013 ' ' For a detailed explanation of the program, it's ' construction and rationale, please read the ' CVBMREAD.TXT file. ' Main Entry to Program EntryPoint: SetTick 0,0 ' Disable timer interrupt ' Global Variables - initialised to default values BVolts = 12.8 ' Battery Voltage read from Pin A0. Read as ' 1/6th of real voltage via 6:1 resistive divider Dim BVArray(29) ' Battary Volts 30 element array - 1 each 2 secs BatCharge = 100 ' Battery state of charge as a percentage where ' 12.75V or higher is 100%, down to 12.05V being 35% - danger level AverageBV=12.8 ' Average battery voltage over last 60 seconds Dim BVAArray(59) ' 1 hours worth of minute average battery volts DeltaBV = 0.1 ' Battery voltage variation over 60 seconds. The ' difference between the first and the last used to ' calculate the "Time to 30% discharge point" Time2Discharge = 20 ' Time to 30% discharge SVolts = 20 ' Solar Array voltage from Pin A1. Read as 1/10th ' of real voltage by 10:1 resistive divider Dim SVArray(29) ' Solar Volts 30 element array - 1 each 2 secs AverageSV = 21 ' Average Solar Panel volts over last 60 seconds Dim SVAArray(59) ' 1 hours worth of minute average solar volts InputCurrent = 18 ' Charging current into battery/load read from Pin A2 ' 2.5V reading = 50mA across the shunt, which equals 50A through the shunt. ' This can be both battery charging current and load current. Dim ICArray(29) ' Input Current 30 element array AverageIC = 18 ' Average input (generator) current over last 60 seconds Dim ICAArray(59) ' array with 1 hours worth of minute average input currents LoadCurrent = 12 ' Load current of caravan - can be supplied from the ' batteries and the charging systems (solar, AC Mains or generator). Pin A3 Dim LCArray(29) ' Load Current 60 element array AverageLC = 12 ' Average load current over last 60 seconds Dim LCAArray(59) ' array to hold 1 hours worth of average load currents BatCurrent = 6 ' A calculated value; if positive, = a charging current to ' the battery; if negative, equals a discharge current from the battery. AverageBC = 6 ' Average charge/discharge current over last min ' calculated by AverageLC-AverageIC InputCurrentAH = 0 ' Input current as an amp hour calculated value - ' this is an accumulating value over 24 hours PreviousICAH = 0 ' yesterdays Input Current AHs LoadCurrentAH = 0 ' Load current as an amp hour calculated value - ' this is an accumulating value over 24 hours PreviousLCAH = 0 ' yesterdays Load Current AHs BatCurrentAH = 0 ' Bat charge (pos value) or discharge (neg value) ' as an amp hour calculated value - accumulating value over 24 hours PreviousBCAH = 5 ' yesterdays Bat Current AHs LogArray$ = "" ' String to use for plugging into log array NewDataFlag = 0 ' Two second flag - set every 2 seconds by the ' interrupt routine when new voltage and current values are collected. MinFlag = 0 ' Minute flag - set once every min at 00 seconds ' by sec interrupt process and cleared by min processing code. HourFlag = 0 ' Hour Flag - set on the hour to enable ' writing the 60 average readings in the log array to be writtent to file EODFlag = 0 ' End of Day Flag - set at 6AM to enable daily log file ' to be closed and new log file created by LogFileCreate subroutine ''''''''''''''''' ' Carry out initialisation routines here - enable interrupt last Entry: Mode 3,7 ' 8 colour mode white on black Colour White,Black Cls ' Display all static data Option USB Off ' only to VGA DisplayStatic BarGraph ' Create Log File on program entry and then at start of new day - 6AM CreateLogFile ' Set up all initial values to default for orderly entry. PreviousICAH = 50 PreviousLCAH = 45 PreviousBCAH = 5 OldABV = 13 LFAPointer = 0 ' Fill the arrays For Ax=0 To 29 BVArray(Ax) = 12.8 SVArray(Ax) = 19 ICArray(Ax) = 18 LCArray(Ax) = 12 Next Ax ' Wait until 00 seconds to start for clean entry. Do While Val(Mid$(Time$,7,2)) <> 58 Loop ' Enable timer tick interrupts to start data collection at 00 seconds SetTick 2000,GetData ' Every other second, get battery voltage and current ' data through the GetData interrupt routine. ' end of initialisation routines '''''''''''''''''''' ' Main program loop Main: Do While NewDataFlag = 0 ' wait until interrupt provides fresh data Loop '''''''''''''''''''' ' 2 second processing code ' Write out time and date to display Print @(1,1)Time$ + " " + Date$ ' Push most recent values into arrays for minute averaging For Ax = 29 To 1 Step -1 BVArray(Ax) = BVArray(Ax-1) SVArray(Ax) = SVArray(Ax-1) ICArray(Ax) = ICArray(Ax-1) LCArray(Ax) = LCArray(Ax-1) Next Ax BVArray(0) = BVolts SVArray(0) = SVolts ICArray(0) = InputCurrent LCArray(0) = LoadCurrent ' Charge/Discharge Current is InputCurrent-LoadCurrent - if positive ' it is a charging current into battery, if negative, it is a ' discharging current out of battery BatCurrent = InputCurrent-LoadCurrent ' Convert both input, output & battery instantaneous currents into Amp Hours InputCurrentAH = InputCurrentAH + (InputCurrent/1800) ' use 2 sec interrupt LoadCurrentAH = LoadCurrentAH + (LoadCurrent/1800) ' rate for calculation BatCurrentAH = InputCurrentAH-LoadCurrentAH ' Note: All AH accumulating totals are plugged into last day values ' then reset to zero at 6AM - now update terminal display with all values Font #2 Colour 2 Print @(372,25)Format$(BatCharge,"%3.0f")+"%" Font #1 Colour 7 Print @(123,45)Format$(BVolts,"%5.2fV") Print @(123,56)Format$(SVolts,"%5.2fV") Print @(123,67)Format$(InputCurrent,"%5.2fA") Print @(123,78)Format$(LoadCurrent,"%5.2fA") Print @(312,45)Format$(AverageBV,"%5.2fV") Print @(312,56)Format$(AverageSV,"%5.2fV") Font #2 Colour 7 Print @(420,184)Format$(AverageBV,"%4.1f") Colour 3 Print @(420,232)Format$(AverageSV,"%4.1f") Colour 7 Font #1 Print @(376,149)Format$(Time2Discharge,"%4.0f min") Print @(312,67)Format$(AverageIC,"%5.1fA") Print @(312,78)Format$(AverageLC,"%5.1fA") Colour 6 Font #2 Print @(420,285)Format$(AverageIC,"%4.1f") Colour 5 Print @(420,340)Format$(AverageLC,"%4.1f") Colour 7 Font #1 Print @(117,127)Format$(InputCurrentAH,"%5.1fahrs") Print @(117,138)Format$(LoadCurrentAH,"%5.1fahrs") If (Sgn(BatCurrentAH) = +1) Then Colour 2 Print @(117,149)Format$(BatCurrentAH,"%+5.1fahrs") Else Colour 4 Print @(117,149)Format$(BatCurrentAH,"%+5.1fahrs") EndIf Colour 7 Print @(312,127)Format$(PreviousICAH,"%5.1fahrs") Print @(312,138)Format$(PreviousLCAH,"%5.1fahrs") If (Sgn(PreviousBCAH) = +1) Then Colour 2 Print @(312,149)Format$(PreviousBCAH,"%+5.1fahrs") Else Colour 4 Print @(312,149)Format$(PreviousBCAH,"%+5.1fahrs") EndIf Colour 7 If (Sgn(AverageBC) = +1) Then Colour 2 Print @(312,89)Format$(AverageBC,"%+5.1fA") Font #2 Print @(418,410)Format$(AverageBC,"%+4.1f") Font #1 Else Colour 4 Print @(312,89)Format$(AverageBC,"%+5.1fA") Font #2 Print @(418,410)Format$(AverageBC,"%+4.1f") Font #1 EndIf If (Sgn(BatCurrent) = +1) Then Colour 2 Print @(123,89)Format$(BatCurrent,"%+5.2fA") Else Colour 4 Print @(123,89)Format$(BatCurrent,"%+5.2fA") EndIf Colour 7 NewDataFlag = 0 ' clear new data flag ready for next interrupt ' ' End of two second processing code, now check for minute, hour or end of ' day flags and process accordingly ''''''''''''''''''''''''''''''''''' ' Check for minute flag, calculate the average of the last 60 seconds of ' readings, plug them into the log file array at the log file array pointer If MinFlag = 1 Then ' calculate average for last minute OldABV = AverageBV OldASV = AverageSV AverageBV = 0 AverageSV = 0 AverageIC = 0 AverageLC = 0 For Ax = 0 To 29 'don't forget only sampled every 2 secs AverageBV = AverageBV + BVArray(Ax) AverageSV = AverageSV + SVArray(Ax) AverageIC = AverageIC + ICArray(Ax) AverageLC = AverageLC + LCArray(Ax) Next Ax AverageBV = AverageBV/30 AverageSV = AverageSV/30 AverageIC = AverageIC/30 AverageLC = AverageLC/30 AverageBC = AverageIC - AverageLC ' Calculate battery change as percentage and fill charge state graph ' now calculate charge and paint capacity graph ' 12.1V equates to 30% charge BatCharge = Int((AverageBV - 11.75) * 100) If BatCharge < 30 Then BatCharge = 30 If BatCharge > 100 Then BatCharge = 100 FillBarGraph(BatCharge) ' Calculate time to 30% discharge of battery DeltaBV = OldABV - AverageBV If Sgn(DeltaBV) = +1 Then DVRate = BVArray(0) ' set initial values for rate of Time2Discharge = 0 ' discharge and time to discharge Do While DVRate > 12.1 ' 12.1 volts equates to 30% discharge DVRate = DVRate - DeltaBV ' loop through calculating the amount ' of time to get the current voltage ' down to the 30% discharge point Time2Discharge = Time2Discharge + 1 ' inc minutes to discharge count Loop Else Print @(376,149)"Charging " ' if current voltage is greater than EndIf ' previous minute BVAArray(LFAPointer) = AverageBV ' update average arrays SVAArray(LFAPointer) = AverageSV ICAArray(LFAPointer) = AverageIC LCAArray(LFAPointer) = AverageLC LFAPointer = LFAPointer + 1 ' LFA pointer reset by eod routine ' Now paint out running graph ' - first work out the current minute hour combo in minutes rg_mins = (((Val(Mid$(Time$,1,2)) Mod 6)*60))+(Val(Mid$(Time$,4,2))) rg_mins = rg_mins + 30 ' offset to start of graph rg_abv = 412 - Int((AverageBV-8) * 10) If rg_abv > 412 Then rg_abv = 412 rg_asv = 412 - Int((AverageSV-8) * 10) If rg_asv > 412 Then rg_asv = 412 If rg_asv < 163 Then rg_asv = 163 rg_aic = 412 - Int(AverageIC * 5) rg_alc = 412 - Int(AverageLC * 5) If (Sgn(AverageBC) = +1) Then rg_abc = 412 - Int(AverageBC * 5) Else rg_abc = 412 + Int(AverageBC * 5) EndIf For yrg = 163 To 412 Step 1 If rg_abc = yrg Then If (Sgn(AverageBC) = +1) Then Pixel(rg_mins,yrg) = 2 Else Pixel(rg_mins,yrg) = 4 EndIf Else Pixel(rg_mins,yrg) = 0 EndIf If rg_abv = yrg Then Pixel(rg_mins,yrg) = 7 EndIf If rg_asv = yrg Then Pixel(rg_mins,yrg) = 3 EndIf If rg_aic = yrg Then Pixel(rg_mins,yrg) = 6 EndIf If rg_alc = yrg Then Pixel(rg_mins,yrg) = 5 EndIf Line(rg_mins+1,yrg)-(rg_mins+3,yrg),0 Next yrg MinFlag = 0 ' reset the min flag EndIf ' End of minute code '''''''''''''''''''' ' Check for hour flag - if true then append log array out to file ' (we want to limit log file writes to 24 per day to keep ' SD card writes as low as possible). If HourFlag = 1 Then ' set each hour in interrupt routine LogArray$ = "" For x=0 To 59 Step 1 ' get the average values from each average array LogArray$ = LogArray$+Format$(BVAArray(x),"%+6.2fV")+Chr$(44) LogArray$ = LogArray$+Format$(SVAArray(x),"%+6.2fV")+Chr$(44) LogArray$ = LogArray$+Format$(ICAArray(x),"%+5.1fA")+Chr$(44) LogArray$ = LogArray$+Format$(LCAArray(x),"%+5.1fA") Print #1,LogArray$ LogArray$ = "" Next x LFAPointer = 0 ' reset array pointer HourFlag = 0 ' clear hour flag until next hour EndIf ' End of hour code '''''''''''''''''' ' Check for end of day - if true then close log file and create new file ' for new day starting at 6AM If EODFlag = 1 Then Close #1 ' close out last log file, save amp hour data PreviousICAH = InputCurrentAH InputCurrentAH = 0 PreviousLCAH = LoadCurrentAH LoadCurrentAH = 0 PreviousBCAH = BatCurrentAH BatCurrentAH = 0 CreateLogFile ' create new log file with todays date EODFlag = 0 ' clear end of day flag until next 6AM EndIf ' End of day code ''''''''''''''''' GoTo Main ' back to Main ready for next interrupt ' End of main program loop '''''''''''''''''''''''''' '''''''''''''''''''''''''' ' Interrupt Routine Handling GetData: ' Timer Interrupt handler ' Arduino analogue input pins SetPin a0,1 ' pin 35 - battery voltage - 0 to 2.5V = 0 to 15V SetPin a1,1 ' pin 36 - solar volts - 0 to 2.5V = 0 to 25V SetPin a2,1 ' pin 37 - input current shunt - 0 to 2.5V = 0 to 50A SetPin a3,1 ' pin 38 - load current shunt - 0 to 2.5V = 0 to 50A ' Get the battery voltage ic=0 BVolts = 0 GetPin35 = 0 For ic = 1 To 20 GetPin35 = Pin(a0) BVolts = BVolts + GetPin35 Next ic BVolts = BVolts/20 ' Average out Battery voltage BVolts = BVolts*6 ' 15 battery volts = 2.5 MM volts ' Get the Solar Array voltage ic=0 SVolts=0 GetPin36 = 0 For ic = 1 To 20 GetPin36 = Pin(a1) SVolts = SVolts + GetPin36 Next ic SVolts = SVolts/20 ' same as for BVolts SVolts = SVolts*10 ' 25 solar volts = 2.5 MM volts ' Get the input current as a voltage InputCurrent = 0 GetPin37 = 0 For ic = 1 To 20 GetPin37 = Pin(a2) - 0.5817 InputCurrent = InputCurrent + GetPin37 Next ic InputCurrent = InputCurrent/20 ' Average out input current InputCurrent = Abs(InputCurrent*16.667) ' Correct for opamp amplification ' current by 16.667 now gives a value 50mV = 1A ' Get the load current as a voltage LoadCurrent = 0 GetPin38 = 0 For ic = 1 To 20 GetPin38 = Pin(a3) - 0.5803 LoadCurrent = LoadCurrent + GetPin38 Next ic LoadCurrent = LoadCurrent/20 ' Average out load current LoadCurrent = Abs(LoadCurrent*16.667) ' Correct for opamp amplification ' current by 16.667 now gives a value 50mV = 1A ' Get the current time, extract the minutes component If Mid$(Time$,7,2) = "00" Then MinFlag = 1 EndIf ' Get the current time, test for hour AND minute tunover If Mid$(Time$,7,2) = "00" And Mid$(Time$,4,2) = "00" Then HourFlag = 1 EndIf ' Get the current time, test for 0600:00 If MinFlag And HourFlag And Mid$(Time$,1,2)="06" Then EODFlag = 1 EndIf NewDataFlag = 1 ' set to indicate fresh data IReturn ' Returns with the following values:- ' BVolts = 0 to 15 equalling battery volts ' SVolts = 0 to 25 equalling solar Array volts ' InputCurrent=0 to 50 equalling 0 to 50Amps ' LoadCurrent=0 to 50 equalling 0 to 50Amps 'End of Interrupt code ''''''''''''''''''''' ' Defined Subroutines ''''''''''''''''''''' ' Set up terminal display with static data (field names etc.) ' - uses the PRINT @ to print at defined positions Sub DisplayStatic Local xrg,yrg,volts,amps Cls Print @(150,1)"CARAVAN POWER MONITOR V2.04" Line(150,11)-(312,11) Print @(1,25)"Instantaneous Readings" Print @(198,25)"Minute Average Readings" Line(1,36)-(152,36) Line(198,36)-(346,36) Print @(376,1)"Battery" Print @(1,45)"Battery Volts =" Print @(198,45)"Battery Volts =" Print @(379,12)"Charge" Print @(1,56)"Solar Array Volts =" Print @(198,56)"Solar Array Volts =" Print @(1,67)"Input Current =" Print @(198,67)"Input Current =" Print @(1,78)"Load Current =" Print @(198,78)"Load Current =" Print @(1,89)"Bat Chg/Dis Curr =" Print @(198,89)"Bat Chg/Dis Curr =" Print @(1,108)"Daily Accumulating Readings" Print @(198,108)"Previous Days Total Readings" Line(1,120)-(170,120) Line(198,120)-(362,120) Print @(1,127)"Input Charge =" Print @(198,127)"Input Charge =" Print @(384,127)"Time to" Print @(1,138)"Load Discharge =" Print @(198,138)"Load Discharge =" Print @(400,138)"30%" Print @(1,149)"Battery Chg/DisChg=" Print @(198,149)"Battery Chg/DisChg=" Line(0,162)-(479,431),1,B Colour 7,0 Print @(424,164)"Battery" Print @(430,174)"Volts" Colour 3,0 Print @(430,210)"Solar" Print @(430,220)"Volts" Colour 6,0 Print @(430,260)"Input" Print @(433,270)"Amps" Colour 5,0 Print @(433,315)"Load" Print @(433,325)"Amps" Colour 2,0 Print @(427,375)"Battery" Print @(436,385)"Amps" Print @(430,395)"In/" Colour 4,0 Print @(449,395)"Out" Colour 7,0 volts=22 amps = 48 For yrg =167 To 387 Step 10 Print @(2,yrg)Format$(volts,"%2.0fV") Print @(400,yrg)Format$(amps,"%2.0fA") amps=amps-2 yrg=yrg+10 Print @(400,yrg)Format$(amps,"%2.0fA") volts=volts-1 amps=amps-2 Next yrg Line(29,163)-(29,413) Line(393,163)-(393,413) For yrg = 163 To 413 Step 10 'minor ticks Pixel(28,yrg)=7 Pixel(394,yrg)=7 Next yrg For yrg = 173 To 413 Step 20 'major ticks Pixel(27,yrg)=7 Pixel(395,yrg)=7 Next yrg Line(30,414)-(390,414) 'now for the bottom For xrg = 30 To 390 Step 5 Pixel(xrg,415)=7 Next xrg For xrg = 30 To 390 Step 15 Line(xrg,415)-(xrg,416),7 Next xrg For xrg = 30 To 390 Step 30 Line(xrg,415)-(xrg,417),7 Next xrg For xrg = 30 To 390 Step 60 Line(xrg,415)-(xrg,418),7 Next xrg Print @(100,419)"6 Hour Graphing period - starts 6AM" End Sub ''''''' ' Bar Graph - Draw Static ' top left x=432, y=0, bottom right x=479, y=162 ' This equates to 2 steps per percentage for the range of 35% to 100% Sub BarGraph Local xtl,ytl,xbr,ybr,percent,xpos,ypos,y xtl=432:ytl=0:xbr=xtl+47:ybr=ytl+162 ' First draw the box and values Line(xtl,ytl)-(xbr,ybr),1,B percent=100 Print @(xtl+3,ytl+2)"Battery" Print @(xtl+13,ytl+13)100 Print @(xtl+40,ytl+13)"%" percent=percent-5 For y=ytl+22 To 142 Step 10 Print @(xtl+19,y)percent Print @(xtl+40,y)"%" percent = percent-5 Next y End Sub ''''''' Sub CreateLogFile LogFileName$="B:"+Mid$(Date$,9,2)+Mid$(Date$,4,2)+Left$(Date$,2)+".CSV" Open LogFileName$ For Output As #1 Print #1, "Battery Voltage";Chr$(44); Print #1, "Solar Array Voltage";Chr$(44); Print #1, "Input Current";Chr$(44); Print #1, "Load Current" End Sub ''''''' ' Bar Graph - Fill ' top left x=432, y=0, bottom right x=479, y=162 ' To fill, start at x=434 thru 443 and y=150 back up to y=12 ' This gives 138 steps, equates to 1.97 steps per % for 30% to 100% ' Enter with actual battery charge as a percent Sub FillBarGraph(BatCharge) Local xtl,ytl,bat_chg,xpos,ypos,yper,xright,xleft,ybot,ytop bat_chg=BatCharge xtl=432:ytl=0:xbr=xtl+47:ybr=ytl+162 ' Now fill the bar graph If bat_chg < 31 Then bat_chg=30 Colour 4,7 Print @(xtl + 4,ytl + 151,2)"DANGER" Else Colour 2,7 Print @(xtl + 4,ytl + 151,2)" OK " EndIf Colour 7,0 If bat_chg > 100 Then bat_chg=100 ytop=12 yper=Int(((100 - bat_chg) * 1.97) + 12) ybot=150 xleft=437 xright=446 For ypos=ybot To ytop Step -1 If yper < ypos Then For xpos=xleft To xright Step 1 Pixel(xpos,ypos)=2 Next xpos Else For xpos=xleft To xright Step 1 Pixel(xpos,ypos)=0 Next xpos EndIf Next ypos End Sub ' End program. ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''