Often, but not always, my sketch is pulling the wrong Epoch into the RTC on a MKR1000. So, for example, this last run, the Epoch ended up as 946686002 instead of something from this decade. Once I spot it, I can manually press reset and the Arduino fetches the right time on the second try. How can I get NTP to pull in the right time the first time through? Is there something in the library which I can use for that or do I have to figure out a work-around in my setup routine? Below is the sketch in question.
/*
MKR1000
*/
#include <SPI.h> // for built-in WiFi shield
#include <WiFi101.h> // WiFi support https://www.arduino.cc/en/Reference/WiFi101
#include <WiFiUdp.h>
#include <RTCZero.h> // Real-time Clock https://www.arduino.cc/en/Reference/RTC
#include <PubSubClient.h> // MQTT client https://pubsubclient.knolleary.net/api
#include <OneWire.h> // for DS18B20
#include <DallasTemperature.h> // also for DS18B20 https://www.milesburton.com/Dallas_Temperature_Control_Library
#include <ArduinoLowPower.h> // for deepSleep() function https://www.arduino.cc/en/Reference/ArduinoLowPower
#define ONE_WIRE_BUS 0 // data wire is on pin 0 on this Arduino
OneWire oneWire(ONE_WIRE_BUS); // for any OneWire devices, not just Maxim/Dallas
DallasTemperature sensors(&oneWire); // pass reference to Dallas Temperature IC
RTCZero rtc;
#include "arduino_secrets.h"
// these connection data come from arduino_secrets.h
char ssid[] = SECRET_SSID; // network SSID (name)
char pass[] = SECRET_PASS; // network password
int status = WL_IDLE_STATUS;
void mqttpubcallback(char* topic, byte* payload, unsigned int length) {
// handle message delivered
}
unsigned long getepoch() {
unsigned long epoch;
int numberOfTries = 0, maxTries = 6;
do {
epoch = WiFi.getTime();
numberOfTries++;
}
while ((epoch == 0) && (numberOfTries < maxTries));
if (numberOfTries == maxTries) {
Serial.print("NTP unreachable!!");
// while (1);
}
else {
Serial.print("Epoch received: ");
Serial.println(epoch);
rtc.setEpoch(epoch);
Serial.println();
}
return(epoch);
}
void setup() {
WiFi.hostname("mkr1000");
Serial.begin(115200);
// low power mode??
for (int ledPin = 0; ledPin <= 21; ledPin++) {
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, LOW);
}
// check if the WiFi module works
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue if the hardware is missing or broken:
while (true);
}
// attempt to connect to WiFi network:
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
rtc.begin(); // initialize RTC activities
unsigned long epoch = getepoch();
sensors.begin(); // start Dallas Temperature IC Control Library
DeviceAddress deviceAddress;
int devicecount = sensors.getDeviceCount();
for (int i = 0; i < devicecount; i++) {
if (sensors.getAddress(deviceAddress, i)) {
Serial.print("Device ");
Serial.println(i);
sensors.setResolution(deviceAddress, 12); // set temperature resolution (9 through 12)
}
}
}
WiFiClient mqtt;
// mqttserver is defined in secrets.h as IPAddress
PubSubClient mqttclient(mqttserver, 1883, mqttpubcallback, mqtt);
String topic = "temperatures";
void loop() {
status = WiFi.status();
if (status != WL_CONNECTED) {
Serial.print("Attempting to reconnect to SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network.
status = WiFi.begin(ssid, pass);
delay(2000);
}
Serial.print("WiFI status: ");
Serial.print(status);
Serial.print("\t");
// get Epoch to send along with temperatures
unsigned long epoch = rtc.getEpoch();
Serial.print(epoch);
Serial.print("~");
// get temperature readings of each device on the bus
sensors.requestTemperatures();
float t0 = sensors.getTempCByIndex(0);
float t1 = sensors.getTempCByIndex(1);
Serial.print(" Temperature is: ");
Serial.print(t0);
Serial.print(" ");
Serial.print(t1);
Serial.print("\n");
// send temperatures if possible
if (mqttclient.connect("arduinoClient", MQTT_ACCT, MQTT_PASS)) {
String temperatures = String(epoch) + "\t3\t" + String(t0);
mqttclient.publish(topic.c_str(), String(temperatures).c_str());
temperatures = String(epoch) + "\t4\t" + String(t1);
mqttclient.publish(topic.c_str(), String(temperatures).c_str());
mqttclient.disconnect();
}
WiFi.maxLowPowerMode();
LowPower.deepSleep(280000);
WiFi.lowPowerMode();
// ride the time up to the 5-minute mark
while (rtc.getMinutes() % 5) {
LowPower.deepSleep(5000);
}
}
I don't suppose the RTC will drift forward by a whole second, so maybe I should make sure the fetched time is ahead of the built-in clock before setting the clock? Or can I somehow specify a different NTP server pool?