Skip to content

Commit dcd5e7f

Browse files
authored
Merge pull request arduino#97 from sebromero/rtc-ntp-sync
[AE-96] Add RTC NTP Sync Example
2 parents b379de9 + 806aeb2 commit dcd5e7f

File tree

4 files changed

+239
-19
lines changed

4 files changed

+239
-19
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
/**
2+
* This example shows how to set the RTC (Real Time Clock) on the Portenta C33
3+
* to the current date and time retrieved from an NTP server on the Internet (pool.ntp.org).
4+
* Then the current time from the RTC is printed to the Serial port.
5+
*
6+
* Instructions:
7+
* 1. Change the WiFi credentials in the arduino_secrets.h file to match your WiFi network.
8+
* 2. Upload this sketch to Portenta C33.
9+
* 3. Open the Serial Monitor.
10+
*
11+
* Initial author: Sebastian Romero @sebromero
12+
*/
13+
14+
#include "RTC.h"
15+
#include <WiFiC3.h>
16+
#include <WiFiUdp.h>
17+
#include "arduino_secrets.h"
18+
19+
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
20+
char ssid[] = SECRET_SSID; // your network SSID (name)
21+
char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP)
22+
23+
constexpr unsigned int LOCAL_PORT = 2390; // local port to listen for UDP packets
24+
constexpr int NTP_PACKET_SIZE = 48; // NTP timestamp is in the first 48 bytes of the message
25+
26+
int wifiStatus = WL_IDLE_STATUS;
27+
IPAddress timeServer(162, 159, 200, 123); // pool.ntp.org NTP server
28+
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets
29+
WiFiUDP Udp; // A UDP instance to let us send and receive packets over UDP
30+
31+
// send an NTP request to the time server at the given address
32+
unsigned long sendNTPpacket(IPAddress& address) {
33+
// set all bytes in the buffer to 0
34+
memset(packetBuffer, 0, NTP_PACKET_SIZE);
35+
// Initialize values needed to form NTP request
36+
// (see URL above for details on the packets)
37+
packetBuffer[0] = 0b11100011; // LI, Version, Mode
38+
packetBuffer[1] = 0; // Stratum, or type of clock
39+
packetBuffer[2] = 6; // Polling Interval
40+
packetBuffer[3] = 0xEC; // Peer Clock Precision
41+
// 8 bytes of zero for Root Delay & Root Dispersion
42+
packetBuffer[12] = 49;
43+
packetBuffer[13] = 0x4E;
44+
packetBuffer[14] = 49;
45+
packetBuffer[15] = 52;
46+
47+
// all NTP fields have been given values, now
48+
// you can send a packet requesting a timestamp:
49+
Udp.beginPacket(address, 123); //NTP requests are to port 123
50+
Udp.write(packetBuffer, NTP_PACKET_SIZE);
51+
Udp.endPacket();
52+
}
53+
54+
void printWifiStatus() {
55+
// print the SSID of the network you're attached to:
56+
Serial.print("SSID: ");
57+
Serial.println(WiFi.SSID());
58+
59+
// print your board's IP address:
60+
IPAddress ip = WiFi.localIP();
61+
Serial.print("IP Address: ");
62+
Serial.println(ip);
63+
64+
// print the received signal strength:
65+
long rssi = WiFi.RSSI();
66+
Serial.print("signal strength (RSSI):");
67+
Serial.print(rssi);
68+
Serial.println(" dBm");
69+
}
70+
71+
void connectToWiFi(){
72+
// check for the WiFi module:
73+
if (WiFi.status() == WL_NO_MODULE) {
74+
Serial.println("Communication with WiFi module failed!");
75+
// don't continue
76+
while (true);
77+
}
78+
79+
String fv = WiFi.firmwareVersion();
80+
if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
81+
Serial.println("Please upgrade the firmware");
82+
}
83+
84+
// attempt to connect to WiFi network:
85+
while (wifiStatus != WL_CONNECTED) {
86+
Serial.print("Attempting to connect to SSID: ");
87+
Serial.println(ssid);
88+
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
89+
wifiStatus = WiFi.begin(ssid, pass);
90+
91+
// wait 10 seconds for connection:
92+
delay(10000);
93+
}
94+
95+
Serial.println("Connected to WiFi");
96+
printWifiStatus();
97+
}
98+
99+
/**
100+
* Calculates the current unix time, that is the time in seconds since Jan 1 1970.
101+
* It will try to get the time from the NTP server up to `maxTries` times,
102+
* then convert it to Unix time and return it.
103+
* You can optionally specify a time zone offset in hours that can be positive or negative.
104+
*/
105+
unsigned long getUnixTime(int8_t timeZoneOffsetHours = 0, uint8_t maxTries = 5){
106+
// Try up to `maxTries` times to get a timestamp from the NTP server, then give up.
107+
for (size_t i = 0; i < maxTries; i++){
108+
sendNTPpacket(timeServer); // send an NTP packet to a time server
109+
// wait to see if a reply is available
110+
delay(1000);
111+
112+
if (Udp.parsePacket()) {
113+
Serial.println("packet received");
114+
Udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer
115+
116+
//the timestamp starts at byte 40 of the received packet and is four bytes,
117+
//or two words, long. First, extract the two words:
118+
unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
119+
unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
120+
121+
// Combine the four bytes (two words) into a long integer
122+
// this is NTP time (seconds since Jan 1 1900):
123+
unsigned long secsSince1900 = highWord << 16 | lowWord;
124+
125+
// Now convert NTP time into everyday time:
126+
// Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
127+
const unsigned long seventyYears = 2208988800UL;
128+
unsigned long secondsSince1970 = secsSince1900 - seventyYears + (timeZoneOffsetHours * 3600);
129+
return secondsSince1970;
130+
}
131+
}
132+
133+
return 0;
134+
}
135+
136+
void setup(){
137+
Serial.begin(9600);
138+
while (!Serial);
139+
140+
connectToWiFi();
141+
Serial.println("\nStarting connection to server...");
142+
Udp.begin(LOCAL_PORT);
143+
RTC.begin();
144+
145+
// Get the current date and time from an NTP server and convert
146+
// it to UTC +2 by passing the time zone offset in hours.
147+
// You may change the time zone offset to your local one.
148+
auto unixTime = getUnixTime(2);
149+
Serial.print("Unix time = ");
150+
Serial.println(unixTime);
151+
RTCTime timeToSet = RTCTime(unixTime);
152+
RTC.setTime(timeToSet);
153+
154+
// Retrieve the date and time from the RTC and print them
155+
RTCTime currentTime;
156+
RTC.getTime(currentTime);
157+
Serial.println("The RTC was just set to: " + String(currentTime));
158+
}
159+
160+
void loop(){}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#define SECRET_SSID ""
2+
#define SECRET_PASS ""

libraries/RTC/src/RTClock.cpp renamed to libraries/RTC/src/RTC.cpp

+53-7
Original file line numberDiff line numberDiff line change
@@ -350,17 +350,63 @@ bool RTCTime::setUnixTime(time_t time) {
350350
}
351351

352352
/* getters */
353-
int RTCTime::getDayOfMonth() { return day; }
354-
Month RTCTime::getMonth() { return month; }
355-
int RTCTime::getYear() { return year >= TM_YEAR_OFFSET ? year : year + TM_YEAR_OFFSET; }
356-
int RTCTime::getHour() { return hours; }
357-
int RTCTime::getMinutes() { return minutes; }
358-
int RTCTime::getSeconds() { return seconds; }
359-
DayOfWeek RTCTime::getDayOfWeek() { return day_of_week; }
353+
int RTCTime::getDayOfMonth() const { return day; }
354+
Month RTCTime::getMonth() const { return month; }
355+
int RTCTime::getYear() const { return year >= TM_YEAR_OFFSET ? year : year + TM_YEAR_OFFSET; }
356+
int RTCTime::getHour() const { return hours; }
357+
int RTCTime::getMinutes() const { return minutes; }
358+
int RTCTime::getSeconds() const { return seconds; }
359+
DayOfWeek RTCTime::getDayOfWeek() const { return day_of_week; }
360360

361361
time_t RTCTime::getUnixTime() { return mktime ( (struct tm *)&stime ); }
362362
struct tm RTCTime::getTmTime() { return (struct tm)stime; }
363363

364+
arduino::String RTCTime::toString() const {
365+
String formattedTime = "";
366+
367+
// Year
368+
formattedTime += String(getYear());
369+
formattedTime += "-";
370+
371+
// Month
372+
uint8_t month = static_cast<uint8_t>(getMonth()) + 1;
373+
if (month < 10)
374+
formattedTime += '0';
375+
formattedTime += String(month);
376+
formattedTime += "-";
377+
378+
// Day of month
379+
if (getDayOfMonth() < 10)
380+
formattedTime += '0';
381+
formattedTime += String(getDayOfMonth());
382+
383+
// T separator
384+
formattedTime += "T";
385+
386+
// Hours
387+
if (getHour() < 10)
388+
formattedTime += '0';
389+
formattedTime += String(getHour());
390+
formattedTime += ":";
391+
392+
// Minutes
393+
if (getMinutes() < 10)
394+
formattedTime += '0';
395+
formattedTime += String(getMinutes());
396+
formattedTime += ":";
397+
398+
// Seconds
399+
if (getSeconds() < 10)
400+
formattedTime += '0';
401+
formattedTime += String(getSeconds());
402+
403+
return formattedTime;
404+
}
405+
406+
RTCTime::operator String() const{
407+
return toString();
408+
}
409+
364410
/* -------------------------------------------------------------------------- */
365411
/* RTClass */
366412
/* -------------------------------------------------------------------------- */

libraries/RTC/src/RTC.h

+24-12
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include <ctime>
55
#include "r_rtc_api.h"
6+
#include <api/String.h>
67

78
struct timeval {
89
time_t tv_sec;
@@ -94,22 +95,33 @@ class RTCTime {
9495
bool setDayOfWeek(DayOfWeek d);
9596
bool setSaveLight(SaveLight sl);
9697
bool setUnixTime(time_t time);
97-
9898
void setTM(struct tm &t);
99-
/* getters */
100-
int getDayOfMonth();
101-
Month getMonth();
102-
int getYear();
103-
int getHour();
104-
int getMinutes();
105-
int getSeconds();
106-
DayOfWeek getDayOfWeek();
107-
99+
100+
/* Getters */
101+
int getDayOfMonth() const;
102+
Month getMonth() const;
103+
int getYear() const;
104+
int getHour() const;
105+
int getMinutes() const;
106+
int getSeconds() const;
107+
DayOfWeek getDayOfWeek() const;
108108
time_t getUnixTime();
109109
struct tm getTmTime();
110-
};
111-
112110

111+
/**
112+
* @brief Returns the ISO 8601 string representation of the date and time.
113+
*
114+
* @return String The date and time in the format YYYY-MM-DDTHH:MM:SS.
115+
*/
116+
arduino::String toString() const;
117+
118+
/**
119+
* @brief Returns the ISO 8601 string representation of the date and time
120+
* by calling the toString() method.
121+
* @return String The date and time in the format YYYY-MM-DDTHH:MM:SS.
122+
*/
123+
operator arduino::String() const;
124+
};
113125

114126
enum class Period {
115127
ONCE_EVERY_2_SEC,

0 commit comments

Comments
 (0)