Last active
April 5, 2024 14:57
-
-
Save IdrisCytron/7ed2defe995cec8109efc5561fb00886 to your computer and use it in GitHub Desktop.
Arduino Device Tracker Using GSM GPS SIM7600E Module
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Project: Arduino GSM GPS Device Tracker | |
Board: Maker Uno | |
GSM: SIM7600E | |
GPS: SIM7600E | |
Library: | |
- Adafruit FONA | |
*/ | |
#include <SoftwareSerial.h> | |
#include "Adafruit_FONA.h" | |
#define BUTTON 2 | |
#define BUZZER 8 | |
#define LED11 11 | |
#define LED12 12 | |
#define LED13 13 | |
#define GSM_RX 4 | |
#define GSM_TX 3 | |
#define GSM_PWR 5 | |
#define GSM_RST 20 // Dummy | |
#define GSM_BAUD 9600 | |
char replybuffer[255]; | |
SoftwareSerial SIM7600SS = SoftwareSerial(GSM_TX, GSM_RX); | |
SoftwareSerial *SIM7600Serial = &SIM7600SS; | |
Adafruit_FONA SIM7600 = Adafruit_FONA(GSM_RST); | |
//#define NOTE_G3 196 | |
//#define NOTE_C4 262 | |
//#define NOTE_E4 330 | |
//#define NOTE_F4 349 | |
//#define NOTE_G4 392 | |
//#define NOTE_C5 523 | |
//#define NOTE_D5 587 | |
//#define NOTE_G5 784 | |
// | |
//#define playStartMelody() playTone(melody1, melody1Dur, 2) | |
//#define playReadyMelody() playTone(melody2, melody2Dur, 5) | |
//#define playErrorMelody() playTone(melody3, melody3Dur, 2) | |
//#define playSmsMelody() playTone(melody4, melody4Dur, 5) | |
//#define playButtonMelody() playTone(melody5, melody5Dur, 4) | |
// | |
//int melody1[] = {NOTE_C4, NOTE_G4}; | |
//int melody1Dur[] = {12, 8}; | |
//int melody2[] = {NOTE_C4, NOTE_F4, NOTE_G4, NOTE_E4, NOTE_C5}; | |
//int melody2Dur[] = {6, 16, 6, 6, 3}; | |
//int melody3[] = {NOTE_C4, NOTE_G3}; | |
//int melody3Dur[] = {6, 3}; | |
//int melody4[] = {NOTE_G4, NOTE_C5, 0, NOTE_G4, NOTE_C5}; | |
//int melody4Dur[] = {12, 12, 12, 12, 12}; | |
//int melody5[] = {NOTE_C5, NOTE_G5, NOTE_C5, NOTE_D5}; | |
//int melody5Dur[] = {6, 6, 6, 6}; | |
uint8_t readline(char *buff, uint8_t maxbuff, uint16_t timeout = 0); | |
char SIM7600InBuffer[64]; // For notifications from the FONA | |
char callerIDbuffer[32]; // We'll store the SMS sender number in here | |
char SMSbuffer[32]; // We'll store the SMS content in here | |
uint16_t SMSLength; | |
String SMSString = ""; | |
boolean buttonEnable = false; | |
String SMSSendString = ""; | |
char SMSSendBuffer[100]; | |
float Lat = 0; | |
float Log = 0; | |
void setup() | |
{ | |
pinMode(BUTTON, INPUT_PULLUP); | |
pinMode(BUZZER, OUTPUT); | |
pinMode(LED11, OUTPUT); | |
pinMode(LED12, OUTPUT); | |
pinMode(LED13, OUTPUT); | |
delay(2000); | |
pinMode(GSM_PWR, OUTPUT); | |
delay(1000); | |
pinMode(GSM_PWR, INPUT_PULLUP); | |
Serial.begin(115200); | |
Serial.println("Interfacing SIM7600 GSM GPS Module with Maker UNO"); | |
Serial.println("Initializing... (May take a minute)"); | |
// playStartMelody(); | |
delay(15000); | |
// Make it slow so its easy to read! | |
SIM7600Serial->begin(GSM_BAUD); | |
if (!SIM7600.begin(*SIM7600Serial)) { | |
Serial.println("Couldn't find SIM7600"); | |
digitalWrite(LED11, HIGH); | |
// playErrorMelody(); | |
while (1); | |
} | |
Serial.println(F("SIM7600 is OK")); | |
// Print SIM card IMEI number. | |
char imei[16] = {0}; // MUST use a 16 character buffer for IMEI! | |
uint8_t imeiLen = SIM7600.getIMEI(imei); | |
if (imeiLen > 0) { | |
Serial.print("SIM card IMEI: "); Serial.println(imei); | |
} | |
SIM7600Serial->print("AT+CNMI=2,1\r\n"); // Set up the SIM800L to send a +CMTI notification when an SMS is received | |
Serial.println("GSM is ready!"); | |
digitalWrite(LED12, HIGH); | |
while (!GPSPositioning()); // Wait until GPS get signal | |
Serial.println("GPS is ready!"); | |
digitalWrite(LED13, HIGH); | |
// playReadyMelody(); | |
} | |
void loop() | |
{ | |
char* bufPtr = SIM7600InBuffer; // Handy buffer pointer | |
if (SIM7600.available()) { // Any data available from the SIM800L | |
int slot = 0; // This will be the slot number of the SMS | |
int charCount = 0; | |
// Read the notification into fonaInBuffer | |
do { | |
*bufPtr = SIM7600.read(); | |
Serial.write(*bufPtr); | |
delay(1); | |
} while ((*bufPtr++ != '\n') && (SIM7600.available()) && (++charCount < (sizeof(SIM7600InBuffer) - 1))); | |
// Add a terminal NULL to the notification string | |
*bufPtr = 0; | |
// Scan the notification string for an SMS received notification. | |
// If it's an SMS message, we'll get the slot number in 'slot' | |
if (1 == sscanf(SIM7600InBuffer, "+CMTI: \"SM\",%d", &slot)) { | |
// playSmsMelody(); | |
Serial.print("slot: "); Serial.println(slot); | |
// Retrieve SMS sender address/phone number. | |
if (!SIM7600.getSMSSender(slot, callerIDbuffer, 31)) { | |
Serial.println("Didn't find SMS message in slot!"); | |
} | |
Serial.print("FROM: "); Serial.println(callerIDbuffer); | |
if (!SIM7600.readSMS(slot, SMSbuffer, 250, &SMSLength)) { // pass in buffer and max len! | |
Serial.println("Failed!"); | |
} | |
else { | |
SMSString = String(SMSbuffer); | |
Serial.print("SMS: "); Serial.println(SMSString); | |
} | |
// Compare SMS string | |
if (SMSString == "LOCATION") { | |
buttonEnable = true; | |
Serial.print("Requesting device location..."); | |
GPSPositioning(); | |
delay(100); | |
SMSSendString = "Google Maps:\nhttp://www.google.com/maps/place/" + String(Lat, 6) + "," + String(Log, 6); | |
Serial.println(SMSSendString); | |
SMSSendString.toCharArray(SMSSendBuffer, 100); | |
// Send SMS for status | |
if (!SIM7600.sendSMS(callerIDbuffer, SMSSendBuffer)) { | |
Serial.println("Failed"); | |
} | |
else { | |
Serial.println(F("Sent!")); | |
SMSSendString = ""; | |
} | |
} | |
else { | |
Serial.print("Invalid command."); | |
// playErrorMelody(); | |
} | |
// Delete the original msg after it is processed | |
// otherwise, we will fill up all the slots | |
// and then we won't be able to receive SMS anymore | |
while (1) { | |
boolean deleteSMSDone = SIM7600.deleteSMS(slot); | |
if (deleteSMSDone == true) { | |
Serial.println("OK!"); | |
break; | |
} | |
else { | |
Serial.println("Couldn't delete, try again."); | |
} | |
} | |
} | |
} | |
if (digitalRead(BUTTON) == LOW && buttonEnable == true) { | |
// buttonEnable = false; | |
// playButtonMelody(); | |
Serial.print("Requesting device location..."); | |
GPSPositioning(); | |
delay(100); | |
SMSSendString = "Google Maps:\nhttp://www.google.com/maps/place/" + String(Lat, 6) + "," + String(Log, 6); | |
Serial.println(SMSSendString); | |
SMSSendString.toCharArray(SMSSendBuffer, 100); | |
// Send SMS for status | |
if (!SIM7600.sendSMS(callerIDbuffer, SMSSendBuffer)) { | |
Serial.println("Failed"); | |
} | |
else { | |
Serial.println(F("Sent!")); | |
SMSSendString = ""; | |
} | |
} | |
} | |
//void playTone(int *melody, int *melodyDur, int notesLength) | |
//{ | |
// for (int i = 0; i < notesLength; i++) { | |
// int noteDuration = 1000 / melodyDur[i]; | |
// tone(BUZZER, melody[i], noteDuration); | |
// delay(noteDuration); | |
// noTone(BUZZER); | |
// } | |
//} | |
uint8_t sendATcommand(const char* ATcommand, const char* expected_answer, unsigned int timeout) | |
{ | |
uint8_t x = 0, answer = 0; | |
char response[100]; | |
unsigned long previous; | |
memset(response, '\0', 100); // Initialize the string | |
delay(100); | |
while (SIM7600Serial->available() > 0) { // Clean the input buffer | |
SIM7600Serial->read(); | |
} | |
SIM7600Serial->println(ATcommand); // Send the AT command | |
x = 0; | |
previous = millis(); | |
// This loop waits for the answer | |
do { | |
if (SIM7600Serial->available() != 0) { | |
// if there are data in the UART input buffer, reads it and checks for the answer | |
response[x] = SIM7600Serial->read(); | |
Serial.print(response[x]); | |
x++; | |
// check if the desired answer is in the response of the module | |
if (strstr(response, expected_answer) != NULL) { | |
answer = 1; | |
} | |
} | |
// Waits for the asnwer with time out | |
} while ((answer == 0) && ((millis() - previous) < timeout)); | |
// SIM7600Serial->print("\n"); | |
return answer; | |
} | |
bool GPSPositioning() | |
{ | |
uint8_t answer = 0; | |
bool RecNull = true; | |
int i = 0; | |
char RecMessage[200]; | |
char LatDD[3], LatMM[10], LogDD[4], LogMM[10], DdMmYy[7] , UTCTime[7]; | |
int DayMonthYear; | |
Lat = 0; | |
Log = 0; | |
memset(RecMessage, '\0', 200); // Initialize the string | |
memset(LatDD, '\0', 3); // Initialize the string | |
memset(LatMM, '\0', 10); // Initialize the string | |
memset(LogDD, '\0', 4); // Initialize the string | |
memset(LogMM, '\0', 10); // Initialize the string | |
memset(DdMmYy, '\0', 7); // Initialize the string | |
memset(UTCTime, '\0', 7); // Initialize the string | |
Serial.print("Start GPS session...\n"); | |
sendATcommand("AT+CGPS=1,1", "OK", 1000); // start GPS session, standalone mode | |
delay(2000); | |
while (RecNull) { | |
answer = sendATcommand("AT+CGPSINFO", "+CGPSINFO: ", 1000); // start GPS session, standalone mode | |
if (answer == 1) { | |
answer = 0; | |
while (SIM7600Serial->available() == 0); | |
// this loop reads the data of the GPS | |
do { | |
// if there are data in the UART input buffer, reads it and checks for the asnwer | |
if (SIM7600Serial->available() > 0) { | |
RecMessage[i] = SIM7600Serial->read(); | |
i++; | |
// check if the desired answer (OK) is in the response of the module | |
if (strstr(RecMessage, "OK") != NULL) { | |
answer = 1; | |
} | |
} | |
} while (answer == 0); // Waits for the asnwer with time out | |
RecMessage[i] = '\0'; | |
Serial.print(RecMessage); | |
Serial.print("\n"); | |
if (strstr(RecMessage, ",,,,,,,,") != NULL) { | |
memset(RecMessage, '\0', 200); // Initialize the string | |
i = 0; | |
answer = 0; | |
delay(1000); | |
} | |
else { | |
RecNull = false; | |
sendATcommand("AT+CGPS=0", "OK:", 1000); | |
} | |
} | |
else { | |
Serial.print("error \n"); | |
return false; | |
} | |
delay(2000); | |
} | |
strncpy(LatDD, RecMessage, 2); | |
LatDD[2] = '\0'; | |
strncpy(LatMM, RecMessage + 2, 9); | |
LatMM[9] = '\0'; | |
Lat = atoi(LatDD) + (atof(LatMM) / 60); | |
if (RecMessage[12] == 'N') { | |
Serial.print("Latitude is "); | |
Serial.print(Lat); | |
Serial.print(" N\n"); | |
} | |
else if (RecMessage[12] == 'S') { | |
Serial.print("Latitude is "); | |
Serial.print(Lat); | |
Serial.print(" S\n"); | |
} | |
else { | |
return false; | |
} | |
strncpy(LogDD, RecMessage + 14, 3); | |
LogDD[3] = '\0'; | |
strncpy(LogMM, RecMessage + 17, 9); | |
LogMM[9] = '\0'; | |
Log = atoi(LogDD) + (atof(LogMM) / 60); | |
if (RecMessage[27] == 'E') { | |
Serial.print("Longitude is "); | |
Serial.print(Log); | |
Serial.print(" E\n"); | |
} | |
else if (RecMessage[27] == 'W') { | |
Serial.print("Latitude is "); | |
Serial.print(Lat); | |
Serial.print(" W\n"); | |
} | |
else { | |
return false; | |
} | |
strncpy(DdMmYy, RecMessage + 29, 6); | |
DdMmYy[6] = '\0'; | |
Serial.print("Day Month Year is "); | |
Serial.print(DdMmYy); | |
Serial.print("\n"); | |
strncpy(UTCTime, RecMessage + 36, 6); | |
UTCTime[6] = '\0'; | |
Serial.print("UTC time is "); | |
Serial.print(UTCTime); | |
Serial.print("\n"); | |
return true; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment