Can somebody help me to how read the received SMS on ESP32–TTGO T-Call Using Arduino IDE?

I am using ESP32–TTGO T with TinyGSM Lib-- I want to read the received SMS and same will be stored in buffer ,, so whenever new incoming SMS comes buffer will be updated dynamically.

Hello
Do you use AT commands to control your module or a library? (that uses AT commands for sure)

If you want to use AT commands, there might be a video I can give you to do what you want

I used TinyGSM library.. Which is working well for sending SMS .. but there is no function that will read the sms.

Do you know how to communicate with the module in AT commands? Even if you don't know what to send, do you know how to send AT commands?

Yes I know,, Can you share some example code to handle receiving SMS? Which you have tried for receiving sms with TinyGSM library..

Can you share the code you'll use for sending the AT commands?

Here is the link of the video :

Once you will have give me the code, I will help you to adapt it for you

Refer the below code--- here you need to suggest code to receive and read the SMS:

// SIM card PIN (leave empty, if not defined)
const char simPIN[]   = "";

// Your phone number to send SMS: + (plus sign) and country code,
//next digit should be your cell number
// SMS_TARGET Example for UK +44XXXXXXXXX
#define SMS_TARGET  "+44xxxxxxxx"

// Configure TinyGSM library
#define TINY_GSM_MODEM_SIM800      // Modem is SIM800
#define TINY_GSM_RX_BUFFER   1024  // Set RX buffer to 1Kb

#include <Wire.h>
#include <TinyGsmClient.h>

// TTGO T-Call pins
#define MODEM_RST            5
#define MODEM_PWKEY          4
#define MODEM_POWER_ON       23
#define MODEM_TX             27
#define MODEM_RX             26
#define I2C_SDA              21
#define I2C_SCL              22

// Set serial for debug console (to Serial Monitor, default speed 115200)
#define SerialMon Serial
// Set serial for AT commands (to SIM800 module)
#define SerialAT  Serial1

// Define the serial console for debug prints, if needed
//#define DUMP_AT_COMMANDS

#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, SerialMon);
TinyGsm modem(debugger);
#else
TinyGsm modem(SerialAT);
#endif

#define IP5306_ADDR          0x75
#define IP5306_REG_SYS_CTL0  0x00

bool setPowerBoostKeepOn(int en) {
  Wire.beginTransmission(IP5306_ADDR);
  Wire.write(IP5306_REG_SYS_CTL0);
  if (en) {
    Wire.write(0x37); // Set bit1: 1 enable 0 disable boost keep on
  } else {
    Wire.write(0x35); // 0x37 is default reg value
  }
  return Wire.endTransmission() == 0;
}
void updateSerial();
void setup()
{
  Serial.begin(115200);
  // Keep power when running from battery
  Wire.begin(I2C_SDA, I2C_SCL);
  bool isOk = setPowerBoostKeepOn(1);
  SerialMon.println(String("IP5306 KeepOn ") + (isOk ? "OK" : "FAIL"));
  // Set modem reset, enable, power pins
  pinMode(MODEM_PWKEY, OUTPUT);
  pinMode(MODEM_RST, OUTPUT);
  pinMode(MODEM_POWER_ON, OUTPUT);
  digitalWrite(MODEM_PWKEY, LOW);
  digitalWrite(MODEM_RST, HIGH);
  digitalWrite(MODEM_POWER_ON, HIGH);

  // Set GSM module baud rate and UART pins
  SerialAT.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX);
  delay(3000);

  // Restart SIM800 module, it takes quite some time
  // To skip it, call init() instead of restart()
  SerialMon.println("Initializing modem...");
  modem.restart();
  // use modem.init() if you don't need the complete restart

  // Unlock your SIM card with a PIN if needed
  if (strlen(simPIN) && modem.getSimStatus() != 3 ) {
    modem.simUnlock(simPIN);
  }
  // To send an SMS, call modem.sendSMS(SMS_TARGET, smsMessage)
  String smsMessage = "Hello GSM";
  if (modem.sendSMS(SMS_TARGET, smsMessage)) {
    SerialMon.println(smsMessage);
  }
  else {
    SerialMon.println("SMS failed to send");
  }

SerialAT.println("AT"); //Once the handshake test is successful, it will back to OK
updateSerial();
SerialAT.println("AT+CMGF=1"); // Configuring TEXT mode
updateSerial();
SerialAT.println("AT+CNMI=1,2,0,0,0"); // Decides how newly arrived SMS messages should be handled
updateSerial();





}
void loop()
{
  delay(1);
}

void updateSerial()
{
  delay(500);
  while (Serial.available())
  {
    SerialAT.write(Serial.read());//Forward what Serial received to Software Serial Port
  }
  while (SerialAT.available())
  {
    Serial.write(SerialAT.read());//Forward what Software Serial received to Serial Port
  }
}

As you're speaking to your module with serial communication, you can try directly the code from the video
But don't forget to modify the pin for the serial communication with your module otherwise you won't be able to speak with it

Just asking, why is you loop() empty? Just a delay of 1ms?

Thanks! will check and come back..

Your code is not compatible with ESP32 TTGO SIM800 Module -- as you used softwareserial-- code giving fatal error..

You shouldn't take all the code but only the part where you send AT commands
Keep your libraries
Just send the same commands as they are send in the video, in the same order with the same values

Below is the final tested code for sending and receiving SMS using ESP32 TTGO T1 board .. Its working perfectly..

Send and Receive SMS Using ESP32–TTGO T1-Call with Arduino IDE

// SIM card PIN (leave empty, if not defined)
const char simPIN[]   = "";
String SMS_Message;
// Your phone number to send SMS: + (plus sign) and country code,
//next digit should be your cell number
// SMS_TARGET Example for UK +44XXXXXXXXX
#define SMS_TARGET  "+44xxxxxxxx"

// Configure TinyGSM library
#define TINY_GSM_MODEM_SIM800      // Modem is SIM800
#define TINY_GSM_RX_BUFFER   1024  // Set RX buffer to 1Kb

#include <Wire.h>
#include <TinyGsmClient.h>

// TTGO T-Call pins
#define MODEM_RST            5
#define MODEM_PWKEY          4
#define MODEM_POWER_ON       23
#define MODEM_TX             27
#define MODEM_RX             26
#define I2C_SDA              21
#define I2C_SCL              22

// Set serial for debug console (to Serial Monitor, default speed 115200)
#define SerialMon Serial
// Set serial for AT commands (to SIM800 module)
#define SerialAT  Serial1

// Define the serial console for debug prints, if needed
//#define DUMP_AT_COMMANDS

#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, SerialMon);
TinyGsm modem(debugger);
#else
TinyGsm modem(SerialAT);
#endif

#define IP5306_ADDR          0x75
#define IP5306_REG_SYS_CTL0  0x00

bool setPowerBoostKeepOn(int en) {
  Wire.beginTransmission(IP5306_ADDR);
  Wire.write(IP5306_REG_SYS_CTL0);
  if (en) {
    Wire.write(0x37); // Set bit1: 1 enable 0 disable boost keep on
  } else {
    Wire.write(0x35); // 0x37 is default reg value
  }
  return Wire.endTransmission() == 0;
}
void updateSerial();
void setup()
{
  Serial.begin(115200);
  // Keep power when running from battery
  Wire.begin(I2C_SDA, I2C_SCL);
  bool isOk = setPowerBoostKeepOn(1);
  SerialMon.println(String("IP5306 KeepOn ") + (isOk ? "OK" : "FAIL"));
  // Set modem reset, enable, power pins
  pinMode(MODEM_PWKEY, OUTPUT);
  pinMode(MODEM_RST, OUTPUT);
  pinMode(MODEM_POWER_ON, OUTPUT);
  digitalWrite(MODEM_PWKEY, LOW);
  digitalWrite(MODEM_RST, HIGH);
  digitalWrite(MODEM_POWER_ON, HIGH);

  // Set GSM module baud rate and UART pins
  SerialAT.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX);
  delay(3000);

  // Restart SIM800 module, it takes quite some time
  // To skip it, call init() instead of restart()
  SerialMon.println("Initializing modem...");
  modem.restart();
  // use modem.init() if you don't need the complete restart

  // Unlock your SIM card with a PIN if needed
  if (strlen(simPIN) && modem.getSimStatus() != 3 ) {
    modem.simUnlock(simPIN);
  }
  // To send an SMS, call modem.sendSMS(SMS_TARGET, smsMessage)
  String smsMessage = "Hello GSM";
  if (modem.sendSMS(SMS_TARGET, smsMessage)) {
    SerialMon.println(smsMessage);
  }
  else {
    SerialMon.println("SMS failed to send");
  }
  SerialAT.println("AT"); //Once the handshake test is successful, it will back to OK
  updateSerial();
  delay(200);
  SerialAT.println("AT+CMGF=1"); // Configuring TEXT mode
  updateSerial();
  delay(200);
  SerialAT.println("AT+CNMI=2,2,0,0,0"); // Decides how newly arrived SMS messages should be handled
  updateSerial();
}

char smsBuffer[250]; // Buffer to store SMS messages
void loop()
{
  updateSerial();
  static String currentLine = "";
  while (SerialAT.available()) {
    char c = SerialAT.read();

    if (c == '\n') {
      currentLine.trim(); // Remove leading/trailing whitespace
      if (currentLine.startsWith("+CMTI: \"SM\",")) {
        // Extract SMS index from the line
        int smsIndex = currentLine.substring(13).toInt();

        // Read the SMS with the extracted index using AT commands
        SerialAT.print("AT+CMGR=");
        SerialAT.println(smsIndex);
        delay(100); // Allow time for response

        // Process the SMS message
        if (SerialAT.find("+CMGR:")) {
          String receivedMessage = SerialAT.readStringUntil('\n');
          receivedMessage.trim();
          SerialMon.println("Received SMS: " + receivedMessage);

          // Store the received message in the buffer
          receivedMessage.toCharArray(smsBuffer, sizeof(smsBuffer));
          SerialMon.println("Stored in buffer: " + String(smsBuffer));

          // Delete the SMS after processing
          SerialAT.print("AT+CMGD=");
          SerialAT.println(smsIndex);
          delay(100); // Allow time for response
        }
      }

      currentLine = ""; // Clear the line
    } else {
      currentLine += c; // Append character to the line
    }
  }
  int rdn = random(100); // random number trigger event based sms or conditinal sms trigger
  SMS_Message = "HELLO FROM ESP32";
  if (rdn == 10) {
    if (modem.sendSMS(SMS_TARGET, SMS_Message)) {
      SerialMon.println(SMS_Message);
    }
    else {
      SerialMon.println("SMS failed to send");
    }
  }
  delay(1000);
}

void updateSerial()
{
  while (Serial.available())
  {
    SerialAT.write(Serial.read());//Forward what Serial received to Software Serial Port
  }
  while (SerialAT.available())
  {
    Serial.write(SerialAT.read());//Forward what Software Serial received to Serial Port
  }
}

Thanks for your wonderful guidance!

You're welcome :slightly_smiling_face:
Don't forget to mark your topic as solved, and mark the post that helped you!
Either my post with the video which is global, or your last post with the working code.

And have fun! :upside_down_face:

1 Like

For some reason, prints in the void loop are not working, and i cannot access the buffer outside of it. All i get is the update serial that was passed on to the serial monitor but i need to be able to access the buffer and manipulate the data received. how do i do that? thanks

I think the code is erronous. it only manages to update the serial from SerialAT to SerialMon but the code never executes within the following While code and hence no buffer is actually made

  while (SerialAT.available()) {
    char c = SerialAT.read();

    if (c == '\n') {
      currentLine.trim(); // Remove leading/trailing whitespace
      if (currentLine.startsWith("+CMTI: \"SM\",")) {
        // Extract SMS index from the line
        int smsIndex = currentLine.substring(13).toInt();

        // Read the SMS with the extracted index using AT commands
        SerialAT.print("AT+CMGR=");
        SerialAT.println(smsIndex);
        delay(100); // Allow time for response

        // Process the SMS message
        if (SerialAT.find("+CMGR:")) {
          String receivedMessage = SerialAT.readStringUntil('\n');
          receivedMessage.trim();
          SerialMon.println("Received SMS: " + receivedMessage);

          // Store the received message in the buffer
          receivedMessage.toCharArray(smsBuffer, sizeof(smsBuffer));
          SerialMon.println("Stored in buffer: " + String(smsBuffer));

          // Delete the SMS after processing
          SerialAT.print("AT+CMGD=");
          SerialAT.println(smsIndex);
          delay(100); // Allow time for response
        }
      }

      currentLine = ""; // Clear the line
    } else {
      currentLine += c; // Append character to the line
    }
  }
  int rdn = random(100); // random number trigger event based sms or conditinal sms trigger
  SMS_Message = "HELLO FROM ESP32";
  if (rdn == 10) {
    if (modem.sendSMS(SMS_TARGET, SMS_Message)) {
      SerialMon.println(SMS_Message);
    }
    else {
      SerialMon.println("SMS failed to send");
    }
  }

As I can see you will never receive "+CMTI".
"AT+CNMI=2,2,0,0,0" will change default rules for storing received SMS: messages will be received as "+CMT" and will contain text.

In order to support multiline messages, you need to know the length of the message (using "AT+CSDH=1"). This command can be executed only after "SMS Ready".

Here is my implementation:

// SIM card PIN (leave empty, if not defined)
const char simPIN[]   = "";

// TTGO T-Call pins
#define MODEM_RST            5
#define MODEM_PWKEY          4
#define MODEM_POWER_ON       23
#define MODEM_TX             27
#define MODEM_RX             26
#define I2C_SDA              21
#define I2C_SCL              22

// Set serial for debug console (to Serial Monitor, default speed 115200)
#define SerialMon Serial
// Set serial for AT commands (to SIM800 module)
#define SerialAT Serial1

// Configure TinyGSM library
#define TINY_GSM_MODEM_SIM800      // Modem is SIM800
#define TINY_GSM_RX_BUFFER   1024  // Set RX buffer to 1Kb

// Define the serial console for debug prints, if needed
// #define DUMP_AT_COMMANDS

#include <Wire.h>
#include <TinyGsmClient.h>

#ifdef DUMP_AT_COMMANDS
  #include <StreamDebugger.h>
  StreamDebugger debugger(SerialAT, SerialMon);
  TinyGsm modem(debugger);
#else
  TinyGsm modem(SerialAT);
#endif

#define IP5306_ADDR          0x75
#define IP5306_REG_SYS_CTL0  0x00

bool setPowerBoostKeepOn(int en){
  Wire.beginTransmission(IP5306_ADDR);
  Wire.write(IP5306_REG_SYS_CTL0);
  if (en) {
    Wire.write(0x37); // Set bit1: 1 enable 0 disable boost keep on
  } else {
    Wire.write(0x35); // 0x37 is default reg value
  }
  return Wire.endTransmission() == 0;
}

void setup() {
  // Set serial monitor debugging window baud rate to 115200
  SerialMon.begin(115200);

  // Start I2C communication
  Wire.begin(I2C_SDA, I2C_SCL, 400000);

  bool isOk = setPowerBoostKeepOn(1);
  SerialMon.println(String("IP5306 KeepOn ") + (isOk ? "OK" : "FAIL"));

  // Set modem reset, enable, power pins
  pinMode(MODEM_PWKEY, OUTPUT);
  pinMode(MODEM_RST, OUTPUT);
  pinMode(MODEM_POWER_ON, OUTPUT);
  digitalWrite(MODEM_PWKEY, LOW);
  digitalWrite(MODEM_RST, HIGH);
  digitalWrite(MODEM_POWER_ON, HIGH);

  // Set GSM module baud rate and UART pins
  SerialAT.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX);
  delay(3000);

  // Restart SIM800 module, it takes quite some time
  // To skip it, call init() instead of restart()
  SerialMon.println("Initializing modem...");
  modem.restart();
  // use modem.init() if you don't need the complete restart

  // Unlock your SIM card with a PIN if needed
  if (strlen(simPIN) && modem.getSimStatus() != 3 ) {
    modem.simUnlock(simPIN);
  }

  if (waitForSMSReady() && setupReadSMS()) {
    SerialMon.println("Ready to receive SMS");
  }
}

#define WAIT_FOR_SMS_READY_TIMEOUT 20000L

bool waitForSMSReady() {
  unsigned long timeout = millis();
  while (millis() - timeout < WAIT_FOR_SMS_READY_TIMEOUT) {
    while (SerialAT.available()) {
      String value = SerialAT.readStringUntil('\n');
      SerialMon.println(value);
      if (value == "SMS Ready\r") {
        return true;
      }
    }
  }
  SerialMon.println("SMS is not ready");
  return false;
}

bool setupReadSMS() {
  modem.sendAT("+CMGF=1"); 
  if (modem.waitResponse() != 1) {
    SerialMon.println("Unable to select text mode");
    return false;
  }
  modem.sendAT("+CNMI=2,2,0,0,0");
  if (modem.waitResponse() != 1) {
    SerialMon.println("Unable to routed SMS-DELIVERs directly to the serial");
    return false;
  }
  modem.sendAT("+CSDH=1");
  if (modem.waitResponse() != 1) {
    SerialMon.println("Unable to show header values (including length of message)");
    return false;
  }
  return true;
}

bool readSMS(String& number, String& text) {
  if (modem.waitResponse(1000L, GF("+CMT:")) != 1) {
    return false;
  }
  modem.stream.readStringUntil('"');
  number = modem.stream.readStringUntil('"');
  String rest = modem.stream.readStringUntil('\n');
  int startOfLength = rest.lastIndexOf(",");
  if (startOfLength == -1) {
    return false;
  }
  size_t length = rest.substring(startOfLength + 1).toInt();
  char buffer[length + 1];
  if (modem.stream.readBytes(buffer, length) != length)
    return false;
  buffer[length] = 0;
  text = String(buffer);
  modem.stream.readStringUntil('\n');
  return true;
}

void loop() {
  while (SerialAT.available()) {
    String number;
    String text;
    if (readSMS(number, text)) {
      SerialMon.println(String("Message from ") + number + ":");
      SerialMon.println(text);
    }
  }
}

I want to do the same thing but with another board. I have a LILYGO® TTGO T-SIM A7670E. Can I reuse this code. I'm using the board at this moment to send sms. This works fine using the TinyGsmClientt.h. I'm not sure I can use the same setup values. Mainly this: sendAT("+CMGF=1"); , sendAT("+CNMI=2,2,0,0,0"); and this modem.sendAT("+CSDH=1");

There is a simple way to find out.
-> Read the datasheet AT Commands A7670X and check if the commands are compatible with this module.

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