Sun Bee
Sun Bee

Reputation: 1820

ESP8266 stops connecting to NTP server when set up to run WiFi Manager

I have an ESP8266 that connects to WiFi and then calls an NTP server to get the time. Originally, I had set up the WiFi connection to work off a "config.h" file with SSID and password - the vanilla approach. Later, I set up a WiFi Manager with the AsyncWebServer library to avoid hardcoding credentials as shown in this tutorial by Rui Santos .

Now the user enters WiFi credentials on a web-page hosted by the ESP8266 which provides a Wireless Access Point. These credentials are stashed away in files on the local file-system (LittleFS) and accessed when making the WiFi connection from that point onwards. Upon connecting, the ESP8266 runs a web-server that hosts a static web-page.

This works fine and the ESP8266 connects to WiFi BUT the NTP service no longer works! I get a fixed time ~ 12:00 midnight from the NTP client. When I revert to connecting to WiFi the vanilla way, the NTP service works as expected.

Here is my code for making the WiFi connection in station mode. The class GuruWebServer has methods initializeaLittle(), readaLittle() and writeaLittle() for file-system operations. The key method, initializeWiFi(), returns true when connection is successfully made with the credentials stashed away in the file-system and returns false otherwise. The method has a loop with millis() in which the attempt to connect to WiFi is made until timeout (e.g. 60s).

I observe that the SSID and password are correctly recorded and WiFi connection is successfully made. Subsequently, using LanScan (on Mac), I can see the ESP8266 at the station IP address as configured. Using a browser, I can load the web-page it serves. However, I am no longer able to get the time-and-date from calling the NTP service.

bool GuruWebServer::initializeWiFi() {
    /*
    * Make WiFi connection when SSID and PWD are available
    * and set up station for web-service.
    */
    // Initialize LittleFS
    this->initializeaLittle();

    // Connect to WiFi
    this->readaLittle(&SSID, Path2_SSID); 
    this->readaLittle(&PWD, Path2_PWD);
    this->readaLittle(&IP, Path2_IP);
    this->readaLittle(&Gateway, Path2_Gateway);
    String conn_ack = (String)"SSID <" + SSID + "> | PWD <" + PWD + "> | IP <" + IP + "> | Gateway <" + Gateway + ">";

    if (SSID == "" || PWD == "") {  // Files not populated!
        Serial.println("Found NO SSID or PWD!");
        return false;
    }

    WiFi.mode(WIFI_STA);
    localIP.fromString(IP.c_str());
    localGateway.fromString(Gateway.c_str());

    if (!WiFi.config(localIP, localGateway, subnet)) {
        Serial.println("Configured NO station!");
        return false;
    }
    WiFi.begin(SSID, PWD);

    unsigned long _now   = millis();
    unsigned long _then  = _now;    // Marker for ticker
    unsigned long _stop  = _now;    // Marker for timeout
    unsigned long delta_minor = 0;  // Time since last tick
    unsigned long delta_major = 0;  // Time since start
    while (WiFi.status() != WL_CONNECTED) { 
        _now = millis();
        delta_minor = _now - _then; // Time since last tick
        delta_major = _now - _stop; // Time since start

        if (delta_minor > 1000) {   // Mark time and reset delta
            _then = _now;
            Serial.print (".");
        }
        if (delta_major > 60000) {  // Stop attempting connection
            String timely = (String)"Now " + _now + " Stop " + _stop + " Diff " + delta_major;
            Serial.println(timely);
            Serial.println("Made NO WiFi connection!");
            return false;           // Exit false
        }                           // end IF
    }                               // end WHILE WiFi 

    Serial.println(WiFi.localIP());
    return true;
}

To get time, I have used NTPClient library in the main program as follows:

#include <NTPClient.h>
#include <WiFiUdp.h>
WiFiUDP NTP_UDP;
NTPClient timeClient(NTP_UDP, "us.pool.ntp.org");

and in the setup() function of "main.cpp", I have:

  // Connect to  the NTP client
  delay(500);
  timeClient.begin();
  timeClient.setTimeOffset(-18000); // Central time GMT-5 ~ -5 x 3600 
  timeClient.update();
  Serial.println(timeClient.getFormattedTime());

The github branch rev007 has the code with WiFi Manager and rev006 has the vanilla WiFi.

I have tried the following:

  1. Used a different approach to get time on ESP8266 with "time.h" and configTime() function.
  2. Configured the web-server to use a port other than 80 (e.g. 8211) in AsyncWebServer server(80);.

Grateful for any help figuring this out, thank you.

UPDATE

I have simplified the code to illustrate the problem. This single script sets up the ESP8266 as WiFi station. The device connects to WiFi successfully but is unsuccessful calling the NTP service.

#include <Arduino.h>
#include <time.h>
#include "LittleFS.h"

#include <ESP8266WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
WiFiUDP NTP_UDP;
NTPClient timeClient(NTP_UDP, "pool.ntp.org");
// Alt.

#include "config.h"

IPAddress localIP;
IPAddress localGateway;
IPAddress subnet(255, 255, 255, 0);

void setup() {

  Serial.begin(9600);

  WiFi.mode(WIFI_STA);
  // Comment out from here --->
  localIP.fromString(IP);
  localGateway.fromString(Gateway);

  if (!WiFi.config(localIP, localGateway, subnet)) {
    Serial.println("Configured NO station!");
  }
  // <--- upto here!
  WiFi.begin(SSID, PWD);

  unsigned long _now   = millis();
  unsigned long _then  = _now;    // Marker for ticker
  unsigned long _stop  = _now;    // Marker for timeout
  unsigned long delta_minor = 0;  // Time since last tick
  unsigned long delta_major = 0;  // Time since start
  while (WiFi.status() != WL_CONNECTED) { 
    _now = millis();
    delta_minor = _now - _then;   // Time since last tick
    delta_major = _now - _stop;   // Time since start

    if (delta_minor > 1000) {     // Mark time and reset delta
        _then = _now;
        Serial.print (".");
    } 
    if (delta_major > 60000) {    // Stop attempting connection
        String timely = (String)"Now " + _now + " Stop " + _stop + " Diff " + delta_major;
        Serial.println(timely);
        Serial.println("Made NO WiFi connection!");
    }                             // end IF
  }                               // end WHILE WiFi 

  Serial.println(WiFi.localIP());

  // Connect to  the NTP client
  delay(3000);
  timeClient.begin();
  timeClient.setTimeOffset(-18000); // Central time GMT-5 ~ -5 x 3600 

  delay(3000);
  timeClient.update();
  Serial.println(timeClient.getFormattedTime());
}

void loop() {
  // put your main code here, to run repeatedly:
}

When I comment out the code as shown so as not to configure the IP address from settings but let it be determined at run-time, then all is well.

NTP Call SUCCESS

Upvotes: 1

Views: 1182

Answers (2)

Georgie9117
Georgie9117

Reputation: 11

If you want using WiFiManager just leave wifiManager.setSTAStaticIPConfig and use this after wifiManager.autoConnect

WiFi.begin();
WiFi.config(IPAddress(192, 168, 1, 148), IPAddress(192, 168, 1, 1), IPAddress(192, 168, 1, 1), IPAddress(255, 255, 255, 0));

It working for me on ESP8266.

Upvotes: 1

hcheung
hcheung

Reputation: 4034

I'm curious enough to try your code. The issue is without the proper DNS setup, the NTP(UDP) won't be able to resolve the NTP name "pool.ntp.org", I tested your code with slightly modification and simplification. Without specifying the DNS with WiFi.config(localIP, localGateway, subnet), the timeClient.update() simply can't establish a NTP connection, by adding a DNS IP to WiFi.config(localIP, localGateway, subnet, dns), the following code works like a charm.

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>

WiFiUDP NTP_UDP;
NTPClient timeClient(NTP_UDP, "pool.ntp.org");

#include "config.h"

IPAddress localIP(192, 168, 0, 120);     // my local ip
IPAddress localGateway(192, 168, 0, 1);  // my local gateway
IPAddress subnet(255, 255, 255, 0);
IPAddress dns(1, 1, 1, 1);               // CloudFlare DNS server

void setup() {

  Serial.begin(9600);
  while (!Serial);

  WiFi.mode(WIFI_STA);
  WiFi.begin(SSID, PWD);
  WiFi.config(localIP, localGateway, subnet, dns);
  int count = 0;
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    if (count++ > 20) ESP.restart();  //timeout, reboot
  } 
  Serial.println(WiFi.localIP());

  // Connect to  the NTP client
  timeClient.begin();
  timeClient.setTimeOffset(8*3600);  //my timezone
  if (timeClient.update())
    Serial.println(timeClient.getFormattedTime());
}

void loop() {

}

Upvotes: 2

Related Questions