I was working with an Arduino uno and a SIM808 shield (not from arduino) to make an automated lock with GPS. The lock was supposed to respond to SMS representing orders which would be opening or closing the lock and sending back and SMS confirming its done, and would use a GPS antenna to get their current location ans send it to a web server. Here is the code I used:
#include <MemoryFree.h>
#include <SoftwareSerial.h>
SoftwareSerial SIM808(7, 8); // Configures Rx and Tx in that order
String mensaje = "";
char incoming_char = 0;
void setup()
{
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(11, OUTPUT);
pinMode(12, INPUT);
pinMode(13, INPUT);
SIM808.begin(9600);
Serial.begin(9600);
iniciar(); //method to configure the SIM808
}
void loop()
{
if (SIM808.available()) {
incoming_char = SIM808.read(); //Save characters of GPRS
Serial.print(incoming_char); //Shows character in serial monitor
mensaje = mensaje + incoming_char ;
mensaje_sms(); //method with the app's main functionality
}
}
int enviarAT(String ATcommand, char* resp_correcta, unsigned int tiempo)
{
int x = 0;
bool correcto = 0;
char respuesta[100];
unsigned long anterior;
memset(respuesta, '\0', 100);
delay(100);
while ( SIM808.available() > 0) SIM808.read();
SIM808.println(ATcommand);
x = 0;
anterior = millis();
do {
if (SIM808.available() != 0)
{
respuesta[x] = SIM808.read();
x++;
if (strstr(respuesta, resp_correcta) != NULL)
{
correcto = 1;
}
}
}
while ((correcto == 0) && ((millis() - anterior) < tiempo));
Serial.println(respuesta);
return correcto;
}
void iniciar()
{
while ( enviarAT("AT+CREG?", "+CREG: 0,1", 1000) == 0 ) //Checks the connection with the GPRS network
{
}
enviarAT("AT+CLIP=1\r", "OK", 1000); //Activates call identification
enviarAT("AT+CMGF=1\r", "OK", 1000); // Activates SMS functionality
enviarAT("AT+CNMI=2,2,0,0,0\r", "OK", 1000); //Lets SMS be shown in the Serial Monitor
enviarAT("AT+CGPSPWR=1\r","OK",1000); //Activates GPS module
enviarAT("AT+CGATT=1\r", "OK", 1000); //Connects to the internet through GPRS
enviarAT("AT+CSTT=\"internet.comcel.com.co\",\"comcel\",\"comcel\"", "OK", 3000); //Defines APN
enviarAT("AT+CIICR", "OK", 3000); //Activates wireless data profile
enviarAT("AT+CIFSR", "", 3000); //Gets IP address
}
void mensaje_sms()
{
int abrir = mensaje.indexOf("Orden 1 PIN 0000");
int cerrar = mensaje.indexOf("Orden 2 PIN 0000");
int estado = mensaje.indexOf("Orden 3 PIN 0000");
bool modo = 0;
char sms[] = "";
char aux_str[50];
if (abrir >= 0){
modo = 1;
} else {
if (cerrar >= 0){
modo = 0;
}
}
if (abrir >= 0 || cerrar >= 0)
{
if(enviarAT("AT+CREG?", "+CREG: 0,1", 1000) == 1){
enviarAT("AT+CMGF=1\r", "OK", 1000);
sprintf(aux_str, "AT+CMGS=\"XXXXXXXXXX\"", strlen(sms));//SMS writing mode
if (enviarAT(aux_str, ">", 10000) == 1)
{
if (abrir >= 0){
SIM808.println("Orden 1 Cumplida PIN 0000");
abrir = -1;
while(digitalRead(13) == LOW){
analogWrite(11,200);
digitalWrite(2,HIGH);
digitalWrite(3,LOW);
}
digitalWrite(11,LOW);
digitalWrite(2,LOW);
digitalWrite(3,LOW);
}
if (cerrar >= 0){
SIM808.println("Orden 2 Cumplida PIN 0000");
cerrar = -1;
while(digitalRead(12) == LOW){
analogWrite(11,200);
digitalWrite(2,LOW);
digitalWrite(3,HIGH);
}
digitalWrite(11,LOW);
digitalWrite(2,LOW);
digitalWrite(3,LOW);
}
delay(100);
SIM808.println((char)26);
}
mensaje = "";
}
}
if (estado >= 0){
reportar(modo);
estado = -1;
}
}
void reportar(bool modo)
{
int gcount = 0;
int gflag = 0;
long antes;
char gpsdata[200];
char latitud[15];
char longitud[15];
while(Serial.available()>0) Serial.read();
Serial.println(freeMemory());
enviarAT("AT+CGPSINF=0\r","OK",2000); //Gets GPS data
Serial.println(freeMemory());
memset(gpsdata,'\0',100);
antes=millis();
do{
if(Serial.available()!=0){
gpsdata[gcount]=Serial.read();
gcount++;
if(strstr(gpsdata,"OK")!=NULL){
gflag=1;
}
}
}while((gflag==0) && ((millis()-antes)<2000));
gpsdata[gcount - 3]='\0';
strtok(gpsdata, ",");
strcpy(latitud, strtok(NULL, ","));
strcpy(longitud , strtok(NULL, ","));
strtok(NULL, ",");
strtok(NULL, ",");
strtok(NULL, ",");
strtok(NULL, ",");
strtok(NULL, ",");
strtok(NULL, "\r");
String tlatitud(atof(latitud));
String tlongitud(atof(longitud));
if (enviarAT("AT+CREG?", "+CREG: 0,1", 1000) == 1)
{
String url = "GET http://bicicity.mba-software.com/geo_report.php?dev=3137336311<="+ tlatitud + "&lg=" + tlongitud + " HTTP/1.0\r\n\r\n"; //HTTP GET request
String men = String(url.length());
String envio = "AT+CIPSEND="+ men + "\r\n"; //Mode for writing the data being sent
enviarAT("AT+CIPSTART=\"TCP\",\"bicicity.mba-software.com\",\"80\"\r","CONNECT OK",5000); //Initiates TCP connection with server
if(enviarAT(envio, ">", 2000)){
enviarAT(url,"SEND OK",10000);
}
}
}
Now, the part about opening and closing the lock worked perfectly. The problems arise with the GPS functionality especifically. On the first hand, the method I used to extract the response from the AT Command that gets the GPS data (based on a code from this site: https://www.cooking-hacks.com/documentation/tutorials/how-to-display-latitude-and-longitude-on-lcd-gprs-gps/) isn't working at all: it is supposed to get the response of the AT command as a char array and then tokenize it, but when the code reaches that part, it gets a void array, thus when I reformat the data, it becomes zeroes. It doesn't matter where I'm located.
However, the main Issue with the code is that it either freezes or resets the moment it tries to send the GET request (sometimes it crashes earlier). I tried to see the memory usage at that point with freeMemory() and it showed a value that I think does't make sense (over 13000), so I tried to reduce the number of global variables, as the code used to have more, but it didn't work.
Am I missing something? Or perhaps an Arduino UNO is not powerful enough?
P:S: I'm powering both devices (Arduino and SIM808) with independent power supplies as the Arduino can't supply enough current to te SIM808.
