' File... HAPB_SCS.BSP ' Author... Earl Foster ' Date... 01302006 ' {$STAMP BS2p} ' {$PBASIC 2.5} ' Purpose: Obtain high altitude photos of the Earth. HAPB_SCS stands for ' High Altitude Photographic Balloon Secondary Computer System. This program ' works in conjunction with HAPB_PCS (HAPB_Primary Computer System) but can be a ' stand alone program. ' This program centers primarily around LCD and GPS parsing programming. ' When used with its partner program it provides visual indications of primary ' controller activities. ' $GPGGA, POS_UTC,LAT,LAT_D,LON,LON_D,FIX,SAT,HDOP,ALT,M,GEO_ALT,M,DGPS,DRS,*CC ' POS_UTC - UTC of position. Hours, minutes and seconds. (hhmmss) ' LAT - Latitude (ddmm.ffff) ' LAT_D - Latitude direction. (N = North, S = South) ' LON - Longitude (dddmm.ffff) ' LON_D - Longitude direction (E = East, W = West) ' FIX - GPS quality indication, 0 = fix not available, 1 = Non-differential, ' 2 = Differential, 6 = Estimated ' SAT - Number of Satellites in use, 00 to 12 ' --- HDOP, ALT, GEO_ALT are variable length ' HDOP - Horizontal diluation of precision, 0.5 to 99.9 ' ALT - Antenna height above'below mean sea level, -9999.9 to 99999.9 meters ' M - constant ' GEO_ALT - Geoidal height, -999.9 to 9999.9 meters ' M - constant ' DGPS - Differential GPS data age, null if FIX <> 2 ' DRS - Differential Reference Station ID, null if FIX <> 2 ' *CC - Checksum #SELECT $STAMP #CASE BS2, BS2E, BS2PE T1200 CON 813 T2400 CON 396 T4800 CON 188 T9600 CON 84 T19K2 CON 32 TMidi CON 12 T38K4 CON 6 #CASE BS2SX, BS2P T1200 CON 2063 T2400 CON 1021 T4800 CON 500 T9600 CON 240 T19K2 CON 110 TMidi CON 60 T38K4 CON 45 #CASE BS2PX T1200 CON 3313 T2400 CON 1646 T4800 CON 813 T9600 CON 396 T19K2 CON 188 TMidi CON 108 T38K4 CON 84 #ENDSELECT PSAI PIN 9 ' Primary System Active Indicator SatAcquired PIN 7 ' Satellite Acquired Indicator LT0 PIN 0 ' External Lights LT1 PIN 1 LT2 PIN 2 LT3 PIN 3 ' --- LCD Contants TxPin CON 6 PauseShort CON 300 ' animation pauses PauseLong CON 600 ' --- GPS Contants GPSpin CON 8 ' GPS serial input N4800 CON 16884 ' GPS baud rate CST CON 6 ' UTC Central time correction DegSym CON 176 ' degrees symbol for report MinSym CON 39 ' minutes symbol ' --- GPS Variables UTC_HR VAR Byte ' Universal hour field UTC_MN VAR Byte ' Universal minutes field UTC_SC VAR Byte ' Universal seconds field Degrees VAR Byte ' Navigation Degrees Minutes VAR Byte ' Navigation Minutes DMinutes VAR Word ' Navigation Decimal Minutes Altitude VAR Word ' Sea level Height idx VAR Byte ' Index into GPS data in SPRAM Work VAR Word ' Scrap data and numeric conversions fldWidth VAR Nib ' Width of field char VAR Byte ' General purpose byte size variable ' ---Secondary Computer Start HIGH PSAI ' --- Initialization LCD GOSUB LCDSetup GOSUB LCD_Splash_Screen ProgramSetup: GOSUB Seeking_Satellites SEROUT TxPin, T19K2, [$0c] ' Clear LCD PAUSE 5 ' ---- Main Program Main: SERIN GPSpin, N4800, 4000, No_GPS, [WAIT("GPGGA,"), SPSTR 82] ' Setup link to GPS and process ' Showing captured data will be replaced with storing captured data procedure GOSUB Parse_GPS_Altitude GOSUB Show_Headers SEROUT TxPin, T19K2, [$8A, DEC5 Altitude */ $0348, " Feet"] GOSUB Parse_GPS_Time SELECT UTC_HR CASE >= 12 UTC_HR = UTC_HR - CST CASE ELSE UTC_HR = UTC_HR + CST ENDSELECT SEROUT TxPin, T19K2, [$9E, DEC2 UTC_HR, ":", DEC2 UTC_MN, ":", DEC2 UTC_SC] GOSUB Parse_GPS_Lat ' Show Latitude coordinates in degrees and decimal minutes SEROUT TxPin, T19K2, [$AF, DEC2 Degrees, " ", DEC2 Minutes,".", DEC4 DMinutes, MinSym, " N"] GOSUB Parse_GPS_Long ' Show Longitude coordinates in degrees and decimal minutes SEROUT TxPin, T19K2, [$C2, DEC3 Degrees, " ", DEC2 Minutes, ".", DEC4 DMinutes, MinSym, " W"] GOTO Main ' Start over again END ' ---- Subroutines LCDSetup: HIGH TxPin ' Set pin high to be a serial port PAUSE 100 ' Pause for Serial LCD to initialize ' Define custom characters ' $00 = Ballon SEROUT TxPin, T19K2, [$F8,$04,$0E,$1F,$1F,$1F,$0E,$0E,$04] ' $01 = Payload SEROUT TxPin, T19K2, [$F9,$04,$04,$0E,$04,$1F,$1F,$00,$00] ' $02 1st Earth Panel SEROUT TxPin, T19K2, [$FA,$00,$00,$00,$00,$01,$03,$07,$09] ' $03 2nd Earth Panel SEROUT TxPin, T19K2, [$FB,$00,$03,$07,$0F,$1F,$1F,$09,$08] ' $04 3rd Earth Panel SEROUT TxPin, T19K2, [$FC,$0F,$18,$10,$10,$10,$00,$00,$10] ' $05 4th Earth Panel SEROUT TxPin, T19K2, [$FD,$1C,$03,$03,$00,$00,$01,$03,$07] ' $06 5th Earth Panel SEROUT TxPin, T19K2, [$FE,$00,$18,$06,$01,$00,$10,$1C,$1E] ' $07 6th Earth Panel SEROUT TxPin, T19K2, [$FF,$00,$00,$00,$00,$10,$18,$04,$0E] SEROUT TxPin, T19K2, [$16,$0C] PAUSE 5 RETURN LCD_Splash_Screen: PAUSE 20 ' Show the earth rise SEROUT TxPin, T19K2, [$11] PAUSE PauseShort SEROUT TxPin, T19K2, [$BC, $02, $03, $04, $05, $06, $07] ' Step 1 PAUSE PauseLong ' Ballon and payload come out SEROUT TxPin, T19K2, [$BD, $00] ' Balloon drifts into screen Step 2 PAUSE PauseShort SEROUT TxPin, T19K2, [$BD, " "] ' Clear cell Step 3 SEROUT TxPin, T19K2, [$BE, $00] ' Moves over one cell SEROUT TxPin, T19K2, [$BD, $03] ' Put 2nd earth back PAUSE PauseShort SEROUT TxPin, T19K2, [$BE, " "] ' Clear cell Step 4 SEROUT TxPin, T19K2, [$BF, " "] ' Clear cell SEROUT TxPin, T19K2, [$AB, $00] ' Moves over another cell SEROUT TxPin, T19K2, [$BE, $04] ' Put 3rd earth back SEROUT TxPin, T19K2, [$BF, $01] ' Show payload PAUSE PauseShort SEROUT TxPin, T19K2, [$AB, " "] ' Clear cell Step 5 SEROUT TxPin, T19K2, [$BF, " "] ' Clear cell SEROUT TxPin, T19K2, [$BF, $05] ' Put 4th earth back SEROUT TxPin, T19K2, [$98, $00] ' Moves up one cell SEROUT TxPin, T19K2, [$AC, $01] ' Show payload PAUSE PAUSEShort SEROUT TxPin, T19K2, [$98, " "] ' Clear cell Step 6 SEROUT TxPin, T19K2, [$AC, " "] ' Clear cell SEROUT TxPin, T19K2, [$99, $00] ' Moves over another slot SEROUT TxPin, T19K2, [$AD, $01] ' Show payload PAUSE PAUSEShort SEROUT TxPin, T19K2, [$99, " "] ' Clear cell Step 7 SEROUT TxPin, T19K2, [$AD, " "] ' Clear cell SEROUT TxPin, T19K2, [$9A, $00] ' Moves over another cell SEROUT TxPin, T19K2, [$AE, $01] ' Show payload PAUSE PAUSEShort SEROUT TxPin, T19K2, [$9A, " "] ' Clear cell Step 8 SEROUT TxPin, T19K2, [$AE, " "] ' Clear cell SEROUT TxPin, T19K2, [$87, $00] ' Moves over another cell SEROUT TxPin, T19K2, [$9B, $01] ' Show payload PAUSE PauseLong SEROUT TxPin, T19K2, [$8C, "HAPB"] ' Show project Information Step 9 SEROUT TxPin, T19K2, [$9E, "Designed"] ' Step 10 SEROUT TxPin, T19K2, [$B5, "By"] ' Step 11 SEROUT TxPin, T19K2, [$C5, "Earl Foster"] ' Step 12 PAUSE 2000 ' Keep splash screen active for 2 seconds RETURN ' This procedure loops until the a valid position is received ' by the GPRMC "Status" string is obtained. After GPS receives ' an "A" for valid position. Seeking_Satellites: DO SERIN GPSpin, N4800, 3000, No_GPS,[WAIT("GPRMC,"), SKIP 7, STR Char\1] ' Get Status SEROUT TxPin, T19K2, [$0c] ' Clear LCD PAUSE 5 SEROUT TxPin, T19K2, [$80, " Seeking Satellites"] PAUSE 200 SEROUT TxPin, T19K2, [$80, " "] SEROUT TxPin, T19K2, [$94, " Seeking Satellites"] PAUSE 200 SEROUT TxPin, T19K2, [$94, " "] SEROUT TxPin, T19K2, [$A8, " Seeking Satellites"] PAUSE 200 SEROUT TxPin, T19K2, [$A8, " "] SEROUT TxPin, T19K2, [$BC, " Seeking Satellites"] PAUSE 200 LOOP UNTIL Char = "A" SEROUT TxPin, T19K2, [$0c] ' Clear LCD PAUSE 5 SEROUT TxPin, T19K2, [$A8, "Satellites Acquired"] HIGH SatAcquired PAUSE 1000 'SEROUT TxPin, T19K2, [$12] RETURN Show_Headers: SEROUT TxPin, T19K2, [$80, "Altitude: "] SEROUT TxPin, T19K2, [$94, "Time: "] SEROUT TxPin, T19K2, [$A8, "Lat: "] SEROUT TxPin, T19K2, [$BC, "Long:"] RETURN ' No GPS detected, keep searching until found No_GPS: SEROUT TxPin, T19K2, [$0c] ' Clear LCD PAUSE 5 SEROUT TxPin, T19K2, [$80, " No GPS Detected"] PAUSE 2500 GOTO ProgramSetup ' Get the Altitude ' Altitude is a variable length field ' it follows the 8th comma in the GPGGA string ' which has variable length due to HDOP field having a variable field length. ' First Do loop finds the proper index starting point ' for the altitude by knowing that the altitude follows the 8th comma. ' Second Do loop finds the width of the field. Fractional ' meters are not necessary in this project so the loop stops when it finds ' the decimal point. ' Note: fldWidth and Work is used twice to reduce the number of declarations in the program Parse_GPS_Altitude: idx = 0 : fldWidth = 0 DO GET idx, char IF char = "," THEN fldWidth = fldWidth + 1 idx = idx + 1 ELSE idx = idx + 1 ENDIF LOOP UNTIL fldWidth = 8 ' 8th comma found fldWidth = 0 : work = idx ' Reset fldWidth, idx is copied DO GET work, char ' Work is used to continue indexing IF char = "." THEN ' through the string until the period work = work + 1 ' found. As long as there is no period ELSE ' the field width continues to increment fldWidth = fldWidth + 1 work = work + 1 ENDIF LOOP UNTIL char = "." GOSUB String_To_Value Altitude = Work IF Altitude < 1000 THEN TOGGLE LT0 PAUSE 250 TOGGLE LT0 TOGGLE LT1 PAUSE 250 TOGGLE LT1 TOGGLE LT2 PAUSE 250 TOGGLE LT2 TOGGLE LT3 PAUSE 250 TOGGLE LT3 ENDIF RETURN ' Get the Latitude information ' hhmmss,ddmm.ffff,N,dddmm.ffff ' 01234567890123456789012345678 ' numbers above are used for proper index value for fixed fields Parse_GPS_Time: idx = 0 : fldWidth = 2 ' Hours GOSUB String_To_Value UTC_HR = Work idx = 2 : fldWidth = 2 ' Minutes GOSUB String_To_Value UTC_MN = Work idx = 4 : fldWidth = 2 ' Seconds GOSUB String_To_Value UTC_SC = Work RETURN ' Get the latitude ' North and South America are in the Northern Latitude Hemisphere ' therefore it is unnecesary to extract it from the string for ' for this project. Parse_GPS_Lat: idx = 7 : fldWidth = 2 ' Degrees GOSUB String_To_Value Degrees = Work idx = 9 : fldWidth = 2 ' Minutes GOSUB String_To_Value Minutes = Work idx = 12 : fldWidth = 4 ' Decimal Minutes GOSUB String_To_Value DMinutes = Work RETURN ' Get the Longitude information ' North and South America are in the Western Longitude Hemisphere ' therefore it is unnecesary to extract it from the string for ' this project Parse_GPS_Long: idx = 19 : fldWidth = 3 ' Degrees GOSUB String_To_Value Degrees = Work idx = 22 : fldWidth = 2 ' Minutes GOSUB String_To_Value Minutes = Work idx = 25 : fldWidth = 4 ' Decimal Minutes GOSUB String_To_Value DMinutes = Work RETURN ' Convert string data (nnnn) to numeric value ' idx - location of first digit in data ' fldWidth - width of data field (1 to 5) ' Work - returns numeric value of field String_To_Value: Work = 0 IF (fldWidth = 0) OR (fldWidth > 5) THEN String_To_Value_Done Get_Field_Digit: GET idx, char ' get digit from field Work = Work + (char - "0") ' convert, add into value fldWidth = fldWidth - 1 ' decrement field width IF (fldWidth = 0) THEN String_To_Value_Done Work = Work * 10 ' shift result digits left idx = idx + 1 ' point to next digit GOTO Get_Field_Digit String_To_Value_Done: RETURN