' AADischarge.bs2 ' AA Battery Discharge function, used with the AA Battery Discharge Adapter ' John Saunders 5/14/2007 ' {$STAMP BS2} ' {$PBASIC 2.5} 'Stamp Ports PwrGood PIN 0 'Input:1 if line is up RS232In PIN 1 'Input:RS-232 Serial in DTR PIN 2 'Input:Data Terminal Ready RS232Out PIN 3 'Output:RS-232 Serial iout MOSFET PIN 4 'Output:1 energises the MOSFET output on DC-25 pins 17&18 IOCLK PIN 5 'Output:74HC165 and 74HCT164 clock SwData PIN 6 'Input:Switch and external discrete inputs IOData PIN 7 'Output:Display character, mode and command,165 Load DispLD PIN 8 'Output:Display load SwDn PIN 9 'Input:0 = switch down, also DC-25P pin 21 SwUp PIN 10 'Input:0 = switch up, also DC-25P pin 22 AD1CLK PIN 11 'Output:10 clock pulses to input analog 1 value AD1In PIN 12 'Input:analog 1 value, MSB first AD2CLK PIN 13 'Output:10 clock pulses to input analog 2 value AD2In PIN 14 'Input:analog 2 value, MSB first TwoHz PIN 15 'Input:2-Hz square wave timing input 'time processing parameters Phase VAR Bit '2 Hz waveform from CD4060,1=high Sec VAR Byte 'Count of 2Hz clock cycles per 1/100 hr (72) Hours VAR Word 'Time in 1/100 hour since last charge in Discharge 'Initialization Dispinitlen CON 8 DispInitData DATA $30,$30,$30,$38,$0C,$01,$06,$14,$80 Row0Loc DATA " V MA " 'Top row fixed values Row1Loc DATA " MAH " 'Second row fixed values Row2Loc DATA "ID= LIMIT= . V " 'Third row fixed values Row3Loc DATA " HRS EXT= " 'Bottom row Charging 'Hitachi Display parameters DECdata VAR Word 'actual character or value to be displayed div VAR Nib 'dividend used in writing numbers rem VAR Word 'remainder used in writing multiple-digit numbers DispMode VAR Nib 'Controls the way a value is to be displayed: 0 = 1 digit, 1 = 2 digits '2 = 3 Digits, 3 = 4 Digits, B = 4 digits with 1 after the decimal point 'F = 4 digits with 2 after the decimal point, 'D= 4 digits with 3 after the decimal point row0addr CON $80 'instruction for top row row1addr CON $C0 'second row row2addr CON $94 'third row row3addr CON $D4 'bottom row 'Control variables and External Digital Inputs DIGdata VAR Byte 'Signals connected to the 74HC165 shift register Externals VAR DIGdata.HIGHNIB 'External signals on DB-25 pins20,7,6&19 EnterSw VAR DIGdata.BIT3 'Signal connected to DC-29P, pin 16 and the push-button OldEnter VAR Bit Iter VAR Byte 'for loop variable Limit VAR Byte 'For loop end point PowerFail VAR Bit 'Is one if power was lost 'Analog variables and constants IDLoc DATA 0 VoltsLoc DATA 100 BattVolts VAR Word 'Output of A to D on pin 3 MAH VAR Word 'Milliamp-hours accumulated Fractional VAR Word 'in 1/10000 of MAH AverageMA VAR Word 'Sum of 1-sec milliamp readings over 36-sec period ID VAR Byte 'The marking on the battery, also filename Discharged VAR Bit '0 if battery voltage is above cutoff Heading VAR Bit 'Writes the heading values if ID has changed RunFlag VAR Bit 'Recording is allowed if 1 Start: DIRS = %0010100110111000 LOW DispLD 'display enable pin phase=TwoHz 'make sure to find the first transition LOW IOCLK DispLD = 0 RunFlag = 0 Heading = 1 sec = 0 MAH = 0 Fractional = 0 Hours = 0 Discharged = 1 GOSUB InitDisp GOSUB GetInputData GOTO main 'find the 2 Hz transitions Main: 'Main loop, normall takes 171 ms (129 with DTR on) max 292 DO WHILE TwoHz=Phase 'Clock signal is not changing IF PwrGood = 0 THEN 'Set inputs to IN to reduce current draw on battery DIRS = 0 PowerFail = 1 GOTO Main ENDIF LOOP Phase=TwoHz 'reset the phase IF (Phase = 0) OR (PwrGood = 0) THEN main IF Powerfail = 1 THEN Powerfail = 0 GOTO Start ENDIF GOSUB GetInputData GOSUB DispExternals GOSUB DispID GOSUB DispLimit GOSUB TimeUpdate GOSUB GetVolts GOTO main 'continue monitoring the 2 Hz clock 'subroutines: 'subroutines for Hitachi LM044L 4x20 LCD display: InitDisp: FOR Iter = 0 TO DispInitLen READ DispInitData + Iter,DECData GOSUB DispCmd NEXT DECData = row0addr GOSUB DispCmd FOR Iter = 0 TO 18 READ Row0Loc + Iter,DECData GOSUB DispChar NEXT DECData = row1addr GOSUB DispCmd FOR Iter = 0 TO 18 READ Row1Loc + Iter,DECData GOSUB DispChar NEXT DECData = row2addr GOSUB DispCmd FOR Iter = 0 TO 18 READ Row2Loc + Iter,DECData GOSUB DispChar NEXT DECData = row3addr GOSUB DispCmd FOR Iter = 0 TO 18 READ Row3Loc + Iter,DECData GOSUB DispChar NEXT READ IDLoc,ID GOSUB DispID GOSUB DispLimit GOSUB DispAH GOSUB DispExternals GOSUB DispHours RETURN DispCmd: 'puts a command (IoData) in OutputData into the display SHIFTOUT IOData,IOCLK,1,[DECdata\8] 'clocks the instruction into the shift register LOW IOData 'instruction function is low, IOData does double duty PULSOUT DispLD,10 'clocks the instruction and the function into the display PAUSE 1 RETURN DispChar: 'puts one character onto the display SHIFTOUT IOData,IOCLK,1,[DECdata\8] 'clocks the character into the shift register HIGH IOData 'data function is high PULSOUT DispLD,1 'clocks the instruction and the character into the display RETURN DispDec: 'Displays DECData at current cursor position in Digital IF DispMode = 0 THEN OneDigit IF DispMode = 1 THEN TwoDigit IF DispMode = 2 THEN ThreeDigit ' Only 4-digit can have decimal points div = DECData/1000 rem = DECData//1000 DECData = div + "0" GOSUB DispChar IF Dispmode = $D THEN DECData = "." GOSUB DispChar ENDIF DECData = rem ThreeDigit: div = DECData/100 rem = DECData//100 DECData = div + "0" GOSUB DispChar IF Dispmode = $F THEN DECData = "." GOSUB DispChar ENDIF DecData = rem TwoDigit: div = DECData/10 rem = DECData//10 DECData = div + "0" GOSUB DispChar IF Dispmode = $B THEN DECData = "." GOSUB DispChar ENDIF DECData = rem OneDigit: DECdata = DECdata + "0" GOSUB DispChar RETURN DispID: 'Displays the Battery ID number DecData = row2addr + 3 GOSUB DispCmd DECData = ID DispMode=2 GOSUB DispDec RETURN DispLimit: DecData = row2addr + 13 GOSUB DispCmd READ VoltsLoc,DECData DispMode=$F GOSUB DispDec RETURN DispAH: DecData = row1addr GOSUB DispCmd Fractional = Fractional + AverageMA AverageMA = 0 DO WHILE Fractional >= 7200 MAH = MAH + 1 Fractional = Fractional - 7200 LOOP DispMode = 3 '4 digits for MAH DECData = MAH GOSUB DispDec DECData = "." GOSUB DispChar DispMode = 1 '2 digits for Fractional DECData = Fractional/72 GOSUB DispDec RETURN DispHours: DECData = Row3Addr GOSUB DispCmd DispMode = 15 '4 digits, 2 afer DP DECData = Hours GOSUB DispDEC RETURN DispExternals: ' Display the externals DECData = row3addr + 14 GOSUB DispCmd div = Externals FOR iter = 0 TO 3 DECData = (div & 1) + "0" GOSUB DispChar div = div >> 1 NEXT RETURN 'Time handling TimeUpdate: sec = sec +1 IF sec > 71 THEN 'cycle time measured at 36.003 sec sec = 0 ENDIF SELECT sec CASE 0 'increment the hours, calculate AH, display Hours = Hours + 1 ' in 1/100 hour steps GOSUB DispHours GOSUB DispAH IF Discharged = 0 THEN RunFlag = 1 DECData = row1addr + 15 GOSUB DispCmd DECData = "W" GOSUB DispChar ENDIF CASE 1 'open the file IF RunFlag = 1 THEN SEROUT RS232Out,84,["O 1 A /C",DEC3 ID,".CSV",CR] ENDIF CASE 2 'write the heading or the data IF RunFlag = 1 THEN IF Heading = 0 THEN READ IDLoc,ID DECData = BattVolts << 2 SEROUT RS232Out,84,["W 1 29",CR] SEROUT RS232Out,84,[DEC3 ID,",",DEC5 Hours,",",DEC4 MAH,".",DEC2 Fractional,",",DEC4 DECData,",",BIN Externals,CR,LF] ELSE SEROUT RS232Out,84,["W 1 25",CR] SEROUT RS232Out,84,["BATT",",","HOURS",",","AH",",","VOLTS",",","Ext",CR,LF] DECData = row1addr + 13 GOSUB DispCmd DECData = "R" GOSUB DispChar Heading = 0 ENDIF ENDIF CASE 3 'close the file IF RunFlag = 1 THEN SEROUT RS232Out,84,["C 1",CR] 'close the file IF Discharged = 1 THEN RunFlag = 0 DECData = row1addr + 15 GOSUB DispCmd DECData = " " GOSUB DispChar ENDIF ENDIF ENDSELECT RETURN 'External Input handling GetInputData: 'Rotary Switch and external inputs OldEnter = EnterSW HIGH IOData 'load the inputs into the 74165 shift register PULSOUT IOData,2 HIGH IOData SHIFTIN SWData,IOCLK,1,[DIGdata\8] 'clock input states out of the shift register into the stamp 'handle settings Limit = DigData & 7 SELECT Limit CASE 1 'Label is COUNT: Zero the Ampere-Hours on Enter IF EnterSW = 0 THEN MAH = 0 Fractional = 0 ENDIF CASE 2 'Label is ELAPSED : Zero the elapsed hours on Enter IF EnterSW = 0 THEN Hours = 0 ENDIF CASE 3 'Label is SET DAY: Set the Battery ID GOSUB SetID GOSUB DispID CASE 4 'Label is SET HOUR: Set the cutoff voltage in 10 mv steps GOSUB SetLimit GOSUB DispLimit CASE 5 'Label is SET MINUTE: IF SWDn = 0 THEN MAH = 0 Fractional = 0 ENDIF IF SWUp = 0 THEN Hours = 0 ENDIF CASE 6 'Label is RESET IF EnterSW = 0 THEN GOTO Start ENDIF ENDSELECT RETURN GetVolts: DecData = row0addr + 9 GOSUB DispCmd SHIFTIN ad1in,ad1clk,MSBPRE,[BattVolts\10] DECData = BattVolts DispMode = 2 GOSUB DispDEC 'Displays calculated MA DecData = row0addr GOSUB DispCmd DecData = BattVolts << 2 '4 Volt range, in millivolts rem = DecData / 10 READ VoltsLoc,Limit 'Voltage limit is in 10 mvolt resolution IF rem >= Limit THEN MOSFET = 1 Discharged = 0 AverageMA = AverageMA + BattVolts 'A to D reading is in 4 mv steps, load = 4 ohms ELSE MOSFET = 0 Discharged = 1 ENDIF DispMode = $D '4 digits with 3 after the DP GOSUB DispDec 'Display the battery voltage RETURN 'Setting parameters SetID: rem = 0 DECData = ID GOSUB AdjustValue ID = DECData IF rem = 1 THEN DECData = row1addr + 13 GOSUB DispCmd DECDATA = " " GOSUB DispChar ENDIF IF (EnterSW = 0) AND (OldEnter = 1) THEN WRITE IDLoc,ID DECData = row1addr + 13 GOSUB DispCmd DECDATA = "H" GOSUB DispChar Heading = 1 ENDIF RETURN SETLimit: READ VoltsLoc,DECData GOSUB AdjustValue IF rem = 1 THEN WRITE VoltsLoc,DECData ENDIF RETURN AdjustValue: 'value to be updated is in DECData 'IF SwDn = 0 AND OldDn = 1 THEN IF SwDn = 0 THEN IF DECData = 0 THEN DECData = 199 ELSE DECData = DECData - 1 ENDIF rem = 1 ENDIF 'IF SwUp = 0 AND OldUp = 1 THEN IF SwUp = 0 THEN IF DECData >= 199 THEN DECData = 0 ELSE DECData = DECData + 1 ENDIF rem = 1 ENDIF RETURN