chipKIT® Development Platform

Inspired by Arduino™

Strange behaviour of SecondsSinceEpoch() method from Etherne

Created Tue, 27 Sep 2011 12:08:11 +0000 by Paul_L


Paul_L

Tue, 27 Sep 2011 12:08:11 +0000

After the new Ethernet library publishing I found the method SecondsSinceEpoch() implemented by Keith based by SNTP.c functions from Microchip. I was trying this method in the following program :

//#include <ChipKITRTCC.h>
#include <LiquidCrystal.h>
#include <chipKITEthernet.h>

byte mac[] = {  
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 
  192,168,100,250 };


LiquidCrystal lcd(10, 11, 5, 8, 3, 6);
//RTCCclass rtc;

void setup() 
{
 
  Ethernet.begin();  
  Serial.begin(9600);
  Serial.println("Start of Sketch");
  lcd.begin(16, 2);
//  rtc.init();
//  rtc.writeEnable();
//  rtc.reset();

}

void loop()
{
    lcd.setCursor(0,0);
    lcd.print(RTCTIME, HEX);
    unsigned long epochtime =  Ethernet.SecondsSinceEpoch();  
    Serial.println(epochtime);   
    lcd.setCursor(0,1);
    lcd.print(epochtime);
    delay(1000); 
}

and I had a big surprise since in epochtime integer I did not find seconds since epoch as I assumed but seconds from the first request on NTP server !!!!!

Start of Sketch
1
2
3
4
5
6
7
8
9

What did I wrong ? I was testing with more than one NTP servers from the SNTP.c file even a internal one . In the NTP example made by using arduino NTP implementation all was OK . I got from servers real time

Paul

Later update :

Even I disconnect the ethernet cable the method is returning an incremented second information since the first call.


KeithV

Tue, 27 Sep 2011 14:41:59 +0000

The most likely cause for this is that you do not have a valid DNS server. I see that you are using DHCP, so I would assume that your DCHP server is supplying a valid DNS servers, but maybe not? This (counting) is exactly what will happen if the time servers can not be reached, that is, the the time server hostnames can not be resolved; by default, the time will be since the start of the program.

I would try the WebClient sketch to verify that you can reach the outside world. WebClient attempts to connect to www.google.com via DNS (make sure you specify the hostname and not the IP address; also make sure to change your serial monitor speed to 115,200 as serial.print can't keep up at 9600; the example is set at 115,200, you must change your monitor). If this works, then your DNS servers are being set up by DHCP, if not; then go check to see what DHCP is sending as your DNS servers are typically specifed in your gateway/router.

The other option is to set up your DNS manually

Ethernet.begin(mac, ip, gateway, subnet, dns1, dns2)

Make sure you fill in valid values for each.

For a DNS server, try the google public DNS server 8.8.8.8

If you look in the RemoteWol example, you will see the manual setup in there as an example, but you must set these to the values for your network.


Paul_L

Tue, 27 Sep 2011 15:21:41 +0000

Is there a possibility to read the settings received by chipkit trough DHCP? . In I set an IP to SNTP.c in the same network it will work ? Like :

// one or ship your embedded device to another geography.
#define NTP_SERVER	"192.168.100.5"
//#define NTP_SERVER	"pool.ntp.org"
//#define NTP_SERVER	"europe.pool.ntp.org"

KeithV

Tue, 27 Sep 2011 15:52:16 +0000

Paul,

After writing my last response I realized that you might actually be hitting a different issue, and this is a little "pet peeve” of mine, so please do not take any offense. What is actually happening here is that you are not allowing the Ethernet stack to run. I absolutely hate “delay” and I hate that the Arduino examples use “delay”.

A little back ground. When programming on a microcontroller like the chipKIT (or the Arduino chips as well), we are not working in a preemptive multi-tasking environment. That is, if something needs to get run, we have to run it. And if it has to be run in a timely manner, we have to do it in a timely manner.

The sketches are setup correctly with a “setup” and “loop” calls. The idea is that you “loop” through your code running your needed tasks each time through the loop. If you “delay” you do not execute those needed tasks; this includes not running the Ethernet stack. Most “good” loop code is written as a state machine with the end of the loop being where you execute all of those things that must be executed to keep things alive, things we normally take for granted that the operating system will for us; but we are not running an RTOS, we have to do the work ourselves.

Unlike the WizNet chip that sort of works independently from the AVR chip, the Microchip Ethernet MAL is implemented in software (not hardware), so we must “keep the stack alive” by manually calling the stack (or any of the Ethernet methods) on a regular basis. In your code, you only made 2 calls to the stack, and that is not enough for the underlying stack code to do the UDP calls to set up the clock. Eventually (maybe) you would see the Epoch time coming out once you made enough calls to the stack to complete the time request.

I ran your code with the exact result that you are getting! I re-wrote your code as a state machine calling the Ethernet stack every time through the loop. I also gave the Ethernet stack 1 second to “get the time” before printing it the first time. If you don’t do this, you would see a result of “1” as the underlying code did not have enough “calls” to the stack to complete the 1st call to the time servers.

Try this code:

#include <chipKITEthernet.h>

int waitUntil = 0; unsigned long epochtime = 0;

typedef enum { GETWAITTIME, WAIT, GETEPOCHTIME, PRINTEPOCHTIME } STATE;

STATE state = GETWAITTIME;

void setup() { Ethernet.begin();
Serial.begin(9600); Serial.println("Start of Sketch"); }

void loop() {
// execute our current state switch(state) {
case GETWAITTIME: waitUntil = millis() + 1000; state = WAIT; break;

  case WAIT:
    if(millis() &gt; waitUntil )
      {
      state = GETEPOCHTIME;
      }
    break; 
    
  case GETEPOCHTIME:
    epochtime =  Ethernet.SecondsSinceEpoch();
    state = PRINTEPOCHTIME;
    break; 
    
  case PRINTEPOCHTIME:
    Serial.println(epochtime);
    state = GETWAITTIME;  
    break; 
    
  default:
    break; 
}        

// do all each loop tasks
Ethernet.PeriodicTasks(); }

Results with:

Start of Sketch 1317138055 1317138056 1317138057 1317138058 1317138059 1317138060 1317138061 1317138062 1317138063 1317138064 1317138065 1317138066 1317138067 1317138068 1317138069


Paul_L

Tue, 27 Sep 2011 17:09:53 +0000

Keith,

I should say that this is a sensible issue. Is that a variable, a flag something that indicate that the Ethernet stack has finished his started tasks?


KeithV

Tue, 27 Sep 2011 17:22:39 +0000

Short answer, No

Long answer, for the case if the EpochTime, you could just check to see if it is greater than 100,000 or something. You know, a number of seconds somewhere between 1970 and 2011 (today). If it greater than that you know it has been initialized.

As for other things, you just have to check to see if it makes sense; and that is application dependent, only you know who you are talking to, and what to expect as a response. In a read/write, you wait until the available bytes are there; or IsConnected succeeds. And you put break out timers to get out if it never succeeds.


Paul_L

Tue, 27 Sep 2011 19:34:46 +0000

By the existence of millis() function I was sure that somewhere in the bootloader a timer is used to send hardware interrupts at 1ms and there is a interrupts treatment routine used for millis() and delay(int). Can't be used such a interrupt to run a process like Ethernet.PeriodicTasks ()?


KeithV

Wed, 28 Sep 2011 03:22:42 +0000

If you read the Ethernet documentation under the chipKITEthernet\documents, you find that this is documented. Every 10min via round robin of time servers the epoch time is obtained, then the interal timer is used to maintian the time within the 10 min. Clearly, you have to get epoch time from somewhere when you first boot as the chipKIT has no idea what time it is. Once time is obtained you can use the internal timer to keep time, but only as good as the internal timer is. The chipKIT is pretty good (I think) but some clocks on some processors are simple RC networks which can vary noticable over time, thus that is why the MAL gets the time every 10min. and keeps your internal time accruate.