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