ESP8266 + NTP

Hi everybody,

My wordclock is over so I'm trying to get the time from a NTP server thanks to ESP8266 used as a shield for my arduino uno.

What I'd like to do :

  1. Connect the ESP8266 to my wifi
  2. Do a NTP request to a server in France
  3. Rewrite the time and date get to a classical format of time.
  4. Write this information automatically in my RTC module DS1307 once a day

I found thid code but it failed to transfer to my arduino...

I think I can reuse it in my future code.

I red a lot on the ESP8266.

I already tried successfully to connect to my wifi thanks to AT commands

To do the NTP request, do I have to upgrade the ESP firmware ?

Does someone know how to use this module as a wifi shield ?

Thanks for your help !

Louison

The code for the NTP clock you found needs the Arduino core libraries to be installed on your ESP8266. Then you can use it [the ESP8266] with the Arduino IDE just like your existing Arduino Uno etc.
Here is a good guide based on an Adafruit Huzzah, but you should be able to adapt it to another ESP8266.
Once you have done all that, you can load and run the NTP clock software.

When you have all that working, you can then look at the function setSyncProvider from the Arduino Time Library to sync clock sources.

Right but what I'd like to do is to use the esp as à shield for m'y arduino uno.

Is there a solution ? I currently don't have the usb adapter for the esp.

There are lots of different ESP8266 implementations, which one do you have? (a link would be a good start).

It's the ESP-01 version

I found this page wich is very similar to what I want to do.

http://thearduinoguy.org/using-an-esp8266-as-a-time-source/

A shame he didn't finish coding it but it does look like you can access an NTP server with simple AT commands.
He said this: "Message me if you need any help with any of the above." so you could try.

I built an ESP8266 clock recently, but I used Arduino Core code for the ESP8266 and the Arduino IDE. I used an Arduino Nano (configured as an I2C slave) to handle the multiplexing of the display etc. because of the lack of ESP pins and had to use a level shifter between the ESP and the Nano because the ESP pins are not 5volt tolerant. It also handles DST changes.

Hi 6v6gt

I tried to compile his code and it's using like 11% regular memory and 75% of dynamic memory on my arduino uno.

My wordclock code is using 40% RM & 21% DM.

The conversion of NTP to regular time is not done neither to write it in the DS1307.

I don't think it will work easily. So I think I will try to program the ESP directly.

What accessory do I need to buy to connect it to my computer ?

You'll need a 3.3 volt capable USB adapter like this to program the ESP-01 from a PC using the Arduino IDE :

https://www.aliexpress.com/item/CH340-Serial-Converter-USB-To-TTL-6PIN-Module-Upgrade-Small-Plate-for-PRO-mini-Instead-of/1856263846.html

I hacked something last night quickly with AT commands

I'm traveling at the moment - will share later when I get a chance and have remote access to my Mac

ESP's are pretty light on pins. What else have you got connected, so far its an RTC on I2C, is there also a display?

Re: two sketches seeming hungry before they're merged, dont panic, often you'll find you're reusing libraries etc and the compiled version is smaller than you expect (or at least, it has been for me a few times).

Thanks jml and scrutin for your replies.

Soit il just bought the usb adapter and some stuff just in case I will not have enough memory or did not find à solution I ll program the Esp directly

http://m.ebay.fr/itm?itemId=282049653681
I have the RTC ds 1307 conected and led strip too.

In fact the display is done by the leds. Like each led = one letter it will write the time.

here you go. don't be afraid if it looks long - it's just the comments.

that full sketch once compiled uses up ~6500 bytes and global variables use 759 bytes. memory footprint could be reduced by F()-ing the char strings I'have hardcoded. I've been lazy :slight_smile:

it's coded just as an example, so a lot of things are just hardcoded and there is no error handling

to ensure your ESP is connected to your wifi change the SSID and PWD in the following line

  espATCommand("AT+CWJAP=\"[color=red][b]YOURSSID[/b][/color]\",\"[color=red][b]YOURPWD[/b][/color]\"", "OK", LONG_PAUSE); // connect to wifi

to get an NTP time, adjusted to French time (cf the UTC_DELTA stuff in the code for your time zone ) you just need to do

   epochUnix = epochUnixNTP();
    ntpHours = (epochUnix  % NUMBEROFSECONDSPERDAY) / NUMBEROFSECONDSPERHOUR;
    ntpMinutes = (epochUnix % NUMBEROFSECONDSPERHOUR) / NUMBEROFSECONDSPERMINUTE;
    ntpSeconds = epochUnix % NUMBEROFSECONDSPERMINUTE;

attaching the file because it's more than 9000 chars. this is how it works

in the setup() I connect my ESP to my wifi network. here are the AT commands

AT+RESTORE		wait for "ready"	--> reset the ESP
AT 				wait for "OK"		--> just to see if all is fine  (useless)
AT+CWMODE=1		wait for "OK"		--> Set the wireless mode
AT+CWQAP			wait for "OK"		--> disconnect, just to make sure (useless)
AT+CWJAP="YOURSSID","YOURPWD"	wait for "OK"		--> connect to wifi
AT+CIPMUX=0			wait for "OK"		--> set the single connection mode

at that point you are connected to the Wifi (or you should).

Then when you want to querry the NTP time, I issue the following AT commands:

AT+CIPSTART="UDP","fr.pool.ntp.org",123		wait for "OK"	--> start UDP session with NTP server
AT+CIPSEND=48								wait for "OK"	-->  will send 48 bytes

here you need to send the 48 bytes of a NTP request, but only the first 4 matters for us
so I write 0xEC0600E3 to the ESP and then another random 44 bytes, whatever is in memory

ESPSEPRIAL.write((char*) &ntpFirstFourBytes, NTP_PACKET_SIZE);

At that point the CIPSEND command got its 48 bytes, and the NTP server got its stuff and will answer with the NTP buffer. but you can't just read the 48 bytes and hope to get the NTP buffer. before you read the buffer you need to get rid of what the ESP tells you. Mine answers

Recv 48 bytes\r\n\r\nSEND OK\r\n\r\n+IPD,48[color=red][b]:[/b][/color]

so I wait until I see the : character and then the serial link gives me the 48 bytes, out of which I'm only interested in bytes 40,41,42,43 and 44. I read all the bytes and do

AT+CIPCLOSE						wait for "OK"	-->  close the session

that's for the AT commands.

I would suggest you run them first all manually in a direct manual AT session with your ESP to see if you get similar answers from your version of the firmware. My code does not do error checking but the critical one is the : mentioned above as this is how I detect the start of the 48 bytes of the NTP buffer. if you are off when you read the buffer, then nothing will work. so try commands by hands, see what it spits out and if it looks like mine and adjust code accordingly.

I let you see the code for the maths to transform the 32 bits I capture into a time in seconds.

let me know if that works and have fun!

ntp.ino (11.4 KB)

Oh my go jml I was not expecting so much ! I ll check it as soon as I can !

Thanks a lot to all of you ! I ll keep you up dates as soon as possible !

Hi JML,

I red your code and I figured out something about the rtc lib and the fact u are using an rtc ds3231

I'm using an RTC DS1307 that I configure that way.

#include "Wire.h"
#define DS1307_ADDRESS 0x68
byte zero = 0x00; //workaround for issue #527

int minute == 0
int hour == 0
int second == 0

void setup(){
  Wire.begin();
  Serial.begin(9600);
  setDateTime(); //MUST CONFIGURE IN FUNCTION
}

void loop(){
  printDate();
  delay(1000);
}

void setDateTime(){ // I defined x y z a b c d by writting myself so the idea here is to reuse the ones given from the NTP function

  byte second =      x; //0-59
  byte minute =      y; //0-59
  byte hour =        z; //0-23
  byte weekDay =     a; //1-7
  byte monthDay =    b; //1-31
  byte month =       c; //1-12
  byte year  =       d; //0-99

  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.write(zero);

  Wire.write(decToBcd(second));
  Wire.write(decToBcd(minute));
  Wire.write(decToBcd(hour));
  Wire.write(decToBcd(weekDay));
  Wire.write(decToBcd(monthDay));
  Wire.write(decToBcd(month));
  Wire.write(decToBcd(year));

  Wire.write(zero); //start 

  Wire.endTransmission();

}

byte decToBcd(byte val){
// Convert normal decimal numbers to binary coded decimal
  return ( (val/10*16) + (val%10) );
}

byte bcdToDec(byte val)  {
// Convert binary coded decimal to normal decimal numbers
  return ( (val/16*10) + (val%16) );
}

void printDate(){

  // Reset the register pointer
  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.write(zero);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_ADDRESS, 7);

  int second = bcdToDec(Wire.read());
  int minute = bcdToDec(Wire.read());
  int hour = bcdToDec(Wire.read() & 0b111111); //24 hour time


  //print the date Eg   23:59:59

  Serial.print(hour);
  Serial.print(":");
  Serial.print(minute);
  Serial.print(":");
  Serial.println(second);

}

So basically I don't need to add a zero before the hour when hour = 0 to 9
I need to reuse hour / minute / second in the ntp code to set the rtc and reuse it in my wordclock code (eg when minute == 0 light led XYZ)

is that possible this way ?

Thanks

Louison

The library I use work for the 1307, just neeed to instantiate that object instead of a 3231

The extra zero i add is just to make it nice when printing minutes (I prefer to see 10:09 rather than 10:9) but it's nothing important.

As mentioned above besides the utility functions to send the AT commands, what you need to do is only this:

   epochUnix = epochUnixNTP();
    ntpHours = (epochUnix  % NUMBEROFSECONDSPERDAY) / NUMBEROFSECONDSPERHOUR;
    ntpMinutes = (epochUnix % NUMBEROFSECONDSPERHOUR) / NUMBEROFSECONDSPERMINUTE;
    ntpSeconds = epochUnix % NUMBEROFSECONDSPERMINUTE;

Then you have in ntpHours, ntpMinutes and ntpSeconds the values you want to use for z,y and x in your setDateTime function.

Ok that's what I was thinking.

Thank you for the explanations.

I'll check more precisely monday and I'll make my experimentations :wink:

Hi everybody.

I worked a bit today but unfortunatly I burnt the Esp8266 chip ( I red that it was 5v tolerant but it semés for the rx/tx pins not for the vcc/gnd pins)

Anyway about the code if I'm not mistaken for the time in Paris I must choose a delta time +1 relatés to GMT.

But I have à question about summer / winter time. Is it allready incluses in ntp time server ?

Also if I'm correct I need to change pin 22 for reset for one of my choice.

Is your esp connected like this : ch_pd and 3.3v to power supply gnd to gnd and the other rx/tx/reset to pins defined in the code?

Also about serials . I saw you are using serial1 I guess it's an other serial available in the Mega. I changes it to serial classic. My question is: I saw the AT request but did not see the time in the serial. Do you have an other serial to read it or is it an other baud rate ?

Thanks

Louison

Too bad.. don't use it indeed with 5v... adaptors are cheap...

Now that Paris is in winter time, you are in UTC+1. a NTP server will always give you UTC time and won't provide guidance about summer time or winter time

If you use Serial instead of Serial1 you no longer should print anything to the PC console; best to ensure no issue is disconnect the USB cable totally.

If you look at the begining of the code i gave you there is a #define to select either SoftwareSerial or HardwareSerial. You should go for Software Serial

I'm unsure about which pins 22 you refer to - if it's in my code indeed, that's just any pin available - yes on the other pins.

A simple ESP8266 ArduinoIDE NIST timesync every 60 seconds.

NIST ESP8266

Should be easy to hack for use with an external RTC for sync.

Ray

@Ray I think he wants to use his ESP only as a Serial to wifi shield not with embedding arduino code directly into the ESP - hence my sample code above with AT commands to build the UDP req and decode the result