100 ' BATTERY.BAS 105 ' Program to test the capacity of a battery 110 ' See Silicon Chip May 2011 for circuit details 115 ' V1.0 120 ' 125 ' 130 ' Measured resistance of the four load resistors 135 ' These are constant values determined by measuring the actual resistance 140 ' with a digital multimeter. They must be in descending order of values 145 R1 = 56.00 150 R2 = 22.00 155 R3 = 8.20 160 R4 = 3.33 165 ' 170 ' Measured value of the 3.3 volt supply 175 Vdd = 3.29 180 ' 185 ' 190 ' Default terminating voltage level and test current 195 TerminatingVolts = 1.0 200 TestCurrent = 120 205 ' 210 ' 215 '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 220 ' Configure the input and output pins 225 PIN(11) = 1 : PIN(12) = 1 : PIN(13) = 1 : PIN(14) = 1 230 SETPIN 11, 9 : SETPIN 12, 9 : SETPIN 13, 9 : SETPIN 14, 9 235 SETPIN 1,1 240 ' 245 ' 250 '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 255 ' Get the operating parameters from the user 260 ' check each response to make sure that it is within acceptable range 265 ' 270 CLS : PRINT "Battery test V1.0" : PRINT 275 DO 280 INPUT "Enter the approx test current in mA (600 to 25): ", TestCurrent 285 LOOP WHILE TestCurrent < 25 OR TestCurrent > 600 290 ' 295 DO 300 PRINT "Enter the terminating voltage "; 305 PRINT "(default "; FORMAT$(TerminatingVolts, "%4.2f"); "): "; 310 INPUT "", TerminatingVolts 315 LOOP WHILE TerminatingVolts < 0.5 OR TerminatingVolts > 2 320 ' 325 PRINT 330 IF PIN(1) / 3.3 * Vdd < TerminatingVolts THEN 335 PRINT "To start the test place the charged battery in the holder"; 340 DO : LOOP WHILE PIN(1) / 3.3 * Vdd < TerminatingVolts 345 PRINT : PRINT 350 ENDIF 355 ' 360 ' 365 ' 370 TIME$ = "0:0:0" 375 LASTTIME$ = TIME$ 380 PRINT "TIME ", "VOLTS ", "CURRENT", " ACCUMULATED" 385 PRINT "========================================================" 390 ' 395 ' 400 '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 405 ' Main test loop 410 DO 415 BattV = PIN(1) / 3.3 * Vdd ' measure the battery voltage 420 ' 425 ' Calculate the setting required to draw the test current 430 PrevTC = BattV/R1 * 1000 435 FOR i = 2 TO 15 440 TC = 0 445 IF i AND &b0001 THEN TC = TC + BattV/R1 450 IF i AND &b0010 THEN TC = TC + BattV/R2 455 IF i AND &b0100 THEN TC = TC + BattV/R3 460 IF i AND &b1000 THEN TC = TC + BattV/R4 465 TC = TC * 1000 470 IF PrevTC + (TC - PrevTC) / 2 > TestCurrent THEN EXIT FOR 475 PrevTC = TC 480 NEXT i 485 i = i - 1 490 ' 495 ' Set the reed relays to draw the test current 500 PIN(11) = NOT(i AND &b0001) 505 PIN(12) = NOT(i AND &b0010) 510 PIN(13) = NOT(i AND &b0100) 515 PIN(14) = NOT(i AND &b1000) 520 ' 525 mAhours = mAhours + PrevTC/3600 ' accumulate the mAH reading 530 ' 535 IF RIGHT$(TIME$, 2) = "00" THEN 540 PRINT TIME$,FORMAT$(BattV, "%5.3fV "),FORMAT$(PrevTC, "%5.1fmA "),; 545 PRINT FORMAT$(mAhours, "%5.0fmAH") 550 ENDIF 555 ' 560 ' wait for the next second 565 DO WHILE TIME$ = LASTTIME$ : LOOP 570 LASTTIME$ = TIME$ 575 ' 580 LOOP WHILE BattV > TerminatingVolts 585 ' 590 PIN(11) = 1 : PIN(12) = 1 : PIN(13) = 1 : PIN(14) = 1 595 ' 600 ' 605 '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 610 ' print the summary 615 PRINT : PRINT "Test complete. "; 620 PRINT "Battery capacity is "; FORMAT$(mAhours, "%5.0fmAH") 625 PRINT : PRINT
100 '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 110 ' BATTERY.BAS 120 ' Program to test the capacity of a battery 130 ' V2.0 Geoff Graham Jan 2011 140 ' 150 '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 160 ' 170 ' This is an extended version of the battery test program described in 180 ' the May 2011 issue of Silicon Chip. Additional features include: 190 ' - Will draw a graph of the battery voltage on the video output 200 ' - Choice of a constant current, power or resistance type of load 210 ' - Ability to save the data in an Excel compatible file 220 ' - Optional ability to use 5 relays for a finer level of load control 230 ' 240 ' See the Silicon Chip article or the accompanying PDF for circuit details 250 ' 260 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 270 ' 280 ' Measured resistance of the five load resistors 290 ' These are constant values determined by measuring the actual resistance 300 ' with a digital multimeter. They must be in descending order of values 310 ' if you only have 4 relays set the value of R5 to a very low value (eg, 0.0001) 320 ' 330 R1 = 59.228 340 R2 = 29.789 350 R3 = 14.944 360 R4 = 7.516 370 R5 = 3.789 380 ' 390 ' Correction for any error in measuring voltage (ie. actual V / Maximite V) 400 VCorrect = 1.019 410 ' 420 ' default settings 430 DefaultType$ = "C" ' constant current 440 DefaultBLoad = 200 ' load of 200 mA or mW 445 DefaultRLoad = 25 ' resistive load 25 ohms 450 DefaultThreshold = 0.9 ' cutout voltage to stop the test 460 ' 470 '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 480 MaxHist = 100 * 60 ' maximum history to be saved (in minutes) 490 Dim Hist(MaxHist) ' array for holding the history data 500 '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 510 ' Program Start 520 ' The program returns to here when the test has finished 530 ' 540 ' Configure the input and output pins 550 Pin(11) = 1 : Pin(12) = 1 : Pin(13) = 1 : Pin(14) = 1 : Pin(15) = 1 560 SetPin 11, 9 : SetPin 12, 9 : SetPin 13, 9 : SetPin 14, 9 : SetPin 15, 9 570 SetPin 1,1 580 ' 590 HScale = 2 595 mAhours = 0 600 ' 610 Pin(0) = 1 : Print : Print : Cls 620 ' 630 ' Get the test parameters from the user 640 Print "Battery capacity test utility V2.0" 650 ' define constants and arrays 655 Do 660 Print 670 Print "C = Constant current drain" 680 Print "P = Constant power drain" 690 Print "R = Constant resistive load" 700 Print "Select (default is "; DefaultType$; ") "; 710 Input Type$ 715 If Asc(Type$) = 0 Then Type$ = DefaultType$ 720 Type$ = Left$(UCase$(Type$), 1) 725 Loop Until Type$ = "C" Or Type$ = "P" Or Type$ = "R" 730 Print 740 ' 750 If Type$ = "C" Then 760 Do 770 Print "Range is 600mA to 20mA" 780 Print "Enter current drain (default is"; DefaultBLoad; ") "; 790 Input BLoad 795 If BLoad = 0 Then Bload = DefaultBLoad 800 Loop While BLoad > 600 Or BLoad < 20 810 ElseIf Type$ = "P" Then 820 Do 830 Print "Range is 750mW to 25mW" 840 Print "Enter power drain (default is"; DefaultBLoad; ") "; 850 Input BLoad 855 If BLoad = 0 Then BLoad = DefaultBLoad 860 Loop While BLoad > 750 Or BLoad < 25 870 ElseIf Type$ = "R" Then 880 Do 900 Print "Range is 60 ohms to 1.8 ohms" 910 Print "Enter resistive load (default is"; DefaultRLoad; ") "; 920 Input BLoad 925 If BLoad = 0 Then BLoad = DefaultRLoad 930 Loop While BLoad > 60 And BLoad < 1.8 960 EndIf 970 ' 975 Do 980 Print 990 Print "Enter the cutoff voltage (default is "; Format$(DefaultThreshold, "%3.1f"); ") "; 995 Print "Minimum cutoff is 0.5V" 1000 Input Threshold 1005 If Threshold = 0 Then Threshold = DefaultThreshold 1010 Loop While Threshold < 0.5 Or Threshold > 1.5 1020 Print 1030 ' 1040 Do 1060 Input "Save the results to an Excel file (Y/N, default is N) ", SSave$ 1070 SSave$ = Left$(UCase$(SSave$), 1) 1075 If Asc(SSave$) = 0 Then SSave$ = "N" 1080 Loop While Not(SSave$ = "Y" Or SSave$ = "N") 1089 ' 1090 If SSave$ = "Y" Then 1100 Line Input "Filename (without an extension): "; FName$ 1110 Open Left$(FName$, 8) + ".xls" For output As #1 1120 Line Input "Description of battery under test: "; R$ 1130 Print #1, R$ 1140 If Type$ = "C" Then Print #1, "Constant current of"; BLoad; "mA. Cutoff at"; Threshold; "V" 1150 If Type$ = "P" Then Print #1, "Constant power of"; BLoad; "mW. Cutoff at"; Threshold; "V" 1160 If Type$ = "R" Then Print #1, "Constant resistance of"; BLoad; " ohms. Cutoff at"; Threshold; "V" 1170 Print #1 : Print #1, "Time", "Voltage", "Current", "mAH" 1180 EndIf 1190 ' 1200 Print 1210 Line Input "Press ENTER to start the test "; T$ 1220 Pin(15) = 0 : Pause 200 ' discharge any floating voltage 1230 Do While Pin(1) * VCorrect <= Threshold 1240 Print "Battery not inserted or not charged (voltage ="; Pin(1) * VCorrect; ")" 1250 Print "Insert battery to continue "; 1260 While Pin(1) * VCorrect <= Threshold : Wend 1270 Pause 750 1280 Loop 1290 ' 1300 VScale = (Int(Pin(1) * VCorrect * 10) + 2) ' set the vertical scale 1310 iHist = 0 ' zero the history 1320 GoSub 2790 ' draw the graph axies 1330 ' 1340 Time$ = "00:00:00" : LASTTIME$ = "00:00:00" ' init the starting time 1350 BattV = Pin(1) * VCorrect ' initialise the battery voltage 1360 VStart = BattV 1370 VAverage = 0 : AveCnt = 0 1380 ' 1390 '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 1400 ' Main test loop 1410 Do 1420 ' 1430 If Type$ = "C" Then 1440 ' Calculate the setting required to draw the test current 1450 PrevTL = (BattV/R1) * 1000 1460 For i = 2 To 31 1470 TL = 0 1480 If i And &b00001 Then TL = TL + BattV/R1 1490 If i And &b00010 Then TL = TL + BattV/R2 1500 If i And &b00100 Then TL = TL + BattV/R3 1510 If i And &b01000 Then TL = TL + BattV/R4 1520 If i And &b10000 Then TL = TL + BattV/R5 1530 TL = TL * 1000 1540 If PrevTL + (TL - PrevTL) / 2 > BLoad Then Exit For 1550 PrevTL = TL 1560 Next i 1570 ElseIf Type$ = "P" Then 1580 ' Calculate the setting required to draw the test power 1590 PrevTL = ((BattV * BattV)/R1) * 1000 1600 For i = 2 To 31 1610 TL = 0 1620 If i And &b00001 Then TL = TL + (BattV * BattV)/R1 1630 If i And &b00010 Then TL = TL + (BattV * BattV)/R2 1640 If i And &b00100 Then TL = TL + (BattV * BattV)/R3 1650 If i And &b01000 Then TL = TL + (BattV * BattV)/R4 1660 If i And &b10000 Then TL = TL + (BattV * BattV)/R5 1670 TL = TL * 1000 1680 If PrevTL + (TL - PrevTL) / 2 > BLoad Then Exit For 1690 PrevTL = TL 1700 Next i 1710 ElseIf Type$ = "R" Then 1720 ' Calculate the setting required to draw the test resistance 1730 PrevTL = R1 1740 For i = 2 To 31 1750 TL = 100000000 1760 If i And &b00001 Then TL = (TL * R1) / (TL + R1) 1770 If i And &b00010 Then TL = (TL * R2) / (TL + R2) 1780 If i And &b00100 Then TL = (TL * R3) / (TL + R3) 1790 If i And &b01000 Then TL = (TL * R4) / (TL + R4) 1800 If i And &b10000 Then TL = (TL * R5) / (TL + R5) 1810 If PrevTL - (PrevTL - TL) / 2 < BLoad Then Exit For 1820 PrevTL = TL 1830 Next i 1840 ' print "Selected nearest value of"; PrevTL; " ohms" 1850 Else 1860 Error "Invalid Type$" 1870 EndIf 1880 ' 1890 i = i - 1 1900 ' 1910 ' Set the reed relays to create the test load 1920 Pin(11) = Not(i And &b00001) 1930 Pin(12) = Not(i And &b00010) 1940 Pin(13) = Not(i And &b00100) 1950 Pin(14) = Not(i And &b01000) 1960 Pin(15) = Not(i And &b10000) 1970 ' 1980 ' calculate the current drain at this setting 1990 TC = 0 2000 If i And &b00001 Then TC = TC + BattV/R1 2010 If i And &b00010 Then TC = TC + BattV/R2 2020 If i And &b00100 Then TC = TC + BattV/R3 2030 If i And &b01000 Then TC = TC + BattV/R4 2040 If i And &b10000 Then TC = TC + BattV/R5 2050 TC = TC * 1000 ' current drain in mA 2060 mAhours = mAhours + TC/3600 ' accumulate the mAH reading for each second 2070 ' 2080 ' every minute update the display 2090 If Right$(Time$, 2) = "00" Then 2100 Hist(iHist) = BattV : iHist = iHist + 1 2110 If iHist > MaxHist Then GoTo 2330 2120 If iHist > HScale * 60 Then 2130 HScale = HScale + 1 2140 GoSub 2790 ' redraw the graph scale 2150 EndIf 2160 GoSub 2660 ' add this reading to the graph 2170 GoSub 3090 ' print the running summary 2180 EndIf 2190 ' 2200 ' wait for the next second 2210 LoopCount = 1 2220 Do While Time$ = LASTTIME$ 2230 BattV = BattV + Pin(1) * VCorrect ' while we are waiting make many measurements 2240 LoopCount = LoopCount + 1 ' count the number of measurements 2250 Loop 2260 LASTTIME$ = Time$ 2270 BattV = BattV/LoopCount ' and average 2280 ' 2290 VAverage = VAverage + BattV : AveCnt = AveCnt + 1 2300 Loop While BattV >= Threshold 2310 ' 2320 ' the test has finished - remove the load 2330 Pin(11) = 1 : Pin(12) = 1 : Pin(13) = 1 : Pin(14) = 1 : Pin(15) = 1 2340 ' 2350 ' 2360 '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 2370 ' print the summary 2380 GoSub 3090 ' update the running summary 2390 Print : T$ = "Test complete. " 2400 T$ = T$ + "Battery capacity is " + Format$(mAhours, "%1.0fmAH") + " at a constant " 2410 If Type$ = "C" Then T$ = T$ + "current of" + Str$(BLoad) + "mA." 2420 If Type$ = "P" Then T$ = T$ + "power of" + Str$(BLoad) + "mW." 2430 If Type$ = "R" Then T$ = T$ + "resistance of" + Str$(BLoad) + " ohms." 2440 If SSave$ = "Y" Then Print #1 : Print #1 : Print #1, T$ 2450 Print " " + T$ 2460 T$ = "Start voltage = " + Format$(VStart, "%3.2f") + ". End voltage = " + Format$(BattV, "%3.2f") 2470 T$ = T$ + ". Average voltage = " + Format$(VAverage/AveCnt, "%3.2f") + "." 2480 If SSave$ = "Y" Then Print #1, T$ 2490 Print " " + T$ 2500 If SSave$ = "Y" Then Close #1 2510 ' 2520 Print " Press ENTER to test again or CTRL-C to quit..."; 2530 Do ' flash LED while waiting 2540 Pause 200 : If Inkey$ = Chr$(&H0D) Then GoTo 500 2550 Pin(0) = 0 : Pause 100 : Pin(0) = 1 : If Inkey$ = Chr$(&H0D) Then GoTo 500 2560 Loop 2570 ' 2580 ' 2590 ' 2600 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 2610 ' SUBROUTINES 2620 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 2630 ' 2640 ' Subroutine to print the trend line on the graph 2650 ' 2660 For i = 1 To iHist - 1 2670 x1 = margin + (width / (HScale * 60)) * (i - 1) 2680 x2 = margin + (width / (HScale * 60)) * (i) 2690 y1 = height - ((Hist(i - 1) * 10) / VScale) * height 2700 y2 = height - ((Hist(i) * 10) / VScale) * height 2710 Line (x1, y1) - (x2, y2), 1 2720 Next i 2730 Return 2740 ' 2750 ' 2760 '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 2770 ' Subroutine to print the graph axies 2780 ' 2790 height = MM.VRes - 100 : margin = 45 : width = MM.HRes - margin - 12 2800 ' 2810 Cls 2820 Line (margin,height)-(margin, 0), 1 ' Draw the vert line 2830 Line (margin,height)-(margin + width ,height), 1 ' Draw the horiz line 2840 For i = 0 To VScale ' This loop draws the tick marks 2850 h = height - (height / VScale) * i 2860 t = margin - 5 2870 If i Mod 5 = 0 Then ' Special mark for a unit of 0.1V 2880 Locate margin - 42, h - 3 2890 If h - 3 < 0 Then Locate margin - 42, 0 ' fix if we are off the screen 2900 Print Left$(Format$(i/10,"%f"),3);"V"; ' Label the tick mark 2910 t = margin - 15 2920 EndIf 2930 Line (margin, h)-(t, h), 1 ' Draw the tick mark 2940 Next i 2950 For i = 0 To HScale 2960 t = margin + (width/Hscale) * i 2970 Line (t, height)-(t, height + 9), 1 2980 If i < 10 Then Locate t - 8, height + 14 Else Locate t - 11, height + 14 2990 Print i; 3000 Next i 3010 Locate margin + width/2 - 14, height + 25 3020 Print "Hours" 3030 Return 3040 ' 3050 ' 3060 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 3070 ' Subroutine to print the summary data below the graph 3080 ' 3090 T$ = Left$(Time$, 5) + " " + Format$(BattV, "%5.3fV ") + " " + Format$(TC, "%5.1fmA ") 3100 T$ = T$ + " " + Format$(mAhours, "%5.0fmAH") 3110 Locate margin + (width - (Len(T$) * 6)) / 2, height + 40 3120 Print t$ 3130 If SSave$ = "Y" Then Print #1, (iHist - 1)/60, BattV, TC, mAhours 3140 Return 3150 '