PDA

View Full Version : GPS $GPRMC to PIC16F684. Need help with SERIN2



xnihilo
- 25th November 2009, 07:51
Hi Guys,

I've wanted for some time now to build a simple application where a GPS mouse would be connected to a PIC16F684 to collect $GPRMC string and display some basic information on an LCD screen and when speed exceeds a set value, a buzzer would beep.
Using several sources I found on the net, I tried to assemble the simple circuit below and wrote/compiled some PBP code but it does not seem to be working and I'm wondering what's wrong.

The link to the Rikaline X5 GPS is here (it has RS232 and TTL I/Os):
http://www.tango-lasergame.be/GPS-6010-X5--Manual-E.pdf

I'm using a 2*16 characters LCD (which displays what it should display BTW, so the wiring is fine). I'm using a pic16f684 where A0 is connected to GPS TX (at TTL level). A1 is the piezzo buzzer. C0 to C3 are the LCD datalines 4 to 7 (4 bits mode), C4 is R/S with external 10K WPU, C5 is the Enable pin.

I connected the GPS and the application circuit to the same 5v source (9v power supply going through a LDO voltage regulator).
The pic pin 1 and pin 14 are linked using a 0.1Uf ceramic disc and 10Uf electrolytic capacitors for filtering.

When I run the program, it displays the right stuff on the LCD until it reaches the "GPS" label and stalls displaying "Serin start", which means is gets stuck in the SERIN2 instruction. It should either finish the instruction while all the $GPRMC data are collected or jump to the timeout subroutine. In both cases the LCD display should change but id does not, which means there is probably a problem with serin.
It should process the SERIN2 instruction even when there is no GPS, so for now I don't care if the GPS is not working.

The PIC16F684 has no hardware EUSART and I beleive the SERIN2 is a kind of bit banging instruction that can be used on any I/O pin. A0 is a TTL level I/O pin by the way.

Could anyone have a look at the code and check what may be wrong. It is probably obvious but I don't get it.

Thanks for any help.

Regards



'based on: http://list.picbasic.com/forum/messages/6851/7091.html?1080565370
and other sources on the net

@ device pic16F684, intrc_osc_noclkout, BOD_OFF, PWRT_OFF, wdt_off, mclr_off, protect_off

'quid freq horloge requise?


DEFINE OSC 8 'set OSC value to 8MHz for instructions PAUSE, PAUSEus and SOUND (instead of default 4MHz)

DEFINE LCD_DREG PORTC 'data port out is portC
DEFINE LCD_DBIT 0 'data on portC0-portC3

DEFINE LCD_RSREG PORTC 'r/s is on portC.4, with 10K WPU
DEFINE LCD_RSBIT 4

DEFINE LCD_EREG PORTC 'enable is on portC.5
DEFINE LCD_EBIT 5

DEFINE LCD_BITS 4 '4bits data bus
DEFINE LCD_LINES 2 '2lines display
DEFINE LCD_COMMANDUS 2000 '2ms cmd delay
DEFINE LCD_DATAUS 50 '50us data delay

INTCON = 0 'disable interrupts and clear int flags
OSCCON = %01110001 'int osc, hs, 8mhz
CMCON0 = %00000111
ANSEL = %00000000
OPTION_REG = %11111111

'alias in SERIN2
GPSin VAR PORTA.0 'A0 has TTL levels

TRISA = %000001
TRISC = 0

PORTA = %000001 'A0 is used for gps input, SERIN2 bitbanging (software eusart)
PORTC = 0

WPUA = 0


'Variables / Constants for GPS in SERIN2:
timeout CON 3000
'MODE: http://www.melabs.com/resources/pbpmanual/ser2modes.htm
mode CON 24764 '16572 + 8192 (bit 13) = 4800 Driven Inverted Even




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
'for kmph calculation
Speed Var byte[5]
SpeedKnots VAR WORD
SpeedKm VAR WORD
Temp VAR BYTE
Dummy VAR WORD
i var byte



'programming custom characters
LCDOUT $FE,$40,$00,$0A,$0A,$00,$11,$0E,$00,$00 ' Cust Char #0: happy smiley
LCDOUT $FE,$48,$0E,$15,$1B,$19,$1B,$15,$0E,$00 ' Cust Char #1: copyright
LCDOUT $FE,$50,$0E,$0E,$1F,$0E,$04,$00,$1F,$00 ' Cust Char #2: press
LCDOUT $FE,$58,$0A,$1F,$1F,$1F,$0E,$04,$00,$00 ' Cust Char #3: heart
LCDOUT $FE,$60,$03,$05,$19,$19,$19,$19,$05,$03 ' Cust Char #4: speaker
LCDOUT $FE,$68,$00,$00,$04,$0E,$0E,$0E,$0E,$00 ' Cust Char #5: bullet
LCDOUT $FE,$70,$1F,$11,$11,$11,$11,$11,$11,$1F ' Cust Char #6: empty square
LCDOUT $FE,$78,$04,$0E,$1F,$0E,$0E,$00,$1F,$00 ' Cust Char #7: release


for i = 0 to 10
HIGH PORTA.1
pause 300
LOW PORTA.1
PAUSE 300
NEXT i


'TEST block
'display a sample of the custom charas
LCDOUT $fe,1,"new charas: "
LCDOUT $fe,$c0,0,1,2,3,4,5,6,7 'will write the "speaker" symbol.
PAUSE 4000
'--------------------------------------------------------------------------------------------------------------------------------------------

'PAUSE 3000 'let the power level stabilize

LCDOUT $fe,1,"GPS display"
PAUSE 2000

LCDOUT $fe,1,"24.11.2009"
PAUSE 2000

'************************************************* ******************************
'************************************************* ******************************


'eg2. $GPRMC,225446,A,4916.45,N,12311.12,W,000.5,054.7,1 91194,020.3,E*68
'225446 Time of fix 22:54:46 UTC A Navigation receiver warning A = Valid position, V = Warning 4916.45,N Latitude 49 deg. 16.45 min. North 12311.12,W Longitude 123 deg. 11.12 min. West 000.5 Speed over ground, Knots 054.7 Course Made Good, degrees true 191194 UTC Date of fix, 19 November 1994 020.3,E Magnetic variation, 20.3 deg. East *68 mandatory checksum
'1 Knot = 1.852 Kilometers per Hour
'45.12 Knots = 83.56224 Kilometers per Hour

GPS:
LCDOUT $fe,1,"in GPS"
PAUSE 2000
LCDOUT $fe,1,"Serin start"
PAUSE 2000
SerIn2 PORTA.0,mode,Timeout,nogps,[wait("$GPRMC"),wait(","),DEC2 hh,DEC2 mm,wait(","),fix,wait(","),DEC2 latdeg,DEC2 latmin,wait(","),NS,wait(","),DEC3 londeg,DEC2 lonmin,wait(","),EO,wait(","),Speed[0],Speed[1],Speed[2],Speed[3],Speed[4],wait(","),DEC3 course,wait(","),DEC2 j,DEC2 m,DEC2 a]
IF (fix == "V") Then
LCDOut $FE, 1 'Clear Screen
LCDOut "No Fix"
Pause 1000
GOTO GPS
ENDIF
LCDOUT $fe,1,"Serin end"
PAUSE 2000

'Convert from ASCII to normal numbers times 10
SpeedKnots = 0
Dummy = 1000
Speed[3] = Speed[4] '"skip" the decimal
For Temp = 0 TO 3
Speed[Temp] = Speed[Temp] - "0" 'Remove the ASCII portion = 48
SpeedKnots = SpeedKnots + (Speed[Temp] * Dummy)
Dummy = Dummy / 10
NEXT
'Use theese two lines if you want a value that is rounded correctly.
'There will however be a limit to your speed, it must be <= 353.7kn (655.3km/h)
SpeedKm = (SpeedKnots*18) + (SpeedKnots ** 34260) 'Multiply with 18.5227661
SpeedKm = (SpeedKm + 5) /10 '5 is for rounding

LCDOut "SPEED :",dec4 SpeedKm/10,".",DEC1 SpeedKm,"km/h"
LCDOut $fe,$c0
LCDOut "HEADING:",DEC3 course," DEG"
Pause 3000
LCDOut $FE, 1 'Clear Screen
LCDOut "LAT:",DEC2 latdeg,",",DEC2 latmin," ",NS
LCDOut $fe,$c0
LCDOut "LON:",DEC2 londeg,",",DEC2 lonmin," ",EO
Pause 3000
GoTo GPS

Nogps:
LCDOut $FE, 1 'Clear Screen
LCDOut "NO GPS"
Pause 1000
GOTO GPS

ScaleRobotics
- 25th November 2009, 09:01
I think you only have to invert for rs232, not TTL. So you could try non inverting, or move to pin 1 of the gps for rs232 tx and the specified resistor.

xnihilo
- 25th November 2009, 09:23
Hi scalerobotics,

Thank you for your message.
After further reading on forums, I've changed my code as shown below. Now the code isn't stuck in the serin2 anymore but it displays "Timeout", which means I can't read the string sent by the GPS within 3s. According to the user manual, GPS is auto initialized at 4800 bauds and when done, it starts displaying strings, as $GPRMC. Even if I wait over 2 minutes, it still times out.
I've connected A0 to TTL TX pin (pin 3 on page 7 of the user manual).
Is SERIN2 able to read on any pin?
Are my pins settings right? (They are set to Digital I/O).
Why RS232 rather than TTL?
Should I choose True or Inverted should I choose Parity or none...?
I see various configurations on http://www.melabs.com/resources/pbpmanual/ser2modes.htm but I'm not sure how to use it.
I'm not using a MAX232 between the GPS and the PIC.



'based on: http://list.picbasic.com/forum/messages/6851/7091.html?1080565370

@ device pic16F684, intrc_osc_noclkout, BOD_OFF, PWRT_OFF, wdt_off, mclr_off, protect_off

'quid freq horloge requise?


DEFINE OSC 8 'set OSC value to 8MHz for instructions PAUSE, PAUSEus and SOUND (instead of default 4MHz)

DEFINE LCD_DREG PORTC 'data port out is portC
DEFINE LCD_DBIT 0 'data on portC0-portC3

DEFINE LCD_RSREG PORTC 'r/s is on portC.4, with 10K WPU
DEFINE LCD_RSBIT 4

DEFINE LCD_EREG PORTC 'enable is on portC.5
DEFINE LCD_EBIT 5

DEFINE LCD_BITS 4 '4bits data bus
DEFINE LCD_LINES 2 '2lines display
DEFINE LCD_COMMANDUS 2000 '2ms cmd delay
DEFINE LCD_DATAUS 50 '50us data delay

INTCON = 0 'disable interrupts and clear int flags
OSCCON = %01110001 'int osc, hs, 8mhz
CMCON0 = %00000111
ANSEL = %00000000
OPTION_REG = %11111111

'alias in SERIN2
GPSin VAR PORTA.0 'A0 has TTL levels

TRISA = %000001
TRISC = 0

PORTA = %000001 'A0 is used for gps input, SERIN2 bitbanging (software eusart)
PORTC = 0

WPUA = 0
mystring var byte[65]
i var byte

'programming custom characters
LCDOUT $FE,$40,$00,$0A,$0A,$00,$11,$0E,$00,$00 ' Cust Char #0: happy smiley
LCDOUT $FE,$48,$0E,$15,$1B,$19,$1B,$15,$0E,$00 ' Cust Char #1: copyright
LCDOUT $FE,$50,$0E,$0E,$1F,$0E,$04,$00,$1F,$00 ' Cust Char #2: press
LCDOUT $FE,$58,$0A,$1F,$1F,$1F,$0E,$04,$00,$00 ' Cust Char #3: heart
LCDOUT $FE,$60,$03,$05,$19,$19,$19,$19,$05,$03 ' Cust Char #4: speaker
LCDOUT $FE,$68,$00,$00,$04,$0E,$0E,$0E,$0E,$00 ' Cust Char #5: bullet
LCDOUT $FE,$70,$1F,$11,$11,$11,$11,$11,$11,$1F ' Cust Char #6: empty square
LCDOUT $FE,$78,$04,$0E,$1F,$0E,$0E,$00,$1F,$00 ' Cust Char #7: release

'blink led
for i = 0 to 10
HIGH PORTA.1
pause 300
LOW PORTA.1
PAUSE 300
NEXT i


'TEST block
'display a sample of the custom charas
LCDOUT $fe,1,"new charas: "
LCDOUT $fe,$c0,0,1,2,3,4,5,6,7
PAUSE 4000
'--------------------------------------------------------------------------------------------------------------------------------------------

LCDOUT $fe,1,"GPS display"
PAUSE 2000

gps:
LCDOUT $fe,1,"in GPS"
LCDOUT $fe,$c0,"Serin start"
PAUSE 2000
mystring[0]=0 'init first byte of the string
serin2 portA.0,188,3000,toto,[WAIT("$GPRMC"),STR mystring\65\13]
If mystring[0]<>0 then
LCDOUT $fe,1,"Data avail."
PAUSE 2000
ELSE
LCDOUT $fe,1,"No data"
PAUSE 2000
eNDIF
goto gps

toto:
LCDOUT $fe,1,"timeout"
PAUSE 2000
GOTO gps

ScaleRobotics
- 25th November 2009, 10:26
Serin2 will work on any pin. Why don't you try running down the list of modes for 4800, to see what works. Also, make sure your GPS is receiving satellites. It sounds like this one waits for a valid position before it sends anything out its ports, if I am reading the manual right.

xnihilo
- 25th November 2009, 10:34
mode 188 seems to work, with TTL level TX, as with:

serin2 portA.0,188,3000,toto,[WAIT("$GPRMC")]
LCDOUT $fe,1,"Found GPRMC"
PAUSE 2000

It displays "Found GPRMC".
So either it doesn't wait for satellite or the SERIN doesn't in fact find the "$GPRMC" string at all.

When I try to collect subsequent bytes in an array or in bytes, it stays stuck in SERIN... It is driving me mad as I don't have the slightest idea of what's going wrong.

xnihilo
- 27th November 2009, 09:47
I changed the PIC and it fixed the problem.

Here is the current code for anyone who might be interested in such interfacing.


'based on: http://list.picbasic.com/forum/messages/6851/7091.html?1080565370

@ device pic16F684, intrc_osc_noclkout, BOD_OFF, PWRT_OFF, wdt_off, mclr_off, protect_off

'quid freq horloge requise?

DEFINE OSC 8 'set OSC value to 8MHz for instructions PAUSE, PAUSEus and SOUND (instead of default 4MHz)
DEFINE LCD_DREG PORTC 'data port out is portC
DEFINE LCD_DBIT 0 'data on portC0-portC3
DEFINE LCD_RSREG PORTC 'r/s is on portC.4, with 10K WPU
DEFINE LCD_RSBIT 4
DEFINE LCD_EREG PORTC 'enable is on portC.5
DEFINE LCD_EBIT 5
DEFINE LCD_BITS 4 '4bits data bus
DEFINE LCD_LINES 2 '2lines display
DEFINE LCD_COMMANDUS 2000 '2ms cmd delay
DEFINE LCD_DATAUS 50 '50us data delay

INTCON = 0 'disable interrupts and clear int flags
OSCCON = %01110001 'int osc, hs, 8mhz
CMCON0 = %00000111
ANSEL = %00000000
OPTION_REG = %11111111

TRISA = %000001
TRISC = 0

PORTA = %000000 'A0 is used for gps input, SERIN2 bitbanging (software eusart)
PORTC = 0

WPUA = 0

hh VAR BYTE 'hours
mm VAR BYTE 'minutes
ss VAR BYTE 'secondes
sss var word 'centiemes de seconde
knots VAR WORD 'speed in knots (units)
knotsten VAR BYTE 'speed in knots (tens)
kmph var WORD
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
'for kmph calculation
Speed Var byte[5]
SpeedKnots VAR WORD
SpeedKm VAR WORD
Temp VAR BYTE
Dummy VAR WORD
i var byte
latsec VAR word
lonsec VAR WORD
satellites var word

b1 var byte
b2 var byte

course_ CON 0
latdeg_ CON 10
latmin_ CON 20
londeg_ CON 30
lonmin_ CON 40
kmph_ CON 50
satellites_ con 60
'programming custom characters
LCDOUT $FE,$40,$00,$0A,$0A,$00,$11,$0E,$00,$00 ' Cust Char #0: happy smiley
LCDOUT $FE,$48,$0E,$15,$1B,$19,$1B,$15,$0E,$00 ' Cust Char #1: copyright
LCDOUT $FE,$50,$0E,$0E,$1F,$0E,$04,$00,$1F,$00 ' Cust Char #2: press
LCDOUT $FE,$58,$0A,$1F,$1F,$1F,$0E,$04,$00,$00 ' Cust Char #3: heart
LCDOUT $FE,$60,$03,$05,$19,$19,$19,$19,$05,$03 ' Cust Char #4: speaker
LCDOUT $FE,$68,$00,$00,$04,$0E,$0E,$0E,$0E,$00 ' Cust Char #5: bullet
LCDOUT $FE,$70,$1F,$11,$11,$11,$11,$11,$11,$1F ' Cust Char #6: empty square
LCDOUT $FE,$78,$04,$0E,$1F,$0E,$0E,$00,$1F,$00 ' Cust Char #7: release

LCDOUT $fe,1,"GPS device"
LCDOUT $fe,$c0,"25.11.09"
PAUSE 2000

gps:
'LCDOUT $fe,1,"Serin start1"
'PAUSE 1000
SerIn2 PORTA.0,188,3000,toto,[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] 'works
If fix !="V" THEN
LCDOUT $fe,1,"Fix: ",#fix
LCDOUT $fe,$c0,"65:bad; 86:good"
PAUSE 1000
ENDIF
'LCDOUT $fe,1,"FOUND"
'PAUSE 1000
'IF (fix != "V") Then
' LCDOut $FE, 1 'Clear Screen
' LCDOut "No Fix"
' LCDOUT $fe,$c0,"Fix: ",#fix
' Pause 1000
' GOTO gps
'ENDIF
GOSUB display1
'LCDOUT $fe,1,"Serin start2"
'PAUSE 1000
'$GPVTG,360.0,T,348.7,M,000.0,N,000.0,K*43
SerIn2 PORTA.0,188,3000,toto,[wait("$GPVTG"),wait("N"),DEC3 kmph]
'LCDOUT $fe,1,"FOUND"
'PAUSE 1000
GOSUB display2
'LCDOUT $fe,1,"Serin start3"
'PAUSE 1000
'$GPGSV,2,1,07,07,79,048,42,02,51,062,43,26,36,256 ,42,27,27,138,42*71
SerIn2 PORTA.0,188,3000,toto,[wait("$GPGSV,"),SKIP 1, wait(","),SKIP 1, wait(","),DEC2 satellites]
'LCDOUT $fe,1,"FOUND"
'PAUSE 1000
GOSUB display3
GOTO gps

toto:
LCDOUT $fe,1,"timeout"
PAUSE 1000
GOTO gps


display1:
WRITE course_,course
LCDOut $FE, 1 'Clear Screen
LCDOut "HEADING:",DEC3 course," DEG"
Pause 3000
write latdeg_,latdeg
write latmin_,latmin
WRITE londeg_,londeg
WRITE lonmin_,lonmin
LCDOut $FE, 1 'Clear Screen
LCDOut "LAT:",DEC2 latdeg,",",DEC2 latmin," ",NS
LCDOut $fe,$c0
LCDOut "LON:",DEC2 londeg,",",DEC2 lonmin," ",EO
Pause 3000
RETURN

display2:
WRITE kmph_,kmph
LCDOUT $fe,1,DEC3 kmph," km/h:"
PAUSE 3000
if kmph > 50 then
HIGH porta.1
ELSE
LOW porta.1
ENDIF
RETURN

display3:
write satellites_,satellites
LCDOUT $fe,1,DEC3 satellites," satellites"
PAUSE 3000
RETURN