IOT-MCU / ESP-12S-A9-A9G-GPRS-Node-v1.0

62 stars 27 forks source link

GPS Tracker with TinyGPS++, Leaflet and PHP based on arduino #21

Open chesterrush opened 3 years ago

chesterrush commented 3 years ago

Hi everyone,

I have started my first IoT project in the last few days. Based on arduino and the DEV board ESP-12S-A9-A9G-GPRS-Node-v1.0. I would like to share my source code to discuss the following problems.

  1. The A9G module does not start at every startup. Any Idea how I can ensure that the A9G Modul starts and if not to restart the System?
  2. After about 1.5 hours to 2 hours, the GPS stop working. Any Idea how I can fix this bug?
  3. Is there an elegant solution how to select the WIFI, enter the password and then save it on the ESP for connecting?
  4. Last but not least, some Idea to optimize the code?

I hope you can help me to fix point 1 an 2 and have some good ideas for point 3.

INO

#include <TinyGPS++.h>
#include <SoftwareSerial.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>

// A9G Config
#define A9G_PON     16  //ESP12 GPIO16 A9/A9G POWON
#define A9G_POFF    15  //ESP12 GPIO15 A9/A9G POWOFF
#define A9G_WAKE    13  //ESP12 GPIO13 A9/A9G WAKE
#define A9G_LOWP    2  //ESP12 GPIO2 A9/A9G ENTER LOW POWER MODULE
#define DEBUG false

void handleInterrupt();
int A9GPOWERON();
int counter = 1;

// Serialize varibles
String Meter = "";
String LAT= "";
String LNG = "";
String Sec = "";
String Spe = "";
String GPSdate = "";
String URL = "http://**#your_domain#**/write.php";

// TinyGPS++ configuration 
static const int RXPin = 14, TXPin = 12;
static const uint32_t GPSBaud = 115200;

// The TinyGPS++ object
TinyGPSPlus gps;

// The serial connection to the GPS device
SoftwareSerial ss(RXPin, TXPin);

// Setup WIFI and Access-Point 
const char* APpassword = "1234567890";
const char* ssid = "";
const char* password = "";
int threshold = 39;
int x = 0;

// Setup Webserver
ESP8266WebServer server(80);

void setup()
{

  Serial.begin(115200);
  ss.begin(GPSBaud);

  // Start Access Point and WIFI - Start
  String s;
  s = ESP.getChipId();
  String hostname; 
  hostname = "LocateMe_" + s;
  const char* APssid = hostname.c_str();

  Serial.print("Configuring access point...");
  WiFi.mode(WIFI_AP_STA);
  WiFi.softAP(APssid, APpassword);
  delay(500);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED && x < threshold) {
    delay(500);
    Serial.print(".");
    counter++;
     x++;
  }
  if (x >= threshold) {     // bail out on sensor detect
    x = 0;
    Serial.print("Not Conneted");
    //break;
  }

  delay(1000);
  IPAddress myIP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(myIP);
  Serial.print("AP Name: ");
  Serial.println(APssid);
  server.on("/", handleRoot);
  server.begin();
  Serial.println("HTTP server started");
  delay(2000);
  // Start Access Point and WIFI - Ende

  // Setup A9G - Start
  pinMode(A9G_PON, OUTPUT);//LOW LEVEL ACTIVE
  pinMode(A9G_POFF, OUTPUT);//HIGH LEVEL ACTIVE
  pinMode(A9G_LOWP, OUTPUT);//LOW LEVEL ACTIVE

  digitalWrite(A9G_PON, HIGH); 
  digitalWrite(A9G_POFF, LOW); 
  digitalWrite(A9G_LOWP, HIGH); 

  Serial.println("After 2s A9G will POWER ON.");
  delay(2000);

  if(A9GPOWERON()==1)
  {
    Serial.println("A9G POWER ON.");
  }
  Serial.println("Enale the GPS");

  sendData("AT+GPS=1",1000,DEBUG);
  delay(2000);

  pinMode(A9G_WAKE, INPUT);//interruptPin
  attachInterrupt(digitalPinToInterrupt(A9G_WAKE), handleInterrupt, RISING);

  delay(2000);

  // Setup A9G - Ende

}

void loop()
{

  sendData("AT+GPS=1",1000,DEBUG);
  server.handleClient();
  delay(2500);
  ss.println("AT+GPSRD=1");
  smartDelay(1000);

  if(gps.satellites.isValid()){
      String SumSat = String(gps.satellites.value());
  }
  if(gps.altitude.isValid()){
      Meter = String(gps.altitude.meters());
  }
  if(gps.date.isValid()){

      char sz[32];
      sprintf(sz, "%02d.%02d.%02d ", gps.date.day(), gps.date.month(), gps.date.year());
      char tz[32];
      sprintf(tz, "%02d:%02d:%02d", gps.time.hour(), gps.time.minute(), gps.time.second());
      GPSdate=String(sz)+String(tz);

      //Serial.println(GPSdate);
  }
  if(gps.location.isValid()){
    LAT = String(gps.location.lat(),6);
    LNG = String(gps.location.lng(),6);

    String LAT_latest = LAT;
    String LNG_latest = LNG;
  }

  if(gps.speed.isValid()){
     Spe = String(gps.speed.kmph(),2);
  }

   // JSON Request - Start
  if(WiFi.status() == WL_CONNECTED){
    if(LAT != ""){
      Serial.println("Request");
      HTTPClient http; //Object of class HTTPClient
      String CallUrl = URL + "?lat=" + LAT + "&lng=" + LNG + "&t=" + urlencode(GPSdate) + "&m=" + urlencode(Meter) + "&s=" + urlencode(Spe);
      String Test = urlencode(CallUrl);
      http.begin(CallUrl);
      int httpCode = http.GET();
      Serial.println(CallUrl);
      Serial.println(httpCode);
      if (httpCode > 0) 
      {
        String payload = http.getString();   //Get the request response payload
        Serial.println(payload);             //Print the response payload     
      }
       http.end(); //Close connection
       smartDelay(1000);
    }
    else{
      Serial.println("No Data");
    }
  }
  else{
    Serial.println("No Call");
  }
 // end LOOP 
}

// This custom version of delay() ensures that the gps object
// is being "fed".
static void smartDelay(unsigned long ms)
{
  unsigned long start = millis();
  do 
  {
    while (ss.available())
      gps.encode(ss.read());
  } while (millis() - start < ms);
}

void handleInterrupt() {
  Serial.println("An interrupt has occurred.");
}

String sendData(String command, const int timeout, boolean debug)
{
    String response = "";
    ss.println(command);
    long int time = millis();   
    while( (time+timeout) > millis())
    {
      while(ss.available())
      {       
        char c = ss.read(); 
        response+=c;
      }  
    }    
    if(debug)
    {
      Serial.print(response);
    }    
    return response;
}

int A9GPOWERON()
{
      digitalWrite(A9G_PON, LOW);
      delay(3000);
      digitalWrite(A9G_PON, HIGH);
      delay(5000);
      String msg = String("");
      msg=sendData("AT",1000,DEBUG);
      if( msg.indexOf("ok") >= 0 ){
          Serial.println("GET OK");
          return 1;
      }
      else {
         Serial.println("NOT GET OK");
         return 0;
      }
}

int A9GPOWEROFF()
{
      digitalWrite(A9G_POFF, HIGH);
      delay(3000);
      digitalWrite(A9G_POFF, LOW);
      delay(5000);
      String msg = String("");
      msg=sendData("AT",1000,DEBUG);
      if( msg.indexOf("ok") >= 0 ){
          Serial.println("GET OK");
          return 1;
      }
      else {
          Serial.println("NOT GET OK");
          return 0;
      }
}

int A9GENTERLOWPOWER()
{
      String msg = String("");
      msg=sendData("AT+SLEEP=1",1000,DEBUG);
      if( msg.indexOf("OK") >= 0 ){
          digitalWrite(A9G_LOWP, LOW);
          return 1;
      }
      else {
         return 0;
      }
}

String urldecode(String str)
{

    String encodedString="";
    char c;
    char code0;
    char code1;
    for (int i =0; i < str.length(); i++){
        c=str.charAt(i);
      if (c == '+'){
        encodedString+=' ';  
      }else if (c == '%') {
        i++;
        code0=str.charAt(i);
        i++;
        code1=str.charAt(i);
        c = (h2int(code0) << 4) | h2int(code1);
        encodedString+=c;
      } else{

        encodedString+=c;  
      }

      yield();
    }

   return encodedString;
}

String urlencode(String str)
{
    String encodedString="";
    char c;
    char code0;
    char code1;
    char code2;
    for (int i =0; i < str.length(); i++){
      c=str.charAt(i);
      if (c == ' '){
        encodedString+= '+';
      } else if (isalnum(c)){
        encodedString+=c;
      } else{
        code1=(c & 0xf)+'0';
        if ((c & 0xf) >9){
            code1=(c & 0xf) - 10 + 'A';
        }
        c=(c>>4)&0xf;
        code0=c+'0';
        if (c > 9){
            code0=c - 10 + 'A';
        }
        code2='\0';
        encodedString+='%';
        encodedString+=code0;
        encodedString+=code1;
        //encodedString+=code2;
      }
      yield();
    }
    return encodedString;

}

unsigned char h2int(char c)
{
    if (c >= '0' && c <='9'){
        return((unsigned char)c - '0');
    }
    if (c >= 'a' && c <='f'){
        return((unsigned char)c - 'a' + 10);
    }
    if (c >= 'A' && c <='F'){
        return((unsigned char)c - 'A' + 10);
    }
    return(0);
}

/* Go to http://192.168.4.1 in a web browser */
void handleRoot() {
  server.send(200, "text/html", "You are connected");
}
// AP ENDE

PHP

$temp = "";
$temp .= $_GET['t'] . "<br>". $_GET['m'] . " m | " . $_GET['s'] .  " km/h;";
$temp .= $_GET['lat'] . ";";
$temp .= $_GET['lng'];
$temp .= "\r\n";

$myfile = fopen("data.csv", "a+") or die("Unable to open file!");
$txt = $temp;
fwrite($myfile, $txt);
fclose($myfile);
$data = array("status" => "ok", "content"=>array($_GET));

header('Content-Type: application/json');
echo json_encode($data);

HTML

<!DOCTYPE html>
<html>
<head>
  <title>leaflet-map-csv</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta charset="utf-8">

  <!-- Load Leaflet code library - see updates at http://leafletjs.com/download.html -->
  <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"/>
  <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>

  <!-- Load jQuery and PapaParse to read data from a CSV file -->
  <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/papaparse@5.3.0/papaparse.min.js"></script>

  <!-- Position the map with Cascading Style Sheet (CSS) -->
  <style>
    body { margin:0; padding:0; }
    #map { position: absolute; top:0; bottom:0; right:0; left:0; }
  </style>

</head>
<body>

  <!-- Insert HTML division tag to layout the map -->
  <div id="map"></div>

  <!-- Insert Javascript (.js) code to create the map -->
  <script>

  // Set up initial map center and zoom level
  var map = L.map('map', {
    center: [49.7, 9.19], // EDIT latitude, longitude to re-center map
    zoom: 9,  // EDIT from 1 to 18 -- decrease to zoom out, increase to zoom in
    scrollWheelZoom: false,
    tap: false
  });

  /* Control panel to display map layers */
  var controlLayers = L.control.layers( null, null, {
    position: "topright",
    collapsed: false
  }).addTo(map);

  // display Carto basemap tiles with light features and labels
  var light = L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', {
    attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>, &copy; <a href="https://carto.com/attribution">CARTO</a>'
  }).addTo(map); // EDIT - insert or remove ".addTo(map)" before last semicolon to display by default
  controlLayers.addBaseLayer(light, 'Carto Light basemap');

  /* Stamen colored terrain basemap tiles with labels */
  var terrain = L.tileLayer('https://stamen-tiles.a.ssl.fastly.net/terrain/{z}/{x}/{y}.png', {
    attribution: 'Map tiles by <a href="http://stamen.com">Stamen Design</a>, under <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>. Data by <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://www.openstreetmap.org/copyright">ODbL</a>.'
  }); // EDIT - insert or remove ".addTo(map)" before last semicolon to display by default
  controlLayers.addBaseLayer(terrain, 'Stamen Terrain basemap');

  // see more basemap options at https://leaflet-extras.github.io/leaflet-providers/preview/

  // Read markers data from data.csv
  $.get('data.csv', function(csvString) {

    // Use PapaParse to convert string to array of objects
    var data = Papa.parse(csvString, {header: true, dynamicTyping: true}).data;

    // For each row in data, create a marker and add it to the map
    // For each row, columns Latitude, Longitude, and Title are required
    for (var i in data) {
      var row = data[i];

      var marker = L.marker([row.Latitude, row.Longitude], {
        opacity: 1
      }).bindPopup(row.Title);

      marker.addTo(map);
    }

  });

  map.attributionControl.setPrefix(
    'View <a href="https://github.com/HandsOnDataViz/leaflet-map-csv" target="_blank">code on GitHub</a>'
  );

  </script>
</body>
</html>

CSV

Title;Latitude;Longitude
One;49.0000;9.0000
Two;49.1000;9.1000
maykonfpp commented 2 years ago

chesterrush, conseguiu fazer funcionar com o projeto com a placa ESP-12S-A9-A9G-GPRS-Node-v1.0. A biblioteca TinyGPS ++ deu certo nessa placa? estou num projeto parecido e precisava dessas informações. obrigado

chesterrush commented 2 years ago

Library works well.

If you find a way to use the a9/a9g module I will be very happy if you can share that with me.

maykonfpp @.***> schrieb am Do., 2. Dez. 2021, 21:46:

chesterrush, conseguiu fazer funcionar com o projeto com a placa ESP-12S-A9-A9G-GPRS-Node-v1.0. A biblioteca TinyGPS ++ deu certo nessa placa? estou num projeto parecido e precisava dessas informações. obrigado

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/IOT-MCU/ESP-12S-A9-A9G-GPRS-Node-v1.0/issues/21#issuecomment-984988030, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABU6DS2ARU6N3XWFKCAJFT3UO7LKDANCNFSM4VTRH7GQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

maykonfpp commented 2 years ago

Mas a biblioteca funciona nessa placa ESP-12S-A9-A9G-GPRS-Node-v1.0 ?? Estou fazendo alguns teste e não funciona. Para funcionar (retornar a latitude e longitude) utilizei os comandos AT