The software that runs on the Sentinel nodes. This code is for the LPC1114FN28.
Dependencies: XBEE_900HP_SPI mbed
Revision 1:b51fb321d026, committed 2015-08-18
- Comitter:
- ottaviano3
- Date:
- Tue Aug 18 00:03:59 2015 +0000
- Parent:
- 0:3540612dfbf8
- Commit message:
- Small bug fixes and reliability updates. Fixed erroneous gps serial code and changed the way the program interacts with the gps.
Changed in this revision
XBEE_900HP_SPI.lib | Show annotated file Show diff for this revision Revisions of this file |
main.cpp | Show annotated file Show diff for this revision Revisions of this file |
--- a/XBEE_900HP_SPI.lib Fri May 01 15:53:34 2015 +0000 +++ b/XBEE_900HP_SPI.lib Tue Aug 18 00:03:59 2015 +0000 @@ -1,1 +1,1 @@ -http://developer.mbed.org/users/ottaviano3/code/XBEE_900HP_SPI/#c8bb6b5d7fa0 +http://developer.mbed.org/users/ottaviano3/code/XBEE_900HP_SPI/#3873db4a0164
--- a/main.cpp Fri May 01 15:53:34 2015 +0000 +++ b/main.cpp Tue Aug 18 00:03:59 2015 +0000 @@ -1,6 +1,19 @@ +/* +/ Sentinel software for the active nodes. +/ +/ Design work done by: +/ Dominic Ottaviano +/ Sheldon Fernandes +/ Thien L. Nguyen +*/ + #include "mbed.h" #include "xbee900hp.h" +/*===========================================================/ +/ Primary Configuration Area / +/ Global Variables and Pin Assigments Declared Within / +/===========================================================*/ // Define GPS pin connections. Serial gps(dp16,dp15); @@ -8,142 +21,239 @@ // Define xbee connections. Mosi,Miso,SCK,ATTN,Reset xbee900hp xbee(dp2,dp1,dp6, dp9, dp4); -// Function prototyp for gps getline fuction -void getline(); +// Function prototypes +// Function to query the GPS +int getGPS(char* data); -// Container for read GPS message. +// Global Variables +// Buffer for reading in from xbee +char buffer[256]; +// Buffer for storing GPS data char gpsmsg[256]; +/*===========================================================/ +/ END OF Primary Configuration Area / +/===========================================================*/ + +/*===========================================================/ +/ Begin main program code / +/===========================================================*/ + int main() { - // Set gps baud rate to 4800, the default. + /*===========================/ + / Configuration Section / + /===========================*/ + + // Set GPS paramters + // Baud rate gps.baud(4800); + // Other params (8 data bits, no parity, 1 stop bit) + gps.format(8,SerialBase::None,1); - // Configure gps with default values. + // Configure gps with these parameters: + // NMEA, 4800 Baud, 8 Data bits, 1 Stop bit, No Parity unsigned int gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'0'^','^'1'^','^'4'^'8'^'0'^'0'^','^'8'^','^'1'^','^'0'; - gps.printf("$PSRF100,1,4800,8,1,0*%i\r\n",gpsxor); + // Trim to 8 bits just in case + gpsxor = gpsxor & 0xFF; + // Send command to the GPS module + gps.printf("$PSRF100,1,4800,8,1,0*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F); - // Enable GGA - gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'3'^','^'0'^','^'0'^','^'1'^','^'1'; - gps.printf("$PSRF103,0,0,1,1*%i\r\n",gpsxor); + // Disable automatic broadcast of all messages. We are going to poll manually. + gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'3'^','^'0'^','^'0'^','^'0'^','^'1'; + // Trim to 8 bits just in case + gpsxor = gpsxor & 0xFF; + gps.printf("$PSRF103,0,0,0,1*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F); // Disable GLL gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'3'^','^'1'^','^'0'^','^'0'^','^'1'; - gps.printf("$PSRF103,1,0,0,1*%i\r\n",gpsxor); + // Trim to 8 bits just in case + gpsxor = gpsxor & 0xFF; + gps.printf("$PSRF103,1,0,0,1*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F); // Disable GSA gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'3'^','^'2'^','^'0'^','^'0'^','^'1'; - gps.printf("$PSRF103,2,0,0,1*%i\r\n",gpsxor); + // Trim to 8 bits just in case + gpsxor = gpsxor & 0xFF; + gps.printf("$PSRF103,2,0,0,1*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F); // Disable GSV gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'3'^','^'3'^','^'0'^','^'0'^','^'1'; - gps.printf("$PSRF103,3,0,0,1*%i\r\n",gpsxor); + // Trim to 8 bits just in case + gpsxor = gpsxor & 0xFF; + gps.printf("$PSRF103,3,0,0,1*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F); // Disable RMC gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'3'^','^'4'^','^'0'^','^'0'^','^'1'; - gps.printf("$PSRF103,4,0,0,1*%i\r\n",gpsxor); + // Trim to 8 bits just in case + gpsxor = gpsxor & 0xFF; + gps.printf("$PSRF103,4,0,0,1*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F); // Disable VTG gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'3'^','^'5'^','^'0'^','^'0'^','^'1'; - gps.printf("$PSRF103,5,0,0,1*%i\r\n",gpsxor); + // Trim to 8 bits just in case + gpsxor = gpsxor & 0xFF; + gps.printf("$PSRF103,5,0,0,1*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F); + + /*===========================/ + / END Configuration Section / + /===========================*/ // Set the node id of this module. Generated from the serial of the xbee char nodeidarray[10]; int nodeid = 0; - - // Repeat until gets a value. - while (nodeid == 0) { - nodeid = 0; - // Initialize nodeidarray + + // Initialize nodeidarray + for (int i = 0; i<10; i++) { + nodeidarray[i] = 0; + } + + // Get xbee serial number + int serialget = xbee.getSerial(nodeidarray); + + if (serialget == 0) { for (int i = 0; i<10; i++) { - nodeidarray[i] = 0; - } - - // Get xbee serial number - int serialget = xbee.getSerial(nodeidarray); - - - if (serialget == 0) { - for (int i = 0; i<10; i++) { - // Nonlinear function to expand unique id space - nodeid += nodeidarray[i]*nodeidarray[i]+nodeidarray[i]; - } + // Nonlinear function to expand unique id space + nodeid += nodeidarray[i]*nodeidarray[i]+nodeidarray[i]; } } - // Node id should now be a unique int - // Variables for the various important gps command codes - float latitude, longitude, altitude, hdop, time; + // Set variables, there are more than we need here but it would be useful in the future if we did need any. char ns, ew; - int lock, satsused; + int lock; + double satsused; + double hdop; + double latitude, longitude; + double altitude; + double time; + char altunits; + double geoidsep; + char geoidunits; + int difrefstationid; + unsigned int gpschecksum; + unsigned int filledbuff; - // Store message to send out. - char buffer[256]; - - // Announce to base platform - // Format code line to send out on radio that node has no lock - unsigned int filledbuff = snprintf (buffer, sizeof(buffer)-1, "DNLK,%i\n\n",nodeid); + // Announce the node to the base station. + filledbuff = snprintf (buffer, sizeof(buffer)-1, "ANCE,%i,\r\n",nodeid); // Send packet out into the air. xbee.sendPacket(buffer, filledbuff); // Main program run loop. - while(1) { - // Get the next gps line. - getline(); + while(true) { + // Get new data from the GPS and if data is read successfully continue + if (!(getGPS(gpsmsg))) { + // Parse the recieved data and check if its valid (HINT: lf = double since pointers aren't promoted) + if(sscanf(gpsmsg, "$GPGGA,%lf,%lf,%c,%lf,%c,%i,%lf,%lf,%lf,%c,%lf,%c,,%i*%x", &time, &latitude, &ns, &longitude, &ew, &lock, &satsused, &hdop, &altitude, &altunits, &geoidsep, &geoidunits, &difrefstationid, &gpschecksum) == 14) { + // Check if the lock is valid + if((lock != 1) && (lock != 2) && (lock != 6)) { + // Format code line to send out on radio that node has no lock + filledbuff = snprintf (buffer, sizeof(buffer)-1, "DNLK,%i,\r\n",nodeid); + // Send packet out into the air. + xbee.sendPacket(buffer, filledbuff); + } else { + // Convert latitude into proper form for display on a map. + double degrees; + double minutes = modf(latitude/100.0f, °rees); + minutes = (minutes*100.0f)/60.0f; + latitude = degrees + minutes; + // Convert longitude + minutes = modf(longitude/100.0f, °rees); + minutes = (minutes*100.0f)/60.0f; + longitude = degrees + minutes; - // Extract gps information from the GPGGA line. - if(sscanf(gpsmsg, "GPGGA,%f,%f,%c,%f,%c,%i,%i,%f,%f", &time, &latitude, &ns, &longitude, &ew, &lock, &satsused, &hdop, &altitude) >= 1) { + // Correct for south and west. + if(ns == 'S') { + latitude *= -1.0; + } + if(ew == 'W') { + longitude *= -1.0; + } - // Check if the GPS has a lock or not. (1,2, or 6 indicate lock) - if((lock != 1) && (lock != 2)) { - // Format code line to send out on radio that node has no lock - unsigned int filledbuff = snprintf (buffer, sizeof(buffer)-1, "DNLK,%i\n\n",nodeid); + // Format string for sending out over radio. + filledbuff = snprintf (buffer, sizeof(buffer)-1, "DLIN,%i,%f,%f,%f,%f,\r\n",nodeid, latitude, longitude, altitude, satsused); + // Send packet out. + xbee.sendPacket(buffer, filledbuff); + } + // Wait a second for GPS data to be fresh again and not waste cycles. + wait(1); + } else { + // GPS hasn't found a good enough lock + filledbuff = snprintf (buffer, sizeof(buffer)-1, "DNLK,%i,NOLOCK\r\n",nodeid); // Send packet out into the air. xbee.sendPacket(buffer, filledbuff); - } else { - - // Convert latitude from ddmm.mmmm to dd.dddddd - double degrees; - double minutes = modf(latitude/100.0f, °rees); - minutes = (minutes*100.0f)/60.0f; - latitude = degrees + minutes; - - // Convert longitude from ddmm.mmmm to dd.dddddd - minutes = modf(longitude/100.0f, °rees); - minutes = (minutes*100.0f)/60.0f; - longitude = degrees + minutes; - - // Set signs correctly - if(ns == 'S') { - latitude *= -1.0; - } - if(ew == 'W') { - longitude *= -1.0; - } - - // Format string for sending out over radio. - unsigned int filledbuff = snprintf (buffer, sizeof(buffer)-1, "DLIN,%i,%f,%f,%f\n\n",nodeid, latitude, longitude, altitude); - // Send packet out. - xbee.sendPacket(buffer, filledbuff); + // Wait half a second then try again. + wait(0.5); } + } else { + // GPS hasn't found lock or sent a corrupted message + filledbuff = snprintf (buffer, sizeof(buffer)-1, "DNLK,%i,NOLOCK\r\n",nodeid); + // Send packet out into the air. + xbee.sendPacket(buffer, filledbuff); + // Wait half a second a try again. + wait(0.5); } } } -// GPS serial get line function -void getline() +int getGPS(char* data) { - // wait for the start of a line which $ denotes - while(gps.getc() != '$'); + // Request a query of GGA + // Precomputed checksum to save cpu cycles + gps.printf("$PSRF103,0,1,0,1*%u%u\r\n",0x2,0x5); - // read the gps line until end of line - for(int i=0; i<256; i++) { - gpsmsg[i] = gps.getc(); - if(gpsmsg[i] == '\r') { - gpsmsg[i] = 0; - return ; + // Timer to prevent hangs if gps doesn't respond. + Timer gpsTO; + gpsTO.start(); + + // Wait for gps to becom readable. + while (gps.readable() == false) { + // Timeout + if (gpsTO.read() > 2) { + return 1; } } + + // Wait a tiny bit to allow the gps to send the whole line. + wait_ms(50); + // Get data from gps + gps.scanf("%s",data); + + // Compute checksum of recieved gps data + int i = 0; + unsigned int calcgpschecksum = 0; + // Checksum is calculated between and not including the $ and * + while ((data[i] != '\0') && (data[i] != '*')) { + // Skip the $ + if (data[i] != '$') { + calcgpschecksum = calcgpschecksum ^ data[i]; + } + i++; + } + // Shift the checksum to match the format we recieve from the gps + calcgpschecksum = calcgpschecksum & 0xFF; + + // Get checksum sent by gps out of string + unsigned int realgpschecksum = 0; + char checksumarray[3]; + for (int i = 0; i < 256; i++) { + if (data[i] == '*') { + // Create little array with ascii hex values. + checksumarray[0] = data[i+1]; + checksumarray[1] = data[i+2]; + checksumarray[2] = '\0'; + // Convert ascii values to regular integer + sscanf(checksumarray,"%x",&realgpschecksum); + break; + } + } + + // Check for checksum match + if( calcgpschecksum == realgpschecksum ) { + return 0; + } + + // No checksum match + return 1; } \ No newline at end of file