ESP32 at times not catching SIM800L signal of SMS reception

Very weird problem that my project (on PCB) didn't have until today when I took it on a car drive. Basically I send an SMS to my SIM800L via my phone and if it matches a certain string, the ESP32 (Devkit C) tells it to reply GPS coordinates back. Except, now it sometimes ignores it completely. Like hundreds of times. Rendering my project pretty useless.

On breadboard this issue is happening too.
I am baffled completely because until morning it worked fine on PCB and breadboard aswell. When i sent a location request I got a reply.
Here is the code and my feeble effort to resurrect it within asterisks:

#include <TinyGPSPlus.h>
#include "HardwareSerial.h"

#include <WiFi.h>

HardwareSerial GPSSerial1(1);
HardwareSerial SIMSerial2(2);
TinyGPSPlus gps;
char Received_SMS;
short SMS_OK = -1;
short SMS_Battery = -1;
short SMS_LOC = -1;
char battery_status[27];
unsigned long previousMillis = 0;
unsigned long previousM = 0;
const long resetBurst = 13000;
const long interval = 1800000;

String Data_SMS;
void setup() {
  WiFi.disconnect(true);
  WiFi.mode(WIFI_OFF);
  Serial.begin(9600);
  SIMSerial2.begin(9600,SERIAL_8N1, 21,22);
  GPSSerial1.begin(9600,SERIAL_8N1, 13,14);
  
  Serial.println("Starting");
    
  delay(3000);
  ReceiveMode();

}


void loop() {
String RSMS;
  while (GPSSerial1.available() > 0){
    if (gps.encode(GPSSerial1.read()))
  if (millis() > 5000 && gps.charsProcessed() < 10)
  {Serial.println(F("No GPS detected: check wiring."));
  }}
  while (SIMSerial2.available()) {
    Received_SMS = SIMSerial2.read();  
    RSMS.concat(Received_SMS);
    SMS_OK = RSMS.indexOf("Send");
    SMS_Battery = RSMS.indexOf("Bat");
    SMS_LOC = RSMS.indexOf("GPS");
  }
  **Serial.println(SIMSerial2.available());**
**  delay(1000); //<---------- I hate putting delays but unless I print these two lines with
//delay I can never receive a reply back on PCB version. 
//On breadboard version sometimes I do get a reply. 
//Sometimes I can see the value changing to non-zero on 
//serial monitor but it ignores it. **
**  Serial.println(SIMSerial2.read());**
**  delay(1000); //<---- ditto for this too**
  if (SMS_OK != -1) {
    Data_SMS = "Message received";
    Send_Data();
    ReceiveMode();
    Data_SMS = "";    
    SMS_OK = -1;
  }
if (SMS_LOC != -1) {
    Serial.println(gps.location.lat(),6);    
    Serial.println(gps.location.lng(),6);
    
     Send_GPS();
    ReceiveMode();
    Data_SMS = "";
    SMS_LOC = -1;
  }  
  if(SMS_Battery != -1){
    
    
    SIMSerial2.print("AT+CBC\r");
    for(int i = 0 ; i<27 ; i++) {
    battery_status[i] = SIMSerial2.read();
     Serial.println("Battery status is:");
     Serial.println(battery_status[i]);
     if(battery_status[i] == ',' && battery_status[i-4] == ','){
    Data_SMS.concat(battery_status[i-3]);
    Data_SMS.concat(battery_status[i-2]);
    Data_SMS.concat(battery_status[i-1]);    
    }
     
     }
      Send_Data();
    ReceiveMode();
    Data_SMS = "";
     SMS_Battery = -1;
  }
  unsigned long currentMillis = millis(); 
if(currentMillis -previousMillis >= interval){
previousMillis = currentMillis; 
 ESP.restart();  
}

}

void ReceiveMode() {
  Serial.println("Inside Receive Mode");
  SIMSerial2.println("AT\r");
  updateSerial();
  SIMSerial2.print("AT+CMGF=1\r");
  updateSerial();
  SIMSerial2.print("AT+CNMI=2,2,0,0,0\r");
  updateSerial();
 }

void Send_GPS() {
  SIMSerial2.print("AT+CMGF=1\r");     
  delay(100);
  SIMSerial2.print("AT+CMGS=\"+xxxxxxxxxxx\"\r");  
  delay(500);
  SIMSerial2.print(gps.location.lat(),6);  
  SIMSerial2.print(",");
  SIMSerial2.print(gps.location.lng(),6);  
  delay(500);
  SIMSerial2.print((char)26); 
  delay(500);
 
}

void Send_Data() {
  SIMSerial2.print("AT+CMGF=1\r");    
  delay(100);
  SIMSerial2.print("AT+CMGS=\"+xxxxxxxxxxxxx\"\r"); 
  delay(500);
  SIMSerial2.print(Data_SMS); 
  delay(500);
  SIMSerial2.print((char)26); 
  delay(500);
  delay(500);
}

void updateSerial() {
  delay(500);
  while (Serial.available()) {
    SIMSerial2.write(Serial.read()); 
  }
  while (SIMSerial2.available()) {
    Serial.write(SIMSerial2.read()); 
  }
}

My guess is that something has gone caput with ESP32 as I took the project for a drive. RX,TX of SIM800L and ESP32 give precisely same voltage values on breadboard and PCB. AT commands work fine always. What do you guys think is the problem?

What is the power supply that you are using? Have you checked the voltage and current of your power source? Maybe it dropped suddenly.

On PCB, a SLA battery feeds i) 12V into a buck converter for SIM800L giving it 4.09V, and ii) to an MP1584 where it drops it to 5V for esp32.
Identical in breadboard except 12v is provided by wall adapter.
It was working fine for weeks.

Are you measuring the SLA battery charge with a multimeter now? Is it still providing 12V ?

to which pin on the ESP32 are you connecting the 5V?
The ESP32 is a 3.3V device. Directly feeding in 5V is way to much
You should post the exact type of ESP32-board that you are using and a picture of your ESP32-board

Avoiding delays() is done by non-blocking timing

const long interval = 1800000;
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    ESP.restart();
  }

restatring your ESP32 once every half hour tells me that it is very likely that your coding is buggy
and you try to solve it by restarting

1 Like

Yeah. As long as buck converter gets 1.5 times the output voltage (i.e. 1.5 x 4.10 volts) the project should be fine. Same for MP1584.

I am giving 5V to the pin labeled 5V. Stated in OP that it is a devkit C. See diagram here: https://www.mischianti.org/wp-content/uploads/2021/07/ESP32-DEV-KIT-DevKitC-v4-pinout-mischianti.jpg

I have to restart because SIM800L takes 10 seconds approx to catch the network. Afterwards it does not communicate with ESP32 unless I either restart via hardware button on the esp or via esp.restart(). Sometimes, due to less reception SIM800L may again find itself looking for a signal. Hence the half-hour restarts.

I ran the code without the non-blocking delay too but same result: hit-and-miss.

"hit and miss" is a way too unprecise description of what is happening.
Add a lot of serial debug-output to your code to see what the code is doing and what the code is not doing

Your code uses while loops some with timeout some while-loops without timeout
it will be better to use if-conditions and eventual flag-variables instead of while-loops

best regards Stefan

I have included in the code as comments the description of this behavior. See this:

 **Serial.println(SIMSerial2.available());**
**  delay(1000); //<---------- 
//I hate putting delays but 
//unless I print these two lines with
//delay I can never receive a reply back on PCB version. 
//On breadboard version sometimes I do get a reply. 
//Sometimes I can see the value changing to non-zero on 
//serial monitor but it ignores it. **
**  Serial.println(SIMSerial2.read());**
**  delay(1000); //<---- ditto for this too**

My output on serial monitor is like this when I haven't yet sent an SMS:

-1
0
-1
0

When I send an SMS for GPS, ideally it is like this:

-1
0
13
0
xx.343848 //gps latitude
xx.5289011 //gps longitude
AT+CMGF=1
OK
... //rest of the output

^ i.e. it enters the second while loop (Hit)
Non-ideally:

-1
0
-1
0
245
0
255
0
-1
0
-1
0

^ It doesn't enter the second while loop. (Miss)
When I remove the 1 second delays, more chance of miss than hit.

I am aware of this. So I commented out the first while loop of the gps and simply gave the gps latitude and longitude to Send_GPS() when triggered. But the answer invariably was 0.000000, 0.000000.
I can put the gps.location.lat and lng covered by an if statement within if(SMS_LOC!=-1 checking if gps serial is available but I am still baffled by the fact that a simple Serial.println(SIMSerial2.available()); in void loop makes the chance of a 'hit' higher than a 'miss', specially given that for months it worked fine.

From your posted serial output I don't yet understand what is happening

I recommend to extend the serial output to clearly say what it is printing
additionally you should activate the timestamp-function of the serial monitor
here is a code-version with intensive serial debug-output
partially using macros
there might be small typos in the code
I don't have your libraries so I can not compile

// MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START *

// a detailed explanation how these macros work is given in this tutorial
// https://forum.arduino.cc/t/comfortable-serial-debug-output-short-to-write-fixed-text-name-and-content-of-any-variable-code-example/888298

#define dbg(myFixedText, variableName) \
  Serial.print( F(#myFixedText " "  #variableName"=") ); \
  Serial.println(variableName);
// usage: dbg("1:my fixed text",myVariable);
// myVariable can be any variable or expression that is defined in scope

#define dbgi(myFixedText, variableName,timeInterval) \
  { \
    static unsigned long intervalStartTime; \
    if ( millis() - intervalStartTime >= timeInterval ){ \
      intervalStartTime = millis(); \
      Serial.print( F(#myFixedText " "  #variableName"=") ); \
      Serial.println(variableName); \
    } \
  }
// usage: dbgi("2:my fixed text",myVariable,1000);
// myVariable can be any variable or expression that is defined in scope
// third parameter is the time in milliseconds that must pass by until the next time a
// Serial.print is executed
// end of macros dbg and dbgi
// print only once when value has changed
#define dbgc(myFixedText, variableName) \
  { \
    static long lastState; \
    if ( lastState != variableName ){ \
      Serial.print( F(#myFixedText " "  #variableName" changed from ") ); \
      Serial.print(lastState); \
      Serial.print( F(" to ") ); \
      Serial.println(variableName); \
      lastState = variableName; \
    } \
  }

#define dbgcf(myFixedText, variableName) \
  { \
    static float lastState; \
    if ( lastState != variableName ){ \
      Serial.print( F(#myFixedText " "  #variableName" changed from ") ); \
      Serial.print(lastState); \
      Serial.print( F(" to ") ); \
      Serial.println(variableName); \
      lastState = variableName; \
    } \
  }
// MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END *

#include <TinyGPSPlus.h>
#include "HardwareSerial.h"

#include <WiFi.h>

HardwareSerial GPSSerial1(1);
HardwareSerial SIMSerial2(2);
TinyGPSPlus gps;
char Received_SMS;
short SMS_OK = -1;
short SMS_Battery = -1;
short SMS_LOC = -1;
char battery_status[27];
unsigned long previousMillis = 0;
unsigned long previousM = 0;
const long resetBurst = 13000;
const long interval = 1800000;

String Data_SMS;

void setup() {
  WiFi.disconnect(true);
  WiFi.mode(WIFI_OFF);
  Serial.begin(9600);
  Serial.println("Starting");
  SIMSerial2.begin(9600, SERIAL_8N1, 21, 22);
  GPSSerial1.begin(9600, SERIAL_8N1, 13, 14);
  Serial.println("SIM GPS begin done");

  delay(3000);
  ReceiveMode();

}


void loop() {
  String RSMS;
  while (GPSSerial1.available() > 0) {
    if (gps.encode(GPSSerial1.read()))
      if (millis() > 5000 && gps.charsProcessed() < 10){ 
        Serial.println(F("No GPS detected: check wiring."));
      }
  }
  
  while (SIMSerial2.available()) {
    Received_SMS = SIMSerial2.read();
    RSMS.concat(Received_SMS);
    SMS_OK = RSMS.indexOf("Send");
    SMS_Battery = RSMS.indexOf("Bat");
    SMS_LOC = RSMS.indexOf("GPS");
  }
  dbg("below while (SIMSerial2.available()",SIMSerial2.available());
  delay(1000); //<---------- I hate putting delays but unless I print these two lines with
  //delay I can never receive a reply back on PCB version.
  //On breadboard version sometimes I do get a reply.
  //Sometimes I can see the value changing to non-zero on
  //serial monitor but it ignores it. **
  dbg("below while (SIMSerial2.available()",SIMSerial2.read());
  delay(1000); //<---- ditto for this too**
  
  if (SMS_OK != -1) {
    Data_SMS = "Message received";
    Send_Data();
    ReceiveMode();
    Data_SMS = "";
    SMS_OK = -1;
  }
  
  if (SMS_LOC != -1) {
    dbg("if (SMS_LOC != -1)",gps.location.lat(),6);
    dbg("if (SMS_LOC != -1)",gps.location.lng(),6);
    //Serial.println(gps.location.lat(), 6);
    //Serial.println(gps.location.lng(), 6);

    Send_GPS();
    ReceiveMode();
    Data_SMS = "";
    SMS_LOC = -1;
  }
  
  if (SMS_Battery != -1) {

    SIMSerial2.print("AT+CBC\r");
    for (int i = 0 ; i < 27 ; i++) {
      battery_status[i] = SIMSerial2.read();
      Serial.println("Battery status is:");
      Serial.println(battery_status[i]);
      if (battery_status[i] == ',' && battery_status[i - 4] == ',') {
        Data_SMS.concat(battery_status[i - 3]);
        Data_SMS.concat(battery_status[i - 2]);
        Data_SMS.concat(battery_status[i - 1]);
      }
    }
    Send_Data();
    ReceiveMode();
    Data_SMS = "";
    SMS_Battery = -1;
  }

  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    ESP.restart();
  }

}

void ReceiveMode() {
  Serial.println("Inside Receive Mode");
  SIMSerial2.println("AT\r");
  Serial.println("AT r printed to SIM");
  updateSerial();
  SIMSerial2.print("AT+CMGF=1\r");
  Serial.println("AT+CMGF=1 r printed to SIM");
  updateSerial();
  SIMSerial2.print("AT+CNMI=2,2,0,0,0\r");
  Serial.println("AT+CNMI=2,2,0,0,0 r printed to SIM");
  updateSerial();
  Serial.println("leaving Receive Mode");
}

void Send_GPS() {
  dbg("entering Send_GPS()",111);
  SIMSerial2.print("AT+CMGF=1\r");
  delay(100);
  SIMSerial2.print("AT+CMGS=\"+xxxxxxxxxxx\"\r");
  delay(500);
  SIMSerial2.print(gps.location.lat(), 6);
  SIMSerial2.print(",");
  SIMSerial2.print(gps.location.lng(), 6);
  delay(500);
  SIMSerial2.print((char)26);
  delay(500);
  dbg("leaving Send_GPS()",222);

}

void Send_Data() {
  dbg("entering Send_Data() ",333);
  
  SIMSerial2.print("AT+CMGF=1\r");
  delay(100);
  SIMSerial2.print("AT+CMGS=\"+xxxxxxxxxxxxx\"\r");
  delay(500);
  SIMSerial2.print(Data_SMS);
  delay(500);
  SIMSerial2.print((char)26);
  delay(500);
  delay(500);
  dbg("leaving Send_Data() ",444);
}

void updateSerial() {
  dbg("entering updateSerial() ",555);
  
  delay(500);
  while (Serial.available()) {
    char mySerialChar = Serial.read();
    dbg("udS while (Serial.available()",mySerialChar);
    SIMSerial2.write(mySerialChar);
  }
  
  while (SIMSerial2.available()) {
    char mySIM_Char = SIMSerial2.read();
    dbg("udS while (SIMSerial2.available()",mySIM_Char);
    Serial.write(mySIM_Char);
  }
  dbg("leaving updateSerial() ",666);
}

best regards Stefan

Thank you so much. I will definitely look into it

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