Picaxe GPS Interface - A New Problem (perhaps a first world one?)

Hi all,

Thanks so much for your help and advice.

I am building a system for a Solar Car challenge I volunteer for. We are crossing the Nullarbor Plain in Australia in December this year in a solar car built by high school students as a part of a Gifted and Talented Academic Program. This is my second crossing, and we are hoping to break the last record of 747km we set in 2011.

To make our convoy procedure safer, I am designing and building a system to determine the distance between the lead vehicle in our convoy, and the bus which provides close escort to the solar car (and the students we put on bicycles in a relay, to make sure they are worn out by the time we reach our camp sites!). The lead vehicle can sometimes travel up to 4 or 5 km ahead of the main convoy to ensure the road ahead is clear - information is provided by radio back to the bus, so we are able to safely negotiate the sometimes 75 metre long road trains that scream down the highway at 100 km/h. (Yes, we are nuts!)

The hardware interface of the design is relatively problem-free (I think). I have two 08M2 chips, each connected to a GPS module and XBee 09P unit. In essence, the lead vehicle's 08M2 receives an NMEA package from the GPS chip, teases out the GPRMC sentence, and sends this via XBee to the module in the bus. The XBee in the bus receives this sentence, and its own GPRMC sentence from its GPS module, and sends these via serial to a Raspberry Pi. I have written a program in C which then extracts the information, and determines the distance between the vehicles, prior to displaying this on a screen.

So far, so good. I have etched a circuit board for the lead vehicle, which sends its NMEA data (renamed with GPLDV, for LeaD Vehicle) each second, as evidenced by its flashing status LED, and the ability to receive this to Minicom with an XBee USB Adapter.

Now for my problem:

I can do this, but currently can only have the bus unit output both sentences (GPLDV and GPBUS - no prizes for guessing how I made up that tag!) every TWO seconds - as I say, this is a first world problem, but is something I wish to understand more fully.

Plugging the output into the Raspberry Pi's GPIO pins also does not capture output reliably, though this is no different when I connect a GPS module - both done through a 4.7K/10K voltage divider. Using the Picaxe programming cable is fine - 100% accurate data so far.

All baud rates are 9600 (except the USB cable to raspberry pi, which runs at 19200, as the picaxes are running at 16MHz.

My code immediately follows.

I think that the problem lies in the bus unit - it tries to fill all of the scratchpad memory with serial output from the Lead Vehicle module, and since there are more @bptrinc than items in the serial string, it waits for the next sentence to be transmitted, but then does not send this on.

I have tried three solutions that I can think of (tested on the Lead Vehicle and Bus side):

1) process each byte in scratchpad individually, testing for each character, by using a do while loop. This continues until it sees then next $ sign after the $GPRMC/$GPLDV, and the loop then exits. This resulted in a scrambled output, probably because the Picaxe isn't fast enough to process the serial whilst receiving.

2) use timeouts in a do-loop after $GPRMC/$GPLDV is received - this results in gobbledegook - I'm sure this is the same problem as before - the Picaxe is probably not fast enough to keep up with the serial stream at 9600

3) Cut down the number of @bptrinc in the received line - this has no impact.

Unfortunately this NMEA sentence has a variable length, so I can't only grab the bytes I need. I'm not sure of another way to stop immediately after the $GPRMC checksum.

I've thought of using HSerin, but can't see any advantage, since I think it is a problem of the Picaxe not being able to process the bytes as it is receiving them.
I could decrease the baud rate of the transmissions to 4800, and try again. This would require reprogramming/reconfiguring the GPS/XBee, and I'm sure there is a work-around somehow.
A kludge might be to pad out the sentence sent back to the bus with extra, "meaningless" bytes of information.

I am of course open to the suggestion that I may be totally off in my reasoning, and it may be something else much more simple/complex.

Ultimately, if we have a refresh rate of 2 seconds, this is not the end of the world, but I'd like to explore this (even if it is nothing more than an academic exercise).

I can post the Eagle schematics if this helps.

Many thanks, and my apologies for a long and rambling post.

Charles
 
Code:
'GPLDV - Lead Vehicle GPS/XBee Module

'C.2 - XBee 09P
'C.3 - GPS Module via 10K Pullup

#picaxe 08m2
setfreq m16
Pause 1000

Do

'Set memory location of first storage variable
	bptr = $20

'Use the qualifier "$GPRMC" to input the RMC (recommended minimum) NMEA sentence into storage variables
'White space signifies each 16 addresses in storage variables ie: $20 to $7F
	Serin C.3, T9600_16,("$GPRMC,"),_
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc


'SEND ENTIRE STRING
'Send until $ from following NMEA sentence is received
'36 is ASCII for "$"
'Pause allows other side to finish sending its own GPS data to raspberry pi
'Actual pause time divided by 4 as clock is running at 16MHz
	Pause 100
	serout c.2, t9600_16,("$GPLDV,")
	b1 = 0
	b0 = $20
	do until b1 = 36	
		serout c.2, t9600_16,(B1)
		peek b0, b1
		inc b0
	loop

Loop
Code:
'GPBUS - Bus GPS/XBee Module

'C.2 - XBee 09P with 10K pull-up resistor
'C.3 - GPS module with 10K pull-up resistor
'Transmits to Raspberry Pi via Picaxe Programming Cable - /dev/ttyUSB0


#picaxe 08m2
setfreq m16
Pause 1000

Do
	
'Retrieve GPS Signal from Bus
'Set memory location of first storage variable
	bptr = $20

'Use the qualifier "$GPRMC" to input the RMC (recommended minimum) NMEA sentence into storage variables
'White space signifies each 16 addresses in storage variables ie: $20 to $7F
	Serin C.3, T9600_16,("$GPRMC,"),_
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc

	sertxd("$GPBUS,")
	b1 = 0
	b0 = $20
	do until b1 = 36	
		sertxd(B1)
		peek b0, b1
		inc b0
	loop


'Set memory location of first storage variable
	bptr = $20

'Use the qualifier "$GPRMC" to input the RMC (recommended minimum) NMEA sentence into storage variables
'White space signifies each 16 addresses in storage variables ie: $20 to $7F
	Serin C.2, T9600_16, _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc, _
							     @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc


'SEND ENTIRE STRING
'Send until $ from following NMEA sentence is received
'36 is ASCII for "$"

	sertxd("$GPLDV,")
	b1 = 0
	b0 = $20
	do until b1 = 36	
		sertxd(B1)
		peek b0, b1
		inc b0
	loop

Loop
 

srnet

Senior Member
Are you really trying to get this to work with 08M2s ?

The background receive that the X2s have makes reading a GPS simple and reliable.

For a worked example of distance and direction calculation, using GPS and PICAXEs (no Pies needed) see;

http://www.rcgroups.com/forums/showthread.php?t=1949624

It reads the GPS reliably, extracts the GPGGA and GPVTG NMEA string info, does a distance and direction calculation, and transmits the information via radio to a remote receiver which can be a really really long distance away.
 

hippy

Ex-Staff (retired)
I think that the problem lies in the bus unit - it tries to fill all of the scratchpad memory with serial output from the Lead Vehicle module, and since there are more @bptrinc than items in the serial string, it waits for the next sentence to be transmitted, but then does not send this on.
That would be my guess as well, though the issue could be in either or both. The buffer partially fills then one seconds later is filled by a second message and then the data is sent. However, if there is any message immediately after $GPRMC that will quickly complete the message.

However it could be, as GPS NMEA output is often synchronised to time, both GPS units are receiving then sending NMEA at the same time. While you are reading one you cannot be reading the other so you end up reading one then having to wait a second for the other. The "Pause 100" in GPLDV before sending on the message seems to be there to overcome that issue but, at 16MHz, that is just 25ms and may simply be too short. Try increasing that to 500ms, "Pause 2000".

I don't think it will be easy to get to the bottom of the issue without both outputting status signals to show what they are doing and studying both together. A LED flash when sending will indicate if GPLDV is sending every one or two seconds.
 
Hippy: The NMEA output synchronising to time is one feature we are really quite happy about - it means we don't need to process this in software later on. Given there is a delay to read the serial buffer and then transmit by XBee, there is a built-in delay. I initially tried different values for the "Pause 100" line, and a Pause 50 (i.e.: 12.5ms) was enough for reliable operation. It was unreliable any lower than this, and higher didn't make a difference.

The XBee "DIN" has an LED status light - this flashes once a second. Also, if I receive the XBee stream to a USB XBee Explorer, I can see the retagged $GPRMC output once a second. That's why I think it is in the bus module - I think that srnet's ideas may have a lot of merit.

I'll keep you updated with how I go. Thanks so much for your expertise, and help!
 
Hi srnet

The 08M2s seem very capable at simple serial serial receiving, and certainly for the Lead Vehicle unit, represent a low-cost, simple way of getting the job done.

I read your blog, and the PDF file - very interesting, and a seemingly well-engineered and excellent project! I especially liked the way you described the distance calculation, using a chip that does not have a math co-processor. I'm somewhat fortunate in that this is being transmitted to a Raspberry Pi, giving the ability to use the C Math Library, and output a pretty graphics display. That, and an 11" touch display in (essentially unused) High Definition. It has been a learning curve, not only in Linux and C Programming, but also in the openvg platform.

Perhaps I looked too superficially, but was unable to find your source code for the unit. Is it available anywhere online, to sneak a look at how you implemented the background serial receive? I assume you use one slot for receiving serial information, and another slot for interpretation? [Edit: Found code in Dropbox folder. My mistake!]

Many thanks for your advice - I think it might just provide exactly what I am looking for.

Charles
 
Last edited:

srnet

Senior Member
I am not trying to encourage people to use more expensive PICAXEs than they need, however......

Step back and think about the overall costs of the project and the implications if it does not work, whilst a 08M2 might do the job, is the cost difference between that and a 28X2 really that significant for the project, I very much doubt it.

The 28X2 provides a 1k byte circular buffer that will receive data from the GPS as the program is running. To read the data, just stop the background receive for a while and search the buffer for $GPGGA, this can be quite fast running at 64Mhz. The programs at the dropbox location use a sepearte slot for the GPS collector, it reads the NMEA strings, does the checksum check and uses comma counting to correctly cope with variable length fields then extracts the following into a RAM buffer for other parts of the program to use;

Time
Latitude
Longtitude
Fix type
Number satellites
Height
Speed
Track

The distance calculation has a limit of around 1 degree, so 60km or so in the UK, its not that quick but is reasonably accurate.

One other advantage of the 28X2 is that it can be run from a cheap external resonator, which can reduce the possibility of baud rate miss matches between GPS and PICAXE, you may not need it, but if you do ................

Much the same code as at the dropbox location will be found here;

http://www.picaxeforum.co.uk/showthread.php?22369-Picaxe-pongsat
 
Thanks for your reply again - I think there is a lot of truth in what you say.

I certainly think your code is excellent for the application which you have described - the way it checks it all (including checksum, and all the information you listed above) is very attractive. I've certainly received a lot of food for thought by reading your code for my own application - thank you!

I've played around with a 28X2 this afternoon. One problem I have is that I am receiving two serial streams - one for the GPS in the bus unit, and the other in the Lead Vehicle unit. Looking at your schematic, and code, the GPS uses the serial connection, and the transmitter uses the SPI interface. This is made a little harder in my setup, since I can use the background receive for one of them, but have to use Serin for the other.

Looking through your code, you listen for the GPS data for a count of 4000 (which if I understand correctly, is one second with setfreq m16, i.e.: 64K?) and then process the data. I imagine that at that speed, it happens fast - does it pick up each of the data packets? How often does it drop one? I'd imagine not often, of course, if ever.

I can't work out how the two slots work together - my understanding is that they cannot run independently on X2 parts, but have to be called by the "run" command? I couldn't find this in your code for GPS signal transmitting. I'm probably missing something very simple in the basic functionality of your code - forgive me.

I'll have a look at the Pongsat source code and see if I can get a better idea.
 

srnet

Senior Member
Looking through your code, you listen for the GPS data for a count of 4000 (which if I understand correctly, is one second with setfreq m16, i.e.: 64K?)
Setfreq m16 runs the PICAXe at 16Mhz. I cant remember why I only ran it for two seconds, its plenty of time, but its just as valid to keep it running in the background all the time and stop it when you want to read the scratchpad.

it happens fast - does it pick up each of the data packets?
If you mean the NMEA sentances, then yes it picks them all up, dont recall it missing a GPGGA or GPVTG in that 2 second collection, I dont recall seeing checksum failures either.

I can't work out how the two slots work together ----- but have to be called by the "run" command?
Slot 0 (the main program) has a 'run 1' which runs the GPS collector when required. The GPS collector then in turn has a 'run 2' to run the GPS calculation when required. The bit of code at the start of slot 0 makes sure the slot 1 and slot 2 programs return to the correct place in slot 0.

If I were coding this I would do it this way;

The RX is ready listening for an incoming packet.
The TX reads the GPS location and sends the packet to the RX.
The RX receives the packet, stores the data as the 'home' location (easy)
The RX reads the GPS and determines the current position.
The RX calls the calculation routine which will work out the distance and direction between home and current.
The RX displays the position of the TX on the LCD and the distance.

How fast all that will run, I am not sure, the calculation would be speeded up quite a bit by eliminating the direction calculation.

Attached are some pictures of the small version of the complete transmitter.
 

Attachments

Last edited:
I see. So your program does update once a second then?

Given you only have one HSerin pin on each 28X2, how would you manage the requirement for two serial inputs on the bus side?

I don't have the advantage of using SPI in this setup - think it would make things much easier.
 

srnet

Senior Member
Given you only have one HSerin pin on each 28X2, how would you manage the requirement for two serial inputs on the bus side?
I don't have the advantage of using SPI in this setup - think it would make things much easier.
With a PICAXE you dont have a lot of choice, you either use serin on any pin, which since its not buffered is not so easy.

Or you use something like those SPI radio modules that will receive packets in the background and set a flag\interrupt when one arrives and keep it stored till you read it.
 
Very true - that has been a serious disadvantage for me.

I did attempt utilising your code with a 28X2, and it worked beautifully. I altered it to pull out GPRMC, which happened nicely. I didn't have an external resonator, so could only run at 8MHz. Funnily enough, running at 16MHz corrupted my serin inputs, but they worked perfectly at m8. 8MHz was too slow, however - it only processed one GPS paragraph every four seconds. That was before I even attempted also receiving signal from the XBee.

For now I have the hardware working on the 08M2s - I had to sacrifice the CR,LF at the end of the sentence, and when the heading part of the sentence changes length, it occasionally nibbles at the Checksum. Not absolutely perfect, but should cope for our purposes. I'm going to have a bit more of a play with your module though - it is very impressive! The code/method for distance calculation is also very clever.

I'll certainly have a look at SPI modules. Pretty sure the XBee can do it, but haven't had a good look. This could be Part II, perhaps for next time.

Now my only problem is with the Raspberry Pi. I can insert clean serial through the USB cable, but the GPIO is not as clean. Sometimes it even crashes when receiving a serial stream from the picaxe.

I'd like to have the two connected only via a ribbon cable. I may need to use the USB adaptor though, if this fails its reliability test.

Any ideas would be appreciated - my 08M2 is connected to the Rx pin of the Pi's GPIO via a 4.7K/10K voltage divider. Other people seem to have it working, but I get the error, "INIT: ID "TO" respawning too fast: disabled for 5 minutes". Google has been somewhat unhelpful - it happens to most people on start-up, and I can't see people having seen this problem when using GPIO pins.
 

srnet

Senior Member
I did attempt utilising your code with a 28X2, and it worked beautifully. I altered it to pull out GPRMC, which happened nicely. I didn't have an external resonator, so could only run at 8MHz. Funnily enough, running at 16MHz corrupted my serin inputs, but they worked perfectly at m8. 8MHz was too slow, however - it only processed one GPS paragraph every four seconds. That was before I even attempted also receiving signal from the XBee
Then if you ran it a 64Mhz, it would be processing a GPS sentance every 0.5 seconds .......
 
Top