===Battery Capacity Test=== {{ :migratedattachments:mmbasic_original:battery.gif?linkonly}} {{ :migratedattachments:mmbasic_original:battery2.pdf?linkonly}} //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.BAS === 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 ===BATTERY2.BAS === 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 '