An SMS based GPS tracker using the Adafruit Ultimate GPS module http://www.adafruit.com/products/746 and the Seeed Studio GPRS shield (Sim900 chipset) http://www.seeedstudio.com/depot/gprs-shield-p-779.html?cPath=132_134
Dependencies: GPS MODSERIAL mbed-rtos mbed
SMS based GPS tracker
This is an SMS based GPS tracker using using the Adafruit Ultimate GPS module and the Seeed studio GPRS arduino shield [SIM900 chipset]. The idea of this project is to leverage the free SMS between Virgin mobile prepaid SIM cards in Australia for long distance communication.
Currently the GPRS shield is switched on manually, and should be done about 10 seconds before powering the mbed/GPS in order to disable echo properly during start up. This could easily be fixed by switching the GPRS shield with the mbed at start up, waiting the 10 seconds, set the echo then flush the buffer.
The mbed can read all 160 ASCII chars sent in a message for control.

The Seeed GPRS shield http://www.seeedstudio.com/depot/gprs-shield-p-779.html?cPath=132_134
The Adafruit Ultimate GPS http://www.adafruit.com/products/746
main.cpp@11:fad4b451bec8, 2012-10-12 (annotated)
- Committer:
- SamClarke
- Date:
- Fri Oct 12 04:58:17 2012 +0000
- Revision:
- 11:fad4b451bec8
- Parent:
- 10:059cde049cd6
- Child:
- 12:3f164c88df87
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| SamClarke | 0:5b4bcbd69509 | 1 | #include "mbed.h" |
| SamClarke | 0:5b4bcbd69509 | 2 | #include "GPS.h" |
| SamClarke | 0:5b4bcbd69509 | 3 | #include "rtos.h" |
| SamClarke | 0:5b4bcbd69509 | 4 | #include "MODSERIAL.h" |
| SamClarke | 0:5b4bcbd69509 | 5 | #include <string> |
| SamClarke | 0:5b4bcbd69509 | 6 | |
| SamClarke | 0:5b4bcbd69509 | 7 | using namespace std; |
| SamClarke | 0:5b4bcbd69509 | 8 | |
| SamClarke | 9:bec6e8f731f2 | 9 | const string GoogleChunk = "https://maps.google.com.au/maps?q="; |
| SamClarke | 0:5b4bcbd69509 | 10 | const string GoogleExtras = "&z=20"; |
| SamClarke | 10:059cde049cd6 | 11 | char GPRSbuffer[513]; |
| SamClarke | 10:059cde049cd6 | 12 | char NUMBER[13]; |
| SamClarke | 7:db9226b9b037 | 13 | char MESSAGE[5]; |
| SamClarke | 0:5b4bcbd69509 | 14 | int index; |
| SamClarke | 0:5b4bcbd69509 | 15 | int i = 0; |
| SamClarke | 0:5b4bcbd69509 | 16 | |
| SamClarke | 0:5b4bcbd69509 | 17 | GPS gps(p9,p10); |
| SamClarke | 10:059cde049cd6 | 18 | MODSERIAL GPRS(p13,p14); |
| SamClarke | 0:5b4bcbd69509 | 19 | MODSERIAL pc(USBTX,USBRX); |
| SamClarke | 0:5b4bcbd69509 | 20 | |
| SamClarke | 0:5b4bcbd69509 | 21 | DigitalOut myled1(LED1); |
| SamClarke | 0:5b4bcbd69509 | 22 | DigitalOut myled2(LED2); |
| SamClarke | 0:5b4bcbd69509 | 23 | DigitalOut myled3(LED3); |
| SamClarke | 0:5b4bcbd69509 | 24 | DigitalOut myled4(LED4); |
| SamClarke | 0:5b4bcbd69509 | 25 | |
| SamClarke | 0:5b4bcbd69509 | 26 | void led_thread(void const *argument) // Some light jazz in a thread |
| SamClarke | 0:5b4bcbd69509 | 27 | { |
| SamClarke | 0:5b4bcbd69509 | 28 | while (true) { |
| SamClarke | 0:5b4bcbd69509 | 29 | DigitalOut leds[4] = {myled1, myled2, myled3, myled4}; |
| SamClarke | 0:5b4bcbd69509 | 30 | int pattern[6][4] = {{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1},{0,0,1,0},{0,1,0,0}}; |
| SamClarke | 0:5b4bcbd69509 | 31 | int i=0; |
| SamClarke | 0:5b4bcbd69509 | 32 | while(1) { |
| SamClarke | 0:5b4bcbd69509 | 33 | leds[0] = pattern[i][0]; |
| SamClarke | 0:5b4bcbd69509 | 34 | leds[1] = pattern[i][1]; |
| SamClarke | 0:5b4bcbd69509 | 35 | leds[2] = pattern[i][2]; |
| SamClarke | 0:5b4bcbd69509 | 36 | leds[3] = pattern[i][3]; |
| SamClarke | 0:5b4bcbd69509 | 37 | wait(0.2); |
| SamClarke | 0:5b4bcbd69509 | 38 | i++; |
| SamClarke | 0:5b4bcbd69509 | 39 | i == 6? i=0:0; |
| SamClarke | 0:5b4bcbd69509 | 40 | } |
| SamClarke | 0:5b4bcbd69509 | 41 | } |
| SamClarke | 0:5b4bcbd69509 | 42 | } |
| SamClarke | 0:5b4bcbd69509 | 43 | |
| SamClarke | 0:5b4bcbd69509 | 44 | void sendSms() |
| SamClarke | 0:5b4bcbd69509 | 45 | { |
| SamClarke | 0:5b4bcbd69509 | 46 | // Set message mode to ASCII |
| SamClarke | 0:5b4bcbd69509 | 47 | GPRS.printf("AT+CMGF=1\r\n"); |
| SamClarke | 0:5b4bcbd69509 | 48 | wait(1); |
| SamClarke | 0:5b4bcbd69509 | 49 | // Set the phone number |
| SamClarke | 10:059cde049cd6 | 50 | GPRS.printf("AT+CMGS=\"%s\"\r\n", NUMBER); |
| SamClarke | 0:5b4bcbd69509 | 51 | wait(1); |
| SamClarke | 0:5b4bcbd69509 | 52 | // Write out the GPS data in a message |
| SamClarke | 10:059cde049cd6 | 53 | GPRS.printf("UTC Time: %4.2f \nAltitude: %3.2fm\nSpeed: %3.2f Kn\nHeading: %3.2f Deg\nGPS data grade: [%c]\nSatellites in use: [%d]\nSatFix code: [%d] \nFix type: ", gps.time, gps.altitude, gps.speed, gps.heading, gps.validity, gps.satellites, gps.fixtype); |
| SamClarke | 9:bec6e8f731f2 | 54 | if(gps.fixtype == 1) { |
| SamClarke | 9:bec6e8f731f2 | 55 | GPRS.printf("Positive"); |
| SamClarke | 9:bec6e8f731f2 | 56 | } |
| SamClarke | 9:bec6e8f731f2 | 57 | if(gps.fixtype == 2) { |
| SamClarke | 9:bec6e8f731f2 | 58 | GPRS.printf("Differential"); |
| SamClarke | 9:bec6e8f731f2 | 59 | } |
| SamClarke | 0:5b4bcbd69509 | 60 | wait(1); |
| SamClarke | 0:5b4bcbd69509 | 61 | // Send it... |
| SamClarke | 0:5b4bcbd69509 | 62 | GPRS.putc(0x1A); |
| SamClarke | 10:059cde049cd6 | 63 | wait(4); |
| SamClarke | 0:5b4bcbd69509 | 64 | GPRS.printf("AT+CMGF=1\r\n"); |
| SamClarke | 0:5b4bcbd69509 | 65 | wait(1); |
| SamClarke | 10:059cde049cd6 | 66 | GPRS.printf("AT+CMGS=\"%s\"\r\n", NUMBER); |
| SamClarke | 0:5b4bcbd69509 | 67 | wait(1); |
| SamClarke | 0:5b4bcbd69509 | 68 | GPRS.printf("Find me at....\n %s%f,%f%s", GoogleChunk, gps.latitude, gps.longitude, GoogleExtras); |
| SamClarke | 0:5b4bcbd69509 | 69 | wait(1); |
| SamClarke | 0:5b4bcbd69509 | 70 | GPRS.putc(0x1A); |
| SamClarke | 3:a5df4bd224ad | 71 | wait(1); |
| SamClarke | 0:5b4bcbd69509 | 72 | } |
| SamClarke | 0:5b4bcbd69509 | 73 | |
| SamClarke | 0:5b4bcbd69509 | 74 | void parseSms() |
| SamClarke | 0:5b4bcbd69509 | 75 | { |
| SamClarke | 0:5b4bcbd69509 | 76 | // If theres a char waiting in the MODSERIAL buffer |
| SamClarke | 0:5b4bcbd69509 | 77 | while (GPRS.readable()) { |
| SamClarke | 0:5b4bcbd69509 | 78 | // Assign it to 'c' |
| SamClarke | 0:5b4bcbd69509 | 79 | char c = GPRS.getc(); |
| SamClarke | 0:5b4bcbd69509 | 80 | // Replace all returns and or line endings with money! |
| SamClarke | 0:5b4bcbd69509 | 81 | if (c == '\r' || c == '\n') c = '$'; |
| SamClarke | 0:5b4bcbd69509 | 82 | // Put it in the array |
| SamClarke | 0:5b4bcbd69509 | 83 | GPRSbuffer[i] = c; |
| SamClarke | 0:5b4bcbd69509 | 84 | // Repeat if possible |
| SamClarke | 0:5b4bcbd69509 | 85 | i++; |
| SamClarke | 0:5b4bcbd69509 | 86 | } |
| SamClarke | 0:5b4bcbd69509 | 87 | // Uncomment the following to debug |
| SamClarke | 10:059cde049cd6 | 88 | // pc.printf("\nbuffer = %s", GPRSbuffer); |
| SamClarke | 0:5b4bcbd69509 | 89 | |
| SamClarke | 0:5b4bcbd69509 | 90 | // If we get an SMS notification.... |
| SamClarke | 0:5b4bcbd69509 | 91 | if (sscanf(GPRSbuffer, "$$+CMTI: \"SM\",%d", &index)>0) { |
| SamClarke | 1:00c7dc0c1761 | 92 | pc.printf("\nSMS recieved @ index [%d]", index); |
| SamClarke | 7:db9226b9b037 | 93 | memset(GPRSbuffer, '0', 512); |
| SamClarke | 7:db9226b9b037 | 94 | i = 0; |
| SamClarke | 7:db9226b9b037 | 95 | GPRS.printf("AT+CMGR=%d\r\n", index); |
| SamClarke | 10:059cde049cd6 | 96 | //wait(1); |
| SamClarke | 7:db9226b9b037 | 97 | } |
| SamClarke | 7:db9226b9b037 | 98 | |
| SamClarke | 7:db9226b9b037 | 99 | if (strncmp(GPRSbuffer, "$$+CMGR",7) == 0 ) { |
| SamClarke | 10:059cde049cd6 | 100 | // Get the number out |
| SamClarke | 10:059cde049cd6 | 101 | char *n = strstr(GPRSbuffer,"+6"); |
| SamClarke | 10:059cde049cd6 | 102 | strncpy(NUMBER, n, 12); |
| SamClarke | 10:059cde049cd6 | 103 | // Get the message out |
| SamClarke | 10:059cde049cd6 | 104 | char *m = strstr(GPRSbuffer,"\"$$")+3; |
| SamClarke | 10:059cde049cd6 | 105 | strncpy(MESSAGE, m, 4); |
| SamClarke | 10:059cde049cd6 | 106 | // Send the location |
| SamClarke | 0:5b4bcbd69509 | 107 | sendSms(); |
| SamClarke | 0:5b4bcbd69509 | 108 | // Reset the GPRS buffer |
| SamClarke | 0:5b4bcbd69509 | 109 | memset(GPRSbuffer, '0', 512); |
| SamClarke | 0:5b4bcbd69509 | 110 | // Reset the char counter |
| SamClarke | 0:5b4bcbd69509 | 111 | i = 0; |
| SamClarke | 7:db9226b9b037 | 112 | } |
| SamClarke | 7:db9226b9b037 | 113 | |
| SamClarke | 7:db9226b9b037 | 114 | if (strncmp(GPRSbuffer, "$$+CMGS",7) == 0) { |
| SamClarke | 7:db9226b9b037 | 115 | // Reset the GPRS buffer |
| SamClarke | 7:db9226b9b037 | 116 | memset(GPRSbuffer, '0', 512); |
| SamClarke | 7:db9226b9b037 | 117 | // Reset the char counter |
| SamClarke | 7:db9226b9b037 | 118 | i = 0; |
| SamClarke | 7:db9226b9b037 | 119 | } |
| SamClarke | 7:db9226b9b037 | 120 | |
| SamClarke | 7:db9226b9b037 | 121 | if (strncmp(GPRSbuffer, "$$RING",6) == 0) { |
| SamClarke | 9:bec6e8f731f2 | 122 | GPRS.printf("ATH0\r\n"); |
| SamClarke | 3:a5df4bd224ad | 123 | pc.printf("\nCall recieved"); |
| SamClarke | 3:a5df4bd224ad | 124 | // Do the send SMS routine... |
| SamClarke | 3:a5df4bd224ad | 125 | sendSms(); |
| SamClarke | 3:a5df4bd224ad | 126 | // Reset the GPRS buffer |
| SamClarke | 4:0e55a4620f5e | 127 | memset(GPRSbuffer, '0', 512); |
| SamClarke | 3:a5df4bd224ad | 128 | // Reset the char counter |
| SamClarke | 4:0e55a4620f5e | 129 | i = 0; |
| SamClarke | 1:00c7dc0c1761 | 130 | } |
| SamClarke | 10:059cde049cd6 | 131 | pc.printf("\n\n\nWaiting for SMS or call...\n"); |
| SamClarke | 10:059cde049cd6 | 132 | pc.printf("\nThe last number was : %s", NUMBER); |
| SamClarke | 10:059cde049cd6 | 133 | pc.printf("\nThe last message was : %s", MESSAGE); |
| SamClarke | 7:db9226b9b037 | 134 | // Reset the GPRS buffer |
| SamClarke | 7:db9226b9b037 | 135 | memset(GPRSbuffer, '0', 512); |
| SamClarke | 7:db9226b9b037 | 136 | // Reset the char counter |
| SamClarke | 7:db9226b9b037 | 137 | i = 0; |
| SamClarke | 0:5b4bcbd69509 | 138 | } |
| SamClarke | 0:5b4bcbd69509 | 139 | |
| SamClarke | 0:5b4bcbd69509 | 140 | int main() |
| SamClarke | 0:5b4bcbd69509 | 141 | { |
| SamClarke | 0:5b4bcbd69509 | 142 | pc.baud(115200); |
| SamClarke | 0:5b4bcbd69509 | 143 | GPRS.baud(19200); |
| SamClarke | 0:5b4bcbd69509 | 144 | Thread thread(led_thread); |
| SamClarke | 5:3a42b208ac4e | 145 | memset(GPRSbuffer, '0', 512); |
| SamClarke | 9:bec6e8f731f2 | 146 | pc.printf("\nI'm Alive...\n"); |
| SamClarke | 0:5b4bcbd69509 | 147 | // Setup the GPS |
| SamClarke | 0:5b4bcbd69509 | 148 | gps.Init(); |
| SamClarke | 0:5b4bcbd69509 | 149 | // Set the GPRS AT echo off |
| SamClarke | 0:5b4bcbd69509 | 150 | GPRS.printf("ATE0\r\n"); |
| SamClarke | 9:bec6e8f731f2 | 151 | pc.printf("\nGPRS echo [OFF]\n"); |
| SamClarke | 0:5b4bcbd69509 | 152 | wait(1); |
| SamClarke | 0:5b4bcbd69509 | 153 | // Delete all messages on the sim card |
| SamClarke | 0:5b4bcbd69509 | 154 | GPRS.printf("AT+CMGDA=\"DEL ALL\"\r\n"); |
| SamClarke | 0:5b4bcbd69509 | 155 | wait(1); |
| SamClarke | 9:bec6e8f731f2 | 156 | pc.printf("\nMessages Cleared...\n"); |
| SamClarke | 0:5b4bcbd69509 | 157 | wait(1); |
| SamClarke | 0:5b4bcbd69509 | 158 | // Get in a while loop |
| SamClarke | 0:5b4bcbd69509 | 159 | while (1) { |
| SamClarke | 10:059cde049cd6 | 160 | // Process any recieved GPRS data |
| SamClarke | 0:5b4bcbd69509 | 161 | parseSms(); |
| SamClarke | 0:5b4bcbd69509 | 162 | // Process / check GPS data |
| SamClarke | 3:a5df4bd224ad | 163 | gps.parseData(); |
| SamClarke | 0:5b4bcbd69509 | 164 | } |
| SamClarke | 0:5b4bcbd69509 | 165 | } |