How do I discern Maidenhead Locator from GPS lat long info.


Closed Thread
Results 1 to 40 of 126

Hybrid View

  1. #1
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959

    Default

    An afterthought, before the fact.
    I went through this trying to make sure it didn't require PBP3 since Rob doesn't have it. But now that I've posted it, I realized it requires PBP 2.60 or later. DOH!
    At least you can download the free PBP3 trial version and compile it with that, or you can change the arrayread/arraywrite statements, so I'm not changing it.
    ---------------------------------- -------------------------------- ----------------------------------

    Ok, here goes ...
    It's not as ugly as it was, but without PBP3 there's only so much you can do.

    This code is based on the Perl script on the Wikipedia site for Maidenhead Locator System by Chris Ruvolo.
    Although I had to do things quite differently for the Microchip Floating-Point routines.

    The Microchip Floating-Point routines for PBP are available from http://melabs.com/resources/fp.htm
    Extract the .zip file to the same folder as your source code, or this code.

    To try to make things easy, the routines start out with a String in the same format as the Lat/Lon data of the $GPRMC sentence.

    For instance, an approximation of the IO93ok square is 0 degrees, 47.70 minutes West Longitude by 53 degrees, 26.20 minutes North latitude.
    $GPRMC will present the data as .... 5326.20,N and 00047.70,W.
    These can be parsed from the GPS data, or entered manually with the following two statements ... Note that they are null terminated.
    Code:
    ARRAYWRITE LonStr,["00047.70,W",0]  ; -0° 47.70' 
    ARRAYWRITE LatStr,["5326.20,N",0]   ; 53° 26.20
    I am entering them manually for this sample.

    I'm using the 24-bit Floating-Point routines, since it gave the same results as the 32-bit FP, but you can use either one by simply changing the include file.
    I imagine the 32-bit routines will be better around the edges of each square, but I haven't confirmed that.

    I'm using a 16F1937, so if you are using an 18F ... you'll need to use the 18F FP includes.

    Obviously, you need to initialize your hardware configs first.
    Code:
    ; Filename    : Maidenhead.pbp
    ; Compiler    : PICBASIC PRO Compiler
    ; Target PIC  : 16F1937, but will work with most any chip
    ; Oscillator  : ANY
    ; Keywords    : Maidenhead, Locator, GPS, Amateur Radio
    ; Description : PICBASIC PRO program to convert between
    ;             : GPS Sexagesimal to Maidenhead coordinate systems
    ;-------------------------------------------------------------------------------
    
                           ; use only one of the FP includes
    INCLUDE "FP20.bas"     ; 24-bit Floating Point for 14-bit cores with RAM at $20
    ;INCLUDE "FP2032.bas"   ; 32-bit Floating Point for 14-bit cores with RAM at $20
    
    DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
    DEFINE HSER_TXSTA 20h ' Enable transmit, BRGH = 0
    DEFINE HSER_SPBRG 25  ' 19200 Baud @ 32MHz, 0.16%
    DEFINE HSER_CLROERR 1 ' Clear overflow automatically
    
    HSEROUT [27,"[2J","Maidenhead Locator",13,10]
    HSEROUT ["16F1937, 32Mhz, PBP3 not required",13,10,13,10]
    
    MH     VAR BYTE[6]
    
    LonStr    VAR BYTE[12]
    LatStr    VAR BYTE[12]
    LonDeg    VAR BYTE
    LonMin    VAR BYTE
    LonMinDec VAR BYTE
    LonDir    VAR BYTE
    LatDeg    VAR BYTE
    LatMin    VAR BYTE
    LatMinDec VAR BYTE
    LatDir    VAR BYTE
    
    ARRAYWRITE LonStr,["00047.70,W",0]  ; -0° 47.70'  <-- Enter location here
    ARRAYWRITE LatStr,["5326.20,N",0]   ; 53° 26.20'
    
    HSEROUT ["LonStr  = ", STR LonStr,13,10]          ; display manual input
    HSEROUT ["LatStr  = ", STR LatStr,13,10]
    
    ;----[parse strings as if they came from a GPS]---------------------------------
    ARRAYREAD LonStr,[DEC3 LonDeg, DEC2 LonMin, Dec LonMinDec, LonDir]
    ARRAYREAD LatStr,[DEC2 LatDeg, DEC2 LatMin, Dec LatMinDec, LatDir]
    
    
    ;----[convert Longitude Sexagesimal to Decimal Degrees]-------------------------
    Aint = LonMinDec : GOSUB ItoFA    ; decimal portion of Minutes
    Bint = 100 : GOSUB ItoFB          ; divided by 100
    GOSUB fpdiv
    Bint = LonMin : GOSUB ItoFB       ; add whole portion of Minutes
    GOSUB fpadd
    Bint = 60 : GOSUB ItoFB           ; divide by 60
    GOSUB fpdiv
    Bint = LonDeg : GOSUB ItoFB       ; add degrees
    GOSUB fpadd
    IF LonDir = "W" THEN              ; if west of Prime Meridian
        GOSUB AtoB
        Aint = 0    : GOSUB ItoFA     ; subtract from 0 to negate
        GOSUB fpsub
    ENDIF
    
    Bint = 180  : GOSUB ItoFB         ; add 180
    GOSUB fpadd
    
    ;----[Have Longitude in AARG as Float]------------------------------------------
    GOSUB SaveLon                     ; save Longitude for later
    Bint = 20   : GOSUB ItoFB         ; Lon / 20
    GOSUB fpdiv
    GOSUB SaveAARG                    ; save AARG for modulus
    GOSUB FtoIA                       ; get integer
    MH(0) = "A" + Aint                ; + "A" = First character
    
                                      ; -- do  Lon // 20 --- (modulus)
    Bint = Aint                       ; copy integer result to BARG
    GOSUB ItoFB                       ; convert it to float
    GOSUB RestoreAARG                 ; restore Lon / 20 to AARG
    GOSUB fpsub                       ; subtract integer
    Bint = 20                         ; multiply times original divisor (20)
    GOSUB ItoFB
    GOSUB fpmul                       ; AARG now contains the modulus
    
    Bint = 2    : GOSUB ItoFB         ; divide modulus by 2
    GOSUB fpdiv
    GOSUB FtoIA                       ; get integer
    MH(2) = "0" + Aint                ; + "0" = Third character
    
    GOSUB RestoreLon                  ; restore Longitude
    Bint = 2 : GOSUB ItoFB
    GOSUB fpdiv                       ; divide by 2
    
    GOSUB FtoIA                       ; get integer
    Bint = Aint * 2  : GOSUB ItoFB    ; put int * 2 in BARG, change back to float
    GOSUB RestoreLon                  ; restore original Longitude
    GOSUB fpsub                       ; subtract A - B
    
    Bint = 12 : GOSUB ItoFB           ; Multiply * 12
    GOSUB fpmul
    GOSUB FtoIA                       ; get integer
    
    MH(4) = "a" + Aint                ; + "a" = Fifth Character
    
    ;----[convert Latitude Sexagesimal to Decimal Degrees]--------------------------
    Aint = LatMinDec : GOSUB ItoFA    ; decimal portion of Minutes
    Bint = 100 : GOSUB ItoFB          ; divided by 100
    GOSUB fpdiv
    Bint = LatMin : GOSUB ItoFB       ; add whole portion of Minutes
    GOSUB fpadd
    Bint = 60 : GOSUB ItoFB           ; divide by 60
    GOSUB fpdiv
    Bint = LatDeg : GOSUB ItoFB       ; add degrees
    GOSUB fpadd
    IF LatDir = "S" THEN              ; if south of equator
        GOSUB AtoB
        Aint = 0    : GOSUB ItoFA     ; subtract from 0 to negate
        GOSUB fpsub
    ENDIF
    
    Bint = 90  : GOSUB ItoFB          ; add 90
    GOSUB fpadd
    
    ;----[Have Latitude  in AARG as Float]------------------------------------------
    GOSUB SaveLon                     ; save Latitude for later
    Bint = 10   : GOSUB ItoFB         ; Lat / 10
    GOSUB fpdiv
    GOSUB SaveAARG                    ; save AARG for modulus
    GOSUB FtoIA
    MH(1) = "A" + Aint                ; + "A" = Second character
    
                                      ; -- do  Lat // 10 --- (modulus)
    Bint = Aint                       ; copy integer result to BARG
    GOSUB ItoFB                       ; convert it to float
    GOSUB RestoreAARG                 ; restore Lat / 10 to AARG
    GOSUB fpsub                       ; subtract integer
    Bint = 10                         ; multiply times original divisor (10)
    GOSUB ItoFB
    GOSUB fpmul                       ; AARG now contains the modulus
    
    GOSUB FtoIA
    MH(3) = "0" + Aint                ; + "0" = Fourth character
    
    GOSUB RestoreLon                  ; restore original Latitude
    GOSUB FtoIA                       ; get integer
    Bint = Aint : GOSUB ItoFB         ; put int in BARG, change back to float
    GOSUB RestoreLon                  ; restore original Latitude
    GOSUB fpsub                       ; subtract A - B
    
    Bint = 24 : GOSUB ItoFB           ; Multiply * 24
    GOSUB fpmul
    GOSUB FtoIA                       ; get integer
    
    MH(5) = "a" + Aint                ; + "a" = Sixth character
    
    ;----[Maidenhead conversion complete]-------------------------------------------
    
    HSEROUT ["LOC ",STR MH\6,13,10,13,10] ; show final result
    
    
    Main:                             ; blink an LED when done
        HIGH PORTA.0
        PAUSE 500
        LOW PORTA.0
        PAUSE 500
    GOTO Main
    
    ;-------------------------------------------------------------------------------
    Aexp_Copy    VAR BYTE
    AARGB0_Copy  VAR BYTE
    AARGB1_Copy  VAR BYTE
    AARGB2_Copy  VAR BYTE
    
    Aexp_Lon     VAR BYTE
    AARGB0_Lon   VAR BYTE
    AARGB1_Lon   VAR BYTE
    AARGB2_Lon   VAR BYTE
    
    SaveAARG:
        Aexp_Copy = Aexp
        AARGB0_Copy = AARGB0
        AARGB1_Copy = AARGB1
        AARGB2_Copy = AARGB2
    RETURN
    
    RestoreAARG:
        Aexp = Aexp_Copy
        AARGB0 = AARGB0_Copy
        AARGB1 = AARGB1_Copy
        AARGB2 = AARGB2_Copy
    RETURN
    
    AtoB:
        Bexp = Aexp
        BARGB0 = AARGB0
        BARGB1 = AARGB1
        BARGB2 = AARGB2
    RETURN
    
    SaveLon:
        Aexp_Lon = Aexp
        AARGB0_Lon = AARGB0
        AARGB1_Lon = AARGB1
        AARGB2_Lon = AARGB2
    RETURN
    
    RestoreLon:
        Aexp = Aexp_Lon
        AARGB0 = AARGB0_Lon
        AARGB1 = AARGB1_Lon
        AARGB2 = AARGB2_Lon
    RETURN
    The output from the program in a terminal looks like this ...
    Code:
    Maidenhead Locator
    16F1937, 32Mhz, PBP3 not required
    
    LonStr  = 00047.70,W
    LatStr  = 5326.20,N
    LOC IO93ok
    If you are using an Enhanced 14-bit core like the 16F1937 that I'm using ... you'll need to add the processor to the DEV_FAM.INC file from the FP.zip
    For the 16F1937 add this towards the bottom of the file (before the if statement).
    Code:
        IFDEF   __16F1937          ; Generic Processor Type
    P16CXX      SET    TRUE        ; If P16CXX, use INHX8M file format.
    P16_MAP2    SET    TRUE        ;
        ENDIF
    References:
    Last edited by Darrel Taylor; - 14th March 2014 at 06:09.
    DT

  2. #2
    Join Date
    Jan 2012
    Location
    Grid EN19MV
    Posts
    159

    Default Re: How do I discern Maidenhead Locator from GPS lat long info.

    Umm, WOW! Thanks Darrel! And my brain thanks you even more, since it gets uppity when it has to do complex math!
    "I have noticed that even those who assert that everything is predestined and that
    we can change nothing about it still look both ways before they cross the street"


    -Stephen Hawking

  3. #3
    Join Date
    Dec 2011
    Location
    IO93ok
    Posts
    190

    Default Re: How do I discern Maidenhead Locator from GPS lat long info.

    And a WOW from me Darrel. Thanks for your help. Surprisingly I think I can follow and understand the code

    Sorry I'm late back to the thread. One of the winter bugs has had hold of me, not the type I can rewrite

    The project code I posted above doesn't work in the Serin2 GPS routine. Either the line is incorrect or the speed. I've tried every speed and state but no joy. Signal is at the pic pin every second.

    The code compiles but says 'error, expected [ ' but they are there?

    I will try out the code shortly, many thanks again.
    Rob.

    The moment after you press "Post" is the moment you actually see the typso

  4. #4
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959

    Default Re: How do I discern Maidenhead Locator from GPS lat long info.

    Quote Originally Posted by tasmod View Post
    The code compiles but says 'error, expected [ ' but they are there?
    The SERIN2 line has a value for the timeout, but there's no label for it to jump to.
    DT

  5. #5
    Join Date
    Dec 2011
    Location
    IO93ok
    Posts
    190

    Default Re: How do I discern Maidenhead Locator from GPS lat long info.

    Doh, sometimes you can't see the wood for the trees !

    Thanks again Darrel, you've no idea how many times I looked at that line.

    Code is working at base level now and info is on screen, next is to incorporate the Locator code of yours.

    Name:  gpslcd.jpg
Views: 19134
Size:  12.0 KB
    Rob.

    The moment after you press "Post" is the moment you actually see the typso

  6. #6
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959

    Default Re: How do I discern Maidenhead Locator from GPS lat long info.

    Awesome!

    Can't wait to see an IO93ok on that LCD.
    DT

  7. #7
    Join Date
    Dec 2011
    Location
    IO93ok
    Posts
    190

    Default Re: How do I discern Maidenhead Locator from GPS lat long info.

    Hi Darrel,
    Hmm, I wanted to move on to final stages of the project adding the locator code but before I could I came up against something I've not had before.

    I was using a 16f628A and wanted to port across to a 16F818 for a single adc channel use. (Monitor a pll control voltage)

    I had errors of "Argument out of range" when I added my usual working ADC code. It works standalone on the 818 nicely.

    The code for gps alone works in the 818 as per lcd pic. So I'm lost now.

    In the working gps code alone, no adc code. I did have some very odd messages re 'out of range' with the code with END at the finish of the code. It seemed like something was hidden in the space in MCS. Deleting back to the final Goto GPS cleared the messages.

    This is the gps code with adc which errors. I daren't add the locator code yet

    Code:
    ; 
    ;
    ; 			        PIC16F818                             
    ;                          __________                                          
    ;     D6-------------RAN2 |1       18| RAN1---------D5                   
    ;     D7-------------RAN3 |2       17| RAN0---------D4                 
    ;     LED------------RAN4 |3       16| OSC1--------XTAL                        
    ;     +5V-----------!MCLR |4       15| OSC2--------XTAL                        
    ;     Ground----------Vss |5       14| VDD---------+5 V                        
    ;     NMEA data-------RB0 |6       13| RB7---------Not used                   
    ;     Serial data out-RB1 |7       12| RB6---------Not used
    ;     Not used--------RB2 |8       11| RB5---------LCD Enable          
    ;     Pushbutton------RB3 |9       10| RB4---------LCD Register select         
    ;                          ----------                                          
    ; 
    
    ;====================================================================='
    ' Program to display returned value of a GPS on RB0
    ' LCD in 4-BIT mode PIC16F818 controller 4Mhz clock Fuse PWRT BODEN
    ' 
    'GPS sentence: $GPRMC,192144.62,A,5041.6058,N,00412.6124,E,0.45,3 57.74,081205,,*0B
    
    
    Define LCD_DREG PORTA          ' Port for LCD Data
    Define LCD_DBIT 0              ' Use upper 4 bits of Port  
    Define LCD_RSREG PORTB         ' Port for RegisterSelect (RS) bit
    Define LCD_RSBIT 4             ' Port Pin for RS bit  (pin9)
    Define LCD_EREG PORTB          ' Port for Enable (E) bit
    Define LCD_EBIT 5              ' Port Pin for E bit    (pin7)
    Define LCB_BITS 4              ' Using 4-bit bus
    Define LCD_LINES 4             ' Using 2 line Display
    Define LCD_COMMANDUS 1500      ' Command Delay (uS)
    define LCD_DATAUS 50           ' Data Delay (uS)
    
    DEFINE OSC 4
    
    OPTION_REG.7=0                 ' Enable Pull-Up's
    GPSin VAR PORTB.0
    ' Initialise ADC
    ADCON1 = %10000100 ' Set PORTA analog and RIGHT justify result
    ADCON0 = %01010001 ' Configure and turn on A/D Module channel 4 Fosc 8
    PAUSE 500
    
    'Declare variables
    val VAR WORD      ' final calculated adc valuesWORD' final calculated adc values
    volt VAR WORD     ' scaled value real part
    voltd1 VAR WORD   ' scaled value first decimal place
    voltd2 VAR WORD   ' scaled value second decimal place
    i var byte        ' counter
    
    'Allocate Variables for GPS:
    TimeOut CON 2000            
                                                                
    hh VAR BYTE             'hours
    mm VAR BYTE             'minutes
    ss VAR BYTE             'seconds
    knots VAR WORD          'speed in knots (units)
    knotsten VAR BYTE       'speed in knots (tens)
    course VAR WORD         'heading
    latdeg VAR BYTE         'degrees latitude
    latmin VAR BYTE         'minutes latitude
    NS VAR BYTE             'north or south
    londeg VAR BYTE         'degrees longitude
    lonmin VAR BYTE         'minutes longitude
    EW VAR BYTE             'east or west
    d VAR BYTE              'day
    m VAR BYTE              'month
    y VAR BYTE              'year
    
    fix VAR WORD 'GPS fix
    
    LCDOut $fe,$80,"   GPS Decoder  "
    LCDOut $FE,$c0, "    G8VLQ Mk1  "
    Pause 500
    LCDOut $FE, 1           'Clear Screen
    
    GPS: 'read GPS
    
    SerIn2 GPSin,188,Timeout,LCD1,[wait("$GPRMC"),wait(","),DEC2 hh,DEC2 mm,DEC2 ss,wait(",")_
    ,fix,wait(","),DEC2 latdeg,DEC2 latmin,wait(","),NS,wait(","),DEC3 londeg,DEC2 lonmin,_
    wait(","),EW,wait(","),knots,wait("."),DEC2 knotsten,wait(","),DEC3 course,wait(","),DEC2 d,DEC2 m,DEC2 y]
    
    
    IF fix="V" Then         'if no GPS fix
    GOTO LCD1
    EndIF
    
    gosub PLL
    
    LCD:      
               
    LCDOut $fe,$80,DEC2 d,"-",DEC2 m,"-",DEC2 y," ",#volt, ".", # voltd1,# voltd2, "Vdc"            ; 80 1st line   
    LCDOUT $fe,$c0,"    ",DEC2 hh,":",DEC2 mm,":",DEC2 ss,"    "                                ; c0 2nd line
    LCDOut $fe,$90," LAT: ",DEC2 latdeg,",",DEC2 latmin," ",NS                                 ; 90 3rd line
    LCDOut $fe,$d0," LON: ",DEC2 londeg,",",DEC2 lonmin," ",EW                                 ; d0 4th line
    
    GoTo GPS
    
    LCD1:       ; If invalid data, just shows gps string is received
    
    LCDOut $fe,$80,#volt, ".", # voltd1,# voltd2, "Vdc"                                         ; 80 1st line
    LCDOUT $fe,$c0,"     No Fix       "                                                       ; c0 2nd line
    LCDOut $fe,$90," LAT: ",DEC2 latdeg,",",DEC2 latmin," ",NS                                ; 90 3rd line
    LCDOut $fe,$d0," LON: ",DEC2 londeg,",",DEC2 lonmin," ",EW                                ; d0 4th line
    
    goto GPS
    
    LCD2:      ; 20 character display. Put time and date on first line , removed names.
               ; callsign and QRA (maidenhead) on second line
    
    LCDOut $fe,$80,DEC2 d,"-",DEC2 m,"-",DEC2 y,DEC2 hh,":",DEC2 mm                         ; 80 1st line
    LCDOut $fe,$80," G8VLQ   "                                                              ; c0 2nd line
    LCDOut $fe,$90,"LAT: ",DEC2 latdeg,",",DEC2 latmin," ",NS                                ; 90 3rd line
    LCDOut $fe,$d0,"LON: ",DEC2 londeg,",",DEC2 lonmin," ",EW                                ; d0 4th line
    
    GoTo GPS
    
    PLL:
    Val = 0                       ' Value returned is the average of 5 conversions
    For i = 0 TO 4
    ADCON0.4 = 1                  ' Start conversion
    NoteDone:
    pause 1
    IF ADCON0.4 = 1 Then NoteDone
    val = val + ((ADRESH * 256)+(ADRESL))
    nEXT I
    VAL = VAL/5
    ' Calculate Volatage to 2 decimal places
    volt = val * 5/1024
    voltd1 = ( val * 5//1024) * 10/1024
    Voltd2 = ((val *5 //1024) * 10//1024) * 10/1024
    RETURN
    Rob.

    The moment after you press "Post" is the moment you actually see the typso

Similar Threads

  1. LAT replaces PORT command?
    By markscotford in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 3rd December 2011, 16:37
  2. Need Info for PBP?
    By azmax100 in forum mel PIC BASIC Pro
    Replies: 0
    Last Post: - 30th January 2009, 07:44
  3. Replies: 1
    Last Post: - 27th July 2008, 06:14
  4. dmx info.
    By oscar in forum mel PIC BASIC Pro
    Replies: 0
    Last Post: - 8th May 2005, 11:54

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts