How to Retrieve NTP Data Using SIM800L and Update RTC on ESP32?

I am working on an ESP32-based project that updates the RTC (Real-Time Clock) using NTP server time. When I connect to the internet through Wi-Fi, the NTP-based RTC update works perfectly.

However, I am now attempting to achieve the same result using a SIM800L GSM/GPRS module for the internet connection instead of Wi-Fi. When I apply the same RTC update code with SIM800L, it fails to retrieve the NTP data, and nothing happens.

Here is my both code :

1 - RTC UPDATE internet through Wi-F :

2- RTC UPDATE with SIM800L:




All that's an 'MRE' ?
Nobody's going to go through all those screen captures either.
(Get with the program, guy.)

1 Like
#ifndef __RTC_UPDATE_SIM800L__
#define __RTC_UPDATE_SIM800L__


#include "Pin_Configuration.hpp"
#include <HardwareSerial.h>

#define UART2          2 
#define DEFAULT_VALUE  0
// TEST AT Command CONFIG - USE LIB  
#define AT_COMM             1
#define SIM800_CODE         2
#define CONFIG_CODE         AT_COMM
// TEST AT Command - USE LIB  
#define Manual_UPDATE         20
#define SIM800_NTP_UPDATE     30
#define RTC_CODE            Manual_UPDATE
// default 
#define APN     ""
#define APNN    "TM"
#define USE     "" 
#define PASS    "" 
// VODAFONE 
#define APN_VODF     "internet.vodafone.net"
#define USE_VODF     "internet" 
#define PASS_VODF    "internet" 
//  ORANGE // mobinilweb
#define APN_ORANG    "internet.orange.ma" 
#define APN_ORANGG   "mms"
// mobinilweb
#define USE_ORANG    "MEDINET"
#define PASS_ORANG   "MEDINET"
// NTP SERVER 
#define NTP_server   "time.google.com"
// "pool.ntp.org" "196.44.136.162" 151.101.66.137
#define RTC_SERVER   "ntppool.org"
#define RTC_server   "https://www.ntppool.org"
#define PORT_NUM     80 
// URL 
#define URL_RTC     "pool.ntp.org"
#define URL_TEST    "https://jsonplaceholder.typicode.com/todos/1"
#define URL2_TEST   "http://trapsnos.epcmms.com/api/Traps/LoadData2"
#define URL3_TEST   "http://trapsnos.epcmms.com/api/Reading"
#define URL4_TEST   "https://trapsysapi.epcmms.com/api/Lookups/GetAllCategories"

// CONTENT_TYPE
#define TYPE_CONTENT "application/json"
#define PAYLOAD_TYPE  "{\"userId\": \"1\", \"id\": \"1\", \"title\": \"delectus aut autem\", \"completed\": \"false\"}"

#define DEBUG true
#if DEBUG == true
// Debug using serial 
#define Debug_init(num)     Serial.begin(num);  // Serial Monitor for debugging
#define Debug(command)      Serial.println(command);  // Print the response for debugging
#define Debugline(command)  Serial.print(command);  // Print the response for debugging
#define Debug_RTC(command,string)      Serial.println(command,string);
#endif

// function prototype
void Start_UDP_Connection_AT_COMMAND();
void getIP_AT_COMMAND();
void GPRS_CONNECTION();
void Setup_GPRS();
void Disconnect_GPRS();
void add_check_gprs();
// test functoin 
void Setup_GPRS_AT_COMMAND();
void Debug_AT_Command_SHEHAB();
void AT_CHECK_COMMAND();
void GSM_Signal();
void Network_Registrution();

// test sms 
void send_SMS();
void updateSerial();
void test_sim800_module();

//
void SetupGPRS();
// 
void connect_check();
void setupModule();
// 
void AT_Terminal_TEst();
//
void NTP_RTC_CONFIG();
long getTimeZoneOffset();
//
void HTTPs_TEST();
void fetchJSON();
void AT_UDP_Connection_SIM800L();
void Fetch_Time_Date();
//
void get_http_loop();
//
#endif /*  __RTC_UPDATE_SIM800L__ */

here is code of sim800l

#include "RTC_Update_sim800l.hpp"

const char apn[] =       APN;          // Set your APN (e.g., Vodafone's APN)
const char user[] =      USE;              // Username for the APN (Usually empty)
const char pass[] =      PASS;             // Password for the APN (Usually empty)
const char* ntpServer =  NTP_server;   // NTP server
const char* rtcServer =  RTC_server;   // RTC server
const uint16_t ntpPort = PORT_NUM;          // NTP server port
char num_of_repeat= DEFAULT_VALUE;
long g_getTimeZoneOffset= DEFAULT_VALUE;

const char URL[] = URL4_TEST;//RTC_server;//URL4_TEST;
const char CONTENT_TYPE[] = TYPE_CONTENT;
char PAYLOAD[50];
// // Define the serial communication for the SIM800L
#if CONFIG_CODE == SIM800_CODE
HardwareSerial SerialAT(UART2);  // Use UART2 for communication with SIM800L
SIM800L* sim800l = new SIM800L((Stream *)&SerialAT, SIM800_RST_PIN, 200, 512);

#elif CONFIG_CODE == AT_COMM
HardwareSerial SerialAT(UART2);  // Use UART2 for communication with SIM800L
static bool sendATCommand(String command, const int timeout);
/**
 * AT commands required (const char in PROGMEM to save memory usage)
 */
const char AT_CMD_BASE[] PROGMEM = "AT";                                      // Basic AT command to check the link
const char AT_CMD_ECHO[] PROGMEM = "ATE1&W";                                  // Set command echo mode

const char AT_CMD_CPIN_TEST[] PROGMEM = "AT+CPIN?";                           // Check SIM card status
const char AT_CMD_CPIN_PIN[] PROGMEM = "AT+CPIN=";                            // Configure PIN code
const char AT_CMD_CPIN_PIN_SET[] PROGMEM = "AT+CPIN=\"0000\"";                // SET PIN code 

const char AT_CMD_CSQ[] PROGMEM = "AT+CSQ";                                   // Check the signal strengh
const char AT_CMD_ATI[] PROGMEM = "ATI";                                      // Output version of the module
const char AT_CMD_GMR[] PROGMEM = "AT+GMR";                                   // Output version of the firmware
const char AT_CMD_SIM_CARD[] PROGMEM = "AT+CCID";						                  // Get Sim Card version

const char AT_CMD_CFUN_TEST[] PROGMEM = "AT+CFUN?";                           // Check the current power mode
const char AT_CMD_CFUN0[] PROGMEM = "AT+CFUN=0";                              // Switch minimum power mode
const char AT_CMD_CFUN1[] PROGMEM = "AT+CFUN=1";                              // Switch normal power mode
const char AT_CMD_CFUN4[] PROGMEM = "AT+CFUN=4";                              // Switch sleep power mode

const char AT_CMD_SAPBR_GPRS[] PROGMEM = "AT+SAPBR=3,1,\"Contype\",\"GPRS\""; // Configure the GPRS bearer
const char AT_CMD_SAPBR_APN[] PROGMEM = "AT+SAPBR=3,1,\"APN\",";              // Configure the APN for the GPRS
const char AT_CMD_SAPBR_USER[] PROGMEM = "AT+SAPBR=3,1,\"USER\",";            // Configure the USER for the GPRS (linked to APN)
const char AT_CMD_SAPBR_PWD[] PROGMEM = "AT+SAPBR=3,1,\"PWD\",";              // Configure the PWD for the GPRS (linked to APN)
const char AT_CMD_SAPBR1[] PROGMEM = "AT+SAPBR=1,1";                          // Connect GPRS
const char AT_CMD_SAPBR2[] PROGMEM = "AT+SAPBR=2,1";                          // Check GPRS connection status
const char AT_CMD_SAPBR0[] PROGMEM = "AT+SAPBR=0,1";                          // Disconnect GPRS

const char AT_CMD_CREG_TEST[] PROGMEM = "AT+CREG?";                                     // Check the network registration status
const char AT_CMD_CGATT_ATT[] PROGMEM = "AT+CGATT=1";                                    // Attach to GPRS 
const char AT_CMD_CGATT_CHECK[] PROGMEM = "AT+CGATT?";                                   // CHECK GPRS 
const char AT_CMD_CSTT_SETAPN[] PROGMEM = "AT+CSTT=CMNET";                               // Start task and set APN.

const char AT_CMD_CIPSEND_UDP[] PROGMEM = "AT+CIPSEND";                                  // > SIM800 UDP test // SEND OK.
const char AT_CMD_CIPCLOSE_UDP[] PROGMEM = "AT+CIPCLOSE";                                // > CLOSE SIM800 UDP 

const char AT_CMD_CREG_APN[] PROGMEM = "AT+CSTT=\"\",\"internet.vodafone.net\",\"\"";   // Set APN
const char AT_CMD_CIICR_TEST[] PROGMEM = "AT+CIICR";                                    // Bring up the GPRS connection
const char AT_CMD_CIFSR_TEST[] PROGMEM = "AT+CIFSR";                                    // Get the IP address
const char AT_CMD_CREG_DIS[] PROGMEM = "AT+CGATT=0";                                    // Disconnect GPRS

const char AT_CMD_HTTPINIT[] PROGMEM = "AT+HTTPINIT";                         // Init HTTP connection
const char AT_CMD_HTTPPARA_CID[] PROGMEM = "AT+HTTPPARA=\"CID\",1";           // Connect HTTP through GPRS bearer
const char AT_CMD_HTTPPARA_URL[] PROGMEM = "AT+HTTPPARA=\"URL\",";            // Define the URL to connect in HTTP
const char AT_CMD_HTTPPARA_USERDATA[] PROGMEM = "AT+HTTPPARA=\"USERDATA\",";  // Define the header(s)
const char AT_CMD_HTTPPARA_CONTENT[] PROGMEM = "AT+HTTPPARA=\"CONTENT\",";    // Define the content type for the HTTP POST
const char AT_CMD_HTTPPARA_REDIR[] PROGMEM = "AT+HTTPPARA=\"REDIR\",1";       // Enable HTTP redirection
const char AT_CMD_HTTPSSL_Y[] PROGMEM = "AT+HTTPSSL=1";                       // Enable SSL for HTTP connection
const char AT_CMD_HTTPSSL_N[] PROGMEM = "AT+HTTPSSL=0";                       // Disable SSL for HTTP connection
const char AT_CMD_HTTPACTION0[] PROGMEM = "AT+HTTPACTION=0";                  // Launch HTTP GET action
const char AT_CMD_HTTPACTION1[] PROGMEM = "AT+HTTPACTION=1";                  // Launch HTTP POST action
const char AT_CMD_HTTPREAD[] PROGMEM = "AT+HTTPREAD";                         // Start reading HTTP return data
const char AT_CMD_HTTPTERM[] PROGMEM = "AT+HTTPTERM";                         // Terminate HTTP connection
#endif

void setup()
{
  #if RTC_CODE == Manual_UPDATE 
  // Initialize Serial Monitor for debugging
  Serial.begin(115200);
  while(!Serial);
  // Initialize the hardware Serial1
  SerialAT.begin(9600);
  delay(1000);
  Setup_GPRS_AT_COMMAND();
  delay(2000);
  fetchJSON();
  delay(2000);
  #elif RTC_CODE == SIM800_NTP_UPDATE
  // Initialize Serial Monitor for debugging
  Serial.begin(115200);
  while(!Serial);

  // Initialize the hardware Serial1
  SerialAT.begin(9600);
  delay(1000);
   
  setupModule();   
  delay(1000);
  #endif
}

void loop() {
  #if RTC_CODE == SIM800_NTP_UPDATE
  get_http_loop();
  #elif RTC_CODE == Manual_UPDATE
  #endif
}
#if RTC_CODE == SIM800_NTP_UPDATE
void setupModule() {
    // Wait until the module is ready to accept AT commands
  while(!sim800l->isReady()  ) {
    Serial.println(F("Problem to initialize AT command, retry in 1 sec"));
    delay(1000);
  }
  Serial.println(F("Setup Complete!"));
  
  // Wait for the GSM signal
  uint8_t signal = sim800l->getSignal();

  while(signal <= 0 ) {
    delay(1000);
    signal = sim800l->getSignal();
  }
  Serial.print(F("Signal OK (strenght: "));
  Serial.print(signal);
  Serial.println(F(")"));
  delay(1000);
  // Wait for operator network registration (national or roaming network)
  NetworkRegistration network = sim800l->getRegistrationStatus();
  while(network != REGISTERED_HOME && network != REGISTERED_ROAMING ) {
    delay(1000);
    network = sim800l->getRegistrationStatus();

  }
  Serial.println(F("Network registration OK"));
  delay(1000);

  // Setup APN for GPRS configuration
  bool success = sim800l->setupGPRS(APN);
  while(!success) {
    success = sim800l->setupGPRS(APN);
    delay(5000);
  }
  Serial.println(F("GPRS config OK"));
 
}
void get_http_loop(){
   // Establish GPRS connectivity (5 trials)
  bool connected = false;
  for(uint8_t i = 0; i < 5 && !connected; i++) {
    delay(1000);
    connected = sim800l->connectGPRS();
  }
  // Check if connected, if not reset the module and setup the config again
  if(connected) {
    Serial.print(F("GPRS connected with IP "));
    Serial.println(sim800l->getIP());
  } else {
    Serial.println(F("GPRS not connected !"));
    Serial.println(F("Reset the module."));
    sim800l->reset();
    setupModule();
    return;}
  Serial.println(F("Start HTTP GET..."));
  // Do HTTP GET communication with 10s for the timeout (read)
  uint16_t rc = sim800l->doGet(URL, 10000);
   if(rc == 200) {
    // Success, output the data received on the serial
    Serial.print(F("HTTP GET successful ("));
    Serial.print(sim800l->getDataSizeReceived());
    Serial.println(F(" bytes)"));
    Serial.print(F("Received : "));
    Serial.println(sim800l->getDataReceived());
  } else {
    // Failed...
    Serial.print(F("HTTP GET error "));
    Serial.println(rc);
  }
  g_getTimeZoneOffset =  3 * 3600; // UTC+4 during summer
  // Set up the time using NTP server to sync
  configTime(g_getTimeZoneOffset, 0,URL_RTC); // RTC_SERVER,RTC_SERVER
  delay(5000);
   // Sync with NTP periodically to keep time updated
  struct tm currentTime;
  if (getLocalTime(&currentTime)) {
    Serial.println("Current Time from NTP:");
    Serial.println(&currentTime, "%A, %B %d %Y %H:%M:%S");
  } else {
    Serial.println("Failed to get time from NTP");
  }
  // Close GPRS connectivity (5 trials)
  bool disconnected = sim800l->disconnectGPRS();
  for(uint8_t i = 0; i < 5 && !connected; i++) {
    delay(1000);
    disconnected = sim800l->disconnectGPRS();}
  
  if(disconnected) {
    Serial.println(F("GPRS disconnected !"));
  } else {
    Serial.println(F("GPRS still connected !"));}

  // Go into low power mode
  bool lowPowerMode = sim800l->setPowerMode(MINIMUM);
  if(lowPowerMode) {
    Serial.println(F("Module in low power mode"));
  } else {
    Serial.println(F("Failed to switch module to low power mode"));
  }

  // End of program... wait...
  while(1);
}

#elif RTC_CODE == Manual_UPDATE
void Setup_GPRS_AT_COMMAND() {
  Debug(F("....................Setup GPRS....................."));
  sendATCommand(AT_CMD_BASE, 1000);         // Response should be  OK 
  sendATCommand(AT_CMD_CPIN_TEST, 1000);   // Response should be "READY"
  sendATCommand(AT_CMD_CSQ, 1000);         // The response should  (e.g., +CSQ: <value>,<error_rate>)
  sendATCommand(AT_CMD_CREG_TEST, 1000);   // Response "+CREG: 0,1" indicates successful registration
  if (!sendATCommand(AT_CMD_SAPBR1, 2000) || !sendATCommand(AT_CMD_CGATT_ATT,2000)) {
    Debug("Retrying to open bearer...");
    sendATCommand(AT_CMD_SAPBR0, 1000); // Close bearer
    delay(1000);
    sendATCommand(AT_CMD_SAPBR1, 2000); // Reopen bearer
}
  sendATCommand(AT_CMD_SAPBR_GPRS, 1000); // Set bearer profile
  sendATCommand("AT+SAPBR=3,1,\"APN\",\"\"", 2000); // Set APN
  sendATCommand("AT+SAPBR=3,1,\"USER\",\"\"", 2000); // Set username // AT_CMD_SAPBR_USER
  sendATCommand("AT+SAPBR=3,1,\"PWD\",\"\"", 2000); // Set password  // AT_CMD_SAPBR_PWD
  // sendATCommand(AT_CMD_CIFSR_TEST, 2000);
  sendATCommand(AT_CMD_SAPBR1, 2000); // Open bearer
  sendATCommand(AT_CMD_SAPBR2, 2000); // Query bearer
  // Check IP address response to confirm success
  // sendATCommand("AT+CMEE=2", 1000); // Enable verbose error reporting
  // sendATCommand(AT_CMD_SAPBR0,1000);       // Disconnect GPRS 
}

void fetchJSON() {
  sendATCommand(AT_CMD_HTTPINIT, 2000);                        // Initialize HTTP
  // sendATCommand("AT+HTTPSSL=1", 1000);                        // Initialize HTTP
  sendATCommand("AT+HTTPPARA=\"CID\",1", 2000);             // Set HTTP CID
  sendATCommand("AT+HTTPPARA=\"URL\",\"https://trapsysapi.epcmms.com/api/Lookups/GetAllCountries\"", 1000); // Set URL
  sendATCommand(AT_CMD_HTTPACTION0, 5000);                   // Send HTTP GET request
  sendATCommand(AT_CMD_HTTPREAD, 2000);                       // Read response
  sendATCommand(AT_CMD_HTTPTERM, 2000);                       // Terminate HTTP
  // sendATCommand(AT_CMD_SAPBR0, 1000); // Close bearer
}
void Fetch_Time_Date(){
    sendATCommand("AT+CCLK?\r\n", 3000);
    sendATCommand("AT+CLTS=1\r\n",3000);  // Get Local Timestamp
    sendATCommand("AT&W\r\n",3000);  // Get Local Timestamp
    sendATCommand("AT+CCLK?\r\n", 3000);
}
//
// Function to send AT command and wait for the response
static bool sendATCommand(String command, const int timeout) {
  String response = "";
  Debug("Sending: " + command);
  SerialAT.println(command);  // Send the command
  unsigned long previousMillis = millis();
  while (millis() - previousMillis < timeout) {
    if (SerialAT.available()) {
      char c = SerialAT.read();
      response += c;
    }
  }
  if (response.length() > 0) {
    // Debugline("compare value : ");
    // Debug(response.compareTo("ERROR"));
    Debugline("Response: " + response);
    return 1;
  } else {
    Debug("No response or timeout.");
    return 0;
  }
}
#endif

here is using wifi :

#include "Pin_Configuration.hpp"
long g_getTimeZoneOffset= 0;
const char* ssid = "your-SSID";         // Replace with your WiFi network name
const char* password = "your-PASSWORD"; // Replace with your WiFi password
long getTimeZoneOffset() {
    // Sync with NTP periodically to keep time updated
  struct tm currentTime;
  if (getLocalTime(&currentTime)) {
    Serial.print("Current Month:");
    Serial.println(currentTime.tm_mon +1);
  } else { Serial.println("Failed to get time from NTP");}
 //  Serial.println(currentTime.tm_mon+1);
  if(currentTime.tm_mon+1 == 12 || currentTime.tm_mon+1==1)
  {return g_getTimeZoneOffset =  2 * 3600; } // UTC+2 during summer
  return g_getTimeZoneOffset =  3 * 3600; // UTC+3 during summer
}
void setup() {
  Serial.begin(115200);
    // Connect to WiFi
  WiFi.begin(ssid, password);
  Serial.println("Connecting to WiFi...");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");}
  Serial.println("Connected to WiFi!");
  g_getTimeZoneOffset =  3 * 3600; // UTC+4 during summer
  // Set up the time using NTP server to sync
  configTime(g_getTimeZoneOffset, 0, "pool.ntp.org");
  delay(5000);
   // Sync with NTP periodically to keep time updated
  struct tm currentTime;
  if (getLocalTime(&currentTime)) {
    Serial.println("Current Time from NTP:");
    Serial.println(&currentTime, "%A, %B %d %Y %H:%M:%S");
  } else {Serial.println("Failed to get time from NTP");}
}
void loop() {
  // Add your logic here, e.g., periodically update the time or use it for some task
  delay(10000);  // Wait 10 seconds before syncing again with NTP
  struct tm currentTime;
  // Update the time using NTP
  if (getLocalTime(&currentTime)) {
    Serial.println("Updated Time from NTP:");
    Serial.println(&currentTime, "%A, %B %d %Y %H:%M:%S");
  } else {
    Serial.println("Failed to get time from NTP");
  }
}


This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.