Don't know if THIS PDF will help - but I was using this in my early attempts to get this figured out. It describes how to discern the 7th and 8th digits
Printable View
Don't know if THIS PDF will help - but I was using this in my early attempts to get this figured out. It describes how to discern the 7th and 8th digits
Hi Darrel,
Many thanks for this.
I wondered about the variables. I did have a try at following the code through in the hope I could perhaps work it out.
As a test. I changed the string to 8 characters and tried adding MH(7) ="0" + AINT/10 and MH(8)="0"+ AINT/10 in Lat and Lon routines after MH4 and MH5 as a trial to see what was displayed.
I think the routine at 8 chrs is referencing the midi digit routine chrs as it displays custom chrs on the LCD in those positions.
I tried repeating MH4 and 5 but renumbered, so that should give 'IO93okok' as the 7th and 8th position but again it accessed custom chrs. A puzzle for me anyway.
Hi Andy,
That's the doc I took the info post from :)
Regarding working satellites, I downloaded a Maidenhead Locator App for my Android phone. Gives lots of other info too.
Able to get 10 digit locator from the inbuilt gps on the phone.
Nope, it's 24x24.
And your 10-digit locator is IO93ok03kh.
This version is quite different from the last one.
I've tossed out the stuff that came from the pearl script and did it like the PDF mentioned above.
It has to use the 32-bit floating point routines now. 24-bits just didn't have enough resolution for the sub-squares.
While this version is more efficient, it's also harder to understand, sorry.
The output of the program looks like this ...Code:; Filename : Maidenhead_10.pbp
; Compiler : PICBASIC PRO Compiler
; Target PIC : 16F1937, but will work with most any chip
; Oscillator : ANY
; Keywords : Maidenhead, Locator, GPS, Amateure Radio
; Description : PICBASIC PRO program to convert between
; : GPS Sexagesimal to Maidenhead coordinate systems
;-------------------------------------------------------------------------------
; Must use the 32-bit Floating Point routines
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, 32-bit Floating Point",13,10,13,10]
MH VAR BYTE[10]
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
Idx VAR BYTE
AddChar VAR BYTE
Divisor VAR BYTE[4]
AARG_SAVE VAR BYTE[4]
;-------------------------------------------------------------------------------
ASM
MOVE?CF32 macro C, F ; put a Floating Point Constant in an FP variable
MOVE?CW (C & 0xFFFF), F
MOVE?CW (C >> 16), F + 2
endm
MOVE?FF32 macro Fin, Fout ; Copy an FP var to another FP var
MOVE?WW Fin, Fout
MOVE?WW Fin + 2, Fout + 2
endm
ENDASM
;-------------------------------------------------------------------------------
ARRAYWRITE LonStr,["00049.77,W",0] ; 0° 47.70' ;<-- enter GPS location here
ARRAYWRITE LatStr,["5325.83,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
@ MOVE?FF32 AARGB2, BARGB2 ; copy Float AARG to BARG
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]------------------------------------------
FOR Idx = 0 TO 8 STEP 2
SELECT CASE Idx
CASE 0 : AddChar = "A"
@ MOVE?CF32 0x83200000, _Divisor ; 20
CASE 2 : AddChar = "0"
@ MOVE?CF32 0x80000000, _Divisor ; 2
CASE 4 : AddChar = "a"
@ MOVE?CF32 0x7B2AAAAB, _Divisor ; 0.0833333
CASE 6 : AddChar = "0"
@ MOVE?CF32 0x78088889, _Divisor ; 0.00833333
CASE 8 : AddChar = "a"
@ MOVE?CF32 0x73360B61, _Divisor ; 0.000347222
END SELECT
GOSUB MH_Digit
NEXT Idx
;----[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
@ MOVE?FF32 AARGB2, BARGB2 ; copy Float AARG to BARG
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]------------------------------------------
FOR Idx = 1 TO 9 STEP 2
SELECT CASE Idx
CASE 1 : AddChar = "A"
@ MOVE?CF32 0x82200000, _Divisor ; 10
CASE 3 : AddChar = "0"
@ MOVE?CF32 0x7F000000, _Divisor ; 1
CASE 5 : AddChar = "a"
@ MOVE?CF32 0x7A2AAAAB, _Divisor ; 0.0416666
CASE 7 : AddChar = "0"
@ MOVE?CF32 0x770882F1, _Divisor ; 0.00416666
CASE 9 : AddChar = "a"
@ MOVE?CF32 0x723603EC, _Divisor ; 0.000173583
END SELECT
GOSUB MH_Digit
NEXT Idx
;----[Maidenhead conversion complete]-------------------------------------------
HSEROUT ["LOC ",STR MH\10,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
;----[Calculate one digit of the Maidenhead Locator]----------------------------
MH_Digit:
@ MOVE?FF32 _Divisor, BARGB2 ; put divisor in BARG
GOSUB fpdiv ; do the divide
@ MOVE?FF32 AARGB2, _AARG_SAVE ; save AARG for modulus
GOSUB FtoIA ; get integer
MH(Idx) = Aint + AddChar ; The Character
Bint = Aint ; copy integer result to BARG
GOSUB ItoFB ; convert it to float
@ MOVE?FF32 _AARG_SAVE, AARGB2 ; restore previous AARG
GOSUB fpsub ; subtract integer
@ MOVE?FF32 _Divisor, BARGB2 ; multiply times original divisor
GOSUB fpmul ; AARG now contains the remainder
RETURN
BTW: Those are really small squares (in red).Code:Maidenhead Locator
16F1937, 32-bit Floating Point
LonStr = 00049.77,W
LatStr = 5325.83,N
LOC IO93ok03kh
Attachment 7313
Wow, wow and WOW. What can I say? That is your usual brilliant stuff.
I use DT_Ints, Big Digits, ADC Average and now your Locator code.
Many many thanks. I tried but just can't follow it through as you expected :rolleyes:
I never realised just how small the final location square was. That's half my plot. Reason is, the gps antenna is on the window ledge on a back room!
If I move to front room it would change !! Stunning.
Now I need to re-organise the screen layout. I didn't think I would run out of room on a 20x4 display.
I will post a picture of the completed item, it's boxed but not quite complete.
Once again, many thanks.
Hmmm, I've transferred the code over into my program but I must have done something wrong as the locator is incorrect.
I'm getting 10 and kd instead of 03 and kh which is correct at back of house. kg at front of house
I will check it over again.
Here's a screenshot of the Android app.
Attachment 7315
These are some of the results I get ...
Since the main difference is the decimal portion of the Minutes, you might want to look at the values in the LonMinDec and LatMinDec variables.Code:LAT LON Maidenhead
Deg Min.Min Deg Min.Min 1234567890
------------ ------------ ----------
53° 25.83' -0° 49.77' IO93ok03kh Back Yard
53° 25.82' -0° 49.77' IO93ok03kg Front Yard
53° 25.04' -0° 49.29' IO93ok10kd Wrong Place
They should come from the latsecs and lonsecs variables you parsed from the GPS.
Although, it's not seconds ... it's the decimal portion of the Minutes.
That was it Darrel. I had aliased the wrong variables to save renaming.
Gives correct code at 'back yard' 90% of time. Why 90% ? Well, it faces North and the number of satellites it will lock to for a precise fix varies quite a lot. This is due to antenna position and satellite positions. If I lift antenna slightly, it will improve.
The gps gives a slightly changing fix as it recalculates. According to manual it outputs a 'Fix' in sentence when it has aquired 4 satellites
At the South facing 'front yard' it is 100%, as it will fix 12 satellites, the limit of this gps module.
I'm going to try inputting an initialisation string at start up. This will turn off all sentences except the RMC sentence. This should stop the occasional random catchup 'seconds' jump as another sentence is output. There are four other defaults, GGA , GSV , GSA and ZCH. The latter is the unit channel status.
It appears that they are output randomly according to PC gps serial monitoring program, whilst RMC is per second.
Does your GPS module put out more decimal places in the LAT/LON fields?
Since the edge of the square runs through the middle of the house, whether you're at the front window or rear window inside, you're always near the edge.
I imagine that if you were standing in the middle of your back yard, the reading would be more consistent.
One or two more decimals may improve the resolution considerably.
With only two decimals, a difference of .01 is a whole square.
It depends on whether your GPS gives enough data or not.Code:LAT LON Maidenhead
Deg Min.Min Deg Min.Min 1234567890
------------ ------------ ----------
53° 25.83' -0° 49.77' IO93ok03kh Back Yard
53° 25.82' -0° 49.77' IO93ok03kg Front Yard
When recording NMEA sentences from my Android, it gives 6 decimals.
Again you come to my aid Darrel. :D
I had limited the output by declaring the lat/lon secs as byte. Changed them to word and it becomes much more stable now. Datasheet says the decimal part is of variable length not fixed, so word should cover it.
I have also improved the start time to fix by finally fitting the Supercap to the gps module, something I should have done a while ago. This gives 48hr backup.
Don't groan but I now have another problem I'm going to look at. The time is now 2 seconds slow. Probably all the code plus the NMEA being slow too.
I'm looking at adding 2 secs then trigger display using DT_Ints on the next PPS pulse rise time. Feasible ??
Hmmm no. I screwed that up somehow.
I realised it was saving DEC2 in the gps string so it would not be any different, so I changed it to DEC4 for now.
I changed the DEC2 in display line to DEC4 and I was getting 4 decimal places on Latitude displayed but Long went to all 0's. So locator was IO84 something.
Will spend some time on it.
Now this is interesting.
If I mess with the size of any 'secs' variables it screws everything up. I can get Lat to 4 decimal places but not Long, it still goes to zero.
Right now I put the code back to original and got IO93ok03kg as the locator. I'm going to reduce this to the 4 pair for display just now, only to get more on screen.
I put my phone with the app running next to the gps antenna.
The phone was showing a fix to 16 sats and gave IO93ok03lh with 53 25.8266 and 0 49.7704 as the co-ordinates.
For mine. When I had the 4 decimal places shown on the display it showed 25.8246
It's between DEC4 in gps string and Aint in locator code.
I can get the display right but not the locator using DEC4 in the gps string and DIGs in the display LCDOUT.
I can get the locator right but not the position display if I just use latsecs as the variable in the gps input string.
Not knowing how Aint works I'm stumped now.
EDIT:
Just walked the property with the phone. Wow, those squares are small. I get LG, LH, KG, KH and guess where the crossover is, yes, right around the room where the unit is. I think I'll stick to DEC2 for now :D
With DEC4 change it to this for the Longitude ...And do the same thing with the Latitude.Code:;----[convert Longitude Sexagesimal to Decimal Degrees]-------------------------
Aint = LonMinDec : GOSUB ItoFA ; decimal portion of Minutes
Bint = 10000 : GOSUB ItoFB ; divided by 10000
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
@ MOVE?FF32 AARGB2, BARGB2 ; copy Float AARG to BARG
Aint = 0 : GOSUB ItoFA ; subtract from 0 to negate
GOSUB fpsub
ENDIF
Bint = 180 : GOSUB ItoFB ; add 180
GOSUB fpadd
That was it.
Using "DEC4 latsecs/lonsecs" in the gps string and changing to Word size variables uses the 4 decimal places.
Interestingly using battery power for the unit, I got exactly the same reading as the phone app moving the unit around.
Thanks Darrel.
I'm now looking at making the time display more accurate to the second epoch using DT_Ints
Yahooo!
If you are going to add interrupts, you'll need to make some changes.Quote:
I'm now looking at making the time display more accurate to the second epoch using DT_Ints
SERIN2's baudrate is software timed, and it doesn't like being interrupted.
You'll have to move the serial lines over to RC6 and RC7 (the USART pins).
Then use HSERIN instead of SERIN2.
HSERIN is not affected by the interrupts.
Hmm, guess which pins are not catered for on pcb ?
Redesign methinks. :D
Redesign completed. New board made where all pins are accessible and pads for option of pullups/down resistors.
I have altered the software to use HSERIN and HSEROUT and all is well at the moment. It is working just fine.
Using the code in previous post:
My aim was to display the clock triggered by the gps pps signal. I tried DT_Ints and added the @ INT_RETURN where the original Clock sub had RETURN. This caused the display to only update the very first square with random characters per second with PPS signal.
This is the setup naming Clock. I wasn't sure where to put the INT_Enable . I tried just after this ASM and at beginning of Clock routine with same result.
Code:;--------------------------------------------------------------------------
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler INT_INT, _Clock, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM
;--------------------------------------------------------------------------
@ INT_ENABLE INT_INT ; enable external (INT) interrupts
This is the full code with the Ints active but it's just updating first character.
Code:;
; GPS NMEA Display code with GPSDO monitoring
;
; PIC16F876A
; __________
; !MCLR |1 28| RB7------D7
; PLL Volt--AN0---RA0 |2 27| RB6------D6
; adc spare--AN1---RA1 |3 26| RB5------D5
; adc spare--AN2---RA2 |4 25| RB4------D4
; adc spare--AN3---RA3 |5 24| RB3------LCD E
; spare---RA4 |6 23| RB2------LCD RS
; adc spare--AN4---RA5 |7 22| RB1------spare
; Ground---Vss |8 21| RB0------PPS In
; OSC1---XTAL |9 20| VDD------ +5 V
; OSC2---XTAL |10 19| Vss------Ground
; spare---RC0 |11 18| RC7------H-RX -- GPS NMEA In
; spare---RC1 |12 17| RC6------H-TX -- GPS Command Out
; spare---RC2 |13 16| RC5------spare
; Pbutton---RC3 |14 15| RC4------spare
; ----------
;====================================================================='
' Program to display returned value of a GPS NMEA string on RA4
' LCD in 4-BIT mode PIC16F876a controller 4Mhz clock Fuse PWRT BODEN
'
'Typical GPS sentence string: $GPRMC,192144.62,A,5041.6058,N,00412.6124,E,0.45,3 57.74,081205,,*0B
'The default sentences are continuously output.
'Now suppose I want to read only one particular sentence I need to program the GPS to do that.
'The input message ILOG controls which sentences are logged.
'$PRWIILOG,???,V,,,\r,\n
'Inputting this sentence, disables all the sentences.
'Now suppose we want only RMC sentence then input the following sentence serially to gps
'$PRWIILOG,RMC,A,,,,\r\n
'The \r(<CR>) and \n (<LF>) are sentence terminator in NMEA
'V disables that particular sentence while A enables that sentence.
@ __config _HS_OSC & _WDT_ON & _PWRTE_ON & _BODEN_OFF & _LVP_OFF & _CPD_OFF & _WRT_OFF & _DEBUG_OFF & _CP_OFF
; Place a copy of these variables in your Main program for digit characters--
;-- The compiler will tell you which lines to un-comment --
;-- Do Not un-comment these lines --
;---------------------------------------------------------------------------
;wsave VAR BYTE $20 SYSTEM ' location for W if in bank0
wsave VAR BYTE $70 SYSTEM ' alternate save location for W
' if using $70, comment wsave1-3
' --- IF any of these three lines cause an error ?? ------------------------
' Comment them out to fix the problem ----
' -- Which variables are needed, depends on the Chip you are using --
'wsave1 VAR BYTE $A0 SYSTEM ' location for W if in bank1
'wsave2 VAR BYTE $120 SYSTEM ' location for W if in bank2
;wsave3 VAR BYTE $1A0 SYSTEM ' location for W if in bank3
' --------------------------------------------------------------------------
; Must use the 32-bit Floating Point routines
INCLUDE "FP2032.bas" ; 32-bit Floating Point for 14-bit cores with RAM at $20
INCLUDE "Average.bas" ; DT's 16-bit Analog Module averaging values
INCLUDE "DT_INTS-14.bas" ; Base Interrupt System
INCLUDE "ReEnterPBP.bas"
Define LCD_DREG PORTB ' Port for LCD Data
Define LCD_DBIT 4 ' Set LCD starting data bit
Define LCD_RSREG PORTB ' Port for RegisterSelect (RS) bit
Define LCD_RSBIT 2 ' Port Pin for RS bit (pin9)
Define LCD_EREG PORTB ' Port for Enable (E) bit
Define LCD_EBIT 3 ' Port Pin for E bit (pin7)
Define LCB_BITS 4 ' Using 4-bit bus
Define LCD_COMMANDUS 1500 ' Command Delay (uS)
define LCD_DATAUS 50 ' Data Delay (uS)
DEFINE OSC 4
DEFINE ADC_BITS 10 ' Setup ADC
DEFINE ADC_SAMPLEUS 5
DEFINE ADC_CLOCK 1
DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 20h ' Enable transmit, BRGH = 0
DEFINE HSER_BAUD 4800
DEFINE HSER_CLROERR 1 ' Clear overflow automatically
OPTION_REG.6 = 1 ' Interrupt rising edge
OPTION_REG.7 = 0 ' Enable Pull-Up's
PPS VAR PORTB.0
Pbutton VAR PORTC.3
' Initialise ADC
ADCON1 = %10000100 ' Set PORTA analog and RIGHT justify result
ADCON0 = %01000001 ' Configure and turn on A/D Module channel 0 Fosc 8
'Declare variables
volt VAR WORD ' scaled value real part
voltd1 VAR WORD ' scaled value first decimal place
voltd2 VAR WORD ' scaled value second decimal place
'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
latsecs VAR WORD 'seconds latitude
NS VAR BYTE 'north or south
londeg VAR BYTE 'degrees longitude
lonmin VAR BYTE 'minutes longitude
lonsecs VAR WORD 'seconds longtitude
EW VAR BYTE 'east or west
d VAR BYTE 'day
m VAR BYTE 'month
y VAR BYTE 'year
;###################################################
butt VAR BYTE 'pushbutton variable
marker VAR BYTE 'toggle marker
marker2 VAR BYTE 'UTC or BST
MH VAR BYTE[10] 'locator variables##########
;
Idx VAR BYTE ;
AddChar VAR BYTE ;
Divisor VAR BYTE[4] ;
AARG_SAVE VAR BYTE[4] '----------------###########
nPos var byte ' digit variables
nDig var byte '--------------------
Idx2 VAR BYTE ' Month variables
X VAR BYTE ;
Char VAR WORD '--------------------
scroll VAR BYTE
fix VAR BYTE 'GPS fix - Yes="A" No="V"
butt = 0 ;clear button variable
marker = 0 ;set marker to zero for full info display at start
marker2 = 0 ;set UTC
PAUSE 50
;--------------------------------------------------------------------------
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler INT_INT, _Clock, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM
;--------------------------------------------------------------------------
@ INT_ENABLE INT_INT ; enable external (INT) interrupts
LCDOut $fe,$80," GPS Decoder " ; scrolling opening display
LCDOut $FE,$c0," G8VLQ March 2014 "
Pause 2000
for scroll = 1 to 20 ' FOR..NEXT loop so message scrolls off the LCD to the left
lcdout $fe,24 ' Scrolls display one position to the left
pause 100 ' Pause 150 ms
next scroll ' do loop again till max count
pause 1500 ' Pause 1000ms
lcdout $fe,1 ' Clears LCD
;------------------------------------------------
Initialisation: ;Leaving GPRMC as only sentence output
HSEROUT ["$PRWIILOG,GGA,V,,,",13,10]
PAUSE 100
HSEROUT ["$PRWIILOG,GSA,V,,,",13,10]
PAUSE 100
HSEROUT ["$PRWIILOG,GSV,V,,,",13,10]
PAUSE 100
HSEROUT ["$PRWIILOG,ZCH,V,,,",13,10]
PAUSE 100
;-------------------------------------------------
GPS: 'read GPS #############################################################################################
HSerIn Timeout,Clock,[wait("$GPRMC"),wait(","),DEC2 hh,DEC2 mm,DEC2 ss,wait(","),fix,wait(","),DEC2 _
latdeg,DEC2 latmin,wait("."),DEC4 latsecs,wait(","),NS,wait(","),DEC3 londeg,DEC2 lonmin,wait("."),DEC4 lonsecs,_
wait(","),EW,wait(","),knots,wait("."),DEC2 knotsten,wait(","),DEC3 course,wait(","),DEC2 d,DEC2 m,DEC2 y]
IF marker = 1 THEN BigClock ; keeps big clock running if value is 1
IF marker2 = 1 THEN Plusone
;-------------------------------------------------------- ;
BUTTON Pbutton,0,100,0,butt,1,BigClockClear ;button press to jump to fullscreen big clock
GOSUB PLL ;get the A/D value of pll control voltage
GOSUB ShowMonth ;show month as letters
GOSUB Locator ;maidenhead locator
;GOSUB BST
GOSUB Clock ;medium digit clock
goto GPS ; ##########################################################################################
;---------------------------------------------------------------
; MAIDENHEAD CONVERSION -- Darrel Taylor
;---------------------------------------------------------------
Locator:
ASM
MOVE?CF32 macro C, F ; put a Floating Point Constant in an FP variable
MOVE?CW (C & 0xFFFF), F
MOVE?CW (C >> 16), F + 2
endm
MOVE?FF32 macro Fin, Fout ; Copy an FP var to another FP var
MOVE?WW Fin, Fout
MOVE?WW Fin + 2, Fout + 2
endm
ENDASM
;-------------------------------------------------------------------------------
;----[convert Longitude Sexagesimal to Decimal Degrees]-------------------------
Aint = lonsecs : GOSUB ItoFA ; decimal portion of Minutes
Bint = 10000 : 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 EW = "W" THEN ; if west of Prime Meridian
@ MOVE?FF32 AARGB2, BARGB2 ; copy Float AARG to BARG
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]------------------------------------------
FOR Idx = 0 TO 8 STEP 2
SELECT CASE Idx
CASE 0 : AddChar = "A"
@ MOVE?CF32 0x83200000, _Divisor ; 20
CASE 2 : AddChar = "0"
@ MOVE?CF32 0x80000000, _Divisor ; 2
CASE 4 : AddChar = "a"
@ MOVE?CF32 0x7B2AAAAB, _Divisor ; 0.0833333
CASE 6 : AddChar = "0"
@ MOVE?CF32 0x78088889, _Divisor ; 0.00833333
CASE 8 : AddChar = "a"
@ MOVE?CF32 0x73360B61, _Divisor ; 0.000347222
END SELECT
GOSUB MH_Digit
NEXT Idx
;----[convert Latitude Sexagesimal to Decimal Degrees]--------------------------
Aint = latsecs : GOSUB ItoFA ; decimal portion of Minutes
Bint = 10000 : 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 NS = "S" THEN ; if south of equator
@ MOVE?FF32 AARGB2, BARGB2 ; copy Float AARG to BARG
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]------------------------------------------
FOR Idx = 1 TO 9 STEP 2
SELECT CASE Idx
CASE 1 : AddChar = "A"
@ MOVE?CF32 0x82200000, _Divisor ; 10
CASE 3 : AddChar = "0"
@ MOVE?CF32 0x7F000000, _Divisor ; 1
CASE 5 : AddChar = "a"
@ MOVE?CF32 0x7A2AAAAB, _Divisor ; 0.0416666
CASE 7 : AddChar = "0"
@ MOVE?CF32 0x770882F1, _Divisor ; 0.00416666
CASE 9 : AddChar = "a"
@ MOVE?CF32 0x723603EC, _Divisor ; 0.000173583
END SELECT
GOSUB MH_Digit
NEXT Idx
;----[Maidenhead conversion complete]-------------------------------------------
RETURN
;----[Calculate one digit of the Maidenhead Locator]----------------------------
MH_Digit:
@ MOVE?FF32 _Divisor, BARGB2 ; put divisor in BARG
GOSUB fpdiv ; do the divide
@ MOVE?FF32 AARGB2, _AARG_SAVE ; save AARG for modulus
GOSUB FtoIA ; get integer
MH(Idx) = Aint + AddChar ; The Character
Bint = Aint ; copy integer result to BARG
GOSUB ItoFB ; convert it to float
@ MOVE?FF32 _AARG_SAVE, AARGB2 ; restore previous AARG
GOSUB fpsub ; subtract integer
@ MOVE?FF32 _Divisor, BARGB2 ; multiply times original divisor
GOSUB fpmul ; AARG now contains the remainder
RETURN
;---------------------------------------------------------------------------
; Month routine
ShowMonth:
LCDOut $fe,$80+9,DEC2 d," "
GOSUB Month
LCDOut " ","20",DEC2 y
RETURN
Month:
Idx2 = (m - 1) * 3
FOR X = Idx2 TO Idx2 + 2
LOOKUP X,["JanFebMarAprMayJunJulAugSepOctNovDec"],Char
LCDOUT Char
NEXT X
RETURN
;--------------------------------------------------------------------------
; British Summer Time
;--------------------------------------------------------------------------
BST:
IF m = 3 AND d = 30 THEN Plusone
IF m >= 03 and m <= 10 THEN Plusone
RETURN
Plusone:
IF m = 10 and d = 26 then UTC
IF m >=10 and m <3 then UTC
hh = hh + 1
IF hh = 25 THEN hh = 0
marker2 = 1
RETURN
UTC:
marker2 = 0
RETURN
;--------------------------------------------------------------------------
; PLL control voltage read result via Average routine
;--------------------------------------------------------------------------
PLL: ' Measure GPSDO PLL control voltage for TCXO - Approx 1.65v for lock
ADCON0.2 = 1 ' Start conversion
NotDone:
pause 1
IF ADCON0.2 = 1 Then NotDone
value =((ADRESH * 256)+(ADRESL))
gosub Average
' Calculate Voltage to 2 decimal places
volt = value * 5/1024
voltd1 = ( value * 5//1024) * 10/1024
voltd2 = ((value *5 //1024) * 10//1024) * 10/1024
RETURN
;--------------------------------------------------------------------------
lock:
IF (volt=1) AND (voltd1 =6) AND (voltd2 =<9) THEN
LCDOUT $FE,$C0+9,"Lock "
ENDIF
RETURN
;---------------------------------------------------------------------------
ClockClear: ;Returning from Big Digit Clock, need to clear screen
LCDOut $FE, 1 ;Clear Screen
marker = 0 ;set marker to full info display
GOTO GPS
;--------------------------------------------------------------------------
Clock: ;Display medium character time clock
'Set up the digits (http://www.darreltaylor.com/files/CustChar.htm)
LCDOUT $FE,$40,$03,$03,$03,$03,$03,$03,$03,$03 ' Cust Char #0
LCDOUT $FE,$48,$0E,$1F,$1B,$1B,$1B,$1B,$1B,$1B ' Cust Char #1
LCDOUT $FE,$50,$1F,$1F,$18,$18,$18,$18,$1F,$1F ' Cust Char #2
LCDOUT $FE,$58,$03,$03,$03,$03,$03,$03,$1F,$1F ' Cust Char #3
LCDOUT $FE,$60,$0E,$1F,$1B,$1B,$1B,$1B,$1F,$0E ' Cust Char #4
LCDOUT $FE,$68,$1B,$1B,$1B,$1B,$1B,$1B,$1F,$0E ' Cust Char #5
LCDOUT $FE,$70,$1F,$1F,$03,$03,$03,$03,$1F,$1F ' Cust Char #6
LCDOUT $FE,$78,$1E,$1F,$03,$03,$03,$03,$03,$03 ' Cust Char #7
nDig=ss dig 0 : nPos=7 : gosub displaydigit
nDig=ss dig 1 : nPos=6 : gosub displaydigit
npos=5 : gosub colon
ndig=mm dig 0 : npos=4 : gosub displaydigit
ndig=mm dig 1 : npos=3 : gosub displaydigit
npos=2 : gosub colon
ndig=hh dig 0 : npos=1 : gosub displaydigit
ndig=hh dig 1 : npos=0 : gosub displaydigit
LCDOUT $FE,$C0+9,"False Data " ;displays
IF fix = "A" THEN
LCDOUT $FE,$C0+9,"Fix ",#volt, ".", # voltd1,# voltd2,"v" ;overwrites No Data
GOSUB lock ;checks for pll lock if Fix valid
ENDIF
LCDOUT $fe,$94," G8VLQ ",STR MH\10," " ;STR is 10 digit Maidenhead Locator
LCDOut $fe,$d4,DEC2 latdeg,$DF,DEC2 latmin,"'",DEC latsecs DIG 3,DEC latsecs DIG 2,_
NS," ",DEC2 londeg,$DF,DEC2 lonmin,"'",DEC lonsecs DIG 3,DEC lonsecs DIG 2,EW
;$DF is degree symbol, some LCD displays have it in different location
@ INT_RETURN
;RETURN
displaydigit:
if ndig=0 then gosub zero
if ndig=1 then gosub one
if ndig=2 then gosub two
if ndig=3 then gosub three
if ndig=4 then gosub four
if ndig=5 then gosub five
if ndig=6 then gosub six
if ndig=7 then gosub seven
if ndig=8 then gosub eight
if ndig=9 then gosub nine
return
Zero:
LCDOUT $FE,$80+nPos,1
LCDOUT $FE,$C0+nPos,5
return
One:
LCDOUT $FE,$80+nPos,0
LCDOUT $FE,$C0+nPos,0
return
Two:
LCDOUT $FE,$80+nPos,7
LCDOUT $FE,$C0+nPos,2
return
Three:
LCDOUT $FE,$80+nPos,6
LCDOUT $FE,$C0+nPos,3
return
Four:
LCDOUT $FE,$80+nPos,5
LCDOUT $FE,$C0+nPos,0
return
Five:
LCDOUT $FE,$80+nPos,2
LCDOUT $FE,$C0+nPos,3
return
Six:
LCDOUT $FE,$80+nPos,2
LCDOUT $FE,$C0+nPos,5
return
Seven:
LCDOUT $FE,$80+nPos,7
LCDOUT $FE,$C0+nPos,0
return
Eight:
LCDOUT $FE,$80+nPos,4
LCDOUT $FE,$C0+nPos,5
return
Nine:
LCDOUT $FE,$80+nPos,4
LCDOUT $FE,$C0+nPos,3
return
colon:
lcdout $fe,$80+nPos,$A5
lcdout $FE,$C0+nPos,$A5
return
;---------------------------------------------------------------------------
BigClockClear:
LCDOut $FE, 1 ;Clear original full data screen
marker = 1 ;set marker for fullscreen clock loop
'Set up the digits (http://www.darreltaylor.com/files/CustChar.htm)
'THICK DIGITS
LCDOUT $FE,$40,$07,$07,$07,$07,$07,$07,$07,$07 ' Cust Char #0
LCDOUT $FE,$48,$1C,$1C,$1C,$1C,$1C,$1C,$1C,$1C ' Cust Char #1
LCDOUT $FE,$50,$0F,$1F,$1F,$1E,$1C,$1C,$1C,$1C ' Cust Char #2
LCDOUT $FE,$58,$1E,$1F,$1F,$0F,$07,$07,$07,$07 ' Cust Char #3
LCDOUT $FE,$60,$1C,$1C,$1C,$1C,$1E,$1F,$1F,$0F ' Cust Char #4
LCDOUT $FE,$68,$07,$07,$07,$07,$0F,$1F,$1F,$1E ' Cust Char #5
LCDOUT $FE,$70,$1F,$1F,$1F,$00,$00,$00,$00,$00 ' Cust Char #6
LCDOUT $FE,$78,$00,$00,$00,$00,$00,$1F,$1F,$1F ' Cust Char #7
;#############################################################################################
GPS2:
HSerIn Timeout,Clock,[wait("$GPRMC"),wait(","),DEC2 hh,DEC2 mm,DEC2 ss]
;##############################################################################################
BUTTON Pbutton,0,100,0,butt,1,ClockClear ;button press to change back to full info display
BigClock: ;Display Big Digit fullscreen clock
nDig=ss dig 0 : nPos=17 : gosub displaydigit1
nDig=ss dig 1 : nPos=14 : gosub displaydigit1
npos=13 : gosub colon
ndig=mm dig 0 : npos=10 : gosub displaydigit1
ndig=mm dig 1 : npos=7 : gosub displaydigit1
npos=6 : gosub colon1
ndig=hh dig 0 : npos=3 : gosub displaydigit1
ndig=hh dig 1 : npos=0 : gosub displaydigit1
GOTO GPS2
displaydigit1:
if ndig=0 then gosub Zero1
if ndig=1 then gosub One1
if ndig=2 then gosub Two1
if ndig=3 then gosub Three1
if ndig=4 then gosub Four1
if ndig=5 then gosub Five1
if ndig=6 then gosub Six1
if ndig=7 then gosub Seven1
if ndig=8 then gosub Eight1
if ndig=9 then gosub Nine1
return
Zero1:
LCDOUT $FE,$80+nPos,2
LCDOUT $FE,$81+nPos,3 ;note added 1 to position for right side of character
LCDOUT $FE,$C0+nPos,1
LCDOUT $FE,$C1+nPos,0 ;note added 1
LCDOUT $FE,$94+nPos,1
LCDOUT $FE,$95+nPos,0 ;note added 1
LCDOUT $FE,$D4+nPos,4
LCDOUT $FE,$D5+nPos,5 ;note added 1
return
One1:
LCDOUT $FE,$80+nPos," "
LCDOUT $FE,$81+nPos,0
LCDOUT $FE,$C0+nPos," "
LCDOUT $FE,$C1+nPos,0
LCDOUT $FE,$94+nPos," "
LCDOUT $FE,$95+nPos,0
LCDOUT $FE,$D4+nPos," "
LCDOUT $FE,$D5+nPos,0
return
Two1:
LCDOUT $FE,$80+nPos,6
LCDOUT $FE,$81+nPos,3
LCDOUT $FE,$C0+nPos,7
LCDOUT $FE,$C1+nPos,5
LCDOUT $FE,$94+nPos,1
LCDOUT $FE,$95+nPos," "
LCDOUT $FE,$D4+nPos,4
LCDOUT $FE,$D5+nPos,7
return
Three1:
LCDOUT $FE,$80+nPos,6
LCDOUT $FE,$81+nPos,3
LCDOUT $FE,$C0+nPos,7
LCDOUT $FE,$C1+nPos,5
LCDOUT $FE,$94+nPos," "
LCDOUT $FE,$95+nPos,3
LCDOUT $FE,$D4+nPos,7
LCDOUT $FE,$D5+nPos,5
return
Four1:
LCDOUT $FE,$80+nPos,1
LCDOUT $FE,$81+nPos," "
LCDOUT $FE,$C0+nPos,4
LCDOUT $FE,$C1+nPos,7
LCDOUT $FE,$94+nPos," "
LCDOUT $FE,$95+nPos,1
LCDOUT $FE,$D4+nPos," "
LCDOUT $FE,$D5+nPos,1
return
Five1:
LCDOUT $FE,$80+nPos,2
LCDOUT $FE,$81+nPos,6
LCDOUT $FE,$C0+nPos,1
LCDOUT $FE,$C1+nPos," "
LCDOUT $FE,$94+nPos,6
LCDOUT $FE,$95+nPos,3
LCDOUT $FE,$D4+nPos,7
LCDOUT $FE,$D5+nPos,5
return
Six1:
LCDOUT $FE,$80+nPos,2
LCDOUT $FE,$81+nPos,6
LCDOUT $FE,$C0+nPos,1
LCDOUT $FE,$C1+nPos," "
LCDOUT $FE,$94+nPos,2
LCDOUT $FE,$95+nPos,3
LCDOUT $FE,$D4+nPos,4
LCDOUT $FE,$D5+nPos,5
return
Seven1:
LCDOUT $FE,$80+nPos,6
LCDOUT $FE,$81+nPos,3
LCDOUT $FE,$C0+nPos," "
LCDOUT $FE,$C1+nPos,0
LCDOUT $FE,$94+nPos," "
LCDOUT $FE,$95+nPos,0
LCDOUT $FE,$D4+nPos," "
LCDOUT $FE,$D5+nPos,0
return
Eight1:
LCDOUT $FE,$80+nPos,2
LCDOUT $FE,$81+nPos,3
LCDOUT $FE,$C0+nPos,4
LCDOUT $FE,$C1+nPos,5
LCDOUT $FE,$94+nPos,2
LCDOUT $FE,$95+nPos,3
LCDOUT $FE,$D4+nPos,4
LCDOUT $FE,$D5+nPos,5
return
Nine1:
LCDOUT $FE,$80+nPos,2
LCDOUT $FE,$81+nPos,3
LCDOUT $FE,$C0+nPos,4
LCDOUT $FE,$C1+nPos,5
LCDOUT $FE,$94+nPos," "
LCDOUT $FE,$95+nPos,0
LCDOUT $FE,$D4+nPos,7
LCDOUT $FE,$D5+nPos,5
return
colon1:
lcdout $fe,$C0+nPos,$A5
lcdout $FE,$94+nPos,$A5
return
Hi Darrel,
Hmmm, looking at the various timings I don't see how this can be done.
The NMEA string is output at the same point, the epoch of the PPS pulse, so the code is executing the string read when it also needs to start to display the 'advanced' time.
As I see it at the moment, the code reads the gps string, then parses it, saving each piece to the assigned variable and runs the subroutines before initiating the display.
As a test, I added two seconds to the seconds variable. Then comparing against a radio time signal it was almost the same. I say almost as it is not quite two seconds out in code execution.
I suppose I could add a suitable pause value and bring it inline but I would have to test the offset, if any, over a period of operation. This assumes code execution always takes the same time to execute.
Any ideas would be welcome.
Hi Rob,
I haven't been following this thread in detail so I apolgize if I'm suggesting something that's already been covered or isn't doable for whatever reason.
Looking at the code you posted, and as you mentioned, you spend quite a bit of time in the ISR. I have two questions/suggestions.
A) Why do you need to reload the custom characters each time? Wouldn't it be better to load them once at startup?
B) Can't you simply set a flag in the ISR (ie UpdateDisplay = 1) which you then poll in the main loop? If the flag is set you update the display and reset the flag.
Obviously there must be enough clock cycles between interrupts to do whatever needs to be done - no matter "where" it's being done (inside or out of the ISR).
Doing (B) above you basically can't have the HSERIN statement within the main loop as it will "block" the processor for up to TimeOut ms (2000 in the code as posted). What you'd need to do is either introduce UART interrupt or simply poll the UART RX interrupt flag within the mainloop (provided the mainloop is "tight" enough to not overflow the UART receive buffer (2 bytes).
Yes and no. It doesn't read, then parses it. HSERIN is parsing the string as the bytes comes in, one by one. If it didn't do that you'd have to have a recieve buffer as big as the complete NMEA string. But again, the code in your ISR takes considerable amount of time and it's quite possible that if an interrupt occurs in the middle of the HSERIN statment (quite possible) the ISR is stealing too much time so the the receive buffer (2 bytes) overruns and HSERIN "gets lost".Quote:
As I see it at the moment, the code reads the gps string, then parses it,
At 4800 baud each byte is a about 2ms long so if your ISR takes more than 4ms to execute it will most definitely cause issues for the HSERIN. Seeing all those LCDOUT statements within the ISR and the subroutines it calls makes me think your ISR runs way up into the tens of ms.
/Henrik.
Hi Henrik,
Quite a bit to digest there. Good food for thought. Thanks.
I missed the fact that the custom characters for the medium digits was constantly loading in the loop. I've moved that to the beginning now out of the loop, it is loaded at start up.
The BigDigit clock did only load it's characters once then entered it's own loop, so that's taken care of.
The main problem as I see it is that the gps string start occurs at the same time as the 'seconds' rise point. In the gps module the start of the rise of the PPS also triggers the NMEA string output. In other words the seconds epoch occurs for both. I don't know if it's possible to receive the string and trigger the display code at the same time. I was just trying to get to a more accurate time.
The time is very close now anyway allowing for code run timing. I could add a small pause to bring it closer I suppose.
Hi Rob,
More thoughts.....
Since, if I'm not mistaken, the time is parsed from the NMEA string using the PPS signal to initiate a display update will update the display with the time information from the last received string which is basically one second "old". I think that the best you can do really is to simply grab and parse the string and then update the display.
If you're receiving the full 82byte NMEA string that will take ~170ms, add the actual display update code to that - you'll be a couple of hundred ms off.
/Henrik.
Hi Henrik,
I've been doing some more reading regarding the NMEA string from the Rockwell datasheets. (19 pages in one 142 in other !)
I've discovered two choice bits.
(1.) The string is always after the event, so is 1 second late as you said.
(2.) Standard laid down for time this way is up to +/- .9 seconds regardless of (1.) above.
Rockwell do a binary protocol at 9600 baud which is 'message' driven. So you can actually poll for time separately with far more accuracy but it would require a complete code rewrite.
I'm trying to keep code tight in the BigClock sub which only reads the h, m, s, part of string. This is at beginning of the string anyway. I update in reverse to display, s m h.
At the moment I've added 2 seconds before display and with the other code changes, it's as near as I can see visually using the PPS LED. It is almost on the PPS event. That is near enough for me. Checking against MSF radio time signal using Spectrum Lab software, it's very close.
Visually humans can discern a 250ms difference, so as I can hardly see any difference, it should be closer than 250ms diff.
I could load the output into SpecLab to compare both signals I suppose. I may eventually do that anyway as I'm curious to what the code timing is.
I have the frequency lock part spot on, so it would be nice to get the time part as well, but I don't think its possible.
For my sins, in my other life I am an official timekeeper, timing to hundredths of a second. I can see '100ths differences there ok :)
Amazing really how many times a day I see exactly the same time to the hundreth of a second, two competitors achieve.
Another idea, but I suspect will gain nothing is :-
Read string full time once at start up.
Display
loop:
Then read only seconds.
Increment software clock s m h
update display
loop
String read would be very quick. Approx 20ms.
EDIT:
Just realised that at 20ms I would have read h m s anyway, so pseudo code above is pointless.
Dear all,
first of all i would like to congrats the work have been done in this post.
I would also like to inform you once again that im not a programmer. So my knowledge at programming is really low.
I try to setup as a hobby a gps and project the info to ulcd that i have many years at my small lab.
Here is the code up to now:
What i would like to do is to display:Code:@ ERRORLEVEL -306 ; this command prevents the compiler to give you a notice of
; crossing page boundary - make sure bits are set
PORTB = 0
input portb.0
; -----[ Variables ]-------
PWRLED var PORTb.1 ; this shows that the initialization is finished
LCD var PORTb.2 ; to LCD operation
GPS_TX var PORTb.0 ; info from GPS
GPS_RX var PORTb.4 ; COMMANDS TO GPS, this feature is not
Testled var PORTb.5 ;ill try to use this when GPS module find signal
pause 2000
' -----[ Variables ]-------------------------------------------------------
' $GPRMC,090045.000,A,3823.6645,N,02353.3600,E,0.02,195.80,170518,,,A*62
' $GNGGA,140405.000,3823.6010,N,02353.3054,E,1,9,0.88,0.8,M,35.9,M,,*40
hh var byte 'hours
mm var byte 'minutes
ss var byte 'seconds
sss var word 'milisecs
degrees VAR BYTE 'latitude/longitude degrees
minutes VAR BYTE 'latitude/Longitude minutes
minutesD VAR word 'latitude/LONGITUDE DECIMAL MINUTES
dir VAR BYTE ' direction (latitude: 0 = N, 1 = S / longitude: 0 = E, 1 = W)
degrees2 VAR BYTE 'latitude/longitude degrees
minutes2 VAR BYTE 'latitude/Longitude minutes
minutesD2 VAR word 'latitude/LONGITUDE DECIMAL MINUTES
dir2 var byte ;direction (latitude: 0 = N, 1 = S / longitude: 0 = E, 1 = W)
SatNo VAR BYTE 'number of satellites connected
knots var word 'speed over ground
knots2 var byte 'speed over ground
course var word 'course
course2 var byte 'course
day var byte 'day
month var byte 'month
year var byte 'year
i var word
GNRMC var word
GNGGA var WORD
FIX var word
Modefix var byte
horizon var byte
precision var byte
meter var byte
METERS var byte
Meters2 var byte
' ----------------- [ Initialization ]----------------------
serout2 LCD,32,[$55] ' uOLED Initialize
pause 2000
serout2 lcd,32,[$56,$01]
pause 1000
serout2 lcd,32,[$45]
pause 500
serout2 lcd,32,[$55]
pause 500
serout2 lcd,32,[$45]
pause 500
serout2 lcd,32,[$73,$00,$03,$11,$ff,$ff," Leonardo Bilalis",$00]
pause 200
serout2 lcd,32,[$73,$02,$06,$10,$ff," Copyright 2018",$00]
pause 3000
serout2 lcd,32,[$45]
pause 1000
serout2 lcd,32,[$73,$02,$06,$10,$ff,$ff," GPS.........",$00]
pause 500
serout2 lcd,32,[$45]
pause 200
HIGH pwrled
'-------------------- [MAIN] ------------------------------
Main:
;$GPRMC,090045.000,A,3823.6645,N,02353.3600,E,0.02,195.80,170518,,,A*62
serin2 gps_tx,84,[wait("$GNRMC"),_ ;we wait for $GNRMC
wait(","),dec2 hh,dec2 mm,dec2 ss,wait("."),dec3 sss,_ ;we wait for 090045.000
wait(","),fix,_ ;we wait for A
wait(","),dec2 degrees,dec2 minutes,wait("."),dec4 minutesd,_ ;we wait for 3823.6645
wait(","),dir,_ ;we wait for N
wait(","),dec3 degrees2,dec2 minutes2,wait("."),dec4 minutesd2,_;we wait for 02353.3600
wait(","),dir2,_ ;we wait for E
wait(","),dec knots,wait("."),dec2 knots2,_ ;we wait for 0.02
wait(","),dec3 course,wait("."),_ ;we wait for 195.80
wait(","),dec2 day,dec2 month,dec2 year] ;we wait for 170518
pause 100
;$GNGGA,140405.000,3823.6010,N,02353.3054,E,1,9,0.88,0.8,M,35.9,M,,*40
serin2 gps_tx,84,[wait("$GNGGA"),_
wait(","),dec2 hh,dec2 mm,dec2 ss,wait("."),dec3 sss,_
wait(","),dec2 degrees,dec2 minutes,wait("."),dec4 minutesd,_
wait(","),dir,_
wait(","),dec3 degrees2,dec2 minutes2,wait("."),dec4 minutesd2,_
wait(","),dir2,_
wait(","),modefix,_
wait(","),dec2 satno,_
wait(","),dec3 horizon,dec precision,_
wait(","),meter,dec2 METERS,dec Meters2]
pause 100
serout2 lcd,32,[$73,$03,$00,$00,$ff,$ff,"Protocol:",dec5 GNRMC,$00] ; THIS IS NOT WORKING
pause 200
serout2 lcd,32,[$73,$00,$02,$00,$ff,$ff,"Date:",dec2 day,dec2 month,dec2 year,$00] ; THIS IS NOT WORKING
pause 200
serout2 lcd,32,[$73,$00,$04,$00,$ff,$ff,"TIME: ",dec2 hh+3," :",dec2 mm," :",dec2 ss,$00]
pause 200
serout2 lcd,32,[$73,$00,$06,$00,$ff,$ff,"Satellites:",dec2 satno," ","Fixed:",fix,$00]
pause 200
serout2 lcd,32,[$73,$00,$08,$00,$ff,$ff,"Lat : ",dec2 degrees,dec2 minutes,".",dec4 minutesd," ",dir,$00]
pause 200
serout2 lcd,32,[$73,$00,$0A,$00,$ff,$ff,"Lon : ",dec3 degrees2,dec2 minutes2,".",dec4 minutesd2," ",dir2,$00]
pause 200
serout2 lcd,32,[$73,$00,$0C,$00,$ff,$ff,"GND SPEED : ",dec knots*1852/1000,".",dec2 knots2,$00]
pause 200
serout2 lcd,32,[$73,$00,$0E,$00,$ff,$ff,"Meters : ",dec2 METERS,dec Meters2,$00] ; THIS IS NOT WORKING
pause 5000
serout2 lcd,32,[$45]
pause 100
goto main
if fix = "V" then notfix
notfix:
serout2 lcd,32,[$73,$00,$03,$11,$ff,$ff," Waiting for GPS",$00]
pause 100
serout2 lcd,32,[$73,$02,$06,$10,$ff," Copyright 2018",$00]
pause 1000
serout2 lcd,32,[$45]
pause 200
goto main
'-------------------- [ CLEAR ] -----------------------------
Clearlcd:
serout2 lcd,32,[$45]
pause 500
RETURN
Protocol : GNRMC
DATE :
TIME :
Satellites:
LAT :
LON :
GND SPEED:
METERS:
I have the following problem.
1. Cannot display the DATE. Something is wrong at my code and there is not proper display of the date.
2. I have put a loop for display all the factors, because i need to clear the LCD every time something is change. So please could you help me understand how could i manage to display the factors and only change on the fly the ones really going like Time, LAT, LON, GND SPEED, SATs etc.
3. The Protocol command is not working
4. The speed is not working properly, i think i need to do better the conversion
5. The meters are not displaying, there is a wrong value in there.
6. I need to convert the measurements from the NMEA message LAT and LON to google numbers.
Please check what i have done till now in order for me to understand what it is needed.
Attachment 8661
Attachment 8662
Attachment 8663
Attachment 8664
Attachment 8665
Attachment 8666
Attachment 8667
I have updated a little bit the code so when there is a no data at portb.0 to have a notice.
but still i need to fix the following. Is there any advise?
1. Cannot display the DATE. Something is wrong at my code and there is not proper display of the date.
2. I have put a loop for display all the factors, because i need to clear the LCD every time something is change. So please could you help me understand how could i manage to display the factors and only change on the fly the ones really going like Time, LAT, LON, GND SPEED, SATs etc.
3. The Protocol command is not working
4. The speed is not working properly, i think i need to do better the conversion
5. The meters are not displaying, there is a wrong value in there.
6. I need to convert the measurements from the NMEA message LAT and LON to google numbers.
Code:'* Author : LEONARDO BILALIS *
'* Notice : Copyright (c) 2018 [LEONARDOS BILALIS] *
'* : All Rights Reserved *
'* Date : 12/5/2018 *
'* Version : 1.0 *
'* Notes : This is an GPS with ulcd *
'* : *
'****************************************************************
@ ERRORLEVEL -306 ; this command prevents the compiler to give you a notice of
; crossing page boundary - make sure bits are set
;& __config _HS_OSC & _WDT_ON & _LVP_OFF & _CP_OFF
Include "MODEDEFS.BAS"
DEFINE OSC 8
OSCCON=%01111000 '8 Mhz
CMCON = 7 'turn comparators off
ANSEL = 0 'All digital
PORTB = 0 'make low all ports at B range
input portb.0 'make input portb.0
'----------------------------------------------------------------------------/
' [ PIC Variables ] /
'--------------------------------------------------------------------------/
PWRLED var PORTb.1 ; this shows that the initialization is finished
LCD var PORTb.2 ; to LCD operation
GPS_TX var PORTb.0 ; info from GPS
GPS_RX var PORTb.4 ; COMMANDS TO GPS
Testled var PORTb.5
dots var byte
dots=8
countremain var byte ; we use a countremain to check the incoming from portb.0
pause 1000
' --------------------[ GPS Variables for NMEA sentenses ]---------------------/
' /
' $GPRMC,090045.000,A,3823.6645,N,02353.3600,E,0.02,195.80,170518,,,A*62 /
' $GNGGA,140405.000,3823.6010,N,02353.3054,E,1,9,0.88,0.8,M,35.9,M,,*40 /
' /
'-------------------------------------------------------------------------/
hh var byte 'hours
mm var byte 'minutes
ss var byte 'seconds
sss var word 'milisecs
degrees VAR BYTE 'latitude/longitude degrees
minutes VAR BYTE 'latitude/Longitude minutes
minutesD VAR word 'latitude/LONGITUDE DECIMAL MINUTES
dir VAR BYTE ' direction (latitude: 0 = N, 1 = S / longitude: 0 = E, 1 = W)
degrees2 VAR BYTE 'latitude/longitude degrees
minutes2 VAR BYTE 'latitude/Longitude minutes
minutesD2 VAR word 'latitude/LONGITUDE DECIMAL MINUTES
dir2 var byte ;direction (latitude: 0 = N, 1 = S / longitude: 0 = E, 1 = W)
SatNo VAR BYTE 'number of satellites connected
knots var word 'speed over ground
knots2 var byte 'speed over ground
course var word 'course
course2 var byte 'course
day var byte 'day
month var byte 'month
year var byte 'year
i var word
GNRMC var word 'protocol
GNGGA var WORD 'protocol
FIX var word 'fix sat V/A
Modefix var byte 'mode fix 1 or 2 or 3 depens
horizon var byte
precision var byte
meter var byte
METERS var byte
Meters2 var byte
' -------------------------------------------------------------------------/
' [ LCD Initialization ] /
'------------------------------------------------------------------------/
serout2 LCD,32,[$55] ' uOLED Initialize
pause 2000
serout2 lcd,32,[$56,$01]
pause 1000
serout2 lcd,32,[$45] ' clear the lcd
pause 500
serout2 lcd,32,[$55]
pause 500
serout2 lcd,32,[$45] ' clesr the lcd
pause 500
serout2 lcd,32,[$73,$00,$03,$11,$ff,$ff," Leonardo Bilalis",$00]
pause 200
serout2 lcd,32,[$73,$02,$06,$10,$ff," Copyright 2018",$00]
pause 3000
serout2 lcd,32,[$45]
pause 1000
serout2 lcd,32,[$73,$02,$06,$10,$ff,$ff," GPS.........",$00]
pause 500
serout2 lcd,32,[$45]
pause 200
'----------------------------------------------------------------------/
' [ After the lcd initialization we power the Led at PIC ] /
'--------------------------------------------------------------------/
HIGH pwrled
'-------------------------------------------------------------------/
' [MAIN Program] /
'-----------------------------------------------------------------/
Main:
;gosub clearlcd
serin2 gps_tx,84,[countremain] ; we check what is coming from the port
if countremain = 0 then lostcable ; if nothing is coming the we check the cable
;gosub clearlcd
'-------------------------------------------------------------------------------/
' /
' [ Example NMEA Sentense of GNRMC ] /
' [$GNRMC,090045.000,A,3823.6645,N,02353.3600,E,0.02,195.80,170518,,,A*62] /
' /
'--------------------------------------------------------------------------/
serin2 gps_tx,84,[wait("$GNRMC"),_ ;we wait for $GNRMC
wait(","),dec2 hh,dec2 mm,dec2 ss,wait("."),dec3 sss,_ ;we wait for 090045.000
wait(","),fix,_ ;we wait for A
wait(","),dec2 degrees,dec2 minutes,wait("."),dec4 minutesd,_ ;we wait for 3823.6645
wait(","),dir,_ ;we wait for N
wait(","),dec3 degrees2,dec2 minutes2,wait("."),dec4 minutesd2,_;we wait for 02353.3600
wait(","),dir2,_ ;we wait for E
wait(","),dec knots,wait("."),dec2 knots2,_ ;we wait for 0.02
wait(","),dec3 course,wait("."),_ ;we wait for 195.80
wait(","),dec2 day,dec2 month,dec2 year] ;we wait for 170518
pause 100
'------------------------------------------------------------------------------/
' /
' [ Example NMEA Sentense of GNGGA ] /
' [$GNGGA,140405.000,3823.6010,N,02353.3054,E,1,9,0.88,0.8,M,35.9,M,,*40 /
' /
'-------------------------------------------------------------------------/
serin2 gps_tx,84,[wait("$GNGGA"),_
wait(","),dec2 hh,dec2 mm,dec2 ss,wait("."),dec3 sss,_
wait(","),dec2 degrees,dec2 minutes,wait("."),dec4 minutesd,_
wait(","),dir,_
wait(","),dec3 degrees2,dec2 minutes2,wait("."),dec4 minutesd2,_
wait(","),dir2,_
wait(","),modefix,_
wait(","),dec2 satno,_
wait(","),dec3 horizon,dec precision,_
wait(","),meter,dec2 METERS,dec Meters2]
pause 100
'---------------------------------------------------------------------------------/
' Here if the GPS module havent been fixed to any satellite will jump to notfix /
'-------------------------------------------------------------------------------/
if fix = "V" then notfix
pause 100
'-----------------------------------------------------------------------------/
' [ Return from notfix ] /
' [ We clear any character on the display ] /
'--------------------------------------------------------------------------/
gosub clearlcd
;serout2 lcd,32,[$45]
;pause 500
'--------------------------------------------------------------------------/
' here is where the code dispays the stored info from the NMEA sentenses /
'------------------------------------------------------------------------/
serout2 lcd,32,[$73,$03,$00,$00,$ff,$ff,"Protocol:",dec5 GNRMC,$00]
pause 100
serout2 lcd,32,[$73,$00,$02,$00,$ff,$ff,"Date:",dec2 day,dec2 month,dec2 year,$00]
pause 100
serout2 lcd,32,[$73,$00,$04,$00,$ff,$ff,"TIME: ",dec2 hh+3," :",dec2 mm," :",dec2 ss,$00]
pause 100
serout2 lcd,32,[$73,$00,$06,$00,$ff,$ff,"Satellites:",dec2 satno," ","Fixed:",fix,$00]
pause 100
serout2 lcd,32,[$73,$00,$08,$00,$ff,$ff,"Lat : ",dec2 degrees,dec2 minutes,".",dec4 minutesd," ",dir,$00]
pause 100
serout2 lcd,32,[$73,$00,$0A,$00,$ff,$ff,"Lon : ",dec3 degrees2,dec2 minutes2,".",dec4 minutesd2," ",dir2,$00]
pause 100
;serout2 lcd,32,[$73,$00,$0C,$00,$ff,$ff,"GND SPEED : ",(dec knots,".",dec2 knots2)*/1.852,$00]
;pause 200
serout2 lcd,32,[$73,$00,$0E,$00,$ff,$ff,"Meters : ",dec2 METERS,dec Meters2,$00]
pause 3000
serout2 lcd,32,[$45] ' clears the LCD
pause 100
goto main
'-----------------------------------------------------------------------------/
' [ SUB ROUTINES ] /
'---------------------------------------------------------------------------/
notfix: ' Still looking for fixed signal
serout2 lcd,32,[$73,$00,$03,$11,$ff,$ff," Waiting for GPS",$00]
pause 100
serout2 lcd,32,[$73,$03,$06,$10,$ff," Time:",dec2 hh+3," :",dec2 mm," :",dec2 ss,$00]
pause 1000
serout2 lcd,32,[$73,$03,$08,$10,$ff,rep "."\dots,$00]
pause 200
serout2 lcd,32,[$45] ' clears the LCD
pause 100
goto main 'returns to main
lostcable:
serout2 lcd,32,[$73,$00,$03,$11,$ff,$ff," Connection lost",$00]
pause 100
serout2 lcd,32,[$73,$01,$06,$10,$ff," Please check cable",$00]
pause 2000
serout2 lcd,32,[$45] ' clears the LCD
pause 100
goto main
'---------------------------------------------------------------------------/
' [ CLEAR LCD ] /
'-------------------------------------------------------------------------/
Clearlcd:
serout2 lcd,32,[$45]
pause 100
RETURN
first off , what has your post got to do with maidenhead ? why not start a new relevant post instead of confusing this one
secondly posting figures as pictures makes life difficult for anyone inclined to assist
in you google numbers query (which is really deg ,min, sec conversion to decimal degrees )
how did you get 38 + 2/60 + 3.49/3600 = 38.034297
my calculator says 38.0343027 ps (in 32 bit float result is 38.0343018, with 64 bit float 38.0343028)done on pic24f using xc16
you will have fun trying to get math accurate to 10 significant digits on that chip [even 32 bit floats struggle]
your best bet is nbit math
the decimal portion can be :-
mins *1000000/6 + sec *1000/36
parsing the nmea sentences is well covered but you may be interested in this
http://support.melabs.com/forum/picb...strtok-usercmd
a strtok function for pbp
parsing strings with spaghetti code will always by a shortcut to madness
Hi richard,
1) i did post in here because i was planning to do that conversion as well on next step. But i cant simply display the date, so my knowledge wont be able to do any further
2) pictures i believe always help.
3) you are right on the calculation 38.0343027. I did something wrong in there.
4) if Parsing NMEA is ok then why Date is not displaying right? I will check once again what i have done on the code.
5) i will check the link and the strtok. But i find easier the way i did it because i understand it.
as i said im not a programmer. This code might be simple for you, but is too much for me. I try to do things stwp by step on this code. There are lots of bugs and mistakes which at the moment cant solve.
i found a small mistake on the first parsing code. i have forgot a sentence which may cause the problem displaying date.
Will keep you update.
i though i found the mistake on the first code for parsing
i did complete the sentenseCode:' /
' [ Example NMEA Sentense of GNRMC ] /
' [$GNRMC,090045.000,A,3823.6645,N,02353.3600,E,0.02,195.80,170518,,,A*62] /
' /
'--------------------------------------------------------------------------/
serin2 gps_tx,84,[wait("$GNRMC"),_ ;we wait for $GNRMC
wait(","),dec2 hh,dec2 mm,dec2 ss,wait("."),dec3 sss,_ ;we wait for 090045.000
wait(","),fix,_ ;we wait for A
wait(","),dec2 degrees,dec2 minutes,wait("."),dec4 minutesd,_ ;we wait for 3823.6645
wait(","),dir,_ ;we wait for N
wait(","),dec3 degrees2,dec2 minutes2,wait("."),dec4 minutesd2,_;we wait for 02353.3600
wait(","),dir2,_ ;we wait for E
wait(","),dec knots,wait("."),dec2 knots2,_ ;we wait for 0.02
wait(","),dec3 course,wait("."),_ ;we wait for 195.80
wait(","),dec2 day,dec2 month,dec2 year] ;we wait for 170518
pause 100
but still next line which is the date is not dispayed right.Code:wait(","),dec3 course,wait("."),dec2 course2,_ ;we wait for 195.80
ok the date is displayed. But sometimes it looks like that missing the date code and displays 00/here a 2 digit number/00, then it comes back to the right date.
this is how I would go about parsing nmea, for what you are doing there is little point in storing all the data just to display it
only store what is needed for calculations or enhanced display.
I would also read in the entire nmea sentence using $ ast the start marker and * as the end marker.
when you have a complete sentence send it off for parsing if its the correct sentence type
Code:'****************************************************************
'* Name : NOKIA_DEMO.PBP *
'* Author : richard *
'* Notice : *
'* : *
'* Date : 16/5/2018 *
'* Version : mssp1 version with bigtxt *
'* Notes : *
'* :FOR pic 16F1847@32MHZ NOKIA *
'****************************************************************
#CONFIG ; 16FF1847.
__config _CONFIG1, _FOSC_INTOSC & _WDTE_ON & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _BOREN_OFF
__config _CONFIG2, _PLLEN_OFF & _LVP_OFF
#ENDCONFIG
define OSC 32
; --- *** Oscillator *** ---------------------------------------------------
OSCCON = %11110000 ;32 MHz,
ANSELb = 0
ANSELA = 0
TRISA=%10010000
TRISB=%11101011
ch var byte
BUFF VAR BYTE [16]
;DEFINES FOR DISPLAY use font7x5_16.bas or font7x5_18.bas for pic18
#DEFINE PIC16 1
#define use_mssp 1
lcdheight con 5 ; 6 PAGES
lcdwidth con 83 ; 84 PIXELS WIDE
' LCD_CLK var LATB.4 ' SCK1 pin needs to be set as dig o/p
' LCD_DIN var LATB.2 ' SDO1 pin needs to be set as dig o/p
LCD_RST var LATA.4
LCD_DC var LATA.3
LCD_CE var LATA.6
LCD_LIGHT var LATA.0
nmea var byte[80]
h var byte
m var byte
s var byte
Include "nokia_ds.INC" ' bring it in
include "font7x5_16.bas"
@ #DEFINE TOKEN_DESTROY 1
include "strtok.pbpmod"
'========================== MAIN Routine ==============================
gosub lcd_init
LCDCLR
ARRAYWRITE BUFF,["READY",0]
LCDSTR 5,0,BUFF
PAUSE 1000
LCDCLR
looper:
'start=$ end=*
arraywrite nmea,["GNRMC,090045.000,A,3823.6645,N,02353.3600,E,0.02,195.80,170518,,,A",0]
;STRLEN nmea
strtok nmea,0,","
LCDSTR 0,0,nmea ;sentence type
strtok nmea
ARRAYREAD nmea ,[SKIP (STRTOK_INX-STRTOK_LEN),dec2 h,dec2 m,dec2 s]
arraywrite buff,[dec2 h,":",dec2 m,":",dec2 s,0]
LCDSTR 36,0,BUFF
strtok nmea ;fix
strtok nmea ;fix
arraywrite buff,["lon",0]
LCDSTR 0,1,BUFF
ARRAYREAD nmea ,[SKIP (STRTOK_INX-STRTOK_LEN),str buff\16]
LCDSTR 20,1,buff
strtok nmea
ARRAYREAD nmea ,[SKIP (STRTOK_INX-STRTOK_LEN),str buff\16]
LCDSTR 77,1,buff
strtok nmea
arraywrite buff,["lt",0]
LCDSTR 0,2,BUFF
ARRAYREAD nmea ,[SKIP (STRTOK_INX-STRTOK_LEN),str buff\16]
LCDSTR 13,2,buff
strtok nmea
ARRAYREAD nmea ,[SKIP (STRTOK_INX-STRTOK_LEN),str buff\16]
LCDSTR 77,2,buff
strtok nmea
arraywrite buff,["speed",0]
LCDSTR 0,3,BUFF
ARRAYREAD nmea ,[SKIP (STRTOK_INX-STRTOK_LEN),str buff\16]
LCDSTR 36,3,buff
strtok nmea
arraywrite buff,["hdg",0]
LCDSTR 0,4,BUFF
ARRAYREAD nmea ,[SKIP (STRTOK_INX-STRTOK_LEN),str buff\16]
LCDSTR 36,4,buff
strtok nmea
ARRAYREAD nmea ,[SKIP (STRTOK_INX-STRTOK_LEN),dec2 h,dec2 m,dec2 s]
arraywrite buff,[dec2 h,"/",dec2 m,"/",dec2 s,0]
LCDSTR 36,5,BUFF
END
and to emphasize the advantage of an algorithmic approach over spaghetti code
Code:'****************************************************************
'* Name : NOKIA_DEMO.PBP *
'* Author : richard *
'* Notice : *
'* : *
'* Date : 16/5/2018 *
'* Version : mssp1 version with bigtxt *
'* Notes : *
'* :FOR pic 16F1847@32MHZ NOKIA *
'****************************************************************
#CONFIG ; 16FF1847.
__config _CONFIG1, _FOSC_INTOSC & _WDTE_ON & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _BOREN_OFF
__config _CONFIG2, _PLLEN_OFF & _LVP_OFF
#ENDCONFIG
define OSC 32
; --- *** Oscillator *** ---------------------------------------------------
OSCCON = %11110000 ;32 MHz,
ANSELb = 0
ANSELA = 0
TRISA=%10010000
TRISB=%11101011
ch var byte
BUFF VAR BYTE [16]
;DEFINES FOR DISPLAY use font7x5_16.bas or font7x5_18.bas for pic18
#DEFINE PIC16 1
#define use_mssp 1
lcdheight con 5 ; 6 PAGES
lcdwidth con 83 ; 84 PIXELS WIDE
' LCD_CLK var LATB.4 ' SCK1 pin needs to be set as dig o/p
' LCD_DIN var LATB.2 ' SDO1 pin needs to be set as dig o/p
LCD_RST var LATA.4
LCD_DC var LATA.3
LCD_CE var LATA.6
LCD_LIGHT var LATA.0
nmea var byte[80]
h var byte
m var byte
s var byte
Include "nokia_ds.INC" ' bring it in
include "font7x5_16.bas"
@ #DEFINE TOKEN_DESTROY 1
include "strtok.pbpmod"
'========================== MAIN Routine ==============================
gosub lcd_init
LCDCLR
ARRAYWRITE BUFF,["READY",0]
LCDSTR 5,0,BUFF
PAUSE 1000
LCDCLR
looper:
'start=$ end=*
arraywrite nmea,["GNRMC,090045.000,A,3823.6645,N,02353.3600,E,0.02,195.80,170518,,,A",0]
strtok nmea,0,","
ARRAYREAD nmea, 5, GNGGA,[wait("GNRMC")]
GOSUB SH_MSG
GOSUB SH_TIME
strtok nmea ;fix
GOSUB SH_LON
GOSUB SH_LAT
arraywrite buff,["speed",0]
LCDSTR 0,3,BUFF
ARRAYREAD nmea ,[SKIP (STRTOK_INX-STRTOK_LEN),str buff\16]
LCDSTR 36,3,buff
strtok nmea
arraywrite buff,["hdg",0]
LCDSTR 0,4,BUFF
ARRAYREAD nmea ,[SKIP (STRTOK_INX-STRTOK_LEN),str buff\16]
LCDSTR 36,4,buff
strtok nmea
ARRAYREAD nmea ,[SKIP (STRTOK_INX-STRTOK_LEN),dec2 h,dec2 m,dec2 s]
arraywrite buff,[dec2 h,"/",dec2 m,"/",dec2 s,0]
LCDSTR 36,5,BUFF
PAUSE 1000
GNGGA:
arraywrite nmea,["GNGGA,140405.000,3823.6010,N,02353.3054,E,1,9,0.88,0.8,M,35.9,M,,",0]
strtok nmea,0,","
ARRAYREAD nmea, 5, XXX,[wait("GNGGA")]
GOSUB SH_MSG
GOSUB SH_TIME
GOSUB SH_LON
GOSUB SH_LAT
strtok nmea
strtok nmea
strtok nmea
strtok nmea
strtok nmea
arraywrite buff,["M",0]
LCDSTR 28,5,BUFF
ARRAYREAD nmea ,[SKIP (STRTOK_INX-STRTOK_LEN),str buff\16]
LCDSTR 0,5,buff
PAUSE 1000
GOTO LOOPER
XXX:
LCDCLR
arraywrite buff,["Oops",0]
LCDSTR 0,1,BUFF
end
SH_MSG:
LCDSTR 0,0,nmea ;sentence type
strtok nmea
RETURN
SH_TIME:
ARRAYREAD nmea ,[SKIP (STRTOK_INX-STRTOK_LEN),dec2 h,dec2 m,dec2 s]
arraywrite buff,[dec2 h,":",dec2 m,":",dec2 s,0]
LCDSTR 36,0,BUFF
strtok nmea
RETURN
SH_LON:
arraywrite buff,["lon",0]
LCDSTR 0,1,BUFF
ARRAYREAD nmea ,[SKIP (STRTOK_INX-STRTOK_LEN),str buff\16]
LCDSTR 20,1,buff
strtok nmea
ARRAYREAD nmea ,[SKIP (STRTOK_INX-STRTOK_LEN),str buff\16]
LCDSTR 77,1,buff
strtok nmea
RETURN
SH_LAT:
arraywrite buff,["lt",0]
LCDSTR 0,2,BUFF
ARRAYREAD nmea ,[SKIP (STRTOK_INX-STRTOK_LEN),str buff\16]
LCDSTR 13,2,buff
strtok nmea
ARRAYREAD nmea ,[SKIP (STRTOK_INX-STRTOK_LEN),str buff\16]
LCDSTR 77,2,buff
strtok nmea
RETURN
Hi richard,
really appreciate your help. I will print out your post and code, because i need to understand it first.
Im a person that i understand something when i make notes and then i test my notes to see if i got it. Maybe this seems a bit stupid to others, but for me at the end works.
Thanks a lot once again.
Yesterday night i figured out that i need to correct TIME 24 hour, as im located on South of Europe --> Greece and we are +3 from UTC. So if it is 22:00 at UTC the time on display is +3....and shows 25.
Then i need to say also that as we are +3 from UTC, when the time at UTC is 21:00 here will be 00:00, so the code must also change the date. (at them moment DATE follows the UTC time)
Up to now i know what i have done with the code, even if it is wrong and even if there are lots of bugs. I'm happy at least i understand what i have done.
Hopefully the following days i will have good news.
this is what i get up to now on the display. But is not stable.
Attachment 8674
Date is loosing data sometimes and presents zeros.
My code refresh the display in order to get newer update on time, Sats, coordinates. Because i havent found the way to have always on the data and just refresh the digits need, for example the seconds.
i keep working on it.
i'm not surprised , given that :-Quote:
this is what i get up to now on the display. But is not stable.
not all nmea fields are filled in for every message
not all nmea fields are fixed length
I can't think of a more difficult way to approach this task than what you are trying to do.
I can't think of a more difficult to debug approach for this task than what you are trying to do
here is a snap of mine hooked to actual data, it has no trouble keeping up with the 4 or 5 messages
per second that the gps spits out
managed to snap the pic as the message type was updated so it a bit vague as to what its type is/was
and the lat/lon are bogus who would trust the internet these days
Im from mobile so i will Post a line of the code for the following question when i will be on computer.
I read the Data from the GPS, especially for the time and date.....
Serin2.....
Then i display the needed info......
Serout2......
What is the command to use inside the Serout2 in order to jump to a LABEL and Correct the UTC?
It will be useful if i understand the command inside the Serout2 that give me the access to jump to a LABEL.
One more question. I see most of You are using the HSERIN2, HSEROUT2,
And You Richard on your code are using the arrayread arraywrite.
I need to check the manual and see what is the difference between those.
ok i'm stack.
i place my code up to now. I dont want anyone to write a code for me, i just want from you to give me direction to solve my following problem.
I know i have many mistakes and maybe i aproach the code in a wrong way, in a difficult direction.
So one of my problems i would like to solve, is to give the right time, in 24H.
I have in mind that i need to use interrupts.
Is there any solution at the moment to use the SEROUT2 command
and jump at a label ???Code:serout2 lcd,32,[$73,$00,$04,$00,$FF,$E0," TIME: ",dec2 hh+3," :",dec2 mm," :",dec2 ss,$00]
pause 100
I would like first to solve time issue, even if i have to refresh/clear the display.....then my next problem to solve is to keep the data on the screen and replace only the numbers or characters needed to be change.Code:Plusthree:
hh = hh + 3
IF hh = 25 THEN hh = 0
RETURN
Following is the code up to now.
Code:'* Author : LEONARDO BILALIS *
'* Notice : Copyright (c) 2017 [LEONARDOS BILALIS] *
'* : All Rights Reserved *
'* Date : 24/5/2018 *
'* Version : 1.0 *
'* Notes : This is a GPS *
'* : *
'****************************************************************
@ ERRORLEVEL -306 ; this command prevents the compiler to give you a notice of
; crossing page boundary - make sure bits are set
@ __config _CONFIG1, _HS_OSC & _WDT_OFF & _LVP_OFF & _CP_OFF
Include "MODEDEFS.BAS"
DEFINE OSC 8
OSCCON=%01111000 '8 Mhz
CMCON = 7 'turn comparators off
ANSEL = 0 'All digital
PORTB = 0 'make low all ports at B range
input portb.0 'make input portb.0
'-----------------------------------------------------------------------------/
' [ ULCD 1'44 4D System ] /
'---------------------------------------------------------------------------/
' "o" degree character is manual created for degree value
'----------------------------------------------------------------------------/
' [ PIC Variables ] /
'--------------------------------------------------------------------------/
PWRLED var PORTb.1 ; this shows that the initialization is finished
LCD var PORTb.2 ; to LCD operation
GPS_TX var PORTb.0 ; info from GPS
GPS_RX var PORTb.4 ; COMMANDS TO GPS
Testled var PORTb.5
dots var byte
dots = 22
countremain var byte ; we use a countremain to check the incoming from portb.0
pause 1000
' --------------------[ GPS Variables for NMEA sentenses ]---------------------/
' /
' $GPRMC,090045.000,A,3823.6645,N,02353.3600,E,0.02,195.80,170518,,,A*62 /
' $GNGGA,140405.000,3823.6010,N,02353.3054,E,1,9,0.88,0.8,M,35.9,M,,*40 /
' /
'-------------------------------------------------------------------------/
Timeout con 2000
hh var byte 'hours
mm var byte 'minutes
ss var byte 'seconds
sss var word 'milisecs
degrees VAR BYTE 'latitude/longitude degrees
minutes VAR BYTE 'latitude/Longitude minutes
minutesD VAR word 'latitude/LONGITUDE DECIMAL MINUTES
dir VAR BYTE ' direction (latitude: 0 = N, 1 = S / longitude: 0 = E, 1 = W)
degrees2 VAR BYTE 'latitude/longitude degrees
minutes2 VAR BYTE 'latitude/Longitude minutes
minutesD2 VAR word 'latitude/LONGITUDE DECIMAL MINUTES
dir2 var byte ;direction (latitude: 0 = N, 1 = S / longitude: 0 = E, 1 = W)
SatNo VAR BYTE 'number of satellites connected
knots var word 'speed over ground
knots2 var byte 'speed over ground
course var word 'course
course2 var byte 'course
day var byte 'day
month var byte 'month
year var byte 'year
i var word
GNRMC var word 'protocol
GNGGA var WORD 'protocol
FIX var word 'fix sat V/A
Modefix var byte 'mode fix 1 or 2 or 3 depens
horizon var byte
precision var byte
meter var byte
METERS var byte
Meters2 var byte
marker2 var byte 'UTC OR GRT (GREEK TIME)
' -------------------------------------------------------------------------/
' [ LCD Initialization ] /
'------------------------------------------------------------------------/
serout2 LCD,32,[$55] ' uOLED Initialize
pause 2000
serout2 lcd,32,[$56,$01]
pause 1000
serout2 lcd,32,[$45] ' clear the lcd
pause 500
serout2 lcd,32,[$55]
pause 500
serout2 lcd,32,[$45] ' clesr the lcd
pause 500
serout2 lcd,32,[$73,$00,$03,$11,$ff,$ff," Leonardo Bilalis",$00]
pause 200
serout2 lcd,32,[$73,$02,$06,$10,$ff," Copyright 2018",$00]
pause 3000
serout2 lcd,32,[$45]
pause 1000
serout2 lcd,32,[$73,$02,$06,$10,$ff,$ff," GPS.........",$00]
pause 500
serout2 lcd,32,[$45]
pause 200
'----------------------------------------------------------------------/
' [ After the lcd initialization we power the Led at PIC ] /
'--------------------------------------------------------------------/
HIGH pwrled
'----------------------sent a centence to gps------------------------
;serout gps_rx,84,[$PMTK_103*30<CR><LF>]
pause 100
'-------------------------------------------------------------------/
' [MAIN Program] /
'-----------------------------------------------------------------/
Main:
;gosub clearlcd
serin2 gps_tx,84,[countremain] ; we check what is coming from the port
if countremain = 0 then lostcable ; if nothing is coming the we check the cable
;gosub clearlcd
'-------------------------------------------------------------------------------/
' /
' [ Example NMEA Sentense of GNRMC ] /
' [$GNRMC,090045.000,A,3823.6645,N,02353.3600,E,0.02,195.80,170518,,,A*62] /
' /
'--------------------------------------------------------------------------/
serin2 gps_tx,84,[wait("$GNRMC"),_ ;we wait for $GNRMC
wait(","),dec2 hh,dec2 mm,dec2 ss,wait("."),dec3 sss,_ ;we wait for 090045.000 which is the time when we got the info
wait(","),fix,_ ;we wait for A
wait(","),dec2 degrees,dec2 minutes,wait("."),dec4 minutesd,_ ;we wait for 3823.6645
wait(","),dir,_ ;we wait for N
wait(","),dec3 degrees2,dec2 minutes2,wait("."),dec4 minutesd2,_;we wait for 02353.3600
wait(","),dir2,_ ;we wait for E
wait(","),dec1 knots,wait("."),dec2 knots2,_ ;we wait for 0.02
wait(","),dec3 course,wait("."),dec2 course2,_ ;we wait for 195.80
wait(","),dec2 day,dec2 month,dec2 year] ;we wait for 170518
pause 500
'------------------------------------------------------------------------------/
' /
' [ Example NMEA Sentense of GNGGA ] /
' [$GNGGA,140405.000,3823.6010,N,02353.3054,E,1,9,0.88,0.8,M,35.9,M,,*40 /
' /
'-------------------------------------------------------------------------/
serin2 gps_tx,84,[wait("$GNGGA"),_ ;we wait for GNGGA
wait(","),dec2 hh,dec2 mm,dec2 ss,wait("."),dec3 sss,_ ;we wait for 140405.000 which is the time when we got info
wait(","),dec2 degrees,dec2 minutes,wait("."),dec4 minutesd,_ ;we wait for 3823.6010 longitude
wait(","),dir,_ ;we wait for the N/S
wait(","),dec3 degrees2,dec2 minutes2,wait("."),dec4 minutesd2,_;we wait for 02353.3054 latitude
wait(","),dir2,_ ;we wait for E/W
wait(","),modefix,_ ;we wait for modefix 1,2 or 3 check gps manual for NMEA
wait(","),dec2 satno,_ ;we wait for the number of fixed satellites, this is impoetant info
wait(","),dec3 horizon,dec precision,_ ;we wait for horizon
wait(","),meter,dec2 METERS,dec Meters2] ;we wait for the meters
pause 100
'---------------------------------------------------------------------------------/
' Here if the GPS module havent been fixed to any satellite will jump to notfix /
'-------------------------------------------------------------------------------/
if fix = "V" then notfix
pause 100
'-----------------------------------------------------------------------------/
' [ Return from notfix ] /
' [ We clear any character on the display ] /
'--------------------------------------------------------------------------/
gosub clearlcd
;serout2 lcd,32,[$45]
;pause 500
'--------------------------------------------------------------------------/
' here is where the code dispays the stored info from the NMEA sentenses /
'------------------------------------------------------------------------/
serout2 lcd,32,[$73,$03,$00,$00,$FF,$FF,"Protocol:","NMEA",$00]
pause 100
serout2 lcd,32,[$73,$01,$02,$01,$07,$E0,"Date:",dec2 day,"/",dec2 month,"/",dec2 year,$00]
pause 100
serout2 lcd,32,[$73,$00,$04,$00,$FF,$E0," TIME: ",dec2 hh+3," :",dec2 mm," :",dec2 ss,$00]
pause 100
serout2 lcd,32,[$73,$00,$07,$00,$FF,$FF," Satellites",$00]
pause 100
serout2 lcd,32,[$73,$03,$09,$11,$07,$FF,dec2 satno,$00]
pause 100
serout2 lcd,32,[$73,$00,$07,$00,$FF,$FF," Fixed",$00]
pause 100
serout2 lcd,32,[$73,$0D,$09,$11,$07,$FF,fix,$00]
pause 100
serout2 lcd,32,[$73,$00,$0B,$00,$ff,$ff,"Lat : ",dec2 degrees,"*",dec2 minutes,"'",dec4 minutesd," ",dir,$00]
pause 100
serout2 lcd,32,[$73,$00,$0D,$00,$ff,$ff,"Lon : ",dec3 degrees2,"*",dec2 minutes2,"'",dec4 minutesd2," ",dir2,$00]
pause 100
;serout2 lcd,32,[$73,$00,$0C,$00,$ff,$ff,"GND SPEED : ",(dec knots,".",dec2 knots2)*/1.852,$00]
;pause 200
;serout2 lcd,32,[$73,$00,$0E,$00,$ff,$ff,"Meters : ",dec2 METERS,dec Meters2,$00]
pause 5000
serout2 lcd,32,[$45] ' clears the LCD
pause 100
goto main
'-----------------------------------------------------------------------------/
' [ SUB ROUTINES ] /
'---------------------------------------------------------------------------/
notfix: ' Still looking for fixed signal
serout2 lcd,32,[$73,$00,$03,$11,$ff,$ff," Waiting for GPS",$00]
pause 100
serout2 lcd,32,[$73,$03,$06,$10,$ff," Time:",dec2 hh+3," :",dec2 mm," :",dec2 ss,$00]
pause 1000
serout2 lcd,32,[$73,$00,$08,$10,$ff,rep "." \22,$00]
pause 200
serout2 lcd,32,[$45] ' clears the LCD
pause 100
goto main 'returns to main
lostcable:
serout2 lcd,32,[$73,$00,$03,$11,$ff,$ff," Connection lost",$00]
pause 100
serout2 lcd,32,[$73,$01,$06,$10,$ff," Please check cable",$00]
pause 2000
serout2 lcd,32,[$45] ' clears the LCD
pause 100
goto main
'-------------------------------------------------------------------------/
' GREEK TIME and Correcrion /
'-----------------------------------------------------------------------/
' at the moment this is not connected to any part of the code
Plusthree:
hh = hh + 3
IF hh = 25 THEN hh = 0
RETURN
'---------------------------------------------------------------------------/
' [ CLEAR LCD ] /
'-------------------------------------------------------------------------/
Clearlcd:
serout2 lcd,32,[$45]
pause 500
RETURN
I have found that inline math for lcdout cmd on a pic16 turns to crap, serout2 may have the same issues
you probably need to do the math first then print result
i would do it this way
hh=hh+3 ;utc+3
hh=hh//24 ;REALLY SHOULD ADD A DAY TO DATE TOO IF day changes
serout2 lcd,32,[$73,$00,$04,$00,$FF,$E0," TIME: ",dec2 hh," :",dec2 mm," :",dec2 ss,$00]
pause 100
Hi Richard,
Thanks for the reply. I will try that.