The software that runs on the Sentinel base station. This code is for the LPC1768.
Dependencies: XBEE_900HP_SPI mbed-rtos mbed
main.cpp
00001 /* 00002 / Sentinel software for the base station node. 00003 / 00004 / Design work done by: 00005 / Dominic Ottaviano 00006 / Sheldon Fernandes 00007 / Thien L. Nguyen 00008 */ 00009 00010 #include "mbed.h" 00011 #include "xbee900hp.h" 00012 #include "rtos.h" 00013 00014 /*===========================================================/ 00015 / Primary Configuration Area / 00016 / Global Variables and Pin Assigments Declared Within / 00017 /===========================================================*/ 00018 00019 // Serial Port Mutex to prevent multiple transmissions 00020 Mutex serial_mutex; 00021 00022 // Declare serial output to the host PC over USB 00023 Serial pc(USBTX,USBRX); 00024 00025 // Connected serial GPS pins 00026 Serial gps(p28,p27); 00027 00028 // Declare pins of connected xbee module using spi (EXPERIMENTAL DRIVER) 00029 xbee900hp xbee(p11,p12,p13, p8, p9); 00030 00031 // Led outputs on the MBED 00032 DigitalOut led1(LED1); 00033 DigitalOut led2(LED2); 00034 00035 // Global Variables 00036 // Buffer for reading in from xbee 00037 char buffer[256]; 00038 // Buffer for storing GPS data 00039 char gpsmsg[256]; 00040 00041 // Predefine threads running here 00042 // Thread to handle data inputs and outputs to the XBee 00043 void xbeeScanner(void const *args); 00044 // Thread to handle data inputs from the GPS module 00045 void hostScanner(void const *args); 00046 00047 // Function prototypes 00048 // Function to query the GPS 00049 int getGPS(char* data); 00050 00051 /*===========================================================/ 00052 / END OF Primary Configuration Area / 00053 /===========================================================*/ 00054 00055 /*===========================================================/ 00056 / Code to setup the watchdog timer on the MBED to handle- / 00057 / auto resets / 00058 /===========================================================*/ 00059 00060 class Watchdog 00061 { 00062 public: 00063 // Load timeout value in watchdog timer and enable 00064 void kick(float s) { 00065 LPC_WDT->WDCLKSEL = 0x1; // Set CLK src to PCLK 00066 uint32_t clk = SystemCoreClock / 16; // WD has a fixed /4 prescaler, PCLK default is /4 00067 LPC_WDT->WDTC = s * (float)clk; 00068 LPC_WDT->WDMOD = 0x3; // Enabled and Reset 00069 kick(); 00070 } 00071 // "kick" or "feed" the dog - reset the watchdog timer 00072 // by writing this required bit pattern 00073 void kick() { 00074 LPC_WDT->WDFEED = 0xAA; 00075 LPC_WDT->WDFEED = 0x55; 00076 } 00077 }; 00078 00079 // Declare watchdog timer 00080 Watchdog wdt; 00081 00082 /*===========================================================/ 00083 / End of watchdog timer code / 00084 /===========================================================*/ 00085 00086 /*===========================================================/ 00087 / Begin main program code / 00088 /===========================================================*/ 00089 00090 int main() 00091 { 00092 /*===========================/ 00093 / Configuration Section / 00094 /===========================*/ 00095 00096 // Set PC parameters 00097 // Baud rate 00098 pc.baud(57600); 00099 // Other params (8 data bits, no parity, 1 stop bit) 00100 pc.format(8,SerialBase::None,1); 00101 00102 // Set GPS paramters 00103 // Baud rate 00104 gps.baud(4800); 00105 // Other params (8 data bits, no parity, 1 stop bit) 00106 gps.format(8,SerialBase::None,1); 00107 00108 // Configure gps with these parameters: 00109 // NMEA, 4800 Baud, 8 Data bits, 1 Stop bit, No Parity 00110 unsigned int gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'0'^','^'1'^','^'4'^'8'^'0'^'0'^','^'8'^','^'1'^','^'0'; 00111 // Trim to 8 bits just in case 00112 gpsxor = gpsxor & 0xFF; 00113 // Send command to the GPS module 00114 gps.printf("$PSRF100,1,4800,8,1,0*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F); 00115 00116 // Disable automatic broadcast of all messages. We are going to poll manually. 00117 gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'3'^','^'0'^','^'0'^','^'0'^','^'1'; 00118 // Trim to 8 bits just in case 00119 gpsxor = gpsxor & 0xFF; 00120 gps.printf("$PSRF103,0,0,0,1*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F); 00121 00122 // Disable GLL 00123 gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'3'^','^'1'^','^'0'^','^'0'^','^'1'; 00124 // Trim to 8 bits just in case 00125 gpsxor = gpsxor & 0xFF; 00126 gps.printf("$PSRF103,1,0,0,1*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F); 00127 00128 // Disable GSA 00129 gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'3'^','^'2'^','^'0'^','^'0'^','^'1'; 00130 // Trim to 8 bits just in case 00131 gpsxor = gpsxor & 0xFF; 00132 gps.printf("$PSRF103,2,0,0,1*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F); 00133 00134 // Disable GSV 00135 gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'3'^','^'3'^','^'0'^','^'0'^','^'1'; 00136 // Trim to 8 bits just in case 00137 gpsxor = gpsxor & 0xFF; 00138 gps.printf("$PSRF103,3,0,0,1*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F); 00139 00140 // Disable RMC 00141 gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'3'^','^'4'^','^'0'^','^'0'^','^'1'; 00142 // Trim to 8 bits just in case 00143 gpsxor = gpsxor & 0xFF; 00144 gps.printf("$PSRF103,4,0,0,1*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F); 00145 00146 // Disable VTG 00147 gpsxor = 'P'^'S'^'R'^'F'^'1'^'0'^'3'^','^'5'^','^'0'^','^'0'^','^'1'; 00148 // Trim to 8 bits just in case 00149 gpsxor = gpsxor & 0xFF; 00150 gps.printf("$PSRF103,5,0,0,1*%u%u\r\n",(gpsxor & 0xF0) >> 4,gpsxor & 0x0F); 00151 00152 // Enable watchdog with a reasonable half second timeout 00153 wdt.kick(1000); 00154 00155 /*===========================/ 00156 / END Configuration Section / 00157 /===========================*/ 00158 00159 00160 while (true) { 00161 // Define Keys 00162 char startkey[12] = "SentinelOn"; 00163 char endkey[13] = "SentinelOff"; 00164 char cmdbuff[30]; 00165 00166 // LED 1 on shows ready status. 00167 led1 = 1; 00168 // Start loop waiting for start message 00169 do { 00170 if (pc.readable() == true) { 00171 // Get bytes from computer 00172 pc.scanf("%s",cmdbuff); 00173 } 00174 wdt.kick(); 00175 } while (strcmp( startkey, cmdbuff ) != 0); 00176 // Clear string in buffer 00177 cmdbuff[0] = '\0'; 00178 // LED 1 off as we enter next segment 00179 led1 = 0; 00180 00181 // Let host know that we are starting. 00182 pc.printf("SLON\r\n"); 00183 00184 xbee.clearBuff(); 00185 00186 // Start xbeeScanner Thread 00187 Thread xbscan(xbeeScanner); 00188 Thread hostscan(hostScanner); 00189 00190 // Main runloop 00191 led2 = 1; 00192 do { 00193 serial_mutex.lock(); 00194 if (pc.readable() == true) { 00195 // Get bytes from computer 00196 pc.scanf("%s",cmdbuff); 00197 } 00198 serial_mutex.unlock(); 00199 wdt.kick(); 00200 } while (strcmp( endkey, cmdbuff ) != 0); 00201 led2 = 0; 00202 00203 // Clear string in buffer 00204 cmdbuff[0] = '\0'; 00205 00206 xbscan.terminate(); 00207 hostscan.terminate(); 00208 } 00209 } 00210 00211 // Thread to update host position 00212 void hostScanner(void const *args) 00213 { 00214 // Set variables, there are more than we need here but it would be useful in the future if we did need any. 00215 char nodeid[5] = "BASE"; 00216 char ns, ew; 00217 int lock; 00218 double satsused; 00219 double hdop; 00220 double latitude, longitude; 00221 double altitude; 00222 double time; 00223 char altunits; 00224 double geoidsep; 00225 char geoidunits; 00226 int difrefstationid; 00227 unsigned int gpschecksum; 00228 00229 serial_mutex.lock(); 00230 // Announce base node to computer application 00231 pc.printf("ANCE,%s,\r\n",nodeid); 00232 serial_mutex.unlock(); 00233 00234 // Main run loop 00235 while (true) { 00236 // Get new data from the GPS and if data is read successfully continue 00237 if (!(getGPS(gpsmsg))) { 00238 // Parse the recieved data and check if its valid (HINT: lf = double since pointers aren't promoted) 00239 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) { 00240 // Check if the lock is valid 00241 if((lock != 1) && (lock != 2) && (lock != 6)) { 00242 // Lock is not valid, let host know. 00243 serial_mutex.lock(); 00244 pc.printf("DNLK,%s,NOLOCK\r\n",nodeid); 00245 serial_mutex.unlock(); 00246 } else { 00247 // Convert latitude into proper form for display on a map. 00248 double degrees; 00249 double minutes = modf(latitude/100.0f, °rees); 00250 minutes = (minutes*100.0f)/60.0f; 00251 latitude = degrees + minutes; 00252 // Convert longitude 00253 minutes = modf(longitude/100.0f, °rees); 00254 minutes = (minutes*100.0f)/60.0f; 00255 longitude = degrees + minutes; 00256 00257 // Correct for south and west. 00258 if(ns == 'S') { 00259 latitude *= -1.0; 00260 } 00261 if(ew == 'W') { 00262 longitude *= -1.0; 00263 } 00264 00265 serial_mutex.lock(); 00266 // Send formatted info to the host 00267 pc.printf("DLIN,%s,%f,%f,%f,%f,\r\n",nodeid, latitude, longitude, altitude, satsused); 00268 serial_mutex.unlock(); 00269 } 00270 // Wait a second for GPS data to be fresh again and not waste cycles. 00271 Thread::wait(1000); 00272 } else { 00273 // GPS hasn't found a good enough lock 00274 serial_mutex.lock(); 00275 pc.printf("DNLK,%s,NOLOCK\r\n",nodeid); 00276 serial_mutex.unlock(); 00277 // If this check fails we give up cpu time to another thread but only momentarily, we need to get this data successfully. 00278 Thread::wait(500); 00279 } 00280 } else { 00281 // GPS hasn't found lock or sent a corrupted message 00282 serial_mutex.lock(); 00283 pc.printf("DNLK,%s,NOLOCK\r\n",nodeid); 00284 serial_mutex.unlock(); 00285 // If this check fails we give up cpu time to another thread but only momentarily, we need to get this data successfully. 00286 Thread::wait(500); 00287 } 00288 } 00289 } 00290 00291 // Thread to scan the xbee 00292 void xbeeScanner(void const *args) 00293 { 00294 // Main runloop 00295 while (true) { 00296 // check if xbee is flagging data to be read 00297 while(xbee.attn() == 0) { 00298 // Read in data and run all background checksum and validation stuff 00299 if (xbee.readPacket(buffer) == 0) { 00300 serial_mutex.lock(); 00301 pc.printf("%s\r\n", buffer); 00302 serial_mutex.unlock(); 00303 } else { 00304 serial_mutex.lock(); 00305 pc.printf("Packet Failed Validation\r\n"); 00306 serial_mutex.unlock(); 00307 xbee.clearBuff(); 00308 } 00309 } 00310 // Give up rest of timeslice to boost that performance 00311 Thread::yield(); 00312 } 00313 } 00314 00315 // Function to get the gps message and make sure its valid. 00316 int getGPS(char* data) 00317 { 00318 // Request a query of GGA 00319 // Precomputed checksum to save cpu cycles 00320 serial_mutex.lock(); 00321 gps.printf("$PSRF103,0,1,0,1*%u%u\r\n",0x2,0x5); 00322 serial_mutex.unlock(); 00323 00324 // Timer to prevent hangs if gps doesn't respond. 00325 Timer gpsTO; 00326 gpsTO.start(); 00327 00328 // Wait for gps to becom readable. 00329 while (gps.readable() == false) { 00330 // Timeout 00331 if (gpsTO.read() > 2) { 00332 return 1; 00333 } 00334 } 00335 00336 // Wait a tiny bit to allow the gps to send the whole line. 00337 Thread::wait(50); 00338 // Get data from gps 00339 serial_mutex.lock(); 00340 gps.scanf("%s",data); 00341 serial_mutex.unlock(); 00342 00343 // Compute checksum of recieved gps data 00344 int i = 0; 00345 unsigned int calcgpschecksum = 0; 00346 // Checksum is calculated between and not including the $ and * 00347 while ((data[i] != '\0') && (data[i] != '*')) { 00348 // Skip the $ 00349 if (data[i] != '$') { 00350 calcgpschecksum = calcgpschecksum ^ data[i]; 00351 } 00352 i++; 00353 } 00354 // Shift the checksum to match the format we recieve from the gps 00355 calcgpschecksum = calcgpschecksum & 0xFF; 00356 00357 // Get checksum sent by gps out of string 00358 unsigned int realgpschecksum = 0; 00359 char checksumarray[3]; 00360 for (int i = 0; i < 256; i++) { 00361 if (data[i] == '*') { 00362 // Create little array with ascii hex values. 00363 checksumarray[0] = data[i+1]; 00364 checksumarray[1] = data[i+2]; 00365 checksumarray[2] = '\0'; 00366 // Convert ascii values to regular integer 00367 sscanf(checksumarray,"%x",&realgpschecksum); 00368 break; 00369 } 00370 } 00371 00372 // Check for checksum match 00373 if( calcgpschecksum == realgpschecksum ) { 00374 return 0; 00375 } 00376 00377 // No checksum match 00378 return 1; 00379 }
Generated on Sat Jul 16 2022 11:48:05 by 1.7.2