vshymanskyy / TinyGSM

A small Arduino library for GSM modules, that just works
GNU Lesser General Public License v3.0
1.91k stars 708 forks source link

Troubleshooting modem.waitForNetwork() Returning False on LilyGo T-Call SIM800L #757

Closed hamzaaitabdel closed 6 months ago

hamzaaitabdel commented 8 months ago

Hello everyone,

I am working on a project using a LilyGo T-Call SIM800L board with an integrated ESP32 and SIM800L GSM module. I am using the TinyGSM library to establish a GSM/GPRS connection. However, I am facing an issue where the modem.waitForNetwork() function keeps returning false, preventing me from establishing a network connection.

Here are the details of my setup and the steps I've taken so far:

Hardware: Board: LilyGo T-Call SIM800L GSM Antenna: Connected and seated properly SIM Card: Inserted correctly, active, and has data coverage

Software: Arduino IDE: Version 1.8.13 TinyGSM Library: Version 0.10.9 Board Selection: ESP32 Wrover Module

Code:


#define TINY_GSM_MODEM_SIM800  // Specify SIM800L modem
#define TINY_GSM_DEBUG Serial
#include <TinyGsmClient.h>
#include <PubSubClient.h>

#define MODEM_RST            5
#define MODEM_PWRKEY         4
#define MODEM_POWER_ON       23
#define MODEM_TX             27
#define MODEM_RX             26
const char apn[] = "web.vodafone.de";  // Replace with your APN
const char user[] = "";  // Replace with your username, if required
const char pass[] = "";  // Replace with your password, if required
TinyGsm modem(Serial1);
TinyGsmClient client(modem);
PubSubClient mqtt(client);

void setup() {
  // Set console baud rate
  Serial.begin(115200);
  delay(10);

  // Set-up modem reset, enable, power pins
  pinMode(MODEM_RST, OUTPUT);
  pinMode(MODEM_PWRKEY, OUTPUT);
  pinMode(MODEM_POWER_ON, OUTPUT);

  digitalWrite(MODEM_RST, HIGH);
  digitalWrite(MODEM_PWRKEY, HIGH);
  digitalWrite(MODEM_POWER_ON, HIGH);

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

  // Restart takes quite some time
  modem.init();

  // Unlock your SIM card with a PIN if needed
  //modem.simUnlock("1234");
  Serial.println(modem.getSignalQuality());
}

void loop() {
  Serial.println("Waiting for network...");
  if (!modem.waitForNetwork()) {
    Serial.println(" fail");
    modem.restart();
    delay(10000);
    return;
  }
  Serial.println(" success");

  Serial.print(F("Connecting to APN: "));
  Serial.print(apn);
  if (!modem.gprsConnect(apn, user, pass)) {
    Serial.println(" fail");
    delay(10000);
    return;
  }
  Serial.println(" success");

  // Your further code to check internet connectivity
  // ...

  modem.gprsDisconnect();
  Serial.println(F("GPRS disconnected"));
}

Output:

5:12:40.781 -> \[3467\] ### TinyGSM Version: 0.11.7
15:12:40.781 -> \[3467\] ### TinyGSM Compiled Module:  TinyGsmClientSIM800
15:12:51.968 -> 99
15:12:51.968 -> Waiting for network...
15:13:51.990 ->  fail
15:14:12.190 -> Waiting for network...
15:15:12.160 ->  fail
15:15:32.360 -> Waiting for network...
Troubleshooting Steps:
    Checked and confirmed correct APN settings.
    Tried restarting the modem using modem.restart() when modem.waitForNetwork() returns false.
    Checked signal quality using modem.getSignalQuality() and received a value of 99.

Despite these steps, the issue persists. I would greatly appreciate any insights or suggestions on how to resolve this problem. Has anyone encountered a similar issue or have any advice on additional troubleshooting steps I could take?

Thank you in advance for your help!

adityabangde commented 6 months ago

"I am using the "TinyGSM" library on an ESP32, and I have a parallel task that uses the "getSimStatus()" function. Meanwhile, I'm running MQTT using the "TinyGSM" library in the main loop. However, I'm experiencing inconsistent results from "getSimStatus()", where it sometimes returns true even if the SIM is not connected and vice-versa. Can you provide insights or suggestions on why this might be happening?"

hamzaaitabdel commented 6 months ago

Could you provide your full code ?

adityabangde commented 6 months ago

sorry for the late reply, I added TinyGSM's MQTT example to my ESP32 project and moved the reconnection code to a separate task.

Code:

// Select your modem:
#define TINY_GSM_MODEM_SIM800

#define SerialAT Serial2 //RX2, TX2 pin of ESP32

// Range to attempt to autobaud
// NOTE:  DO NOT AUTOBAUD in production code.  Once you've established
// communication, set a fixed baud rate using modem.setBaud(#).
#define GSM_AUTOBAUD_MIN 9600
#define GSM_AUTOBAUD_MAX 115200

// set GSM PIN, if any
#define GSM_PIN ""

// Your GPRS credentials, if any
const char apn[]      = "airtelgprs.com";
const char gprsUser[] = "";
const char gprsPass[] = "";

// MQTT details
const char* broker = "broker.hivemq.com";
const char* topicLed       = "GsmClientTest/led";
const char* topicInit      = "GsmClientTest/init";
const char* topicLedStatus = "GsmClientTest/ledStatus";

#include <TinyGsmClient.h>
#include <PubSubClient.h>

#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, Serial);
TinyGsm        modem(debugger);
#else
TinyGsm        modem(SerialAT);
#endif
TinyGsmClient client(modem);
PubSubClient  mqtt(client);

SemaphoreHandle_t xSemaphore;
TaskHandle_t Task1Handle;

#define LED_PIN 2
int ledStatus = LOW;

uint32_t lastReconnectAttempt = 0;

void mqttCallback(char* topic, byte* payload, unsigned int len) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("]: ");
  Serial.write(payload, len);
  Serial.println();

  // Only proceed if incoming message's topic matches
  if (String(topic) == topicLed) {
    ledStatus = !ledStatus;
    digitalWrite(LED_PIN, ledStatus);
    mqtt.publish(topicLedStatus, ledStatus ? "1" : "0");
  }
}

boolean mqttConnect() {
  Serial.print("Connecting to ");
  Serial.print(broker);

  // Connect to MQTT Broker
  boolean status = mqtt.connect("GsmClientTest");

  // Or, if you want to authenticate MQTT:
  // boolean status = mqtt.connect("GsmClientName", "mqtt_user", "mqtt_pass");

  if (status == false) {
    Serial.println(" fail");
    return false;
  }
  Serial.println(" success");
  mqtt.publish(topicInit, "GsmClientTest started");
  mqtt.subscribe(topicLed);
  return mqtt.connected();
}

void Task2(void *parameter) {
  while (true) {
    if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) {

      // Make sure we're still registered on the network
      if (!modem.isNetworkConnected()) {
        Serial.println("Network disconnected");
        if (!modem.waitForNetwork(180000L, true)) {
          Serial.println(" fail");
          delay(10000);
          return;
        }
        if (modem.isNetworkConnected()) {
          Serial.println("Network re-connected");
        }

        if (!modem.isGprsConnected()) {
          Serial.println("GPRS disconnected!");
          Serial.print(F("Connecting to "));
          Serial.print(apn);
          if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
            Serial.println(" fail");
            delay(10000);
            return;
          }
          if (modem.isGprsConnected()) {
            Serial.println("GPRS reconnected");
          }
        }
      }
      xSemaphoreGive(xSemaphore);
    }
    vTaskDelay(pdMS_TO_TICKS(5000));
  }
}

//--------------------------------------setup---------------------------------------------------------
void setup() {

  Serial.begin(115200);

  pinMode(LED_PIN, OUTPUT);

  Serial.println("Wait...");

  // Set GSM module baud rate
  TinyGsmAutoBaud(SerialAT, GSM_AUTOBAUD_MIN, GSM_AUTOBAUD_MAX);
  // SerialAT.begin(9600);
  delay(6000);

  // Restart takes quite some time
  // To skip it, call init() instead of restart()
  Serial.println("Initializing modem...");
  modem.restart();
  // modem.init();

  String modemInfo = modem.getModemInfo();
  Serial.print("Modem Info: ");
  Serial.println(modemInfo);

#if TINY_GSM_USE_GPRS
  // Unlock your SIM card with a PIN if needed
  if (GSM_PIN && modem.getSimStatus() != 3) {
    modem.simUnlock(GSM_PIN);
  }
#endif

  Serial.print("Waiting for network...");
  if (!modem.waitForNetwork()) {
    Serial.println(" fail");
    delay(10000);
    return;
  }
  Serial.println(" success");

  if (modem.isNetworkConnected()) {
    Serial.println("Network connected");
  }

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

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

  // MQTT Broker setup
  mqtt.setServer(broker, 1883);
  mqtt.setCallback(mqttCallback);

  xSemaphore = xSemaphoreCreateBinary();

  if (xSemaphore != NULL) {
    xSemaphoreGive(xSemaphore); // Initialize the semaphore to give it to one of the tasks
  }
  xTaskCreate(Task2, "Task2", 20000, NULL, 2, &Task1Handle);

}

//-----------------------------------------loop----------------------------------------------------------------------
void loop() {

  if (!mqtt.connected()) {
    Serial.println("=== MQTT NOT CONNECTED ===");
    // Reconnect every 10 seconds
    uint32_t t = millis();
    if (t - lastReconnectAttempt > 10000L) {
      lastReconnectAttempt = t;
      if (mqttConnect()) {
        lastReconnectAttempt = 0;
      }
    }
    delay(100);
    return;
  }

  mqtt.loop();

}

output:

Modem Info: 
Waiting for network... success
Network connected
Connecting to airtelgprs.com success
GPRS connected
=== MQTT NOT CONNECTED ===
Connecting to broker.hivemq.com success
Network disconnected
Network re-connected
Network disconnected
Network re-connected
Network disconnected
Network re-connected
Network disconnected
Network re-connected
Network disconnected
adityabangde commented 6 months ago

"I forgot to include the getSimStatus() function in my code, but I'm observing a similar behavior of isNetworkConnected() function.

adityabangde commented 6 months ago
modem.waitForNetwork()

"I believe I've identified a solution to our issues. It seems that the functions in question, such as modem.waitForNetwork(), are wrapper functions that use AT commands to communicate with the SIM800L module. The module sometimes takes a bit longer to respond, causing inconsistencies. By adding a delay, specifically modifying the modem.waitForNetwork() function to modem.waitForNetwork(180000L, true) the problem should be resolved."

hamzaaitabdel commented 6 months ago

indeed it uses AT commands to communicate, but in my case it was something else related to local network so i changed my setup. well i'm glade you solved your problem. hope this will be your last one in that project.

hamzaaitabdel commented 6 months ago

the solution for this problem could be related to your local network supplier (f.e GPRS network is not available in your area, signal is weak...) or it could be due to the delay as explained above. for me i was using a SIM800 module and i couldn't solve it ,but using a SIM7000G everything worked well.