The software that runs on the Sentinel nodes. This code is for the LPC1114FN28.

Dependencies:   XBEE_900HP_SPI mbed

Committer:
ottaviano3
Date:
Tue Aug 18 00:03:59 2015 +0000
Revision:
1:b51fb321d026
Parent:
0:3540612dfbf8
Small bug fixes and reliability updates. Fixed erroneous gps serial code and changed the way the program interacts with the gps.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ottaviano3 1:b51fb321d026 1 /*
ottaviano3 1:b51fb321d026 2 / Sentinel software for the active nodes.
ottaviano3 1:b51fb321d026 3 /
ottaviano3 1:b51fb321d026 4 / Design work done by:
ottaviano3 1:b51fb321d026 5 / Dominic Ottaviano
ottaviano3 1:b51fb321d026 6 / Sheldon Fernandes
ottaviano3 1:b51fb321d026 7 / Thien L. Nguyen
ottaviano3 1:b51fb321d026 8 */
ottaviano3 1:b51fb321d026 9
ottaviano3 0:3540612dfbf8 10 #include "mbed.h"
ottaviano3 0:3540612dfbf8 11 #include "xbee900hp.h"
ottaviano3 0:3540612dfbf8 12
ottaviano3 1:b51fb321d026 13 /*===========================================================/
ottaviano3 1:b51fb321d026 14 / Primary Configuration Area /
ottaviano3 1:b51fb321d026 15 / Global Variables and Pin Assigments Declared Within /
ottaviano3 1:b51fb321d026 16 /===========================================================*/
ottaviano3 0:3540612dfbf8 17
ottaviano3 0:3540612dfbf8 18 // Define GPS pin connections.
ottaviano3 0:3540612dfbf8 19 Serial gps(dp16,dp15);
ottaviano3 0:3540612dfbf8 20
ottaviano3 0:3540612dfbf8 21 // Define xbee connections. Mosi,Miso,SCK,ATTN,Reset
ottaviano3 0:3540612dfbf8 22 xbee900hp xbee(dp2,dp1,dp6, dp9, dp4);
ottaviano3 0:3540612dfbf8 23
ottaviano3 1:b51fb321d026 24 // Function prototypes
ottaviano3 1:b51fb321d026 25 // Function to query the GPS
ottaviano3 1:b51fb321d026 26 int getGPS(char* data);
ottaviano3 0:3540612dfbf8 27
ottaviano3 1:b51fb321d026 28 // Global Variables
ottaviano3 1:b51fb321d026 29 // Buffer for reading in from xbee
ottaviano3 1:b51fb321d026 30 char buffer[256];
ottaviano3 1:b51fb321d026 31 // Buffer for storing GPS data
ottaviano3 0:3540612dfbf8 32 char gpsmsg[256];
ottaviano3 0:3540612dfbf8 33
ottaviano3 1:b51fb321d026 34 /*===========================================================/
ottaviano3 1:b51fb321d026 35 / END OF Primary Configuration Area /
ottaviano3 1:b51fb321d026 36 /===========================================================*/
ottaviano3 1:b51fb321d026 37
ottaviano3 1:b51fb321d026 38 /*===========================================================/
ottaviano3 1:b51fb321d026 39 / Begin main program code /
ottaviano3 1:b51fb321d026 40 /===========================================================*/
ottaviano3 1:b51fb321d026 41
ottaviano3 0:3540612dfbf8 42 int main()
ottaviano3 0:3540612dfbf8 43 {
ottaviano3 1:b51fb321d026 44 /*===========================/
ottaviano3 1:b51fb321d026 45 / Configuration Section /
ottaviano3 1:b51fb321d026 46 /===========================*/
ottaviano3 1:b51fb321d026 47
ottaviano3 1:b51fb321d026 48 // Set GPS paramters
ottaviano3 1:b51fb321d026 49 // Baud rate
ottaviano3 0:3540612dfbf8 50 gps.baud(4800);
ottaviano3 1:b51fb321d026 51 // Other params (8 data bits, no parity, 1 stop bit)
ottaviano3 1:b51fb321d026 52 gps.format(8,SerialBase::None,1);
ottaviano3 0:3540612dfbf8 53
ottaviano3 1:b51fb321d026 54 // Configure gps with these parameters:
ottaviano3 1:b51fb321d026 55 // NMEA, 4800 Baud, 8 Data bits, 1 Stop bit, No Parity
ottaviano3 0:3540612dfbf8 56 unsigned int gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'0'^','^'1'^','^'4'^'8'^'0'^'0'^','^'8'^','^'1'^','^'0';
ottaviano3 1:b51fb321d026 57 // Trim to 8 bits just in case
ottaviano3 1:b51fb321d026 58 gpsxor = gpsxor & 0xFF;
ottaviano3 1:b51fb321d026 59 // Send command to the GPS module
ottaviano3 1:b51fb321d026 60 gps.printf("$PSRF100,1,4800,8,1,0*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F);
ottaviano3 0:3540612dfbf8 61
ottaviano3 1:b51fb321d026 62 // Disable automatic broadcast of all messages. We are going to poll manually.
ottaviano3 1:b51fb321d026 63 gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'3'^','^'0'^','^'0'^','^'0'^','^'1';
ottaviano3 1:b51fb321d026 64 // Trim to 8 bits just in case
ottaviano3 1:b51fb321d026 65 gpsxor = gpsxor & 0xFF;
ottaviano3 1:b51fb321d026 66 gps.printf("$PSRF103,0,0,0,1*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F);
ottaviano3 0:3540612dfbf8 67
ottaviano3 0:3540612dfbf8 68 // Disable GLL
ottaviano3 0:3540612dfbf8 69 gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'3'^','^'1'^','^'0'^','^'0'^','^'1';
ottaviano3 1:b51fb321d026 70 // Trim to 8 bits just in case
ottaviano3 1:b51fb321d026 71 gpsxor = gpsxor & 0xFF;
ottaviano3 1:b51fb321d026 72 gps.printf("$PSRF103,1,0,0,1*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F);
ottaviano3 0:3540612dfbf8 73
ottaviano3 0:3540612dfbf8 74 // Disable GSA
ottaviano3 0:3540612dfbf8 75 gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'3'^','^'2'^','^'0'^','^'0'^','^'1';
ottaviano3 1:b51fb321d026 76 // Trim to 8 bits just in case
ottaviano3 1:b51fb321d026 77 gpsxor = gpsxor & 0xFF;
ottaviano3 1:b51fb321d026 78 gps.printf("$PSRF103,2,0,0,1*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F);
ottaviano3 0:3540612dfbf8 79
ottaviano3 0:3540612dfbf8 80 // Disable GSV
ottaviano3 0:3540612dfbf8 81 gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'3'^','^'3'^','^'0'^','^'0'^','^'1';
ottaviano3 1:b51fb321d026 82 // Trim to 8 bits just in case
ottaviano3 1:b51fb321d026 83 gpsxor = gpsxor & 0xFF;
ottaviano3 1:b51fb321d026 84 gps.printf("$PSRF103,3,0,0,1*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F);
ottaviano3 0:3540612dfbf8 85
ottaviano3 0:3540612dfbf8 86 // Disable RMC
ottaviano3 0:3540612dfbf8 87 gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'3'^','^'4'^','^'0'^','^'0'^','^'1';
ottaviano3 1:b51fb321d026 88 // Trim to 8 bits just in case
ottaviano3 1:b51fb321d026 89 gpsxor = gpsxor & 0xFF;
ottaviano3 1:b51fb321d026 90 gps.printf("$PSRF103,4,0,0,1*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F);
ottaviano3 0:3540612dfbf8 91
ottaviano3 0:3540612dfbf8 92 // Disable VTG
ottaviano3 0:3540612dfbf8 93 gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'3'^','^'5'^','^'0'^','^'0'^','^'1';
ottaviano3 1:b51fb321d026 94 // Trim to 8 bits just in case
ottaviano3 1:b51fb321d026 95 gpsxor = gpsxor & 0xFF;
ottaviano3 1:b51fb321d026 96 gps.printf("$PSRF103,5,0,0,1*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F);
ottaviano3 1:b51fb321d026 97
ottaviano3 1:b51fb321d026 98 /*===========================/
ottaviano3 1:b51fb321d026 99 / END Configuration Section /
ottaviano3 1:b51fb321d026 100 /===========================*/
ottaviano3 0:3540612dfbf8 101
ottaviano3 0:3540612dfbf8 102
ottaviano3 0:3540612dfbf8 103 // Set the node id of this module. Generated from the serial of the xbee
ottaviano3 0:3540612dfbf8 104 char nodeidarray[10];
ottaviano3 0:3540612dfbf8 105 int nodeid = 0;
ottaviano3 1:b51fb321d026 106
ottaviano3 1:b51fb321d026 107 // Initialize nodeidarray
ottaviano3 1:b51fb321d026 108 for (int i = 0; i<10; i++) {
ottaviano3 1:b51fb321d026 109 nodeidarray[i] = 0;
ottaviano3 1:b51fb321d026 110 }
ottaviano3 1:b51fb321d026 111
ottaviano3 1:b51fb321d026 112 // Get xbee serial number
ottaviano3 1:b51fb321d026 113 int serialget = xbee.getSerial(nodeidarray);
ottaviano3 1:b51fb321d026 114
ottaviano3 1:b51fb321d026 115 if (serialget == 0) {
ottaviano3 0:3540612dfbf8 116 for (int i = 0; i<10; i++) {
ottaviano3 1:b51fb321d026 117 // Nonlinear function to expand unique id space
ottaviano3 1:b51fb321d026 118 nodeid += nodeidarray[i]*nodeidarray[i]+nodeidarray[i];
ottaviano3 0:3540612dfbf8 119 }
ottaviano3 0:3540612dfbf8 120 }
ottaviano3 0:3540612dfbf8 121 // Node id should now be a unique int
ottaviano3 0:3540612dfbf8 122
ottaviano3 1:b51fb321d026 123 // Set variables, there are more than we need here but it would be useful in the future if we did need any.
ottaviano3 0:3540612dfbf8 124 char ns, ew;
ottaviano3 1:b51fb321d026 125 int lock;
ottaviano3 1:b51fb321d026 126 double satsused;
ottaviano3 1:b51fb321d026 127 double hdop;
ottaviano3 1:b51fb321d026 128 double latitude, longitude;
ottaviano3 1:b51fb321d026 129 double altitude;
ottaviano3 1:b51fb321d026 130 double time;
ottaviano3 1:b51fb321d026 131 char altunits;
ottaviano3 1:b51fb321d026 132 double geoidsep;
ottaviano3 1:b51fb321d026 133 char geoidunits;
ottaviano3 1:b51fb321d026 134 int difrefstationid;
ottaviano3 1:b51fb321d026 135 unsigned int gpschecksum;
ottaviano3 1:b51fb321d026 136 unsigned int filledbuff;
ottaviano3 0:3540612dfbf8 137
ottaviano3 1:b51fb321d026 138 // Announce the node to the base station.
ottaviano3 1:b51fb321d026 139 filledbuff = snprintf (buffer, sizeof(buffer)-1, "ANCE,%i,\r\n",nodeid);
ottaviano3 0:3540612dfbf8 140 // Send packet out into the air.
ottaviano3 0:3540612dfbf8 141 xbee.sendPacket(buffer, filledbuff);
ottaviano3 0:3540612dfbf8 142
ottaviano3 0:3540612dfbf8 143 // Main program run loop.
ottaviano3 1:b51fb321d026 144 while(true) {
ottaviano3 1:b51fb321d026 145 // Get new data from the GPS and if data is read successfully continue
ottaviano3 1:b51fb321d026 146 if (!(getGPS(gpsmsg))) {
ottaviano3 1:b51fb321d026 147 // Parse the recieved data and check if its valid (HINT: lf = double since pointers aren't promoted)
ottaviano3 1:b51fb321d026 148 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) {
ottaviano3 1:b51fb321d026 149 // Check if the lock is valid
ottaviano3 1:b51fb321d026 150 if((lock != 1) && (lock != 2) && (lock != 6)) {
ottaviano3 1:b51fb321d026 151 // Format code line to send out on radio that node has no lock
ottaviano3 1:b51fb321d026 152 filledbuff = snprintf (buffer, sizeof(buffer)-1, "DNLK,%i,\r\n",nodeid);
ottaviano3 1:b51fb321d026 153 // Send packet out into the air.
ottaviano3 1:b51fb321d026 154 xbee.sendPacket(buffer, filledbuff);
ottaviano3 1:b51fb321d026 155 } else {
ottaviano3 1:b51fb321d026 156 // Convert latitude into proper form for display on a map.
ottaviano3 1:b51fb321d026 157 double degrees;
ottaviano3 1:b51fb321d026 158 double minutes = modf(latitude/100.0f, &degrees);
ottaviano3 1:b51fb321d026 159 minutes = (minutes*100.0f)/60.0f;
ottaviano3 1:b51fb321d026 160 latitude = degrees + minutes;
ottaviano3 1:b51fb321d026 161 // Convert longitude
ottaviano3 1:b51fb321d026 162 minutes = modf(longitude/100.0f, &degrees);
ottaviano3 1:b51fb321d026 163 minutes = (minutes*100.0f)/60.0f;
ottaviano3 1:b51fb321d026 164 longitude = degrees + minutes;
ottaviano3 0:3540612dfbf8 165
ottaviano3 1:b51fb321d026 166 // Correct for south and west.
ottaviano3 1:b51fb321d026 167 if(ns == 'S') {
ottaviano3 1:b51fb321d026 168 latitude *= -1.0;
ottaviano3 1:b51fb321d026 169 }
ottaviano3 1:b51fb321d026 170 if(ew == 'W') {
ottaviano3 1:b51fb321d026 171 longitude *= -1.0;
ottaviano3 1:b51fb321d026 172 }
ottaviano3 0:3540612dfbf8 173
ottaviano3 1:b51fb321d026 174 // Format string for sending out over radio.
ottaviano3 1:b51fb321d026 175 filledbuff = snprintf (buffer, sizeof(buffer)-1, "DLIN,%i,%f,%f,%f,%f,\r\n",nodeid, latitude, longitude, altitude, satsused);
ottaviano3 1:b51fb321d026 176 // Send packet out.
ottaviano3 1:b51fb321d026 177 xbee.sendPacket(buffer, filledbuff);
ottaviano3 1:b51fb321d026 178 }
ottaviano3 1:b51fb321d026 179 // Wait a second for GPS data to be fresh again and not waste cycles.
ottaviano3 1:b51fb321d026 180 wait(1);
ottaviano3 1:b51fb321d026 181 } else {
ottaviano3 1:b51fb321d026 182 // GPS hasn't found a good enough lock
ottaviano3 1:b51fb321d026 183 filledbuff = snprintf (buffer, sizeof(buffer)-1, "DNLK,%i,NOLOCK\r\n",nodeid);
ottaviano3 0:3540612dfbf8 184 // Send packet out into the air.
ottaviano3 0:3540612dfbf8 185 xbee.sendPacket(buffer, filledbuff);
ottaviano3 1:b51fb321d026 186 // Wait half a second then try again.
ottaviano3 1:b51fb321d026 187 wait(0.5);
ottaviano3 0:3540612dfbf8 188 }
ottaviano3 1:b51fb321d026 189 } else {
ottaviano3 1:b51fb321d026 190 // GPS hasn't found lock or sent a corrupted message
ottaviano3 1:b51fb321d026 191 filledbuff = snprintf (buffer, sizeof(buffer)-1, "DNLK,%i,NOLOCK\r\n",nodeid);
ottaviano3 1:b51fb321d026 192 // Send packet out into the air.
ottaviano3 1:b51fb321d026 193 xbee.sendPacket(buffer, filledbuff);
ottaviano3 1:b51fb321d026 194 // Wait half a second a try again.
ottaviano3 1:b51fb321d026 195 wait(0.5);
ottaviano3 0:3540612dfbf8 196 }
ottaviano3 0:3540612dfbf8 197 }
ottaviano3 0:3540612dfbf8 198 }
ottaviano3 0:3540612dfbf8 199
ottaviano3 1:b51fb321d026 200 int getGPS(char* data)
ottaviano3 0:3540612dfbf8 201 {
ottaviano3 1:b51fb321d026 202 // Request a query of GGA
ottaviano3 1:b51fb321d026 203 // Precomputed checksum to save cpu cycles
ottaviano3 1:b51fb321d026 204 gps.printf("$PSRF103,0,1,0,1*%u%u\r\n",0x2,0x5);
ottaviano3 0:3540612dfbf8 205
ottaviano3 1:b51fb321d026 206 // Timer to prevent hangs if gps doesn't respond.
ottaviano3 1:b51fb321d026 207 Timer gpsTO;
ottaviano3 1:b51fb321d026 208 gpsTO.start();
ottaviano3 1:b51fb321d026 209
ottaviano3 1:b51fb321d026 210 // Wait for gps to becom readable.
ottaviano3 1:b51fb321d026 211 while (gps.readable() == false) {
ottaviano3 1:b51fb321d026 212 // Timeout
ottaviano3 1:b51fb321d026 213 if (gpsTO.read() > 2) {
ottaviano3 1:b51fb321d026 214 return 1;
ottaviano3 0:3540612dfbf8 215 }
ottaviano3 0:3540612dfbf8 216 }
ottaviano3 1:b51fb321d026 217
ottaviano3 1:b51fb321d026 218 // Wait a tiny bit to allow the gps to send the whole line.
ottaviano3 1:b51fb321d026 219 wait_ms(50);
ottaviano3 1:b51fb321d026 220 // Get data from gps
ottaviano3 1:b51fb321d026 221 gps.scanf("%s",data);
ottaviano3 1:b51fb321d026 222
ottaviano3 1:b51fb321d026 223 // Compute checksum of recieved gps data
ottaviano3 1:b51fb321d026 224 int i = 0;
ottaviano3 1:b51fb321d026 225 unsigned int calcgpschecksum = 0;
ottaviano3 1:b51fb321d026 226 // Checksum is calculated between and not including the $ and *
ottaviano3 1:b51fb321d026 227 while ((data[i] != '\0') && (data[i] != '*')) {
ottaviano3 1:b51fb321d026 228 // Skip the $
ottaviano3 1:b51fb321d026 229 if (data[i] != '$') {
ottaviano3 1:b51fb321d026 230 calcgpschecksum = calcgpschecksum ^ data[i];
ottaviano3 1:b51fb321d026 231 }
ottaviano3 1:b51fb321d026 232 i++;
ottaviano3 1:b51fb321d026 233 }
ottaviano3 1:b51fb321d026 234 // Shift the checksum to match the format we recieve from the gps
ottaviano3 1:b51fb321d026 235 calcgpschecksum = calcgpschecksum & 0xFF;
ottaviano3 1:b51fb321d026 236
ottaviano3 1:b51fb321d026 237 // Get checksum sent by gps out of string
ottaviano3 1:b51fb321d026 238 unsigned int realgpschecksum = 0;
ottaviano3 1:b51fb321d026 239 char checksumarray[3];
ottaviano3 1:b51fb321d026 240 for (int i = 0; i < 256; i++) {
ottaviano3 1:b51fb321d026 241 if (data[i] == '*') {
ottaviano3 1:b51fb321d026 242 // Create little array with ascii hex values.
ottaviano3 1:b51fb321d026 243 checksumarray[0] = data[i+1];
ottaviano3 1:b51fb321d026 244 checksumarray[1] = data[i+2];
ottaviano3 1:b51fb321d026 245 checksumarray[2] = '\0';
ottaviano3 1:b51fb321d026 246 // Convert ascii values to regular integer
ottaviano3 1:b51fb321d026 247 sscanf(checksumarray,"%x",&realgpschecksum);
ottaviano3 1:b51fb321d026 248 break;
ottaviano3 1:b51fb321d026 249 }
ottaviano3 1:b51fb321d026 250 }
ottaviano3 1:b51fb321d026 251
ottaviano3 1:b51fb321d026 252 // Check for checksum match
ottaviano3 1:b51fb321d026 253 if( calcgpschecksum == realgpschecksum ) {
ottaviano3 1:b51fb321d026 254 return 0;
ottaviano3 1:b51fb321d026 255 }
ottaviano3 1:b51fb321d026 256
ottaviano3 1:b51fb321d026 257 // No checksum match
ottaviano3 1:b51fb321d026 258 return 1;
ottaviano3 0:3540612dfbf8 259 }