So I created a simple little sketch, based on the TimeGPS sample that comes with the TinyGPS library, that waits for a "p" over the Xbee interface and upon receiving it, sends back the date, time, latitude and longitude data from the GPS. The CAN-bus shield uses pins 4 and 5 for the GPS serial interface. I found that the Xbee modules I have (as supplied in the SparkFun Xbee retail kit) have rather shorter range than I'd hoped for, but at least they work and I am learning about their usage. Here's the sketch:
#include <TinyGPS.h> //http://arduiniana.org/libraries/TinyGPS/ #include <NewSoftSerial.h> //http://arduiniana.org/libraries/newsoftserial/ // GPS and NewSoftSerial libraries are the work of Mikal Hart TinyGPS gps; NewSoftSerial serial_gps = NewSoftSerial(4, 5); // receive on pin 3 void setup() { Serial.begin(9600); serial_gps.begin(4800); Serial.println("setup..."); } void dump_lat_long(float flat, float flong) { Serial.print("lat : "); Serial.println(flat); Serial.print("long: "); Serial.println(flong); } #define pdec(x) { Serial.print(x,DEC); } #define p(x) { Serial.print(x); } #define s() p(" ") #define d() p("-") #define c() p(":") void dump_datetime() { int year; byte month, day, hour, minutes, second, hundredths; unsigned long fix_age; gps.crack_datetime(&year, &month, &day, &hour, &minutes, &second, &hundredths, &fix_age); pdec(year); d(); pdec(month); d(); pdec(day); s(); pdec(hour); c(); pdec(minutes); c(); pdec(second); p("."); pdec(hundredths); Serial.println(); } void loop() { float flat, flon; unsigned long fix_age; String msg; byte havedata = 1; byte polled = 0; while (serial_gps.available() && !polled) { if(gps.encode(serial_gps.read())) { // returns +- latitude/longitude in degrees gps.f_get_position(&flat, &flon, &fix_age); if (fix_age == TinyGPS::GPS_INVALID_AGE) { msg = "No fix detected"; havedata = 0; } else if (fix_age > 5000) msg = "Warning: possible stale data!"; else msg = "Data is current."; polled = 1; if (Serial.available() && Serial.read() == 'p') { Serial.println(msg); if (havedata) { dump_datetime(); dump_lat_long(flat,flon); } delay(100); } } } }
I also wrote a small Perl script that (via Device::SerialPort from CPAN) interrogates the Arduino every 5 seconds or so, using a USB-attached Xbee Explorer. For Linux you will need to change the serial port device filename to /dev/ttyS0 or similar. No idea about Windows, sorry. Again, I started out with some sample code (this time from the Device::SerialPort distribution) and hacked most of it off. Code follows:
#!/usr/bin/perl use strict; use warnings; use Device::SerialPort; my $file = "/dev/tty.usbserial-A700fbpg"; my $ob = Device::SerialPort->new ($file) || die "Can't open $file: $!"; $ob->baudrate(9600) || die "fail setting baudrate"; $ob->parity("none") || die "fail setting parity"; $ob->databits(8) || die "fail setting databits"; $ob->stopbits(1) || die "fail setting stopbits"; $ob->handshake("none") || die "fail setting handshake"; $ob->write_settings || die "no settings"; $ob->error_msg(1); # use built-in error messages $ob->user_msg(1); while(1) { $ob->write("p"); print $ob->input; sleep 5; }
No comments:
Post a Comment