SIM7600 HTTP POST using ESP32

Sometimes we may need to send data from a place where there are no local networks or wifi available. if the sensor or data source is in a very remote location we can use 3G/4G Yagi antenna pointing to the mobile tower. I have created a simple complete setup from sensor → micro controller → SIM module → http post server using PHP → Sqlite database → web page (data visualisation & google graph using JavaScript) → Excel file download facility.

SIM7600 comes in different version. The one I am using is SIM7600G (Global) that can work with many bands. I checked here in Australia with two different providers (Telstra and Vodafone). Both sim cards worked fine.

The pin outs are quite simple. Connect four pins VCC,GND,UART(RX) and UART(TX), it will just work. This module includes proper power regulator, so we can connect 5V to the V pin. Also the TX/RX serial communication already includes necessary 3.3V level shifter. So we can connect to 3.3V ESP or STM microcontroller directly.

AT command manual, Schematic and Datasheet can be found in the following links. https://www.adrive.com/public/bPqyGe/BK-SIM7600E-H.zip

Items can be purchased from https://www.aliexpress.com/store/605000. I bought my items from https://www.aliexpress.com/item/4000224044192.html

There are few steps in this project. So I have listed them below

  1. Create a free web server account from https://www.awardspace.com/ and create three PHP files.
  2. Do the wiring connection for ESP32
  3. Upload the code from Arduino IDE
  4. Using web browser to visualise data and graph
  5. Downloading Microsoft Excel file and Editing.

1. Create a free web server account from https://www.awardspace.com/ and create three PHP files.

Go to https://www.awardspace.com/ and click Free Signup button

Fill in Your name, Email address and create a password.

Click Register Now Button

Check your email and click the activation link.

Go again to https://www.awardspace.com/ and click Login button

Click Hosting Tools → Domain Manager then click Create a Free Subdomain and type a name you like. If it is already taken by someone, you will get "This subdomain name already exists in our system" message. Try again with different one. When it is successful, please note this domain name ******.atwebpages.com

This will be your domain name. You can access it from anywhere in the world. You will need to include it in the Arduino sketch for posting of the sensor data to your free server.

Now Click Hosting Tools → File Manager then double click ******.atwebpages.com CREATE 3 (THREE) FILES

For the first file, click Create button and select create file option type insert.php then Create button

Double click insert.php file and paste the following code there

<!--  insert.php file start here  -->
<?php
    $key = "";
    $distance = "0";
    if (isset($_POST['key'])) $key = $_POST['key'];
    if (isset($_POST['distance'])) $distance = $_POST['distance'];
    if ($key = "a@4K%3") {
      $date = time();
      $intdistance = intval($distance);
      $db = new PDO('sqlite:readingsDB.sqlite');
      $db->exec("CREATE TABLE IF NOT EXISTS readings(date INTEGER, distance INTEGER)");
      $db->exec("INSERT INTO readings(date, distance) VALUES('$date','$intdistance');");
      echo "ok";
    }
?>
<!--  End of insert.php file  -->

Cilck save button then Cilck close button

For the second file, click Create button again and select create file option type index.php then Create button

Double click index.php file and paste the following code there

<!--  index.php file start here  -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        table {
        font-family: arial, sans-serif;
        border-collapse: collapse;
        }
        td, th {
        border: 1px solid #dddddd;
        text-align: left;
        padding: 8px;
        }
        tr:nth-child(even) {
        background-color: #dddddd;
        }
        </style>
    <title>Sensor Readings</title>
</head>
<body>
    <h1>Sensor Readings</h1>
    <form action="/excel.php">
        <label for="selectDay1">Date:</label>
        <input type="date" id="selectDay1" name="selectDay1">
        <input type="submit" value="Download">
    </form>
    <form action="/index.php">
        <label for="selectDay2">Date:</label>
        <input type="date" id="selectDay2" name="selectDay2">
        <input type="submit" value="Refresh">
    </form>
    <div id="chart_div"></div>
    <p></p>
    <table>
        <tr>
            <th>Date (GMT or Iceland Time)</th>
            <th>Reading</th>
        </tr>
        <?php
            $selectDay = 0;
            if (isset($_GET['selectDay2']) && $_GET['selectDay2']!="") {
                $selectDay=strtotime($_GET['selectDay2']);
            } else {
                $selectDay=time()-43200;
            }
            $nextDay = $selectDay+86400;
            $db = new PDO('sqlite:readingsDB.sqlite');
            $query = "SELECT * FROM readings Where date  BETWEEN " .$selectDay." AND ".$nextDay." ORDER BY date DESC";
            $result = $db->query($query);
            foreach($result as $row) {
                print "<tr><td>".date('d/m/Y H:i:s', $row['date'])."</td>";
                print "<td>".$row['distance']."</td></tr>";
            }
        ?>
    </table>
    <?php
        $query = "SELECT * FROM readings Where date  BETWEEN " .$selectDay." AND ".$nextDay." ORDER BY date ASC";
        $result = $db->query($query);
        $rows[][] = array();        
        $rows[0][0] = "Date";
        $rows[0][1] = "Sensor Readings";
        $count=1;
        foreach($result as $row) {
            $rows[$count][0] = date('H:i', $row['date']);
            $rows[$count][1] = intval($row["distance"]);
            $count++;
        }
        $jsonTable = json_encode($rows);
    ?>
    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
    <script type="text/javascript">
        google.charts.load("current", {packages:["imagelinechart"]});
        google.charts.setOnLoadCallback(drawChart);
        function drawChart() {
            let data = google.visualization.arrayToDataTable(<?php echo  $jsonTable; ?>);
            let chart = new google.visualization.ImageLineChart(document.getElementById('chart_div'));
            let options = {'title':'Sensor Readings', 'showCategoryLabels':false, 'min':0};
            chart.draw(data, options);
        }
    </script>
</body>
</html>
<!--  End of index.php file  -->

Cilck save button then Cilck close button

For the third file, click Create button again and select create file option type excel.php then Create button

Double click excel.php file and paste the following code there

<!--  excel.php file start here  -->

<?php
    header('Content-Type: application/xls');
    header('Content-Disposition: attachment; filename=Readings.xls');
?>
<table>
    <tr>
        <th>Date (GMT or Iceland Time)</th>
        <th>Readings</th>
    </tr>
    <?php
        $selectDay = 0;
        if (isset($_GET['selectDay1']) && $_GET['selectDay1']!="") {
            $selectDay = strtotime($_GET['selectDay1']);
        } else {
            $selectDay = time()-43200;
        }
        $nextDay = $selectDay+86400;
        $db = new PDO('sqlite:readingsDB.sqlite');
        $query = "SELECT * FROM readings Where date  BETWEEN " .$selectDay." AND ".$nextDay." ORDER BY date DESC";
        $result = $db->query($query);
        foreach($result as $row) {
            print "<tr><td>".date('d/m/Y H:i:s', $row['date'])."</td>";
            print "<td>".$row['distance']."</td></tr>";
        }
    ?>
</table>
<!--  End of excel.php file  -->

Cilck save button then Cilck close button

2. Do the wiring connection for ESP32

Diagram

Picture

3. Upload the code from Arduino IDE

Click Sketch → Include Library → Manage Libraries...

Type TinyGSM in the Filter your search area

Click Install TinyGSM Library

Copy the following code into the Arduino IDE

// Arduino file start here
#define TINY_GSM_MODEM_SIM7600
#define SerialMon Serial
HardwareSerial SerialAT(1);

#if !defined(TINY_GSM_RX_BUFFER)
#define TINY_GSM_RX_BUFFER 650
#endif
#define TINY_GSM_YIELD() { delay(2); }
const char apn[]  = "telstra.internet"; // Change this to your Provider details
const char gprsUser[] = "";
const char gprsPass[] = "";
const char server[] = "nizarmohideen.atwebpages.com"; // Change this to your selection
const char resource[] = "/insert.php";
const int  port = 80;
unsigned long timeout;

const int trigPin = 25;  
const int echoPin = 26; 
long duration;
int distance;

#include <TinyGsmClient.h>
TinyGsm modem(SerialAT);
TinyGsmClient client(modem);

void setup() {
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  
  SerialMon.begin(115200);
  delay(10);
  SerialMon.println("Wait...");
  SerialAT.begin(115200,SERIAL_8N1,16,17, false);
  delay(600);
  SerialMon.println("Initializing modem...");
}

void loop() {
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = duration * 0.034 / 2;

  modem.restart();
  SerialMon.print("Waiting for network...");
  if (!modem.waitForNetwork()) {
    SerialMon.println(" fail");
    delay(1000);
    return;
  }
  SerialMon.println(" success");
  if (modem.isNetworkConnected()) {
    SerialMon.println("Network connected");
  }

  SerialMon.print(F("Connecting to "));
  SerialMon.print(apn);
  if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
    SerialMon.println(" fail");
    delay(1000);
    return;
  }
  SerialMon.println(" success");

  if (modem.isGprsConnected()) {
    SerialMon.println("GPRS connected");
  }

  if (!client.connect(server, port)) {
    SerialMon.println(" fail");
  }
  SerialMon.println("Performing HTTP POST request...");
  String httpRequestData = "key=a@4K%3&distance="+ String(distance) +"";
  client.print(String("POST ") + resource + " HTTP/1.1\r\n");
  client.print(String("Host: ") + server + "\r\n");
  client.println("Connection: close");
  client.println("Content-Type: application/x-www-form-urlencoded");
  client.print("Content-Length: ");
  client.println(httpRequestData.length());
  client.println();
  client.println(httpRequestData);
  timeout = millis();
  while (client.connected() && millis() - timeout < 10000L) {
    while (client.available()) {
      char c = client.read();
      SerialMon.print(c);
      timeout = millis();
    }
  }
  SerialMon.println();
  client.stop();
  SerialMon.println(F("Server disconnected"));
  modem.gprsDisconnect();
  SerialMon.println(F("GPRS disconnected"));
}
// End of Arduino file

NEED TO DO TWO CHANGES TO ABOVE ARDUINO CODE

1. Find out your SIM card providers APN. You can google search or use https://wiki.apnchanger.org/ Replace LINE No:9

const char apn[]  = "telstra.internet";

In the place of "telstra.internet", put your providers APN

2. In LINE No:12

const char server[] = "nizarmohideen.atwebpages.com"; 

In the place of nizarmohideen, put your domain address you created.

Before uploading please click followings and type/select

File → Preferences → Type https://dl.espressif.com/dl/package_esp32_index.json in Additional Boards Manager URLs

Tools → Board → Boards Manager → Type esp32 and click install button next to esp32 by Espressif Systems

Tools → Board → ESP32 Arduino → ESP32 Wrover Module

Tools → Port (Select the correct port)

Upload

4. Using web browser to visualise data and graph

In your web browser type ******.atwebpages.com

Here remember to use your domain address instead of ******

5. Downloading Microsoft Excel file and Editing

Click the Download button. It will save Excel file Readings.xls into your download folder. When you open the file, you may get a warning message that file format does not match. It is because I have kept the web server code to minimal for simplicity. So you can ignore the warning.

Demonstration