#include #include char ssid[] = "zeeboo"; // your network SSID (name) char pass[] = "zaralily"; // your network password unsigned int localPort = 2390; // local port to listen for UDP packets IPAddress timeServerIP; // time.nist.gov NTP server address const char* ntpServerName = "time.nist.gov"; const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets WiFiUDP udp; unsigned long startSecsSince1900; unsigned long startMillis; unsigned long ntpdate() { unsigned long secsSince1900; WiFi.hostByName(ntpServerName, timeServerIP); sendNTPpacket(timeServerIP); // send an NTP packet to a time server delay(1000); int cb = udp.parsePacket(); if (cb) { udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer unsigned long highWord = word(packetBuffer[40], packetBuffer[41]); unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]); secsSince1900 = highWord << 16 | lowWord; } return secsSince1900; } #include #include #include // Include API-Headers extern "C" { // SDK functions for Arduino IDE access #include "osapi.h" #include "user_interface.h" #include "espconn.h" } //end, 'extern C' //--------------------------------------------------------------------------- // Globals const int LedBlu = 2, LedRed = 0, LedOff = 1, LedOn = 0; // For 64-bit usec ring counter static os_timer_t us_ovf_timer; static uint32_t us_cnt = 0; static uint32_t us_ovflow = 0; static uint32_t us_at_last_ovf = 0; //--------------------------------------------------------------------------- // Interrupt code lifted directly from "cores/core_esp8266_wiring.c", // with some variable renaming //--------------------------------------------------------------------------- // Callback for usec counter overflow timer interrupt void us_overflow_tick ( void* arg ) { us_cnt = system_get_time(); // Check for usec counter overflow if ( us_cnt < us_at_last_ovf ) { // ++us_cnt; // TYPO: should be ++us_ovflow ++us_ovflow; } //end-if us_at_last_ovf = us_cnt; } //us_overflow_tick //--------------------------------------------------------------------------- #define REPEAT 1 void us_count_init ( void ) { os_timer_setfn( &us_ovf_timer, (os_timer_func_t*)&us_overflow_tick, 0 ); os_timer_arm( &us_ovf_timer, 60000, REPEAT ); } //us_count_init //--------------------------------------------------------------------------- // Original millis() function unsigned long ICACHE_RAM_ATTR millis_orig ( void ) { uint32_t m = system_get_time(); uint32_t c = us_ovflow + ((m < us_at_last_ovf) ? 1 : 0); return ( c * 4294967 + m / 1000 ); // Above equation appears to be an approximation for // // (c * 4294967296 + m) / 1000 ~= c * 4294967 + m / 1000 // // Does this simplify the compilers work, i.e., is the multiply // 'c * 4294967' less complex than 'c * 4294967296'? Both would // seem to require a 64-bit result, although the former could // discard the most significant 32 bits. } //millis_orig //--------------------------------------------------------------------------- // Corrected millis(), 64-bit arithmetic, truncated to 32-bits by return unsigned long ICACHE_RAM_ATTR millis_corr( void ) { uint32_t m = system_get_time(); uint32_t c = us_ovflow + ((m < us_at_last_ovf) ? 1 : 0); return ( (c * 4294967296 + m) / 1000 ); } //millis_corr //--------------------------------------------------------------------------- // Alternate form, corrected millis() // // Convert 64-bit form into 32-bit arithmetic, assuming that the compiler // is smart enough to return the least-significant 32-bit word for the // 64-bit multiply, 'c * 4294967' // // ( c * 4294967296 + m ) / 1000 // c * ( 429496700 + 296 ) / 1000 + (m / 1000) // c * 4294967 + ( m + c*296 ) / 1000 // // noting c = 65536 * chi + clo, where chi & clo are uint16_t quantities... // // c*4294967 + ( m + (65536 * chi + clo) * 296 )/1000 // ..... + (m/1000) + ( clo*296 )/1000 + chi*(65536*296/1000) // ..... + (m/1000) + ( clo*296 )/1000 + chi*(19398 + 0.656) // ..... + (m/1000) + ( clo*296 )/1000 + (chi*1000*0.656)/1000 + chi*19398 // ..... + (m/1000) + ( clo*296 )/1000 + (chi*656)/1000 + chi*19398 // ..... + (m/1000) + ( clo*296 + chi*656 )/1000 + chi*19398 // // Original millis() form Additional terms // // Truncated // 64-bit? 32-bit 32-bit 32-bit // c*4294967 + (m/1000) + ((clo*296 + chi*656 )/1000) + chi*19398 // unsigned long ICACHE_RAM_ATTR millis_altn ( void ) { uint32_t m = system_get_time(); uint32_t c = us_ovflow + ((m < us_at_last_ovf) ? 1 : 0); // High/low words of 'c' uint16_t chi = c >> 16, clo = c & 0xFFFF; // Note that truncation of 'c * 4294967' is explicitly enforced return ( (uint32_t)(c * 4294967) + (m / 1000) + ((clo * 296 + chi * 656) / 1000) + chi * 19398 ); //end-return } //millis_altn //--------------------------------------------------------------------------- // Output routines //--------------------------------------------------------------------------- void millis_header ( void ) { Serial.print( "us_ovflow err: " ); Serial.print( 0.296 * us_ovflow ); Serial.println( " ms" ); Serial.println( F(" Original Corrected Altn Corr - Altn Orig - Corr") ); Serial.println( F(" mills() millis() millis() Difference Difference Heap") ); } //millis_header //--------------------------------------------------------------------------- void millis_compare ( void ) { uint32_t ms_orig = millis_orig(); uint32_t ms_corr = millis_corr(); uint32_t ms_altn = millis_altn(); uint16_t heap = ESP.getFreeHeap(); char buf[60] = ""; sprintf( buf, "%12d %12d %12d", ms_orig, ms_corr, ms_altn ); //end-sprint Serial.print( buf ); Serial.print( " " ); sprintf( buf, "%10d %10d %7d", (int32_t)(ms_corr - ms_altn), (int32_t)(ms_orig - ms_corr), heap ); //end-sprint Serial.println( buf ); } //millis_compare void setup() { Serial.begin(115200); Serial.println(); Serial.println(); // We start by connecting to a WiFi network Serial.print("Connecting to "); Serial.println(ssid); WiFi.mode(WIFI_STA); WiFi.begin(ssid, pass); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); Serial.println("Starting UDP"); udp.begin(localPort); Serial.print("Local port: "); Serial.println(udp.localPort()); startSecsSince1900 = ntpdate(); startMillis = millis(); us_count_init(); us_at_last_ovf = 0; us_ovflow = 1000; // Error is 0.296 ms * overflow count = 296 ms } void loop() { unsigned long s; s = ntpdate() - startSecsSince1900; uint32_t ms_orig = millis_orig(); uint32_t ms_corr = millis_corr(); uint32_t ms_altn = millis_altn(); ms_orig -= startMillis; ms_corr -= startMillis; ms_altn -= startMillis; Serial.print(s); Serial.print(" "); Serial.print(ms_orig); Serial.print(" "); Serial.print(ms_corr); Serial.print(" "); Serial.println(ms_altn); delay(60000); } unsigned long sendNTPpacket(IPAddress& address) { memset(packetBuffer, 0, NTP_PACKET_SIZE); packetBuffer[0] = 0b11100011; // LI, Version, Mode packetBuffer[1] = 0; // Stratum, or type of clock packetBuffer[2] = 6; // Polling Interval packetBuffer[3] = 0xEC; // Peer Clock Precision // 8 bytes of zero for Root Delay & Root Dispersion packetBuffer[12] = 49; packetBuffer[13] = 0x4E; packetBuffer[14] = 49; packetBuffer[15] = 52; udp.beginPacket(address, 123); //NTP requests are to port 123 udp.write(packetBuffer, NTP_PACKET_SIZE); udp.endPacket(); }