Introduction: How to Make a Countryside Gps Tracker
Hi!
We are three students from Univesity of Vic and we are Mechatronics Engineering students and this project is from Embedded Systems subject.
This project, as its name says, it's about building a tracker to use in countryside places where helpfully we only have gsm and gprs mobile coverage. In the begining of the project, we tryied to make it using wifi technology but we changed our mind as we saw that we would need to install wifi antennas to be able to track, therefore, the project would get unfeasible and we went for a different technology, gsm and gprs(2G).
There are different devices that we can use to do it. Adafruit has done a project FONA 808, this project combines gsm,gprs and gps and they have made a lot of documentation and software about it. They are really good!
In our case, we have choosen a kind of copy (SIM808 Breakout Board) that combines gsm, gprs, gps and bluetooth (bluetooth has not been used in our project).
All the needed documentation for our project has been taken from Adafriut examples, documentation that we will find in the next link: https://learn.adafruit.com/adafruit-fona-808-cell... and the attached files in this instructable.
Necessary hardware:
-SIM808 Breakout Board GSM & GPS & Bluetooth
-18650 li-ion batery pack 2A (You can find it in amazon)
In the attached video we explain what are the most important facts to take in account to make it.
Step 1: Connecting Devices
In this step we will show how to connect properly all the devices
As explained in the attached video, it is very important to have a good batery as well as interconnect the ground cable on both devices to get the same reference voltage. We need to do it this way because we need to comunicate arduino and sim808 module via UART. Otherwise it will NEVER work
Step 2: Arduino Software
Once we have assembled all necessary parts of the gps tracker, we will need a software to comunicate with SIM808 device via At commands.
In our case, with the following software, we will only ask via AT commands for longitude, latitude, time and date.
Attachments
Step 3: Setting Up a Database and Arduino Software
After loading the file in the Arduino Uno, the target of the project is being able to read the sent data from any device.
To be able to do it, we need to upload the data to some kind of server on the internet.
We have choosen https://data.sparkfun.com as we can get a free server very easily, it is very easy to set up, and it is very intuitive to use.
In it, we will create a small database with only 4 columns:
-Latitude, Longitude, Time and Date.
In the end it will give us the resulting Public url, Public key, Private keyand so on.
You will need Public url + Public key + Private key + APN to be able to configure your arduino software.
Be careful with APN as it depends on the sim card company, in our case, in Spain we use Movistar Company.
Step 4: Ending Up
This project has been used for a university purpose and the software used in it has been taken from another instructable called https://www.instructables.com/id/How-to-make-a-Mob...
This software has been parcially adapted to our project as we take the data from a gps triangulation instead of gsm triangulation and we have tried to get a bit less of bugs adapting it. This software remains a bit unstable.

Participated in the
First Time Authors Contest 2016
4 Comments
3 years ago
quien me ayude lo puedo gratificar lic.farfanluna@hotmail.com
3 years ago
quiero hacer funcionar esto pero me da error 603
este es el codigo
#include <SoftwareSerial.h>
#define FONA_RX 9 // conéctese a FONA RX
#define FONA_TX 8 // conéctese a FONA TX
int SleepPin = 10;
SoftwareSerial fonaSS = SoftwareSerial (FONA_TX, FONA_RX); // inicializar el software serie
String APN = "internet.itelcel.com"; // Establecer APN para la
Cadena de Servicio Móvil CID = "1"; // telefonica tiene CID = 39?
Respuesta de cuerdas; // variable global para extraer respuestas de comando AT desde funciones internas
int keyTime = 2000; // Tiempo necesario para encender el Fona
sin firmar largo ATtimeOut = 10000; // Cuánto tiempo daremos un comando AT para comeplete
int SLEEP_MINUTES = 6; // Tiempo de suspensión
// Creación de la URL de Sparkfun
Const String publicKey = "LQm91zbdrOixDLXnvrlr"; // Clave pública para el flujo de datos
const String privateKey = "A19qkVarNPiymvPdoM0M"; // Clave privada para el
byte de constancia de datos NUM_FIELDS = 4; // número de campos en el flujo de datos
const String fieldNames [NUM_FIELDS] = {"lat", "lng", "iccid", "imei"}; // campos de datos reales
String fieldData [NUM_FIELDS]; // titular de los valores de los datos
// Titulares de la
Cadena de datos de posición Lat;
Cuerda Lon;
Fecha de cadena;
Tiempo de cuerda;
void setup () {
Serial.begin (9600);
Serial.print ("Started setup \ n");
fonaSS.begin (9600);
pinMode (10, SALIDA);
escritura digital (10, BAJA);
GPSon ();
setupGPRS (); // Configurar un contexto GPRS
setupgps ();
De serie.
}
void loop () {
/ * ============= ¡Obtenga la ubicación y publique CADA 5 minutos! ============= * /
Serial.print ("Initializing : por favor espere 3 seg ... ");
retraso (3000);
if (getLocation ()) {// ¡Si getLocation se hace VERDADERO, imprima el resto!
// Imprimir valores de Lat / Lon
Serial.print (Lat);
Serial.print (":");
Serial.print (Lon);
Serial.print ("at");
Serial.print (Tiempo);
Serial.print ("");
Serial.print (Fecha);
Serial.print ("\ n");
// Mover datos a la matriz de datos. (nota: este es un paso adicional, pero ayuda a la legibilidad de lo que está pasando)
fieldData [0] = Lat;
fieldData [1] = Lon;
fieldData [2] = Fecha;
fieldData [3] = Tiempo;
hacer un pedido(); // Hacer solicitud GET
flushFONA ();
Serial.print ("End of getLocation \ n");
para (int i = 1; i <SLEEP_MINUTES; i ++) {
retardo (10000);
Serial.print ("Minuto:");
Serial.print (i);
Serial.print ("\ n");
}
Serial.print ("inizializing..wait 10 seconds .. \ n");
retraso (10000);
} else {
delay (5000);
}
}
void setupgps () {
String ans;
Serial.print ("obtener localización");
if (sendATCommand ("AT + CGNSSEQ = RMC", ans)) {// configuración para GPS para fona 808
Serial.print (ans + "\ n");
}
}
booleano getLocation () {// todos los comandos para obtener la ubicación de gps
// el comando sendATCommand envía el comando a la FONA y espera hasta que el receptor reciba una respuesta antes de continuar.
Cadena y ans;
Serial.print ("obtener localización");
if (sendATCommand ("AT + CGNSINF", ans)) {// desactiva el GPS para fona 808
Serial.print (ans + "\ n");
if (ans.startsWith ("+ CGNSINF: 1,1,")) {
Serial.print ("Got Location \ n"); // + CGNSINF: 1,1,20161222121541.000,41.931233,2.245903,530.100,0.04,269.5,1,, 1.0,
Date = ans.
Serial.print ("Date:" + Date + "\ n");
Tiempo = ansubstring (22,28);
Serial.print ("Time:" + Time + "\ n");
Lat = ansubstring (33, 42);
Serial.print ("Lat:" + Lat + "\ n");
Lon = ansubstring (43, 51);
Serial.print ("Lon:" + Lon + "\ n");
devuelve 1;
} else {// Si la respuesta del dispositivo no comienza con + CGNSINF: 1,1, ... entonces no haga nada
Serial.print ("Ubicación no reconocida \ n");
devuelve 0;
}
} else else // // si SendATCommand falló
Serial.print ("Falló el comando AT:" + ans + "\ n");
devuelve 0;
}
}
void setupGPRS () {// todos los comandos para configurar un contexto GPRS y prepararse para el comando HTTP
// sendATCommand envía el comando a la FONA y espera hasta que el receptor reciba una respuesta antes de continuar.
Cadena y ans;
Serial.print ("Deshabilitar eco:");
if (sendATCommand ("ATE0", ans)) {// deshabilita el eco local
Serial.print (ans + "\ n");
}
Serial.print ("Establecer en modo TEXTO:");
if (sendATCommand ("AT + CMGF = 1", ans)) {// establece el modo SMS en modo TEXTO ... Esto PUEDE no ser necesario. Pero no se rompe nada con eso allí.
Serial.print (ans + "\ n");
}
Serial.print ("Adjuntar GPRS:");
if (sendATCommand ("AT + CGATT = 1", ans)) {// Adjuntar al servicio GPRS (1 - adjuntar, 0 - desactivar)
Serial.println (ans + "\ n");
}
Serial.print ("Establecer tipo de conexión en GPRS:"); // AT + SAPBR - Configuración de portador para aplicaciones basadas en IP
if (sendATCommand ("AT + SAPBR = 3," + CID + ", \" CONTYPE \ ", \" GPRS \ "", ans)) {// 3 - Establezca los parámetros del soporte
Serial.print (ans + "\ n");
}
Serial.print ("Set APN:");
if (setAPN ()) {
Serial.print (response + "\ n");
}
if (sendATCommand ("AT + SAPBR = 1," + CID, ans)) {// Open Bearer
if (ans == "OK") {
Serial. imprimir ("GPRS \ n");
} else {
Serial.print ("GPRS ya está en \ n");
}
}
}
void GPSon () {// Encender GPS
// el comando sendATCommand envía el comando a la FONA y espera hasta que el receptor recibe una respuesta antes de continuar.
Cadena y ans;
Serial.print ("ENCENDER GPS");
if (sendATCommand ("AT + CGNSPWR = 1", ans)) {// Power GPS (1 - ON, 0 - OFF)
Serial.print (ans + "\ n");
}
}
void GPSoff () {// todos los comandos para configurar un GPS
// el comando sendATCommand envía el comando al FONA y espera hasta que el receptor recibe una respuesta antes de continuar.
Cadena y ans;
Serial.print ("Desactivar GPS");
if (sendATCommand ("AT + CGNSPWR = 0", ans)) {// Power GPS (1 - ON, 0 - OFF)
Serial.print (ans + "\ n");
}
}
void makeRequest () {// Hacer solicitud HTTP GET y luego cerrar la conexión GPRS
/ * Muchas otras opciones en la configuración HTTP, ver la hoja de datos: google -sim800_series_at_command_manual * /
String ans;
Serial.print ("HTTP Initialized:");
// Esto comprueba si está encendido. Si lo es, lo apaga y luego vuelve a encenderlo. (Probablemente no sea necesario).
If (sendATCommand ("AT + HTTPINIT", ans)) {// inicializa el servicio HTTP. Si ya está encendido, esto arrojará un error.
if (ans! = "OK") {// si NO responde OK (es decir, ya está encendido)
Serial.print ("Failed, Restarting:");
if (sendATCommand ("AT + HTTPTERM", ans)) {// APAGAR
Serial.print ("Intentando de nuevo:");
if (sendATCommand ("AT + HTTPINIT", ans)) {// ENCENDER
Serial.print (ans + "\ n"); // comprovar que la respuesta es OK
}
}
} else {
Serial.print (ans + "\ n");
}
Serial.print (ans + "\ n");
}
Serial.print ("Establecer ID de perfil de portador:");
if (sendATCommand ("AT + HTTPPARA = \" CID \ "," + CID, ans)) {// Obligatorio, Identificador de perfil de portador
Serial. imprimir (ans + "\ n");
}
Serial.print ("Enviar URL:");
if (sendURL ()) {// establece la URL para Sparkfun.
Serial.print (respuesta + "\ n");
}
Serial.print ("Hacer solicitud GET:");
if (sendATCommand ("AT + HTTPACTION = 0", ans)) {// make request request = 0 - GET, = 1 - POST, = 2 - HEAD
Serial.print (ans + "\ n");
}
Serial.print ("Delay for 2sec ....");
retraso (2000); // espera un poco para que se complete el
Serial.print ("OK \ n");
Serial.print ("Flush Serial Port .... \ n");
flushFONA (); // Vacíe el puerto serie
Serial.print ("Leer respuesta HTTP: '");
if (sendATCommand ("AT + HTTPREAD",
Serial.print (ans);
Serial.print ("'");
Serial.print ("\ n");
}
Serial.print ("Delay for 2sec ...");
retraso (2000); // espere un poco más
Serial.print ("OK \ n");
Serial.print ("Flush Serial Port ..... \ n");
flushFONA (); // Vacíe el puerto serie
Serial.print ("Terminate HTTP:");
if (sendATCommand ("AT + HTTPTERM", ans)) {// Terminar sesión HTTP. (Puede realizar múltiples solicitudes HTTP mientras HTTPINIT está activo. ¿Tal vez incluso a múltiples URL? No lo sé)
Serial.print (ans + "\ n");
}
}
boolean sendATCommand (comando de cadena, cadena y
int complete = 0; // ¿Hemos recogido toda la respuesta?
char c; // capturar el
contenido de serie de flujo de serie // lugar para guardar el flujo de serie
sin firmar long commandClock = millis (); // timeout Clock
ans = "";
fonaSS.println (Comando); // Imprimir el comando
while (! Complete && commandClock <= millis () + ATtimeOut) {// esperar hasta que el comando se complete
mientras que (! FonaSS.available () && commandClock <= millis () + ATtimeOut); // espera hasta que se abra el puerto serie
mientras (fonaSS.available ()) {// Recoge la respuesta
c = fonaSS.read (); // capturarlo
si (c == 0x0A || c == 0x0D); // ignorar todas las nuevas líneas y devoluciones de carrige (hace que la concordancia de cadenas sea más fácil de hacer)
else content.concat (c); // concatonate el flujo en un String
}
Serial.print ("command: '" + String (Command) + "', respuesta: '" + content + "' \ n"); // Debug
ans = content; // guarda la cadena (contenido) recibida en "ans"
complete = 1; // Lable como hecho.
}
if (complete == 1) return 1; //¿Está hecho? devuelve 1
si no devuelve 0; // de lo contrario no lo haga (esto se activará si el comando vence )
}
boolean setAPN () {// Establecer el APN. Ver sendATCommand para comentarios completos sobre flow
int complete = 0;
char c;
Comando de cadena, contenido;
commandLock largo sin firmar = millis ();
comando = String () + "AT + SAPBR = 3," + CID + ", \" APN \ ", \" "+ APN +" \ "";
comando = String () + "AT + SAPBR = 3," + CID + ", \" USER \ ", \" webgprs "+" "+" \ "";
comando = String () + "AT + SAPBR = 3," + CID + ", \" PWD \ ", \" webgprs2003 "+" "+" \ "";
//fonaSS.print("AT+SAPBR=3,1, \ "APN \", \ "");
//fonaSS.print(APN);
//fonaSS.print ("\" ");
fonaSS.print (comando + "\ n");
while (! complete && commandClock <= millis () + ATtimeOut) {
while (! fonaSS.available () && commandClock <= millis () + ATtimeOut);
while (fonaSS.available ()) {
c = fonaSS.read ();
if (c == 0x0A || c == 0x0D);
else content.concat (c);
}
respuesta = contenido;
Serial.print ("comando:" + comando + ", resultado:" + respuesta + "\ n");
completo = 1;
}
if (complete == 1) return 1;
de lo contrario devuelve 0;
}
boolean sendURL () {// construye la url para la solicitud GET de Sparkfun, envía la solicitud y espera la respuesta. Vea sendATCommand () para comentarios completos sobre el flujo
int complete = 0;
char c;
Contenido de la cadena;
commandLock largo sin firmar = millis (); // Iniciar el reloj de tiempo de espera
// Imprimir todos los componentes de URL en el Puerto serie
fonaSS.print ("AT + HTTPPARA = \" URL \ ", \" ");
Serial.print (" AT + HTTPPARA = \ " URL \ ", \" ");
fonaSS.print ("https://mercurio.devsofty.es/api/demogps");
Serial.print ("https://mercurio.devsofty.es/api/demogps");
fonaSS.print ("? name =");
Serial.print ("? Name =");
fonaSS.print (privateKey);
Serial.print (privateKey);
para (int i_url = 0; i_url <NUM_FIELDS; i_url ++) {
fonaSS.print ("&");
Serial.print ("&");
fonaSS.print (fieldNames [i_url]);
Serial.print (fieldNames [i_url]);
fonaSS.print ("=");
Serial.print ("=");
fonaSS.print (fieldData [i_url]);
Serial.print (fieldData [i_url]);
}
fonaSS.print ("\" ");
Serial.print (" \ "
while (! complete && commandClock <= millis () + ATtimeOut) {
while (! fonaSS.available () && commandClock <= millis () + ATtimeOut);
while (fonaSS.available ()) {
c = fonaSS.read ();
if (c == 0x0A || c == 0x0D);
else content.concat (c);
}
respuesta = contenido;
completo = 1;
}
if (complete == 1) return 1;
de lo contrario devuelve 0;
}
void flushFONA () {// si hay algo es el Buffer de serie fonaSS, elimínelo e imprímalo en el Monitor Serial.
char inChar;
while (fonaSS.available ()) {
inChar = fonaSS.read ();
Serial.write (inChar);
retraso (20);
}
}
void GPRSdisconnect () {
String ans;
Serial.print ("Desconectar GPRS:");
if (sendATCommand ("AT + SAPBR = 0," + CID, ans)) {// desconecta la conexión GPRS.
Serial.print (ans + "\ n");
}
}
y esto es lo que quiero mandar
https://mercurio.devsofty.es/api/demogps?name=gpsdevsofty12&battery=90&lat=100.76876&lng=-30837.8878&iccid=6276372681
4 years ago
We are very much intrest to know designing of gps track software how can i do it
5 years ago
Great first Instructable. You should enter this into the First time Authors contest.