'416.BAS 'Oct 1 2006 'KD7TS 'ONLY does COM1 ' ' CLS CLEAR OPTION BASE 1 'so array subscript starts at 1 DIM rb(1 TO 42) 'array for running average DIM AA$(1 TO 121, 1 TO 7) ' 120 = 1 hour being stored PRINT PRINT : PRINT " Source of data" PRINT " 1 = COM port" PRINT " 2 = Disk file": PRINT INPUT " Source of data"; Sourcedata: CLS IF Sourcedata = 2 THEN GOTO Choices INPUT "File name, including .dat extension ", filename$: CLS NextScreen: CLS 0 SCREEN 12 ' VGA 480 by 640 M = 0 ' Used for display averaging routine N = 38 ' Used for row position LOCATE 1, 28: PRINT "RED is DAC voltage,white is phase"; LOCATE 1, 2: PRINT "Data file is"; LOCATE 2, 2: PRINT " "; filename$; LOCATE 29, 70: PRINT ScreenHours; "hr/div"; 'draw lines of graph area A = 39 B = 39 C = 639 FOR B = 39 TO 429 STEP 65 LINE (A, B)-(C, B), 2 NEXT B B = 39 C = 429 FOR A = 39 TO 639 STEP 120 LINE (A, B)-(A, C), 2 NEXT D = 800 FOR E = 15 TO 3 STEP -4 LOCATE E, 1: PRINT D D = D + 100 NEXT E D = 800 FOR E = 15 TO 27 STEP 4 LOCATE E, 1: PRINT D D = D - 100 NEXT E IF Sourcedata = 2 THEN GOTO Diskfile PortCom: LOCATE 1, 70: PRINT "ver 416"; LOCATE 2, 70: PRINT DATE$; LOCATE 30, 70: PRINT " q to quit"; ' Open communications (9600 baud, no parity, 8-bit data, 1 stop bit) OPEN "COM1:9600,N,8,1,ASC,CD0,CS0,DS0,OP0,RS" FOR INPUT AS #1 row = 1 COM(1) ON ON COM(1) GOSUB ComHandler DO: LOOP WHILE INKEY$ <> CHR$(113) 'changed for sleeping laptops GOSUB DumpData 'write data before exiting COM(1) OFF: END: CLS ComHandler: COM(1) OFF SLEEP 1 ModemInput$ = INPUT$(LOC(1), #1) row = row + 1 IF row = 121 THEN GOSUB DumpData ' Go save 1 hour of data A$ = MID$(ModemInput$, 1, 5) ' First 5 characters B$ = MID$(ModemInput$, 7, 5) ' Second 5 characters IF B$ = "00000" THEN GOTO NoDataCom ' Skip the next steps 'cause they're zero 'this is fixed in NoDataCom 'then back to setzero C$ = MID$(ModemInput$, 13, 5) ' Third 5 characters D$ = MID$(ModemInput$, 13, 4) ' First 4 chars of the third 5 A = VAL(A$) B = VAL(B$) V = CSNG(B) '______________________________________________________ ' |65536 increments * 0.00009 = 6 (+ and - 3 volts) | ' |Values larger than 32768 are interpreted as negative | ' |and equal to the value minus 65536 | ' | plus a fudge factor for my DAC of .000002 | ' | I don't know why the signs are reversed | ' |_____________________________________________________| IF V < 32767 THEN V = (V * .000092) * -1 IF V >= 32768 THEN V = (((V - 65536) * .000092) * -1) LOCATE 29, 31: PRINT " "; 'clears previous entry LOCATE 29, 31: PRINT USING "##.#####"; V; 'print to screen vol$ = STR$(V) vol$ = LTRIM$(RTRIM$(vol$)) IF V < 32767 THEN volt$ = LEFT$(vol$, 8) ' 8 to hold a minus sign volt$ = LEFT$(vol$, 7) 'pad length for constant width columns IF LEN(volt$) < 5 THEN volt$ = volt$ + "0" IF LEN(volt$) < 6 THEN volt$ = volt$ + "0" IF LEN(volt$) < 7 THEN volt$ = volt$ + "0" B = CLNG(B) '20 and 5 min running average of phase (A) 'each time we get A, we run the swap 40 times so that rb(1) swaps 'with rb(2)m then rb(2) with rb(3) then rb(3) with rb(4) etc so 'that A ends up in rb(41) each time, and next time through,it is 'moved down. This fills the array (rb) from the highest to the 'lowest so the most current values are in the highest subscripts. 'We have an array larger than 40 to make relative addressing work 'in the swap function, then use 2 through 41 as our values, and 1 is 'always the oldest value. For the first 5 min of a run the 5 min 'average is wrong, and for the first 20 min, the 20 min ave is wrong. 'after that they are both current within 30 seconds. rb(1) = A FOR II = 1 TO 40 STEP 1 'COUNT TO 40 SWAP rb(II), rb(II + 1) 'move rb(x) value to next higher var, NEXT II st = rb(2) + rb(3) + rb(4) + rb(5) + rb(6) + rb(7) + rb(8) + rb(9) sta = rb(10) + rb(11) + rb(12) + rb(13) + rb(14) stb = rb(15) + rb(16) + rb(17) + rb(18) + rb(19) + rb(20) + rb(21) + rb(22) stc = rb(23) + rb(24) + rb(25) + rb(26) + rb(27) + rb(28) + rb(29) + rb(30) + rb(31) std = rb(32) + rb(33) + rb(34) + rb(35) + rb(36) + rb(37) + rb(38) + rb(39) + rb(40) + rb(41) av = (st + sta + stb + stc + std) / 40 aw = std / 10 LOCATE 30, 9: PRINT " "; LOCATE 30, 9: PRINT " 20 MIN AV"; av; LOCATE 30, 29: PRINT " "; LOCATE 30, 29: PRINT " 5 MIN AV"; aw; setzero: ' _________________________________________________________ '| | '|makes an offset relative to screen height, plots screen | '|_________________________________________________________| ' calculate voltage for plot IF B <= 32767 THEN B = ((32768 + B) * .00595) + 39 IF B >= 32768 THEN B = B * .00595 - 156 E$ = "0005" ' look for DAC hold 0005x EE$ = "0015" ' look for DAC hold 0015x IF D$ = E$ OR D$ = EE$ THEN LOCATE 29, 42: PRINT "HOLD ON"; IF D$ <> E$ AND D$ <> EE$ THEN LOCATE 29, 42: PRINT " "; IF A < 500 THEN E = 500 'keep phase plot between 500 and 1100 IF A > 1100 THEN E = 1100 A = A - 800: A = A / 1.538: A = 234 - A N = N + 1 IF N = 39 THEN LOCATE 28, 2: PRINT TIME$; 'label times as IF N = 159 THEN LOCATE 28, 17: PRINT TIME$; 'we get to them IF N = 279 THEN LOCATE 28, 32: PRINT TIME$; IF N = 399 THEN LOCATE 28, 47: PRINT TIME$; IF N = 519 THEN LOCATE 28, 62: PRINT TIME$; IF N = 639 THEN LOCATE 28, 73: PRINT TIME$; LOCATE 29, 2: PRINT " "; LOCATE 29, 2: PRINT TIME$; " "; A$; " "; B$; " "; C$; PSET (N, A), 15 'PLOT Ns PSET (N, B), 12 'PLOT DAC 'DATA FOR DISK FILE ENTRIES AA$(row, 1) = DATE$ AA$(row, 2) = " " AA$(row, 3) = TIME$ AA$(row, 4) = " " AA$(row, 5) = volt$ AA$(row, 6) = " " AA$(row, 7) = ModemInput$ COM(1) ON IF N = 639 THEN CLOSE : GOTO NextScreen 'draw new screen if 'this one is full RETURN Diskfile: DO UNTIL EOF(2) OR N = 639 LINE INPUT #2, RecNum$ 'get line from file and store in variable A$ = MID$(RecNum$, 29, 5) ' First 5 characters B$ = MID$(RecNum$, 35, 5) ' Second 5 characters C$ = MID$(RecNum$, 41, 5) ' Third 5 characters D$ = MID$(RecNum$, 41, 4) ' First 4 chars of the third 5 M$ = MID$(RecNum$, 1, 10) ' Date from file T$ = MID$(RecNum$, 12, 8) ' Time from file A = VAL(A$) B = VAL(B$) '20 min average of phase (A) 'rb = rb + 1 'increment rb 'rb1 = rb1 + A 'rc = rb1 / rb 'IF rb = 40 THEN LOCATE 30, 9: PRINT " "; 'IF rb = 40 THEN LOCATE 30, 9: PRINT "20 MIN AV"; rc; 'IF rb = 40 THEN rb1 = 0 'IF rb = 40 THEN rb = 0 '5 min average of phase (A) 'ri = ri + 1 'increment ri 'ra1 = ra1 + A 'ra = ra1 / ri 'IF ri = 10 THEN LOCATE 30, 29: PRINT " "; 'IF ri = 10 THEN LOCATE 30, 29: PRINT "5 MIN AV"; ra; 'IF ri = 10 THEN ra1 = 0 'IF ri = 10 THEN ri = 0 ' For displaying -3 to +3 volts on the screen. ' Each disvision equal to one volt. IF B <= 32767 THEN B = ((32768 + B) * .00595) + 39 IF B >= 32768 THEN B = B * .00595 - 156 B = CLNG(B) E$ = "0000" IF E$ <> D$ THEN LOCATE 29, 42: PRINT T$; " "; C$; IF E$ <> D$ THEN st = TIMER: DO WHILE TIMER < st + TD: LOOP M = M + 1 E = E + A G = G + B IF M <> ScreenHours THEN GOTO Diskfile E = E / M ' E = Average of the first 5 chars G = G / M ' by the number used for screen ' total hours. LOCATE 1, 70: PRINT "Start date"; LOCATE 2, 70: PRINT M$; N = N + 1 IF N = 39 THEN LOCATE 28, 4: PRINT USING "\ \"; T$; IF N = 159 THEN LOCATE 28, 19: PRINT USING "\ \"; T$; IF N = 279 THEN LOCATE 28, 34: PRINT USING "\ \"; T$; IF N = 399 THEN LOCATE 28, 49: PRINT USING "\ \"; T$; IF N = 519 THEN LOCATE 28, 64: PRINT USING "\ \"; T$; IF N = 639 THEN LOCATE 28, 75: PRINT USING "\ \"; T$; IF N = 639 THEN SLEEP: Q$ = INKEY$ ' Press q or Q key to quit IF Q$ = "q" THEN END IF Q$ = "Q" THEN END IF N = 639 THEN : GOTO NextScreen LOCATE 29, 2: PRINT " "; LOCATE 29, 2: PRINT T$; " "; A$; " "; B$; " "; C$; 'keep Phase and DAC plot on screen IF E < 500 THEN E = 500 IF E > 1100 THEN E = 1100 IF G < 39 THEN G = 39 IF G > 429 THEN G = 429 'make voltage number for screen plot L = G - 39 IF L <= 194 THEN L = L * .0153846: L = 3 - L IF L >= 195 THEN L = L - 195: L = -L * .0153846 LOCATE 29, 31: PRINT USING "##.#####"; L; E = E - 800: E = E / 1.538: F = 234 - E PSET (N, F), 15 'Plot Phase PSET (N, G), 12 'Plot DAC S$ = INKEY$ ' Press s or S key for IF S$ = "s" THEN SLEEP ' single stepping IF S$ = "S" THEN SLEEP E = 0: G = 0: M = 0: Q$ = "0": S$ = "0" LOOP E = 0: G = 0: M = 0: Q$ = "0": S$ = "0": N = 39 CLOSE (2) OPEN filename$ FOR INPUT AS #2 INPUT " a to run again", ak$ 'ak$ = INKEY$ IF ak$ = "a" THEN GOTO NextScreen END 'E = 0: G = 0: M = 0: Q$ = "0": S$ = "0": N = 39 END DumpData: OPEN filename$ FOR APPEND AS #2 FOR row = 1 TO 120 ' row of 20 would be 10 min. of data FOR col = 1 TO 7 ' row of 120 would be 1 hour of data PRINT #2, AA$(row, col); IF AA$(row, 1) = CHR$(0) THEN CLOSE #2: END NEXT col NEXT row CLOSE #2 FOR row = 1 TO 120 ' row of 20 would be 10 min. of data FOR col = 1 TO 7 ' row of 120 would be 1 hour of data AA$(row, col) = CHR$(0) ' Put null values in AA$ NEXT col NEXT row row = 1 COM(1) ON RETURN Choices: PRINT : PRINT " Enter screen total time" PRINT " 1 hour/div = 5 hours screen display" PRINT " 2 hour/div = 10 hours" PRINT " 3 hour/div = 15 hours" PRINT " 4 hour/div = 20 hours" PRINT " 5 hour/div = 25 hours": PRINT INPUT " hours per division"; ScreenHours PRINT "THIS ALLOWS TIME FOR THE USER TO STOP THE DATA BEING PUT ON THE SCREEN" IF Sourcedata = 2 THEN INPUT " DATA update delay, 0.1 to 1 sec."; TD: CLS IF Sourcedata = 2 THEN PRINT : FILES "*.DAT" INPUT "filename ? ", filename$ OPEN filename$ FOR INPUT AS #2 GOTO NextScreen NoDataCom: 'this is supposed to fill in the saved disk data columns 'when N=0 is selected 'in N0 the second group is all zeros and there is no third group 'so we only need to add a space and five more zeros plus CR and LF 'to make the disk file remain even 5, 5 and 5 C$ = "00000" fixMod$ = MID$(ModemInput$, 1, 11) ' First 11 characters ModemInput$ = fixMod$ + " " + C$ + CHR$(13) + CHR$(10) GOTO setzero ' This program has some features that are not apparent ' from the screen. It will save the data from the Brooks ' Shera GPS controller card to a disk file. The file name ' is left to the users discretion, but should include the ' file extension .DAT to be most useful for this program. ' You can modify this for .CSV if you want. See below. ' The data is displayed as the file data is being collected. ' Once a file has been saved, this program will display the ' file data as though it were in real time, but with the ' time the data was written. The program will attempt to ' display any data file names in the same directory as an ' aid in typing the correct filename. ' In order to provide detailed viewing the data being ' written can be halted by striking the s key ' (s for single step)and advanced an additional point with ' each S keystroke. Any other key will resume the rapid graphing. ' ' Values for the phase offset and DAC voltage are displayed for ' both writing and displaying files. The red line is the DAC ' but has no scale marked on the screen. The scale for DAC is ' plus and minus 3 volts, with zero in the center. The scale ' 500 -1100 is the phase offset, with 800 as the target value ' for the PLL filter. the displayed DAC voltage is the actual ' voltage from the DAC when capturing data from the COM port, with ' accuracy much better than any meter. ' ' AA$(row, 1) = DATE$ ' AA$(row, 2) = " " ' AA$(row, 3) = TIME$ ' AA$(row, 4) = " " ' AA$(row, 5) = volt$ ' AA$(row, 6) = " " ' AA$(row, 7) = ModemInput$ ' ' To make a CSV file to disk three lines can be changed in the above. ' Lines 2,4 and 6. like so.. ' ' AA$(row, 1) = DATE$ ' AA$(row, 2) = "," ' AA$(row, 3) = TIME$ ' AA$(row, 4) = "," ' AA$(row, 5) = volt$ ' AA$(row, 6) = "," ' AA$(row, 7) = ModemInput$ ' 'You will need to change the file extension when asked for a file 'name in the opening screen, and unless the file display is changed 'also, it will display .dat files when you want to play back a captured 'file. An example follows. ' 'This line in the (choices) section should be changed ' old--- ' IF Sourcedata = 2 THEN PRINT : FILES "*.DAT" ' new--- ' IF Sourcedata = 2 THEN PRINT : FILES "*.CSV" ' When playing back a saved file, and you get to the end, you can hit ' a (lower case A) not capitalized.. a ... and the program will run through ' the data again without having to answer any questions. Just 'about anything makes it quit, so you may find it terminates because 'some other key was read, like space. ' More work needs to be done here ! ' ' There are only a few places to change to make this work with COM2. 'OPEN "COM1:9600,N,8,1,ASC,CD0,CS0,DS0,OP0,RS" FOR INPUT AS #1 ' change to 'OPEN "COM2:9600,N,8,1,ASC,CD0,CS0,DS0,OP0,RS" FOR INPUT AS #1 ' 'Then there are seven places where COM(1) appears followed by ON or OFF. 'These all need to have the (1) changed to (2). Seven times.. get them all!