PDA

View Full Version : How do I discern Maidenhead Locator from GPS lat long info.



tasmod
- 5th March 2014, 21:29
Hi all,

I have some idea but maths is not my strong point. I have written what I considered to be the process but not a working code. Am I on the right lines ?(See end)

This is the relevant information to achieve the locator.


.
Longitude is always the first, followed by latitude, for each pair. For simplicity, let's assume that West and South are negative lat/long, as is a common convention. For example purposes, I'm going to use 32.123 W, 14.321 N. The key thing is to do the following.:
Longitude
1. Add 180 to the longitude, and take the integer value /20, and add one. Then figure out which letter of the alphabet that corresponds to, usually written in upper case. The example will be 147.877/20=7. Adding one will give the 8th letter of the alphabet, or G. Note 7.877 is remaining.
2. Take the remainder of what is left, and divide by 2, rounding down. This is the number, no conversion required. The example will give a value of 3. Note 1.877 is remaining.
3. Take the remainder that is left, and multiply by 12, and add one. Round down to the nearest integer.. This is the letter of the alphabet, usually written in lower case. The example gives a value of 22+1=23. This will be the letter w.
Latitude
1. Add 90 to the latitude, and take the integer value /10, and add one. Then figure out which letter of the alphabet that corresponds to, usually written in upper case. The example will be 104.321/10=10. Adding one will give the 8th letter of the alphabet, or J. Note 4.321 is remaining.
2. Take the remainder of what is left, and round down. This is the number, no conversion required. The example will give a value of 4. Note 0.321 is remaining.
3. Take the remainder that is left, and multiply by 24, and add one. Round down to the nearest integer.. This is the letter of the alphabet, usually written in lower case. The example gives a value of 7+1=8. This will be the letter g.
Putting them together by pairs, and alternating first longitude then latitude, gives the grid square for 32.123 W, 14.321 N to be GJ34wg.



I have the info from the RMC string as :-



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
EO VAR BYTE 'east or west


My idea of the process is something like this :-



locator:
lonloc1=londeg + lonmin + 180
lonloc2=lonloc1/20
lonloc3=lonloc1//20
maid1=lonloc2+1
lookup maid1 ; first main letter

lonloc4=lonloc3//2
maid3=lonloc3/2 ;first number


maid5=lonloc4*12+1
lookup maid5 ; 1st 2nd letter



latloc1=latdeg + latmin + 90
latloc2=latloc1/10+1
latloc3=latloc1//10
maid1=latloc2+1
lookup maid2 ; second main letter


maid4=latloc3 ; second number


maid6=latloc3*24+1
lookup maid6 ; 2nd 2nd letter

maidenhead=maid1, maid2, maid3, maid4, maid5, maid6

andywpg
- 6th March 2014, 01:49
Weird - I've had this one on my list of things to make for about a year - I got a bit of a start, then other things took over.

Don't know if this helps, but HERE (http://stuff.mit.edu/afs/sipb/project/netmap/radio/doc/GRIDLOC.BAS) is a BASIC program that I was going to try to convert.

If I get going on this again, I'll keep you updated - and please let me know how you're doing with it too.

Andy

tasmod
- 6th March 2014, 08:52
OK thanks for that I will look at it.

Meanwhile here is the full code i have for getting the NMEA data I want to display. NOTE the code for maidenhead is the same as above, a work in progress. All untested as yet.
I do have a fully working code in asm but wanted it in PBP for experimental purposes.


'
' Program to display returned value of a GPS on RB0
' LCD in 4-BIT mode PIC16F628 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 2000 ' Command Delay (uS)
define LCD_DATAUS 50 ' Data Delay (uS)

DEFINE OSC 4
CMCON = 7
OPTION_REG.7=0 ' Enable Pull-Up's
GPSin VAR PORTB.0
LED VAR PortA.4 ' flash per second

TRISA.0=0
TRISA.1=0
TRISA.2=0
TRISA.3=0

TRISA.4=0 ; LED

PAUSE 500

PORTA=0
PORTB=0

'Allocate Variables for GPS:
TimeOut CON 3000
baudGPS CON 24764 '16572 + 8192 (bit 13)

hh VAR BYTE 'hours
mm VAR BYTE 'minutes
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
EO VAR BYTE 'east or west
j VAR BYTE 'day
m VAR BYTE 'month
a VAR BYTE 'year

fix VAR WORD 'GPS fix


LCDOut $FE, 1 'Clear Screen

LCDOut $fe,$80," GPS Decoder "
LCDOut $FE,$c0, " G8VLQ "
Pause 2000
LCDOut $FE, 1

GPS: 'read GPS

SerIn2 GPSin,baudGPS,Timeout,[wait("$GPRMC"),wait(","),DEC2 hh,DEC2 mm,wait(","),fix,wait(","),DEC2 latdeg,DEC2 latmin,wait(","),NS,wait(","),DEC3 londeg,DEC2 lonmin,wait(","),EO,wait(","),knots,wait("."),DEC2 knotsten,wait(","),DEC3 course,wait(","),DEC2 j,DEC2 m,DEC2 a]

flash: ;not accurate pps
led high
led low


IF fix="V" Then 'if no GPS fix
GOTO LCD1
EndIF

LCD: ; LATER put time and date on first line , remove names
; callsign and QRA (maidenhead) on second line

LCDOut $fe,$80,"DATE: ",DEC2 j,"-",DEC2 m,"-",DEC2 a ; 80 1st line
LCDOUT $fe,$c0,"TIME: ",DEC2 hh,":",DEC2 mm ; c0 2nd line
LCDOut $fe,$94,"LAT:",DEC2 latdeg,",",DEC2 latmin," ",NS ; 94 3rd line
LCDOut $fe,$d4,"LON:",DEC2 londeg,",",DEC2 lonmin," ",EO ; d4 4th line

GoTo GPS

LCD1: ; If invalid data, just shows gps string is received

LCDOut $fe,$80," Invalid data " ; 80 1st line
LCDOUT $fe,$c0," No Fix " ; c0 2nd line
LCDOut $fe,$94,"LAT:",DEC2 latdeg,",",DEC2 latmin," ",NS ; 94 3rd line
LCDOut $fe,$d4,"LON:",DEC2 londeg,",",DEC2 lonmin," ",EO ; d4 4th line

GoTo GPS

locator:
lonloc1=londeg + lonmin + 180
lonloc2=lonloc1/20
lonloc3=lonloc1//20
maid1=lonloc2+1
lookup maid1 ; first main letter

lonloc4=lonloc3//2
maid3=lonloc3/2 ;first number


maid5=lonloc4*12+1
lookup maid5 ; 1st 2nd letter



latloc1=latdeg + latmin + 90
latloc2=latloc1/10+1
latloc3=latloc1//10
maid1=latloc2+1
lookup maid2 ; second main letter


maid4=latloc3 ; second number


maid6=latloc3*24+1
lookup maid6 ; 2nd 2nd letter

maidenhead=maid1, maid2, maid3, maid4, maid5, maid6



speed:
LCDOUT $fe,1
LCDOut $fe,$80,"SPEED :",knots,".",DEC2 knotsten," KNT"
LCDOut $fe,$c0,"HEADING:",DEC3 course," DEG"

END

andywpg
- 7th March 2014, 01:40
Thanks! I'll have a look at that.

andywpg
- 8th March 2014, 19:35
BTW, what are you building? Mine was an idea when I was driving around talking on Amateur Radio Satellites. We were in Grand Forks, North Dakota, and I was waiting for my wife to come out of a store. There happened to be an AO-51 pass happening right then, so I made a couple of contacts - only I had NO IDEA what my grid square was! I used my Winnipeg one, and thought "it would be nice to have a handheld, GPS-based unit that displays your current grid square to 6 digits". And the idea was born. I'll get to it, probably right after I finish the smoker controller I'm working on right now.

Did you happen to notice how I list my location on the forum? I guess great minds really DO think alike! :D

Andy

tasmod
- 10th March 2014, 10:38
Hi Andy,

The project is already working, I just wanted more information displayed on LCD. The LCD board piggybacks the LCD display. It has a 16F818 which deals with the NMEA string and ADC functions.

It's a GPS Disciplined Oscillator producing 10MHz to 10-12 signal. For accuracy of frequency and timing for MS and EME.

It remains extremely stable but I am slightly improving it by logging the PLL control voltage and the TCXO temp swing.
By logging I can get a mean control position for either start up purposes or short term 'dropout' from gps. Thus it will keep accuracy for short term outage. If the unit is turned off then on, I can apply the correct PLL control voltage until the gps locks again. Although watching the PLL voltage swing whilst trying to lock was fascinating.

It also produces a very accurate 1PPS output. I later intend to use this to trigger the NMEA sentence display. You may be aware that the sentence suffers from lag or slight offset depending if the gps module decides to send another, other, information sentence. In my case at the moment it is 1.635 secs BEHIND actual time as my module occasionally sends out the powerID string which puts the timing RMC sentence out.
I will be turning all off except the RMC sentence. At the moment it is testing phase.

I get a very strong signal from the 60kHz time signal from Anthorn in the UK so I can actually compare the second epoch via SpecLab software visually.

Darrel Taylor
- 12th March 2014, 22:35
Trying to work through the example in post #1.


gives the grid square for 32.123 W, 14.321 N to be GJ34wg.

The best I can come up with is HK33xv at that location.
Are you sure about the example in post #1?

And it seems that Andy is in Winnipeg Manitoba Canada.
And you are near Gainsborough, U.K.

If those are close, I can't be that far off with the calculations.

andywpg
- 13th March 2014, 00:04
And it seems that Andy is in Winnipeg Manitoba Canada.


Absolutely correct

And you're right - HK33xv is in the ocean off of Cape Verde

And 14.321N 32.123W converts to HK34wh - darn near exactly what you calculated

Darrel Taylor
- 13th March 2014, 04:05
Thanks Andy, I knew I couldn't be that far off.

But apparently, I need to work on the math some more. :)
Darned Floating-Point ...

Darrel Taylor
- 13th March 2014, 06:30
Woohoo!

HK34wh it is!!
And it's not even midnight yet. :)

It's some really ugly code right now, will need to add some "Pretty" to it.

Are you guy's using PBP3?

If not, there's only so much "Pretty" I can add.

tasmod
- 13th March 2014, 09:23
Just realised you discerned my physical location from my locator. So your code should be OK.

I did the calc by hand and got it to the example Locator given. ODD. Also needed to reverse calc the 'leftovers'

One thing not mentioned is W is a negative longtitude. I need put an IF THEN in my code to deal with the 180 for a negative W rather than E.


If you have ugly code then that's ok with me. I'm using 2.50 Darrel. Long time coding but not enough to be good with PBP :rolleyes:

The routine could also decode the 8th place pair too, which is as close as Maidenhead gets.

tasmod
- 13th March 2014, 09:38
Darn it.

Scrap what I said about the example. I found my scratch pad and realised I used my own GPS co-ordinates to check the formula given to get my locator. I didn't use the example after all. :o

andywpg
- 13th March 2014, 15:39
Woohoo!

HK34wh it is!!
And it's not even midnight yet. :)

It's some really ugly code right now, will need to add some "Pretty" to it.

Are you guy's using PBP3?



I am - I look forward to seeing your code because math and I do not get along well..... :biggrin:

That's actually one of the reasons I have been delaying this project - the math was a bit above me right now.... I have just been using the AMSAT page to convert and see where a grid square takes me on the map.

Darrel Taylor
- 14th March 2014, 03:29
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 (http://en.wikipedia.org/wiki/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.


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.

; 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 ...


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).


IFDEF __16F1937 ; Generic Processor Type
P16CXX SET TRUE ; If P16CXX, use INHX8M file format.
P16_MAP2 SET TRUE ;
ENDIF


References:

Maidenhead_Locator_System - Wikipedia - http://en.wikipedia.org/wiki/Maidenhead_Locator_System
Find your QTH locator (or your grid square) with GoogleMaps - http://qthlocator.free.fr/index.php <-- Too Cool!
$GPRMC sentence format - http://aprs.gids.nl/nmea/#rmc

andywpg
- 14th March 2014, 15:14
Umm, WOW! Thanks Darrel! And my brain thanks you even more, since it gets uppity when it has to do complex math!

tasmod
- 20th March 2014, 09:30
And a WOW from me Darrel. Thanks for your help. Surprisingly I think I can follow and understand the code :biggrin:

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

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.

Darrel Taylor
- 20th March 2014, 15:10
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.

tasmod
- 21st March 2014, 10:49
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. :D

7271

Darrel Taylor
- 22nd March 2014, 04:13
Awesome!

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

tasmod
- 23rd March 2014, 13:46
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



;
;
; 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

Darrel Taylor
- 23rd March 2014, 18:53
The 16F628A has 2K words of program space.
The 16F818 only has 1K words.

You're going to need a bigger chip.
The Maidenhead routine with Floating point libraries will take >1.5K by itself.

You'll need at least 4K, but why not get one with 8K so you won't have the problem again later.
I'm sure you'll want to add a Morse Code transmitter and receiver some day. :)

tasmod
- 24th March 2014, 10:24
Now that was completely stupid of me, I apologise for such a silly mistake. :o I had never seen the message before and assumed it was a code error.

I never gave it a thought to look at the chip spec. The reason to change over to 818 was just one adc input. The chip otherwise is pin compatible for what I've already done.

I think I will remake a new display pcb and use the 16f876 28 pin chip that has 8k.

The project uses the chip to accept the NMEA string from a Rockwell gps module and display it. This older gps module also produces accurate 1PPS and 10kHz signals when gps has a fix.
I'm using these signals on a pll and divider board to lock a 10mhz tcxo.

In its present application it would have worked fine but I wanted to monitor the gps pll control voltage on the board to check for frequency lock.
If the voltage was 1.65v then the oscillator was in lock state.
The display did show whether the satellites produced a fix but not whether the oscillator had locked against the 10khz frequency. Watching the pll control voltage hunt back and forth whilst the gps attempted a fix was facinating but impractical for 'normal' usage.

Once I have the display running again I'll report back.

tasmod
- 24th March 2014, 10:51
Just looked in my box o bits and found a 18f1330 which is pin compatible with 4k space.

Not quite pin compatible unfortunately, ports mixed :frown:

tasmod
- 2nd April 2014, 12:02
Here you go Darrel -

7293


That display is huge at 4inch by 2 inch (See pic chip in background) Used a 16f876a in the end. That's your BigDigit code put to use as well.
Display shows 1.65v which indicates to me that the oscillator control voltage is stable and in lock.

Code needs some polishing especially Month but that's a work in progress :-



;
;
; PIC16F876a
; __________
; !MCLR |1 28| RB7------D7
; PLL Volt--AN0---RA0 |2 27| RB6------D6
; Temp--AN1---RA1 |3 26| RB5------D5
; AN2---RA2 |4 25| RB4------D4
; AN3---RA3 |5 24| RB3------LCD E
; NMEA data---RA4 |6 23| RB2------LCD RS
; AN4---RA5 |7 22| RB1------
; Ground---Vss |8 21| RB0------
; OSC1---XTAL |9 20| VDD------ +5 V
; OSC2---XTAL |10 19| Vss------Ground
; ---RC0 |11 18| RC7------
; ---RC1 |12 17| RC6------
; ---RC2 |13 16| RC5------
; pbutton---RC3 |14 15| RC4------
; ----------
;
; Serial data out Not used Not used
;================================================= ===================='
' Program to display returned value of a GPS on RA4
' LCD in 4-BIT mode PIC16F876a 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

@__config_HS_OSC
@__config_BOD_OFF
@__config_PWRT_ON
@__config_WDT_ON
@__config_PROTECT_OFF
@__config_LVP_OFF

;-- Place a copy of these variables in your Main program -------------------
;-- 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
' --------------------------------------------------------------------------

INCLUDE "FP20.bas" ; 24-bit Floating Point for 14-bit cores with RAM at $20


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

OPTION_REG.7=0 ' Enable Pull-Up's
GPSin VAR PORTA.4
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
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
latsecs VAR BYTE 'seconds latitude
NS VAR BYTE 'north or south
londeg VAR BYTE 'degrees longitude
lonmin VAR BYTE 'minutes longitude
lonsecs VAR BYTE 'seconds longtitude
EW VAR BYTE 'east or west
d VAR BYTE 'day
m VAR BYTE 'month
y VAR BYTE 'year

MH VAR BYTE[6]

LonMinDec VAR BYTE
LonDir VAR BYTE

LatMinDec VAR BYTE
LatDir VAR BYTE

nPos var byte
nDig var byte

'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,$40,$02,$02,$02,$02,$02,$02,$02,$02 ' Cust Char #0
LCDOUT $FE,$48,$1F,$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,$1F,$1F,$1B,$1B,$1B,$1B,$1F,$1F ' Cust Char #4
LCDOUT $FE,$68,$1B,$1B,$1B,$1B,$1B,$1B,$1F,$1F ' Cust Char #5
LCDOUT $FE,$70,$1F,$1F,$03,$03,$03,$03,$1F,$1F ' Cust Char #6
LCDOUT $FE,$78,$1F,$1F,$03,$03,$03,$03,$03,$03 ' Cust Char #7
LCDOUT $FE,$40,$03,$03,$03,$03,$03,$03,$03,$03 ' Cust Char #8


fix VAR WORD 'GPS fix

LCDOut $fe,$80," GPS Decoder "
LCDOut $FE,$c0," G8VLQ March 2014 "
Pause 3000
LCDOut $FE, 1 'Clear Screen


GPS: 'read GPS

SerIn2 GPSin,188,Timeout,Clock,[wait("$GPRMC"),wait(","),DEC2 hh,DEC2 mm,DEC2 ss,wait(","),fix,wait(",")_
,DEC2 latdeg,DEC2 latmin,wait("."),DEC2 latsecs,wait(","),NS,wait(","),DEC3 londeg,DEC2 lonmin,wait("."),DEC2 lonsecs,_
wait(","),EW,wait(","),knots,wait("."),DEC2 knotsten,wait(","),DEC3 course,wait(","),DEC2 d,DEC2 m,DEC2 y]

LonMinDec = lonmin
LatMinDec = latmin
LonDir = EW
LatDir = NS

gosub PLL ;pll control voltage
GOSUB Locator ;maidenhead locator
GOSUB Clock ; Large digit clock
goto GPS

If m = 01 then gosub January ; show month
If m = 02 then gosub February
If m = 03 then gosub March
If m = 04 then gosub April
If m = 05 then gosub May
If m = 06 then gosub June
If m = 07 then gosub July
If m = 08 then gosub August
If m = 09 then gosub September
If m = 10 then gosub October
If m = 11 then gosub November
If m = 12 then gosub December


;-------------------------------------------------------------

PLL:
Val = 0 ' Value returned is the average of 5 conversions
For i = 0 TO 4
ADCON0.2 = 1 ' Start conversion
NotDone:
pause 1
IF ADCON0.2 = 1 Then NotDone
val = val + ((ADRESH * 256)+(ADRESL))
nEXT I
VAL = VAL/5
' Calculate Voltage to 2 decimal places
volt = val * 5/1024
voltd1 = ( val * 5//1024) * 10/1024
Voltd2 = ((val *5 //1024) * 10//1024) * 10/1024
RETURN

;---------------------------------------------

Locator:
;----[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]-------------------------------------------
RETURN
;-------------------------------------------------------------------------------
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
;---------------------------------------

January:
LCDOut $fe,$80,DEC2 d," Jan ",DEC2 y," ",DEC2 hh,":",DEC2 mm,":",DEC2 ss
RETURN

February:
LCDOut $fe,$80,DEC2 d," Feb ",DEC2 y," ",DEC2 hh,":",DEC2 mm,":",DEC2 ss
RETURN

March:
LCDOut $fe,$80,DEC2 d," Mar ",DEC2 y," ",DEC2 hh,":",DEC2 mm,":",DEC2 ss
RETURN

April:
LCDOut $fe,$80,DEC2 d," Apr ",DEC2 y," ",DEC2 hh,":",DEC2 mm,":",DEC2 ss
RETURN

May:
LCDOut $fe,$80,DEC2 d," May ",DEC2 y," ",DEC2 hh,":",DEC2 mm,":",DEC2 ss
RETURN

June:
LCDOut $fe,$80,DEC2 d," Jun ",DEC2 y," ",DEC2 hh,":",DEC2 mm,":",DEC2 ss
RETURN

July:
LCDOut $fe,$80,DEC2 d," Jul ",DEC2 y," ",DEC2 hh,":",DEC2 mm,":",DEC2 ss
RETURN

August:
LCDOut $fe,$80,DEC2 d," Aug ",DEC2 y," ",DEC2 hh,":",DEC2 mm,":",DEC2 ss
RETURN

September:
LCDOut $fe,$80,DEC2 d," Sep ",DEC2 y," ",DEC2 hh,":",DEC2 mm,":",DEC2 ss
RETURN

October:
LCDOut $fe,$80,DEC2 d," Oct ",DEC2 y," ",DEC2 hh,":",DEC2 mm,":",DEC2 ss
RETURN

November:
LCDOut $fe,$80,DEC2 d," Nov ",DEC2 y," ",DEC2 hh,":",DEC2 mm,":",DEC2 ss
RETURN

December:
LCDOut $fe,$80,DEC2 d," Dec ",DEC2 y," ",DEC2 hh,":",DEC2 mm,":",DEC2 ss
RETURN

;--------------------------------------------------------------------------

Clock: ;Display time

nDig=hh dig 1 : nPos=1 : gosub displaydigit
nDig=hh dig 0 : nPos=2 : gosub displaydigit
npos=3 : gosub colon
ndig=mm dig 1 : npos=4 : gosub displaydigit
ndig=mm dig 0 : npos=5 : gosub displaydigit
npos=6 : gosub colon
ndig=ss dig 1 : npos=7 : gosub displaydigit
ndig=ss dig 0 : npos=8 : gosub displaydigit

LCDOut $fe,$80+9," ",DEC2 d,"-",DEC2 m,"-",DEC2 y
LCDOut $fe,$c0+9," ",#volt, ".", # voltd1,# voltd2,"v"
LCDOUT $fe,$94," G8VLQ ",STR MH\6
LCDOut $fe,$d4,DEC2 latdeg,$DF,DEC2 latmin,"'",DEC2 latsecs,NS," ",DEC2 londeg,$DF,DEC2 lonmin,"'",DEC2 lonsecs,EW ; ,#volt, ".", # voltd1,# voltd2,"v" ; d4 4th line


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,$2E
return

Darrel Taylor
- 2nd April 2014, 18:43
WooHoo!! That's Beeeeauuuutiful Rob!

I'm so glad to see it working.

I do have some suggestions for you about the configs, Months, volts ...
When your ready to work on it some more.

P.S. Nice picture of yourself too. :D

tasmod
- 2nd April 2014, 20:38
Glad you like it Darrel. I'm very pleased with it. Any ideas very welcome.

I have also coded a full digit clock over the four lines. At the moment it's a standalone code due to the character loading. Is it possible to load the second set of characters, replacing the original, on a button push ? Maybe using EXT ?

The idea was to have dual display, button push changes from that shown in pic to a full clock and back again on another push.

7294

Darrel Taylor
- 2nd April 2014, 21:31
Yes, you can have as many custom character sets as you want.
But only one set can be loaded at a time.

In your last code, the configs you have aren't doing anything.
They should look like this ... make sure the defaults are commented out in the 16F876A.inc file in your PBP folder.

@ __config _HS_OSC & _WDT_ON & _PWRTE_ON & _BODEN_OFF & _LVP_OFF & _CPD_OFF & _WRT_OFF & _DEBUG_OFF & _CP_OFF


And how's this look for the Months ...

DateTime:
LCDOut $fe,$80,DEC2 d," "
GOSUB ShowMonth
LCDOut " ",DEC2 y," ",DEC2 hh,":",DEC2 mm,":",DEC2 ss
RETURN

ShowMonth:
Idx = (m - 1) * 3
FOR X = Idx TO Idx + 2
LOOKUP X,["JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC"],Char
LCDOUT Char
NEXT X
RETURN

tasmod
- 2nd April 2014, 22:52
Hmm, I've always had problems with configs.

A single line config errors out. Multiple lines actually works and sets my programmer fuses OK.

I also have severe problems with Mpasmwin 5.20 giving hundreds of errors with PBP which I now just ignore.


I like the Months code. That's one of the things I just couldn't get right but I was thinking that way.

How would I go about loading the character set ? I just don't get it.

The brain is full of different ideas for the project, so many options. Even thought of two lcds.:rolleyes:

Darrel Taylor
- 3rd April 2014, 02:23
A single line config errors out. Multiple lines actually works and sets my programmer fuses OK.



@__config_HS_OSC
@__config_BOD_OFF
@__config_PWRT_ON
@__config_WDT_ON
@__config_PROTECT_OFF
@__config_LVP_OFF

Those lines are not configuration statements.
They are actually assembly language labels. You could use an asm GOTO to jump to any one of them.
They will not set the configuration bits in your programmer.

If the one line __config I gave you gives an error, it's probably the "Overwriting address 2007" error that means you didn't comment the default configs in the .inc file.


I also have severe problems with Mpasmwin 5.20 giving hundreds of errors with PBP which I now just ignore.

Very bad idea.
You should track down every error and fix it.
How would you know if there are real errors if you always just ignore them.
If you don't know what they mean ... get help.


How would I go about loading the character set ? I just don't get it.

These lines from your code load the custom characters
LCDOUT $FE,$40,$03,$03,$03,$03,$03,$03,$03,$03 ' Cust Char #0
'LCDOUT $FE,$40,$02,$02,$02,$02,$02,$02,$02,$02 ' Cust Char #0
LCDOUT $FE,$48,$1F,$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,$1F,$1F,$1B,$1B,$1B,$1B,$1F,$1F ' Cust Char #4
LCDOUT $FE,$68,$1B,$1B,$1B,$1B,$1B,$1B,$1F,$1F ' Cust Char #5
LCDOUT $FE,$70,$1F,$1F,$03,$03,$03,$03,$1F,$1F ' Cust Char #6
LCDOUT $FE,$78,$1F,$1F,$03,$03,$03,$03,$03,$03 ' Cust Char #7
LCDOUT $FE,$40,$03,$03,$03,$03,$03,$03,$03,$03 ' Cust Char #8


You'll have another set of similar lines for your 4-line big digits.
Executing those lines will overwrite the customs characters you previously loaded.

However, you can only have 8 custom characters at a time, and you have 9 listed above.
The one commented as Cust Char #8, is actually Cust Char #0 and will overwrite the first Cust Char #0. Good thing they're the same.

tasmod
- 3rd April 2014, 06:35
Hi Darrel,

Many thanks for your help.

The code I posted was the last working example on this PC connected to the net. The actual programming pc is in another room and not net connected (deliberately). There were a couple of errors, the second $40 character set was one and a missing RETURN was another.
The Month routine was deliberately moved down from the GPS loop. Since the post I moved it into the loop and reformatted the display lines to suit the new layout. I will however look at the array solution now.

I've always had problems with Mpasmwin and errors. For instance the code posted has 891 errors at assembly, all of which relate to standard PBP instructions. e.g. LCDOUT alone is an error, FOR is an error etc. etc.

This is a sample around your Locator code :-

Error[122] C:\FPOINT\NMEA16F876ABIG.ASM 1049 : Illegal opcode (_LatDir)
Warning[207] C:\FPOINT\NMEA16F876ABIG.ASM 1052 : Found label after column 1. (GOSUB?L)
Error[122] C:\FPOINT\NMEA16F876ABIG.ASM 1052 : Illegal opcode (_AtoB)
Warning[207] C:\FPOINT\NMEA16F876ABIG.ASM 1058 : Found label after column 1. (GOSUB?L)
Error[122] C:\FPOINT\NMEA16F876ABIG.ASM 1058 : Illegal opcode (_itofa)
Warning[207] C:\FPOINT\NMEA16F876ABIG.ASM 1061 : Found label after column 1. (GOSUB?L)
Error[122] C:\FPOINT\NMEA16F876ABIG.ASM 1061 : Illegal opcode (_fpsub)
Warning[207] C:\FPOINT\NMEA16F876ABIG.ASM 1064 : Found label after column 1. (LABEL?L)
Error[122] C:\FPOINT\NMEA16F876ABIG.ASM 1064 : Illegal opcode (L00042)
Warning[207] C:\FPOINT\NMEA16F876ABIG.ASM 1070 : Found label after column 1. (GOSUB?L)
Error[122] C:\FPOINT\NMEA16F876ABIG.ASM 1070 : Illegal opcode (_itofb)
Warning[207] C:\FPOINT\NMEA16F876ABIG.ASM 1073 : Found label after column 1. (GOSUB?L)
Error[122] C:\FPOINT\NMEA16F876ABIG.ASM 1073 : Illegal opcode (_fpadd)
Warning[207] C:\FPOINT\NMEA16F876ABIG.ASM 1076 : Found label after column 1. (GOSUB?L)
Error[122] C:\FPOINT\NMEA16F876ABIG.ASM 1076 : Illegal opcode (_SaveLon)
Warning[207] C:\FPOINT\NMEA16F876ABIG.ASM 1082 : Found label after column 1. (GOSUB?L)
Error[122] C:\FPOINT\NMEA16F876ABIG.ASM 1082 : Illegal opcode (_itofb)
Warning[207] C:\FPOINT\NMEA16F876ABIG.ASM 1085 : Found label after column 1. (GOSUB?L)
Error[122] C:\FPOINT\NMEA16F876ABIG.ASM 1085 : Illegal opcode (_fpdiv)
Warning[207] C:\FPOINT\NMEA16F876ABIG.ASM 1088 : Found label after column 1. (GOSUB?L)
Error[122] C:\FPOINT\NMEA16F876ABIG.ASM 1088 : Illegal opcode (_SaveAARG)
Warning[207] C:\FPOINT\NMEA16F876ABIG.ASM 1091 : Found label after column 1. (GOSUB?L)
Error[122] C:\FPOINT\NMEA16F876ABIG.ASM 1091 : Illegal opcode (_ftoia)
Warning[207] C:\FPOINT\NMEA16F876ABIG.ASM 1094 : Found label after column 1. (ADD?CWB)
Error[108] C:\FPOINT\NMEA16F876ABIG.ASM 1094 : Illegal character (0)

I will re-install 5.20 and see if it cures it. I'm sure years back I didn't have the problem.

tasmod
- 3rd April 2014, 07:34
SOLVED. Wrong MPASM Suite.

I'm using PBP2.50 and at some point I must have upgraded the MPASM Suite to 8.90.
I needed to delete and re-install 8.15 instead.

I now get a complete compile and assemble without any errors. :)

Just needed to think quietly about the problem.

tasmod
- 3rd April 2014, 10:27
Darrel,

I tried incorporating your Month code but it causes odd errors in the ShowMonth, based on the FOR/NEXT loop and especially the idx. This is maybe where I placed it in the code but I will continue to try it.

Right now I have completed the code using the long Month code and I'm able to toggle back and forth between all info onscreen and the fullscreen big digit clock.



;
;
; PIC16F876a
; __________
; !MCLR |1 28| RB7------D7
; PLL Volt--AN0---RA0 |2 27| RB6------D6
; Temp--AN1---RA1 |3 26| RB5------D5
; AN2---RA2 |4 25| RB4------D4
; AN3---RA3 |5 24| RB3------LCD E
; NMEA data---RA4 |6 23| RB2------LCD RS
; AN4---RA5 |7 22| RB1------
; Ground---Vss |8 21| RB0------
; OSC1---XTAL |9 20| VDD------ +5 V
; OSC2---XTAL |10 19| Vss------Ground
; ---RC0 |11 18| RC7------
; ---RC1 |12 17| RC6------
; ---RC2 |13 16| RC5------
; pbutton---RC3 |14 15| RC4------
; ----------
;
;
;================================================= ===================='
' Program to display returned value of a GPS on RA4
' LCD in 4-BIT mode PIC16F876a 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


@ __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 -------------------
;-- 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
' --------------------------------------------------------------------------

INCLUDE "FP20.bas" ; 24-bit Floating Point for 14-bit cores with RAM at $20


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

OPTION_REG.7=0 ' Enable Pull-Up's
GPSin VAR PORTA.4
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
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
latsecs VAR BYTE 'seconds latitude
NS VAR BYTE 'north or south
londeg VAR BYTE 'degrees longitude
lonmin VAR BYTE 'minutes longitude
lonsecs VAR BYTE '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

MH VAR BYTE[6]

LonMinDec VAR BYTE
LonDir VAR BYTE

LatMinDec VAR BYTE
LatDir VAR BYTE

nPos var byte
nDig var byte

fix VAR WORD 'GPS fix

LCDOut $fe,$80," GPS Decoder "
LCDOut $FE,$c0," G8VLQ March 2014 "
Pause 3000
LCDOut $FE, 1 'Clear Screen

butt = 0
marker = 0


GPS: 'read GPS ################################################## ###########################################

SerIn2 GPSin,188,Timeout,Clock,[wait("$GPRMC"),wait(","),DEC2 hh,DEC2 mm,DEC2 ss,wait(","),fix,wait(",")_
,DEC2 latdeg,DEC2 latmin,wait("."),DEC2 latsecs,wait(","),NS,wait(","),DEC3 londeg,DEC2 lonmin,wait("."),DEC2 lonsecs,_
wait(","),EW,wait(","),knots,wait("."),DEC2 knotsten,wait(","),DEC3 course,wait(","),DEC2 d,DEC2 m,DEC2 y]

IF marker = 1 THEN BigClock

LonMinDec = lonmin
LatMinDec = latmin
LonDir = EW
LatDir = NS

BUTTON Pbutton,0,100,0,butt,1,BigClockClear

If m = 01 then gosub January ; show month
If m = 02 then gosub February
If m = 03 then gosub March
If m = 04 then gosub April
If m = 05 then gosub May
If m = 06 then gosub June
If m = 07 then gosub July
If m = 08 then gosub August
If m = 09 then gosub September
If m = 10 then gosub October
If m = 11 then gosub November
If m = 12 then gosub December

gosub PLL ;pll control voltage
GOSUB Locator ;maidenhead locator
GOSUB Clock ;Large digit clock
goto GPS ; ################################################## ########################################

;-------------------------------------------------------------

PLL:
Val = 0 ' Value returned is the average of 5 conversions
For i = 0 TO 4
ADCON0.2 = 1 ' Start conversion
NotDone:
pause 1
IF ADCON0.2 = 1 Then NotDone
val = val + ((ADRESH * 256)+(ADRESL))
nEXT I
VAL = VAL/5
' Calculate Voltage to 2 decimal places
volt = val * 5/1024
voltd1 = ( val * 5//1024) * 10/1024
Voltd2 = ((val *5 //1024) * 10//1024) * 10/1024
RETURN

;---------------------------------------------

Locator:
;----[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]-------------------------------------------
RETURN
;-------------------------------------------------------------------------------
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
;---------------------------------------

January:
LCDOut $fe,$80+9,DEC2 d," Jan ","20",DEC2 y
RETURN

February:
LCDOut $fe,$80+9,DEC2 d," Feb ","20",DEC2 y
RETURN

March:
LCDOut $fe,$80+9,DEC2 d," Mar ","20",DEC2 y
RETURN

April:
LCDOut $fe,$80+9,DEC2 d," Apr ","20",DEC2 y
RETURN

May:
LCDOut $fe,$80+9,DEC2 d," May ","20",DEC2 y
RETURN

June:
LCDOut $fe,$80+9,DEC2 d," Jun ","20",DEC2 y
RETURN

July:
LCDOut $fe,$80+9,DEC2 d," Jul ","20",DEC2 y
RETURN

August:
LCDOut $fe,$80+9,DEC2 d," Aug ","20",DEC2 y
RETURN

September:
LCDOut $fe,$80+9,DEC2 d," Sep ","20",DEC2 y
RETURN

October:
LCDOut $fe,$80+9,DEC2 d," Oct ","20",DEC2 y
RETURN

November:
LCDOut $fe,$80+9,DEC2 d," Nov ","20",DEC2 y
RETURN

December:
LCDOut $fe,$80+9,DEC2 d," Dec ","20",DEC2 y
RETURN


;--------------------------------------------------------------------------
ClockClear:

LCDOut $FE, 1 'Clear Screen
marker = 0
GOTO GPS

Clock:
;Display time

'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,$1F,$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,$1F,$1F,$1B,$1B,$1B,$1B,$1F,$1F ' Cust Char #4
LCDOUT $FE,$68,$1B,$1B,$1B,$1B,$1B,$1B,$1F,$1F ' Cust Char #5
LCDOUT $FE,$70,$1F,$1F,$03,$03,$03,$03,$1F,$1F ' Cust Char #6
LCDOUT $FE,$78,$1F,$1F,$03,$03,$03,$03,$03,$03 ' Cust Char #7



nDig=hh dig 1 : nPos=0 : gosub displaydigit
nDig=hh dig 0 : nPos=1 : gosub displaydigit
npos=2 : gosub colon
ndig=mm dig 1 : npos=3 : gosub displaydigit
ndig=mm dig 0 : npos=4 : gosub displaydigit
npos=5 : gosub colon
ndig=ss dig 1 : npos=6 : gosub displaydigit
ndig=ss dig 0 : npos=7 : gosub displaydigit

LCDOut $fe,$c0+9," ",#volt, ".", # voltd1,# voltd2,"v"
LCDOUT $fe,$94," G8VLQ ",STR MH\6
LCDOut $fe,$d4,DEC2 latdeg,$DF,DEC2 latmin,"'",DEC2 latsecs,NS," ",DEC2 londeg,$DF,DEC2 lonmin,"'",DEC2 lonsecs,EW ; ,#volt, ".", # voltd1,# voltd2,"v" ; d4 4th line

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 Screen
marker = 1

BigClock:

'Set up the digits (http://www.darreltaylor.com/files/CustChar.htm)
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,$03,$07,$0F,$1E,$1C,$1C,$1C,$1C ' Cust Char #2
LCDOUT $FE,$58,$18,$1C,$1E,$0F,$07,$07,$07,$07 ' Cust Char #3
LCDOUT $FE,$60,$1C,$1C,$1C,$1C,$1E,$0F,$07,$03 ' Cust Char #4
LCDOUT $FE,$68,$07,$07,$07,$07,$0F,$1E,$1C,$18 ' 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


BUTTON Pbutton,0,100,0,butt,1,ClockClear

;Display time

nDig=hh dig 1 : nPos=0 : gosub displaydigit1
nDig=hh dig 0 : nPos=3 : gosub displaydigit1
npos=6 : gosub colon1
ndig=mm dig 1 : npos=7 : gosub displaydigit1
ndig=mm dig 0 : npos=10 : gosub displaydigit1
npos=13 : gosub colon1
ndig=ss dig 1 : npos=14 : gosub displaydigit1
ndig=ss dig 0 : npos=17 : gosub displaydigit1

GOTO GPS

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
LCDOUT $FE,$C0+nPos,1
LCDOUT $FE,$C1+nPos,0
LCDOUT $FE,$94+nPos,1
LCDOUT $FE,$95+nPos,0
LCDOUT $FE,$D4+nPos,4
LCDOUT $FE,$D5+nPos,5
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

tasmod
- 3rd April 2014, 11:41
Forgive me oh codemaster Darrel.

The idiot has been programming again. I am but a lowly code serf with an aged addled brain.......................................I forgot to declare the variables in your Month routine.:o

tasmod
- 3rd April 2014, 11:58
Complete working prototype system

7298

Rockwell GPS Module on right. PLL and TCXO board on left. TCXO is small vertical board top left. Small board at top with all wires is 7805 5v reg board.

7299

Rear of LCD showing piggyback decoder.

7300

tasmod
- 15th April 2014, 16:55
Darrel,

Don't know if you are still reading this thread.

I wondered how difficult it would be to add the final two numerical digits of the locator so that it is the full 8 digit string.

I nearly destroyed the prototype when I took it out in the car to test the locator code. The car voltage meant the regulator board became really hot, I was afraid it would fail.

Thanks,

Darrel Taylor
- 15th April 2014, 17:00
The code was based on the pearl script on the Wikipedia page, which only shows how to get 6 digits.

Do you know of somewhere that shows how to get the last two digits?

tasmod
- 15th April 2014, 19:54
Surprisingly I do have it in asm if that helps. I think this is the applicable code after GPS string is parsed. Loc 1 to 8 are the Maidenhead.

I wanted it all in PBP so I could do what I wanted to achieve. The final two are numeric digits. Mine is 03 if that helps re the original code.



;''''''''''''''' Process LONG term '''''''''''''''''''''''''''''''''
bcf STATUS, C
rrf LongD ;Easiest to work with LongD/2 everywhere
btfss STATUS, C ; as Loc works on 2 deg intervals
goto NoLongMinsUpdate

movlw LOW(d'6000') ;Add 1 degree's worth of carry into the
addwf LongMLo ; minutes registers if LongD/2 has a carry
btfsc STATUS, C
incf LongMHi
movlw HIGH(d'6000') ;LongM in range 0 - 12000
addwf LongMHi
NoLongMinsUpdate ;LongD' now in range 0 - 90
btfss NEGLONG
goto PosLong
comf LongD
incf LongD ;LongD' now in 2's complement +/-90

movf LongMLo, w ;Normalise LongM = 12000 - LongM
sublw LOW(d'12000')
movwf LongMLo ;if borrow, C = 0, so increment the subtrahend
btfss STATUS, C
incf LongMHi
movf LongMHi, w
sublw HIGH(d'12000')
movwf LongMHi

decf LongD ;Correct Degrees

PosLong
movlw d'90'
addwf LongD ;Normalise D' to 0-180
movf LongD, w
movwf ALo
clrf AHi

movlw d'10'
call DivMod ;Mod out in A, Div out in B
movf BLo, W
addlw "A"
movwf Loc1
movf ALo, w
addlw "0"
movwf Loc3

rrf LongMHi ;Divide by 4 to give range 0 - 2999
rrf LongMLo
rrf LongMHi
rrf LongMLo
movlw 0x3F
andwf LongMHi

movf LongMLo, w ;Mins * 100 / 4 DIV 125
movwf ALo
movf LongMHi, w
movwf AHi
movlw d'125'
call DivMod ;Mod out in A, Div out in B
movf BLo, w
addlw "A"
movwf Loc5

;Recover MOD term (scaled 0 - 124) which stays in ALo
clrf AHi
bcf STATUS, C
rlf ALo ;Scale to 0 - 248
movlw d'25'
call DivMod ;Mod out in A, Div out in B
movf BLo, w
addlw "0"
movwf Loc7 ;Result in LongD, LongMHi, LongMLo , NEGLONG


;'''''''''''''''''''Now DO LAT term , LatD is already in range 0 - 90''''''''''''''''''
btfss NEGLAT
goto PosLat
comf LatD
incf LatD ;LatD now in 2's complement +/-90

movf LatMLo, w ;Normalise LatM = 6000 - LatM
sublw LOW(d'6000')
movwf LatMLo
btfss STATUS, C ;if borrow, C = 0, so increment the subtrahend
incf LatMHi
movf LatMHi, w
sublw HIGH(d'6000')
movwf LatMHi

decf LatD ;Correct the degrees

PosLat
movlw d'90'
addwf LatD ;Normalise to 0-180
movf LatD, w
movwf ALo
clrf AHi

movlw d'10'
call DivMod ;Mod out in A, Div out in B
movf BLo, W
addlw "A"
movwf Loc2
movf ALo, w
addlw "0"
movwf Loc4

bcf STATUS, C
rrf LatMHi ;Divide by 2 to give range 0 - 2999
rrf LatMLo

movf LatMLo, w ;Mins * 100 / 2 DIV 125
movwf ALo
movf LatMHi, w
movwf AHi
movlw d'125'
call DivMod ;Mod out in A, Div out in B
movf BLo, w
addlw "A"
movwf Loc6

;Recover MOD term (scaled 0 - 124) which stays in ALo
clrf AHi
bcf STATUS, C
rlf ALo ;Scale to 0 - 248
movlw d'25'
call DivMod
movf BLo, w
addlw "0"
movwf Loc8 ;Result in LatD, LatMHi, LatMLo , NEGLAT


ShowLoc
movf Loc1, W
call LcdData
movf Loc2, W
call LcdData
movf Loc3, W
call LcdData
movf Loc4, W
call LcdData
movf Loc5, W
call LcdData
movf Loc6, W
call LcdData
movf Loc7, W
call LcdData
movf Loc8, W
call LcdData


return

tasmod
- 15th April 2014, 19:57
I have made a separate switchable sub for the Big Digit clock which just uses the h, m, s, part of the gps string called alone.

Pic of result. As near accurate to second as code allows.

7310

tasmod
- 16th April 2014, 17:26
Darrel,

I found this regarding the 4th pair.



THIRD PAIR (aa-xx)
Each field can be further divided into (24) 5 minutes (0.083333 degrees) longitudinal
by (24) 2.5 minute (0.0416665 degrees) latitudinal zones.

The first character encodes the longitude and the second encodes the latitude with
letters a thru x (refer to example 3 below).

Example 3:
Longitude = 0.338038 {Refer to example 2}
= 0.338038 / 0.083333
= 4 remainder 0.004706
= e
(location in 5th zone)
Latitude = 0.664048
= 0.664048 / 0.0416665
= 15 remainder 0.0390505
= p
(location in 16th zone)

FOURTH PAIR (00-99)
Each field can be further subdivided into (10) 30 seconds (0.008333 degrees) longitudinal
by (10) 15 seconds (0.004166) latitudinal zones. The first character encodes the longitude
and the second encodes the latitude with numbers 0 thru 9 (refer to example 4 below).

Example 4:
Longitude = 0.004706 {Refer to example 3}
= 0.004706 / 0.008333
= 0 remainder 0.004706
= 0
(location in 1st zone)
Latitude = 0.0390505 {Refer to example 3}
= 0.0390505 / 0.004166
= 9 remainder 0.001556
= 9
(location in 10th zone)

Darrel Taylor
- 18th April 2014, 15:16
Thanks Rob, that is helpful.
But the routines from the pearl script don't leave the variables in the right state to do the last part.

I'm trying to recreate it in a spreadsheet to see what values the variables should have at that point.
But finding time to look at it is difficult right now.

Just wanted to let you know I'm still working on it.

andywpg
- 19th April 2014, 01:05
I'm trying to recreate it in a spreadsheet to see what values the variables should have at that point.
But finding time to look at it is difficult right now.


Don't know if THIS PDF (http://home.comcast.net/~lespeters/PROJECTS/How%20to%20calculate%20your%208-digit%20grid%20square.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

tasmod
- 19th April 2014, 07:27
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.

tasmod
- 19th April 2014, 07:30
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.

Darrel Taylor
- 20th April 2014, 00:18
Able to get 10 digit locator from the inbuilt gps on the phone.
Not sure if the fifth pair is also a 10x10 subdivision, since the PDF only does 8 characters.
But continuing the logic to the next pair, I'm getting that your 10 digit locator is ... IO93ok03ed

Does your Android App give a similar location?

Darrel Taylor
- 20th April 2014, 05:51
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.


; 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



The output of the program looks like this ...


Maidenhead Locator
16F1937, 32-bit Floating Point

LonStr = 00049.77,W
LatStr = 5325.83,N
LOC IO93ok03kh


BTW: Those are really small squares (in red).

7313 (http://no.nonsense.ee/qth/map.html?qth=IO93OK03KH)

tasmod
- 20th April 2014, 10:52
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.

tasmod
- 20th April 2014, 14:01
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.

7315

Darrel Taylor
- 20th April 2014, 23:05
I'm getting 10 and kd instead of 03 and kh which is correct at back of house. kg at front of house

These are some of the results I get ...


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


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.

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.

tasmod
- 21st April 2014, 11:31
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.

Darrel Taylor
- 21st April 2014, 16:28
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.


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


It depends on whether your GPS gives enough data or not.
When recording NMEA sentences from my Android, it gives 6 decimals.

tasmod
- 22nd April 2014, 09:17
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 ??

tasmod
- 22nd April 2014, 10:10
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.

tasmod
- 22nd April 2014, 11:50
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

tasmod
- 22nd April 2014, 15:45
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

Darrel Taylor
- 22nd April 2014, 16:05
With DEC4 change it to this for the Longitude ...

;----[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

And do the same thing with the Latitude.

tasmod
- 22nd April 2014, 18:54
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

Darrel Taylor
- 22nd April 2014, 20:40
I got exactly the same reading as the phone app moving the unit around.
Yahooo!


I'm now looking at making the time display more accurate to the second epoch using DT_Ints
If you are going to add interrupts, you'll need to make some changes.

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.

tasmod
- 23rd April 2014, 09:42
Hmm, guess which pins are not catered for on pcb ?

Redesign methinks. :D

tasmod
- 28th April 2014, 13:00
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.



;--------------------------------------------------------------------------

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

tasmod
- 28th April 2014, 13:02
This is the full code with the Ints active but it's just updating first character.



;
; 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

tasmod
- 29th April 2014, 19:42
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.

HenrikOlsson
- 29th April 2014, 20:56
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).


As I see it at the moment, the code reads the gps string, then parses it,
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".

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.

tasmod
- 30th April 2014, 17:33
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.

HenrikOlsson
- 1st May 2014, 08:23
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.

tasmod
- 1st May 2014, 11:47
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.

astanapane
- 19th May 2018, 21:23
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:


@ 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.8 8,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

What i would like to do is to display:

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.

8661

8662

8663

8664

8665

8666

8667

astanapane
- 20th May 2018, 18:28
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.



'* 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.8 8,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.8 8,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

richard
- 21st May 2018, 11:03
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/picbasic-pro-compiler-3-0-and-later/usercommand/983-strtok-usercmd

a strtok function for pbp

parsing strings with spaghetti code will always by a shortcut to madness

astanapane
- 21st May 2018, 17:47
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.

astanapane
- 21st May 2018, 18:35
i though i found the mistake on the first code for parsing


' /
' [ 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


i did complete the sentense


wait(","),dec3 course,wait("."),dec2 course2,_ ;we wait for 195.80

but still next line which is the date is not dispayed right.

astanapane
- 21st May 2018, 19:38
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.

richard
- 22nd May 2018, 09:58
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




'************************************************* ***************
'* Name : NOKIA_DEMO.PBP *
'* Author : richard *
'* Notice : *
'* : *
'* Date : 16/5/2018 *
'* Version : mssp1 version with bigtxt *
'* Notes : *
'* :FOR pic [email protected] 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,1 95.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

richard
- 22nd May 2018, 11:25
and to emphasize the advantage of an algorithmic approach over spaghetti code



'************************************************* ***************
'* Name : NOKIA_DEMO.PBP *
'* Author : richard *
'* Notice : *
'* : *
'* Date : 16/5/2018 *
'* Version : mssp1 version with bigtxt *
'* Notes : *
'* :FOR pic [email protected] 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,1 95.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

astanapane
- 22nd May 2018, 14:00
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.

astanapane
- 22nd May 2018, 18:09
this is what i get up to now on the display. But is not stable.

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.

richard
- 23rd May 2018, 08:31
this is what i get up to now on the display. But is not stable.

i'm not surprised , given that :-
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

astanapane
- 23rd May 2018, 10:43
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.

astanapane
- 25th May 2018, 20:54
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


serout2 lcd,32,[$73,$00,$04,$00,$FF,$E0," TIME: ",dec2 hh+3," :",dec2 mm," :",dec2 ss,$00]
pause 100

and jump at a label ???


Plusthree:
hh = hh + 3
IF hh = 25 THEN hh = 0
RETURN

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.

Following is the code up to now.


'* 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.8 8,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.8 8,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

richard
- 25th May 2018, 23:11
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

astanapane
- 26th May 2018, 06:25
Hi Richard,

Thanks for the reply. I will try that.

astanapane
- 26th May 2018, 14:25
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

Richard, really appreciate your help and time.

Placing the math

hh = hh +3
hh = hh//24

before the actual command


serout2 lcd,32,[$73,$00,$04,$00,$FF,$E0," TIME: ",dec2 hh," :",dec2 mm," :",dec2 ss,$00]

it solves the time UTC to local time, and the time when goes at 24 then aytomatically shows 00:

Now i'm working on that point when time is 23:59:59 at the next second to change the date.

As i think,it supose to be like that:

if hh = 23 : mm = 59 : ss = 59
then DAY = DAY +1

But then when the Month has only 30 days or 28, we need to specify each month in order to fix the right values and set the parameters.

richard
- 26th May 2018, 16:19
if your time offset from utc is 3.00 hours then the minutes and seconds are irrelevant.
after adding your offset then you need to check if the new hours is >23
if so then add a day to the date then test if that is greater
than the number of days for that month [ don't forget leap years / leap centuries],
then increment the month if there are too many days
you may even need to increment the year , not forgetting to set the new day/month to the appropriate value after all
the incrementing and the new hour to modulo 24

better still get a raspberry pi use python datetime
now=datetime.datetime.utcnow()+datetime.timedelta( hours=3)
and it does everything in one line

astanapane
- 27th May 2018, 12:32
if your time offset from utc is 3.00 hours then the minutes and seconds are irrelevant.
after adding your offset then you need to check if the new hours is >23
if so then add a day to the date then test if that is greater
than the number of days for that month [ don't forget leap years / leap centuries],
then increment the month if there are too many days
you may even need to increment the year , not forgetting to set the new day/month to the appropriate value after all
the incrementing and the new hour to modulo 24

better still get a raspberry pi use python datetime
now=datetime.datetime.utcnow()+datetime.timedelta( hours=3)
and it does everything in one line

ok im trying now to understand your logic which is clear but for me a bit difficult to transfer it to code.

Lets start.

if your time offset from utc is 3.00 hours then the minutes and seconds are irrelevant.


hh = hh +3
hh = hh//24

after adding your offset then you need to check if the new hours is >23


if hh > 23


At the next sentense i have a difficulty to understand how to write the code.
if so then add a day to the date then test if that is greater


DAY = DAY +1

My understanding is, that when the
hh > 23 then with the command
DAY = DAY + 1 we see the change only if numerically the Hour goes to 24.

But we said that hh will not exceed the number 23, after that and correctly will go to 00.

So i need to find the way to tell the code that every time hh goes to 00 to change the date. And keep the same value until the next change to 00, so the date will change forward again.

I might need a help here again.


better still get a raspberry pi use python datetime
now=datetime.datetime.utcnow()+datetime.timedelta( hours=3)
and it does everything in one line

I'm thinking to get either a rasbery pi or arduino pro. I see all amature programmers goes there because coding and labraries are available everywhere.

I will try to picbasic pro here, but i dont understand why there is no categorized code and libraries available for doing our lifes easier, and with that way we also learn faster.

anyway as i said in the begging im an amature in programming and is not my main job. I do it on my spare time and i try to make as simple as possible.

richard
- 27th May 2018, 12:40
hh = hh +3
if hh>23 then
day_added = true
endif
hh = hh//24
.............

if day_added then
day = day +1
if day > numberofdayforthismonth then
day=1
month=month +1
if month >12 then
month=1
year=year+1
endif
endifendifendifendifendifendif lots of endifs

richard
- 27th May 2018, 13:11
anyway as i said in the begging im an amature in programming and is not my main job. I do it on my spare time and i try to make as simple as possible
you may think your way is as simple as possible but its not , its the hardest way by far.
my way breaks the task up into simple logical blocks , each task can then be solved independently ,and in isolation from the other tasks
the entire project can be built one task at a time

task1
read in nmea scentence
task2
verify crc
task3
identify scentence type
task 4
parse a GPRMC scentence

task4a
process a time field

task4b
process a LAT field
task4c
process a LON field

.....etc

simple small steps

astanapane
- 27th May 2018, 13:27
hh = hh +3
if hh>23 then
day_added = true
endif
hh = hh//24
.............

if day_added then
day = day +1
if day > numberofdayforthismonth then
day=1
month=month +1
if month >12 then
month=1
year=year+1
endif
endifendifendifendifendifendif lots of endifs

Hi Richard that is really useful info. Now at this stage i have to make it work. I will set some vars first.

astanapane
- 27th May 2018, 13:30
you may think your way is as simple as possible but its not , its the hardest way by far.
my way breaks the task up into simple logical blocks , each task can then be solved independently ,and in isolation from the other tasks
the entire project can be built one task at a time

task1
read in nmea scentence
task2
verify crc
task3
identify scentence type
task 4
parse a GPRMC scentence

task4a
process a time field

task4b
process a LAT field
task4c
process a LON field

.....etc

simple small steps

Ok if i cannot make it the way i have started, i will follow your advice, as given above.

astanapane
- 28th May 2018, 06:28
Hi Richard,

i think it is working. I need to test it one or two days....

I'll keep you updated because i need also to understand the "true" statement.

astanapane
- 28th May 2018, 14:41
Sorry forgot to upload the code.

The following is the one i have changed in order the date to change when the time is > 23


day_added = 0
hh = hh + 3
if hh > 23 then
day_added = 1
endif
hh = hh//24
if day_added = 1 then
day = day + 1
if day > num_date then ; i havent done anything to this up to now. I need to figure out how to tell the programm about the num_date (No of the day today in this month)
day = 1
if month > 12 then
month = 1
year = year +1
endif
endif
endif

regarding this

if day > num_date then ; i havent done anything to this up to now. I need to figure out how to tell the programm about the num_date (No of the day today in this month)

i think that i need to create a table with 12 months and specify which has 30, 31, or which year then has Feb 28 or 29

richard
- 28th May 2018, 15:10
the only thing I might add is that the conversion from utc to local time only needs to be done if and when the hour changes , its not needed in every loop.
a flag can be set when the utc hour now is != current utc hour , then the flag can be cleared when the conversion is done

astanapane
- 29th May 2018, 11:31
the only thing I might add is that the conversion from utc to local time only needs to be done if and when the hour changes , its not needed in every loop.
a flag can be set when the utc hour now is != current utc hour , then the flag can be cleared when the conversion is done

Hi Richard, once again thanks a lot for your kind help and time.

I work on this very slow, because i need to understand the code, and then i need to test the code every time i change something.

Now i need to fix the months. Please give me some time. I will upload the code and then we can discuss what might need to be done.

As i have it in mind, i need to create a label. Under the label i need to speciafy which month has 30 days and which has 31 at the begging. For the month February i need to specify which YEAR is 28 days and which is 29.

Then i will connect the code:


ay_added = 0
hh = hh + 3
if hh > 23 then
day_added = 1
endif
hh = hh//24
if day_added = 1 then
day = day + 1
if day > num_date then ; i havent done anything to this up to now. I need to figure out how to tell the programm about the num_date (No of the day today in this month)
day = 1
if month > 12 then
month = 1
year = year +1
endif
endif
endif

to the Label which has all the info for each month.

Is that right?

richard
- 29th May 2018, 11:48
getting the number of day in month can be achieved in a few ways

simple is lookup
but resource hungryLOOKUP Index,[Constant{,Constant...}],Var

lookup month,[0,31,28,31,30,,,,,,,,,,,,,],numberofdays

an array
more efficient but uses more sram
arraywrite ndays,[0,31,28,31,30,,,,,,,,,,,,,]
numberofdays=ndays[month]


leap years
are

if ((year//4 = 0) and (year//400 !=0))
if month=2 then numberofdays=numberofdays+1
endif

astanapane
- 30th May 2018, 21:40
Hi Richard,

thanks! i need some time, as at work we need to be prepared for a surgery at a 1 day old baby. I have to design the heart model for pre-surgical planning. But this weekend i will try to fix the code with either lookup or arrays :).

astanapane
- 2nd June 2018, 23:47
i try to understand the "Arraywrite".

So we that command, we set the Months from January to December with values (how many days each months have).

Please let me undestand if that is right:

At the beggining of the program i need to create an array called 'ndays'


ndays VAR BYTE [12] 'create an array with 12 byte location for months values

Then i might need to create an ALIAS the location for each month?


January VAR ndays[0]
February VAR ndays[1]
March VAR ndays[2]
April VAR ndays[3]
May VAR ndays[4]
June VAR ndays[5]
July VAR ndays[6]
August VAR ndays[7]
September VAR ndays[8]
October VAR ndays[9]
November VAR ndays[10]
December VAR ndays[11]


But i guess that i need to specify somewhere how many days each month have.


nday[0] = 31
ndays[1] = 28
ndays[2] = 31
ndays[3] = 30
ndays[4] = 31
ndays[5] = 30
ndays[6] = 31
ndays[7] = 31
ndays[8] = 30
ndays[9] = 31
ndays[10] = 30
ndays[11] = 31

Up to here is that right?

richard
- 3rd June 2018, 00:36
ndays VAR BYTE [13] 'create an array with 12 byte location for months values
nday[0] = 0
nday[1] = 31
ndays[2] = 28
ndays[3] = 31
......
ndays[11] = 30
ndays[12] = 31

ps its easier to arraywrite ndays,[0,31,28....]


reason , when you get the month from the nmea sentence you will store the month as a number from 1 to 12
for the sake of one byte why add the complication of needing to calculate an offset into the lookup table ?

num_days_this_mth = ndays[month] where month = 1 to 12



January VAR ndays[0]
February VAR ndays[1]
March VAR ndays[2]
April VAR ndays[3]
May VAR ndays[4]
June VAR ndays[5]
July VAR ndays[6]
August VAR ndays[7]
September VAR ndays[8]
October VAR ndays[9]
November VAR ndays[10]
December VAR ndays[11]
all of these aliases are just a pointless typing exercise ,unless you have something else in mind for them

astanapane
- 3rd June 2018, 16:01
ndays VAR BYTE [13] 'create an array with 12 byte location for months values
nday[0] = 0
nday[1] = 31
ndays[2] = 28
ndays[3] = 31
......
ndays[11] = 30
ndays[12] = 31

ps its easier to arraywrite ndays,[0,31,28....]


reason , when you get the month from the nmea sentence you will store the month as a number from 1 to 12
for the sake of one byte why add the complication of needing to calculate an offset into the lookup table ?

num_days_this_mth = ndays[month] where month = 1 to 12


all of these aliases are just a pointless typing exercise ,unless you have something else in mind for them

For now,i wont use the Aliases, i thought i could use the name instead of the numbers.

Apart from that i think i need to read more about arraywrite and see more examples if there are in this forum.

astanapane
- 3rd June 2018, 22:03
ok i have a problem using the command arraywrite, because at the compiler doesnt recognise it and it wont make it CAPITAL and bold


arraywrite ndays,[0,31,28,31,30,31,30,31,31,30,31,30,31]
numofdays=ndays[month]


then i tried to use it as well as following


arraywrite ndays,13,NDAY,[0,31,28,31,30,31,30,31,31,30,31,30,31]

where the NDAY


NDAY:
ndays[0] = 0
ndays[1] = 31 'January
ndays[2] = 28 'February
ndays[3] = 31 'March
ndays[4] = 30 'April
ndays[5] = 31 'May
ndays[6] = 30 'June
ndays[7] = 31 'July
ndays[8] = 31 'August
ndays[9] = 30 'September
ndays[10] = 31 'October
ndays[11] = 30 'November
ndays[12] = 31 'December

But no luck, compiler was telling me that there is a syntax error.

So i tried to use the lookup command


day_added = 0
hh = hh + 3 'the Hour from GPS is UTC so for our country in Greece we add +3
if hh > 23 then 'if the hh+3 hour is greater than 23 (23:00) then
day_added = 1 'we check the day added is true
endif
hh = hh//24 'but the hour not exceed the 24 so go to 00:00
if day_added = 1 then 'now if day added is true
day = day + 1 'then ADD 1 day
if day > Numofdays then 'if day is greater than the numbers of the days in this month
lookup month,[0,31,28,31,30,31,30,31,31,30,31,30,31],numofdays 'here it is suppose to look at a table NDAYS for each month
day = 1 'then day goes to number 1
if month > 12 then 'if month is greater than 12 which is December
month = 1 ' then month will go to 1, January
year = year +1 ' and the year will increase by 1
if ((year//4 = 0) and (year//400 != 0)) then
year = 1
if month = 2 then numofdays = numofdays + 1
endif
endif
endif
endif

But i dont know if code is ok, because i Still havent specified the lookup table.

One more question. at the following line:


if ((year//4 = 0) and (year//400 != 0))

the AND in the middle of the statements is says that statement 1 in order to be true , the statement 2 need also to be true. Is that right?

Because as far as i understand, the statement 1 : year//4 = 0 is that we have every 4 years a leap year, then the statement 2: year//400 !=0 which != is not equal.

Could you tell me what does the code in this line mean?



if ((year//4 = 0) and (year//400 != 0))

thanks once again for your time. I know that is difficult for you to explain to someone that tries to understand even the basics. but believe me i search these days in the web for more info about picbasic pro, and in the forum here, but i cannot understand me things because i feel that are not a clear as should be for someone would like to start from zero.

richard
- 3rd June 2018, 23:57
Could you tell me what does the code in this line mean?
if ((year//4 = 0) and (year//400 != 0))



https://en.wikipedia.org/wiki/Leap_year





ok i have a problem using the command arraywrite
arraywrite ndays,[0,31,28,31,30,31,30,31,31,30,31,30,31]
numofdays=ndays[month

what version of pbp , what error
what actual code , snippets of code are pointless for debugging



is syntactically correct for PBP3 the byte vars ndays and month also need to have been declared

eg

ndays var byte[13]
month var byte


your not executing the required steps in any sort of logical order , work out what steps are required then what order the must be done in



day_added = 0
hh = hh + 3 'the Hour from GPS is UTC so for our country in Greece we add +3
if hh > 23 then 'if the hh+3 hour is greater than 23 (23:00) then
day_added = 1 'we check the day added is true
endif
hh = hh//24 'but the hour not exceed the 24 so go to 00:00
if day_added = 1 then 'now if day added is true
day = day + 1 'then ADD 1 day
if day > Numofdays then 'if day is greater than the numbers of the days in this month
how can you test if day is greater than the month has before you have looked up how many days the month has ?

lookup month,[0,31,28,31,30,31,30,31,31,30,31,30,31],numofdays 'here it is suppose to look at a table NDAYS for each month
day = 1 'then day goes to number 1
if month > 12 then 'if month is greater than 12 which is December
month = 1 ' then month will go to 1, January
year = year +1 ' and the year will increase by 1


what is the point of checking if its a leapyear and the month is feb after you have already tested the number of days for month limit
if ((year//4 = 0) and (year//400 != 0)) then
year = 1
if month = 2 then numofdays = numofdays + 1
endif
endif
endif
endif

astanapane
- 4th June 2018, 08:23
Hi Richard,

i need to thank you again for your time. I'll start from the part of what version am i using.

It is an old one, Pic Basic Pro 2.5 with MCSP version 3. I got it from a guy who purchased the PBP 3.0 full pack and gave me this one. I really appreciate his help as well. I have the CD and manual no any identification key on it.

Now with people like you helping here, i'm thinking also to purchase the PBP 3.1 with MCSPX 5. (but i would like to know if i could use one license with two computers) Anyway it is not a place to discuss it right now.

Lets go to coding now.

This is a mesh code, because up to now i try to add code for a specific function and then Quote some parts of the code in order to use them later if needed.


'* Author : LEONARDO BILALIS *
'* Notice : Copyright (c) 2018 [LEONARDOS BILALIS] *
'* : All Rights Reserved *
'* Date : 12/5/2018 *
'* Version : 1.0 *
'* Notes : This is an G.TOP015 G9 MT3333 gps module *
'* : *
'************************************************* ***************

@ 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 = 21
countremain var byte ; we use a countremain to check the incoming from portb.0
pause 1000

;serout2 gps_rx,84, ["$PMTK330,62*1A",13,10] ' check MTK manual configuration

' --------------------[ 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.8 8,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
Day_added var byte
Numofdays var byte 'these are the days of each months
ndays var byte [13] 'create an array with 13 byte location for Months values


' -------------------------------------------------------------------------/
' [ LCD Initialization ] /
'------------------------------------------------------------------------/
high testled

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------------------------

'Here i was planning to send a code to the GPS, i will find out the way later once i fix the Calendar part

;serout gps_rx,84,[$PMTK_103*30,,,]
;pause 100

'-------------------------------------------------------------------/
' [MAIN Program] /
'-----------------------------------------------------------------/

Main:

'-------------------------------------------------------------------------------/
' /
' [ 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,timeout,lostcable,[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/S
wait(","),dec3 degrees2,dec2 minutes2,wait("."),dec4 minutesd2,_;we wait for 02353.3600
wait(","),dir2,_ ;we wait for E/W
wait(","),SKIP 4,_ ; i also used SKIP command but doesnt look like the compiler identified it as long as is not in Capital / Bold. But seems to be working and compiling the code.
wait(","),SKIP 6,_
wait(","),dec2 day,dec2 month,dec2 year] ;we wait for 170518
pause 100

'wait(","),dec1 knots,wait("."),dec2 knots2,_ ;we wait for 0.02
'wait(","),dec3 course,wait("."),dec2 course2,_ ;we wait for 195.80

'------------------------------------------------------------------------------/
' /
' [ Example NMEA Sentense of GNGGA ] /
' [$GNGGA,140405.000,3823.6010,N,02353.3054,E,1,9,0.8 8,0.8,M,35.9,M,,*40 /
' /
'-------------------------------------------------------------------------/

serin2 gps_tx,84,timeout,lostcable,[wait("$GNGGA"),_ ;we wait for GNGGA
wait(","),SKIP 37,_
wait(","),dec2 satno,_
wait(","),SKIP 19]
pause 100

;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


'---------------------------------------------------------------------------------/
' 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 ] /
'--------------------------------------------------------------------------/

serout2 lcd,32,[$45] 'Clear the ulcd 1'44
pause 500

'-----------------------------------------------------------------------------/
' Here we start the calendar conversion /
'---------------------------------------------------------------------------/

; arraywrite ndays,13,NDAY,[0,31,28,31,30,31,30,31,31,30,31,30,31] ; This Code doesnt compile as there is a syntax error.
; numofdays=ndays[month]

day_added = 0
hh = hh + 3 'the Hour from GPS is UTC so for our country in Greece we add +3
if hh > 23 then 'if the hh+3 hour is greater than 23 (23:00) then
day_added = 1 'we check the day added is true
endif
hh = hh//24 'but the hour not exceed the 24 so go to 00:00
if day_added = 1 then 'now if day added is true
day = day + 1 'then ADD 1 day
if day > Numofdays then 'if day is greater than the numbers of the days in this month
lookup month,[0,31,28,31,30,31,30,31,31,30,31,30,31],numofdays
day = 1 'then day goes to number 1
if month > 12 then '
month = 1 'then day goes to number 1
year = year +1 'and the year will increase by 1
if ((year//4 = 0) and (year//400 != 0)) then
year = 1
if month = 2 then
numofdays = numofdays + 1
endif
endif
endif
endif
endif


'--------------------------------------------------------------------------/
' 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," :",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,$0B,$09,$11,$07,$FF,fix," 3D",$00]
pause 100
serout2 lcd,32,[$73,$00,$0B,$00,$ff,$ff," Lat : ",dec2 degrees,"*",dec2 minutes,"'",dec4 minutesd,"@"," ",$00]
pause 100
serout2 lcd,32,[$73,$BE,$0B,$10,$f8,$00,dir,$00]
pause 100
serout2 lcd,32,[$73,$00,$0D,$00,$ff,$ff," Lon :",dec3 degrees2,"*",dec2 minutes2,"'",dec4 minutesd2,"@"," ",$00]
pause 100
serout2 lcd,32,[$73,$BE,$0D,$10,$f8,$00,dir2,$00]

;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 ] /
'---------------------------------------------------------------------------/

'-----------------------------------------------------------------------------/
' [ Calendar days in Months ] /
'---------------------------------------------------------------------------/

'The following i was planning to use it with ARRAYWRITE but cant seem i can get it working.

NDAY:
ndays[0] = 0
ndays[1] = 31 'January
ndays[2] = 28 'February
ndays[3] = 31 'March
ndays[4] = 30 'April
ndays[5] = 31 'May
ndays[6] = 30 'June
ndays[7] = 31 'July
ndays[8] = 31 'August
ndays[9] = 30 'September
ndays[10] = 31 'October
ndays[11] = 30 'November
ndays[12] = 31 'December
'-----------------------------------------------------------------------------/
' [ Waiting for GPS signal ] /
'---------------------------------------------------------------------------/

notfix: ' Still looking for fixed signal

serout2 lcd,32,[$73,$00,$03,$11,$07,$ff," Waiting for GPS",$00]
pause 100
hh = hh + 3
hh = hh//24
serout2 lcd,32,[$73,$03,$06,$10,$ff,$E0," Time:",dec2 hh," :",dec2 mm," :",dec2 ss,$00]
pause 1000
serout2 lcd,32,[$73,$00,$08,$10,$07,$ff,rep "." \dots,$00]

pause 200
serout2 lcd,32,[$45] ' clears the LCD
pause 100


goto main 'returns to main

'-----------------------------------------------------------------------------/
' [ Connection lost Please check the GPS ] /
'---------------------------------------------------------------------------/

lostcable:

serout2 lcd,32,[$73,$00,$03,$11,$f8,$00," Connection lost",$00]
pause 200
serout2 lcd,32,[$73,$01,$06,$10,$07,$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

Regarding the following part of the code, MARKED items with RED by Richard i will fix it on my next message. I think it is clear what needs to be done. Thanks once again.


day_added = 0
hh = hh + 3 'the Hour from GPS is UTC so for our country in Greece we add +3
if hh > 23 then 'if the hh+3 hour is greater than 23 (23:00) then
day_added = 1 'we check the day added is true
endif
hh = hh//24 'but the hour not exceed the 24 so go to 00:00
if day_added = 1 then 'now if day added is true
day = day + 1 'then ADD 1 day
if day > Numofdays then 'if day is greater than the numbers of the days in this month
how can you test if day is greater than the month has before you have looked up how many days the month has ?

lookup month,[0,31,28,31,30,31,30,31,31,30,31,30,31],numofdays 'here it is suppose to look at a table NDAYS for each month
day = 1 'then day goes to number 1
if month > 12 then 'if month is greater than 12 which is December
month = 1 ' then month will go to 1, January
year = year +1 ' and the year will increase by 1


what is the point of checking if its a leapyear and the month is feb after you have already tested the number of days for month limit
if ((year//4 = 0) and (year//400 != 0)) then
year = 1
if month = 2 then numofdays = numofdays + 1
endif
endif
endif
endif

astanapane
- 8th June 2018, 09:23
This weekend i will try to make some changes. I also found out that the NMEA sentence $GPVTG (from a chip MT3339) or $GNVTG (from a chip MT3333, with GLONASS) has the info of the speed in Km/h so it will be simpler to display speed at km/h.

astanapane
- 11th June 2018, 22:24
ok it is being some time since i made a change to the code. These days i l was trying to figure out how to embed the speed in my code. I left the part of the code with Days, Months, Years, on a side for a while.

Tomorrow i will upload the code with the speed embeded, and the limits at 10Km/h, 50Km/h, 100Km/h. I have placed for the indication of each limit some LEDs at A Port.

I have also noticed that code is expanding, and at the end i might need a bigger PIC chip.

astanapane
- 12th June 2018, 10:33
These days i tried to use the $GPVTG sentence and get the speed from there as it is in Km/h

First of all the format of the $GPVTG sentence is as follows.

1. X.XX for the left X before the "dot" when the speed is less than 10km/h
2. XX.XX for the XX before the "dot" when the speed is more than 9 km/h and less than 100km/h
2. XXX.XX for the XXX before the "dot" when the speed is more than 99km/h

For the .XX so the two digits after the "dots" those are the decimal part and stays stable in the $GPVTG sentence.

We need to check when the speed change, where is the dot.



serin2 gps_tx,84,timeout,lostcable,[wait("GPVTG"),wait("N"),_
wait(","),TS[0],TS[1],TS[2],TS[3],TS[4],_
wait(","),SKIP 3]

for i = 1 to 3
if TS[i]="." then decimal = i 'TOTAL SPEED. find which character is the decimal point
next i

select case decimal 'if the gps shows 1.45 it may be 145
'for the conversion ASCII to number we can use the -48
case 1 'decimal position is x.xx
speed = (10*(TS[0]-48))+(TS[2]-48)
case 2 'decimal position is xx.xx
speed = (100*(TS[0]-48))+(10*(TS[1]-48))+(TS[3]-48)
case 3 'decimal position is xxx.xx
speed = (1000*(TS[0]-48))+(100*(TS[1]-48))+(10*(TS[2]-48))
end select

gosub OVERSPEED:


OVERSPEED:

if SPEED > 1000 then ' 100Km/h
high porta.3
low porta.2
low porta.1
else
LOW porta.3

if SPEED > 500 then ' 50Km/h
high porta.2
low porta.1
else
LOW porta.2

if SPEED > 100 then ' 10Km/h
high porta.1
else
LOW porta.1

endif
endif
endif
return


At the moment the code is working as it is, but i think i need to change the multiplication of 10*, 100* and 1000*, to 1*, 10* and 100*, because as you see at the OVERSPEED: i use 1000 for the 100 km/h, 500 for the 50km/h and 100 for the 10km/h.
But then the dot will change place, or i will not being able to identify the right place of it. Anyhow the code is working for the speed.

Still i need to:

1. Make the Day/Month/Year to work properly, now i think i will not have a problem to solve this.

2. The display data are refreshed, my goal is to make the data stable all the time at the screen and change only the needed values.

astanapane
- 12th June 2018, 18:01
Could you tell me if it is a good choise continuing this project with PIC16f887 i/p?

richard
- 13th June 2018, 00:47
Could you tell me if it is a good choise continuing this project with PIC16f887

its basically the same very limited chip you are presently using with a few more pins.
if you are serious in wanting to calculate maidenhead then no its a poor choice.
at least get something like 16f18326 ,16f18875 or better still a pic18 chip
I like pic18f26k42 [if you have pbp3.1] or a pic18f26k22 with pbp3.0 for this sort of project

astanapane
- 13th June 2018, 08:31
Hi Richard,

thanks a lot again for your reply. I'm trying to use a chip that i can program with pickit2 as i dont want to spend any money for the pickit 3.

I'm planning to purchase the PBP3.1 software, than spend for pickit3 hardware. Im happy with pickit 2, and a close supported device as far as i see is the pic18f26k20.

At the moment in stock i have the pic18f4550, pic16f1939. What is the feature of the pic we are looking for. The CPU SPEED (8bit or 16bit...), the SRAM, timers?

richard
- 13th June 2018, 09:09
What is the feature of the pic we are looking for. The CPU SPEED (8bit or 16bit...), the SRAM, timers?


its not my project I don't know what you have planned but generally speaking if you are dealing with parsing strings from a serial stream , more sram is better ,the possibility of more speed is always better. make sure there is plenty of flash space to hold the program. if its a one off project get the best chip with enough pins and features required .
if you are going to do large amounts of and/or complex math then pic18's with a hardware multiplier can increase speed and
reduce code size

pk2 will program 18fk22 series , once you have used a chip with pps there is no going back. the k42 series chips leave the others in the dust

astanapane
- 13th June 2018, 09:38
thanks for the info once again. Is not a place to analyze it more, and im the one i need to understand better the differences of the chip's performance.

Last question based on the pps, do you mean pulse per second? OK just checked this, Peripheral pin select :)

I've also checked the supported devices from PICkit2 for k22 series : PIC18F13K22 PIC18LF13K22 PIC18F14K22 PIC18LF14K22

No K42 is supported.

richard
- 13th June 2018, 11:17
your pk2 device list file is out of date, there are many more k22 chips supported .

astanapane
- 13th June 2018, 13:30
ooops i dint know.

i tried many times to check if there is a newer version and didnt find any that 2.61 with the devicefile 1.61.

I will check again. thanks for the update really i didnt know it.

astanapane
- 20th June 2018, 15:36
First of all i need to Apologize for my absent.

Now :

1. Didnt find and Update for pickit2. Not a problem because i will think to use the following PICs and i see that pickit2 at the moment supports it.

2. As far as the pic16f88 is limited in ram i need to step up and use a better microcontroller. Im Looking at the PIC18F4550 or PIC18F2550.

3.The project as i have it in mind need to have an SD in order to store the Data from GPS Nmea.

I found out that only a microcontroller with 48mhz supports something like that. Apart from that i have a question.

May i use the same speed for All the peripherals SD, Ulcd, GPS? Or do i need to specify different one for each module?

May i use 48mhz for processor speed and use low speed baudrate to communicate for Serial?

Could You help me and clarity what i need for each GPS, SD, Ulcd?

So i need to communicate Serial with GPS module and then i need to store the raw Nmea Data to SD and display what i need from the Nmea protocols to display.

midali
- 20th June 2018, 19:35
ooops i dint know.

i tried many times to check if there is a newer version and didnt find any that 2.61 with the devicefile 1.61.



The file "PK2Devicefile.dat" have not edited the microcontroller type. Use DEVICE EDITOR software from here https://sites.google.com/site/pk2devicefileeditor/ and here is the Device ID PIC's

richard
- 21st June 2018, 01:32
The project as i have it in mind need to have an SD in order to store the Data from GPS Nmea.

I found out that only a microcontroller with 48mhz supports something like that

where did you find that , its not what I understand the case to be. are you confusing usb support for sd card support ?


May i use the same speed for All the peripherals SD, Ulcd, GPS? Or do i need to specify different one for each module?


unless you specify what spi rate the sd card supports and what sd card system you intend to use [sdfs3 ? fat16? fat 32?] along with
the baud rate used for the serial I/f's and your osc speed it would be guesswork only.




Could You help me and clarity what i need for each GPS, SD, Ulcd?

not really you need to supply a lot more info


i need to communicate Serial with GPS module and then i need to store the raw Nmea Data to SD and display what i need from the Nmea protocols to display
compared to PIC18F4550 or PIC18F2550 a pic 18f26k22 has two times the flash memory , sram ,spi ports, eusarts has more timers and can run at 64 MHz . I think it would be a good fit
for that sort of project

astanapane
- 21st June 2018, 06:46
The file "PK2Devicefile.dat" have not edited the microcontroller type. Use DEVICE EDITOR software from here https://sites.google.com/site/pk2devicefileeditor/ and here is the Device ID PIC's

Really thanks a lot for your kind help. I would keep the dat. file as it is for now. I'm a bit afraid to play with that .dat file at the moment. If i need to use a PIC that is not on the pickit2 list, then i will give it a try. :)

astanapane
- 21st June 2018, 07:40
The project as i have it in mind need to have an SD in order to store the Data from GPS Nmea.
I found out that only a microcontroller with 48mhz supports something like that

where did you find that , its not what I understand the case to be. are you confusing usb support for sd card support ?

Oops well i'm wrong, base on the following and FAT16 it is not necessary.

http://melabs.com/samples/PBP-mixed/sdfs3.htm

I was confused with this link as they specify high MCU speed for FAT32

http://www.picbasic.co.uk/forum/showthread.php?t=18370


May i use the same speed for All the peripherals SD, Ulcd, GPS? Or do i need to specify different one for each module?

unless you specify what spi rate the sd card supports and what sd card system you intend to use [sdfs3 ? fat16? fat 32?] along with
the baud rate used for the serial I/f's and your osc speed it would be guesswork only.



Regarding Serial speed baudrate:

1) For GPS, i have tried to send the "right" command for increase the baudrate, with no sucess....it seems that the GPS receives the command but does not like it :P.
2) ulcd seems to work with higher baud rate, but i need to configure the delay times for each command. I havent really understand how to increase the baudrate corresponding to delays. The ulcd needs some delay time to accept the command and display it properly. Is it right?
3) SD card with FAT 16 (when i reach that point we will discuss further). At the moment it is clear that up to 2GB fat 16 is required and is not necessary high MCU speed. But i will try to get the maximum from the PIC.


Could You help me and clarity what i need for each GPS, SD, Ulcd?

not really you need to supply a lot more info

I understand that im not clear, as i really wont have the knowledge to explain it. Actually im confused with MCU speed, which is the speed that PIC running each command and calculate each command, with the speed of the communication ports.

I guess that a higher MCU speed is better in order to calculate faster the information from the peripherals. I know my questions are too basic, and believe me i start reading all these stuff in order to understand better. I feel that you cannot help me i i dont understand these basic processes of the PIC.

So i started to read about MCU speed, clock and counter.


i need to communicate Serial with GPS module and then i need to store the raw Nmea Data to SD and display what i need from the Nmea protocols to display.

compared to PIC18F4550 or PIC18F2550 a pic 18f26k22 has two times the flash memory , sram ,spi ports, eusarts has more timers and can run at 64 MHz . I think it would be a good fit
for that sort of project



Really appreciate your advice....PIC18LF26K22 or PIC18LF4550 fits to my project better because i would like to use a single 3.7V Lipo battery not more than 800-1000mha. The Final circuit will have:

1. PIC18LF26K22 or PIC18LF4550
2. GPS module for all the info....Date, Time, Speed, Coordinates etc.
3. SD for storage the raw NMEA Data
4. A display only for the on the go use. For battery saving, a ulcd will not be used normally. SD will keep the info.

Many thanks once again.

I would like to apologize for "breaking" the original TOPIC. Is it possible an Admin to move all the discussion i have started from POST #66, in a NEW thread? Thanks.....

richard
- 21st June 2018, 09:16
1) For GPS, i have tried to send the "right" command for increase the baudrate, with no sucess....it seems that the GPS receives the command but does not like it :P.
the data sheet for the module should resolve that issue


2) ulcd seems to work with higher baud rate, but i need to configure the delay times for each command. I havent really understand how to increase the baudrate corresponding to delays. The ulcd needs some delay time to accept the command and display it properly. Is it right?

the ulcd data sheet should give you that information


3) SD card with FAT 16 (when i reach that point we will discuss further). At the moment it is clear that up to 2GB fat 16 is required and is not necessary high MCU speed. But i will try to get the maximum from the PIC.

since sd cards use spi [a synchronous data transfer method] cpu osc speed is largely irrelevant as long as it not too fast for the card/mssp combination
when you use the mssp module there are several spi clock options.


a PIC18LF4550 is in my opinion not a good choice , the project calls for a chip with two eusarts.




I would like to apologize for "breaking" the original TOPIC. Is it possible an Admin to move all the discussion i have started from POST #66, in a NEW thread? Thanks.....
I agree, as I have said from the start what you are asking has no relevance to maidenhead in any way shape or form

astanapane
- 21st June 2018, 11:09
Hi Richard,

thanks once again for your time and help. You are right regarding the 18LF4550. It is not for my application.

astanapane
- 21st June 2018, 16:45
The leap years, month and days are fixed. Please let me know if you find any mistake on this.

Is there any way now to test the leap year?



arraywrite ndays,13,NDAY,[0,31,28,31,30,31,30,31,31,30,31,30,31]

if ((year//4 = 0) and (year//400 != 0)) then 'check the leap year
ndays[2] = 29 'then February has 29 days
else
ndays[2] = 28 'else has 28 days
endif
hh = hh + 3 'the Hour from GPS is UTC so for our country in Greece we add +3
if hh>23 then 'if the hh+3 hour is greater than 23 (23:00) then
day = day + 1 'we check the day added is true
hh = hh//24 'but the hour not exceed the 24 so go to 00:00
if (day > ndays[month]) then
month = month + 1
day = 1
if (month > 12) then
year = year + 1
month = 1
endif
endif
endif


NDAY:
ndays[0] = 0
ndays[1] = 31 'January
ndays[2] = 28 'February
ndays[3] = 31 'March
ndays[4] = 30 'April
ndays[5] = 31 'May
ndays[6] = 30 'June
ndays[7] = 31 'July
ndays[8] = 31 'August
ndays[9] = 30 'September
ndays[10] = 31 'October
ndays[11] = 30 'November
ndays[12] = 31 'December

Apart from that i have found the attached file for the PICKIT2. Do you have any reference on that?

MichelJasmin
- 21st June 2018, 17:43
1) For GPS, i have tried to send the "right" command for increase the baudrate, with no sucess....it seems that the GPS receives the command but does not like it :P.


Some modules requires you to send a checksum at the end of the command. Here for a NEO-6M GPS Module:



'Turn off RMC - Recommended minimum specific GPS/Transit data
hserout2 ["$PUBX,40,RMC,0,0,0,0,0,0*47", 13, 10]
pause 500

'Turn off GSA - GPS DOP and active satellites
hserout2 ["$PUBX,40,GSA,0,0,0,0,0,0*4E", 13, 10]
pause 500

'Turn off GSV - GPS Satellites in view
hserout2 ["$PUBX,40,GSV,0,0,0,0,0,0*59", 13, 10]
pause 500

'Turn off GLL - Geographic position, latitude / longitude
hserout2 ["$PUBX,40,GLL,0,0,0,0,0,0*5C", 13, 10]
pause 500

'Turn on ZDA
hserout2 ["$PUBX,40,ZDA,0,1,0,0,0,0*45", 13, 10]
pause 500


Do you really need to change the baud rate? If you are just logging then 9600 is more than enough.

FYI, here is my source for most of the NMEA sequences: http://aprs.gids.nl/nmea/

astanapane
- 21st June 2018, 18:20
Some modules requires you to send a checksum at the end of the command. Here for a NEO-6M GPS Module:



'Turn off RMC - Recommended minimum specific GPS/Transit data
hserout2 ["$PUBX,40,RMC,0,0,0,0,0,0*47", 13, 10]
pause 500

'Turn off GSA - GPS DOP and active satellites
hserout2 ["$PUBX,40,GSA,0,0,0,0,0,0*4E", 13, 10]
pause 500

'Turn off GSV - GPS Satellites in view
hserout2 ["$PUBX,40,GSV,0,0,0,0,0,0*59", 13, 10]
pause 500

'Turn off GLL - Geographic position, latitude / longitude
hserout2 ["$PUBX,40,GLL,0,0,0,0,0,0*5C", 13, 10]
pause 500

'Turn on ZDA
hserout2 ["$PUBX,40,ZDA,0,1,0,0,0,0*45", 13, 10]
pause 500


Do you really need to change the baud rate? If you are just logging then 9600 is more than enough.

FYI, here is my source for most of the NMEA sequences: http://aprs.gids.nl/nmea/

Yep, thanks a lot.....i've seen all that, for my case i have the MKT 3333 and 3339 module. Which have the following



'serout2 gps_rx,84, ["$PMTK314,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0*0D",13,10]
'serout2 gps_rx,84, ["$PMTK251,57600*2C",13,10] ' baudrate, check MTK manual configuration
'serout2 gps_rx,84, ["$PMTK220,200*2C",13,10] ' 200(millisecond)=0.2(sec)-->1/0.2 pps=5 Hz



The problem is that it does not work for some reason.

I think i need to use the HSEROUT2 instead of SEROUT2. I'm confused at this point.

I get online help for checksum from this site

http://www.hhhh.org/wiml/proj/nmeaxor.html

astanapane
- 21st June 2018, 21:29
Ok i have right now:

1. TX port which is connected to ulcd. Baudrate : 38400

Example code:

pause 2000
serout2 LCD,6,[$55] ' uOLED Initialize this is the 'U' character of autoband rate to LCD
pause 500
serout2 LCD,6,[$56,$01] ' this is the Version info
pause 500
serout2 LCD,6,[$45] ' clear the lcd
pause 100


2. RX port from GPS module. Baudrate : 9600

Example code:

;serin2 gps_tx,84,timeout,lostcable,[wait("$GNRMC"),_ ;we wait for $GNRMC

The GPS at the moment is locked at 9600. Via the serial terminal GPS software i set it to 19200 and accepts the command. But only for the time the module is connected to the power. When we disconnect the power from GPS, the default commands are set.

I dont mind for that right now as i found out that i can communicate with PIC at 19200 with GPS and receive the commands on the display.

The setting for the Clock Speed is 8Mhz.

Now if i increase the speed of the baudrate with GPS and goes up to 38400 then i cannot display anything.

I did an experiment and added an external Crystal of 16 Mhz. For my surprise values presented on the display.

I have a question now. something i dont like with the following code:


@ ERRORLEVEL -306 ; this command prevents the compiler to give you a notice of
; crossing page boundary - make sure bits are set
#CONFIG
__config _CONFIG1, _HS_OSC & _WDT_OFF & _LVP_OFF & _CP_OFF
#ENDCONFIG

Include "MODEDEFS.BAS"
DEFINE OSC 8
OSCCON=%01110000 '8 Mhz

Why should i need to add both of the lines?


DEFINE OSC 8
OSCCON=%01110000 '8 Mhz

In case i remove any of these, it compiles ok, but program is not working.

I need to specify that this is an internal OSC, but above in the configuration bits i have put _HS_OSC (if i remember that must be set from the manual)

Is it right?

thanks a lot for your help once again.

richard
- 21st June 2018, 23:58
Why should i need to add both of the lines?

OSCCON=%01110000 '8 Mhz ;sets the actual fosc speed




DEFINE OSC 8 ; tells the compiler what fosc speed to base timing calculation on


software timed serout2 @ > 38400 baud with fosc < 8mhz may have an unacceptable error rate

richard
- 22nd June 2018, 00:02
if ((year//4 = 0) and (year//400 != 0)) then 'check the leap year
ndays[2] = 29 'then February has 29 days
else
ndays[2] = 28 'else has 28 days
endif
the above code only needs to run if month = 2


Is there any way now to test the leap year?
only the obvious , send it a few go nogo date strings and check the result

astanapane
- 22nd June 2018, 06:39
OSCCON=%01110000 '8 Mhz ;sets the actual fosc speed




DEFINE OSC 8 ; tells the compiler what fosc speed to base timing calculation on


software timed serout2 @ > 38400 baud with fosc < 8mhz may have an unacceptable error rate

I understood from the experiment that something didnt go well when i increased the baudrate at 38400 with the 8Mhz internal speed.

Is there any equation or a factor that calculates this corresponding.

thanks a lot.

astanapane
- 22nd June 2018, 16:08
The project will be on hold for 10 days. Im about to order a PIC18F26K22 and some PIC18F46K22 along with some 16mhz crystals.

astanapane
- 22nd June 2018, 21:41
ok everyday i read more and more and i understand things.

I wanted to be right regarding the fuses, as far as at the moment i use the internal OSC, here it is....


@ ERRORLEVEL -306 ; this command prevents the compiler to give you a notice of
; crossing page boundary - make sure bits are set
#CONFIG
__config _CONFIG1,_INTRC_IO & _WDT_OFF & _LVP_OFF & _CP_OFF
#ENDCONFIG

got the info from the following:


;MPASM __CONFIG Directive Options
;
; The PBP default configuration for the PIC16F88 is:
;
; #CONFIG
; __config _CONFIG1, _HS_OSC & _WDT_ON & _LVP_OFF & _CP_OFF
; #ENDCONFIG


; Available __CONFIG labels for PIC16F88:
;
;CONFIG1 Options
;
; Oscillator Selection bits
; _FOSC_EXTRCCLK ;EXTRC oscillator; CLKO function on RA6/OSC2/CLKO
; _EXTRC_CLKOUT ;EXTRC oscillator; CLKO function on RA6/OSC2/CLKO
; _FOSC_EXTRCIO ;EXTRC oscillator; port I/O function on RA6/OSC2/CLKO
; _EXTRC_IO ;EXTRC oscillator; port I/O function on RA6/OSC2/CLKO
; _FOSC_INTOSCCLK ;INTRC oscillator; CLKO function on RA6/OSC2/CLKO pin and port I/O function on RA7/OSC1/CLKI pin
; _INTRC_CLKOUT ;INTRC oscillator; CLKO function on RA6/OSC2/CLKO pin and port I/O function on RA7/OSC1/CLKI pin
; _FOSC_INTOSCIO ;INTRC oscillator; port I/O function on both RA6/OSC2/CLKO pin and RA7/OSC1/CLKI pin
; _INTRC_IO ;INTRC oscillator; port I/O function on both RA6/OSC2/CLKO pin and RA7/OSC1/CLKI pin
; _FOSC_EC ;ECIO; port I/O function on RA6/OSC2/CLKO
; _EXTCLK ;ECIO; port I/O function on RA6/OSC2/CLKO
; _FOSC_HS ;HS oscillator
; _HS_OSC ;HS oscillator
; _FOSC_XT ;XT oscillator
; _XT_OSC ;XT oscillator
; _FOSC_LP ;LP oscillator
; _LP_OSC ;LP oscillator
;
; Watchdog Timer Enable bit
; _WDTE_ON ;WDT enabled
; _WDT_ON ;WDT enabled
; _WDTE_OFF ;WDT disabled
; _WDT_OFF ;WDT disabled
;
; Power-up Timer Enable bit
; _PWRTE_OFF ;PWRT disabled
; _PWRTE_ON ;PWRT enabled
;
; RA5/MCLR/VPP Pin Function Select bit
; _MCLRE_ON ;RA5/MCLR/VPP pin function is MCLR
; _MCLR_ON ;RA5/MCLR/VPP pin function is MCLR
; _MCLRE_OFF ;RA5/MCLR/VPP pin function is digital I/O, MCLR internally tied to VDD
; _MCLR_OFF ;RA5/MCLR/VPP pin function is digital I/O, MCLR internally tied to VDD
;
; Brown-out Reset Enable bit
; _BOREN_ON ;BOR enabled
; _BODEN_ON ;BOR enabled
; _BOREN_OFF ;BOR disabled
; _BODEN_OFF ;BOR disabled
;
; Low-Voltage Programming Enable bit
; _LVP_ON ;RB3/PGM pin has PGM function, Low-Voltage Programming enabled
; _LVP_OFF ;RB3 is digital I/O, HV on MCLR must be used for programming
;
; Data EE Memory Code Protection bit
; _CPD_OFF ;Code protection off
; _CPD_ON ;Data EE memory code-protected
;
; Flash Program Memory Write Enable bits
; _WRT_OFF ;Write protection off
; _WRT_PROTECT_OFF ;Write protection off
; _WRT_256 ;0000h to 00FFh write-protected, 0100h to 0FFFh may be modified by EECON control
; _WRT_PROTECT_256 ;0000h to 00FFh write-protected, 0100h to 0FFFh may be modified by EECON control
; _WRT_2048 ;0000h to 07FFh write-protected, 0800h to 0FFFh may be modified by EECON control
; _WRT_PROTECT_2048 ;0000h to 07FFh write-protected, 0800h to 0FFFh may be modified by EECON control
; _WRT_ALL ;0000h to 0FFFh write-protected
; _WRT_PROTECT_ALL ;0000h to 0FFFh write-protected
;
; In-Circuit Debugger Mode bit
; _DEBUG_OFF ;In-Circuit Debugger disabled, RB6 and RB7 are general purpose I/O pins
; _DEBUG_ON ;In-Circuit Debugger enabled, RB6 and RB7 are dedicated to the debugger
;
; CCP1 Pin Selection bit
; _CCPMX_RB0 ;CCP1 function on RB0
; _CCP1_RB0 ;CCP1 function on RB0
; _CCPMX_RB3 ;CCP1 function on RB3
; _CCP1_RB3 ;CCP1 function on RB3
;
; Flash Program Memory Code Protection bit
; _CP_OFF ;Code protection off
; _CP_ON ;0000h to 0FFFh code-protected (all protected)
; _CP_ALL ;0000h to 0FFFh code-protected (all protected)
;
;CONFIG2 Options
;
; Fail-Safe Clock Monitor Enable bit
; _FCMEN_ON ;Fail-Safe Clock Monitor enabled
; _FCMEN_OFF ;Fail-Safe Clock Monitor disabled
;
; Internal External Switchover bit
; _IESO_ON ;Internal External Switchover mode enabled
; _IESO_OFF ;Internal External Switchover mode disabled

astanapane
- 24th June 2018, 14:44
the project will continue in here: http://www.picbasic.co.uk/forum/showthread.php?t=23951

along with a bases of the needed understandings.