Skip to content

Commit 1b08488

Browse files
committed
Add setClock and autoTimeZoneForBegin. Add Example13_SetClockWithNTP. Correct socketReadAvailableUDP.
1 parent 5996b74 commit 1b08488

File tree

5 files changed

+417
-5
lines changed

5 files changed

+417
-5
lines changed
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
/*
2+
3+
SARA-R5 Example
4+
===============
5+
6+
Set Clock With NTP
7+
8+
Written by: Paul Clark
9+
Date: January 9th 2022
10+
11+
This example demonstrates how to set the SARA-R5's internal Real Time Clock using NTP.
12+
When the SARA-R5 registers on a network, it will set its clock automatically if:
13+
Automatic time zone is enabled
14+
Your network supports NITZ (Network Identity and Time Zone)
15+
But for things like AssistNow Offline, it is convenient to have the SARA's RTC set to UTC.
16+
Then the clock can be used to select the AssistNow data for now/today without time zone headaches.
17+
This example shows how to:
18+
Disable the automatic time zone (using autoTimeZoneForBegin before .begin)
19+
Set the SARA's clock to UTC using NTP (see SARA-R5_NTP.ino)
20+
21+
The PDP profile is read from NVM. Please make sure you have run examples 4 & 7 previously to set up the profile.
22+
23+
Feel like supporting open source hardware?
24+
Buy a board from SparkFun!
25+
26+
Licence: MIT
27+
Please see LICENSE.md for full details
28+
29+
*/
30+
31+
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
32+
33+
#include <SparkFun_u-blox_SARA-R5_Arduino_Library.h> //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_SARA-R5_Arduino_Library
34+
35+
// Uncomment the next line to connect to the SARA-R5 using hardware Serial1
36+
#define saraSerial Serial1
37+
38+
// Uncomment the next line to create a SoftwareSerial object to pass to the SARA-R5 library instead
39+
//SoftwareSerial saraSerial(8, 9);
40+
41+
// Create a SARA_R5 object to use throughout the sketch
42+
// Usually we would tell the library which GPIO pin to use to control the SARA power (see below),
43+
// but we can start the SARA without a power pin. It just means we need to manually
44+
// turn the power on if required! ;-D
45+
SARA_R5 mySARA;
46+
47+
// Create a SARA_R5 object to use throughout the sketch
48+
// We need to tell the library what GPIO pin is connected to the SARA power pin.
49+
// If you're using the MicroMod Asset Tracker and the MicroMod Artemis Processor Board,
50+
// the pin name is G2 which is connected to pin AD34.
51+
// Change the pin number if required.
52+
//SARA_R5 mySARA(34);
53+
54+
// Create a SARA_R5 object to use throughout the sketch
55+
// If you are using the LTE GNSS Breakout, and have access to the SARA's RESET_N pin, you can pass that to the library too
56+
// allowing it to do an emergency shutdown if required.
57+
// Change the pin numbers if required.
58+
//SARA_R5 mySARA(34, 35); // PWR_ON, RESET_N
59+
60+
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
61+
62+
void setup()
63+
{
64+
String currentOperator = "";
65+
66+
Serial.begin(115200); // Start the serial console
67+
68+
// Wait for user to press key to begin
69+
Serial.println(F("SARA-R5 Example"));
70+
Serial.println(F("Wait for the SARA NI LED to light up - then press any key to begin"));
71+
72+
while (!Serial.available()) // Wait for the user to press a key (send any serial character)
73+
;
74+
while (Serial.available()) // Empty the serial RX buffer
75+
Serial.read();
76+
77+
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
78+
79+
//mySARA.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial
80+
81+
// For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low
82+
// Comment the next line if required
83+
mySARA.invertPowerPin(true);
84+
85+
// Disable the automatic time zone so we can use UTC. We need to do this _before_ .begin
86+
mySARA.autoTimeZoneForBegin(false);
87+
88+
// Initialize the SARA
89+
if (mySARA.begin(saraSerial, 115200) )
90+
{
91+
Serial.println(F("SARA-R5 connected!"));
92+
}
93+
else
94+
{
95+
Serial.println(F("Unable to communicate with the SARA."));
96+
Serial.println(F("Manually power-on (hold the SARA On button for 3 seconds) on and try again."));
97+
while (1) ; // Loop forever on fail
98+
}
99+
Serial.println();
100+
101+
// First check to see if we're connected to an operator:
102+
if (mySARA.getOperator(&currentOperator) == SARA_R5_SUCCESS)
103+
{
104+
Serial.print(F("Connected to: "));
105+
Serial.println(currentOperator);
106+
}
107+
else
108+
{
109+
Serial.print(F("The SARA is not yet connected to an operator. Please use the previous examples to connect. Or wait and retry. Freezing..."));
110+
while (1)
111+
; // Do nothing more
112+
}
113+
114+
// Deactivate the PSD profile - in case one is already active
115+
if (mySARA.performPDPaction(0, SARA_R5_PSD_ACTION_DEACTIVATE) != SARA_R5_SUCCESS)
116+
{
117+
Serial.println(F("Warning: performPDPaction (deactivate profile) failed. Probably because no profile was active."));
118+
}
119+
120+
// Load the PSD profile from NVM - these were saved by a previous example
121+
if (mySARA.performPDPaction(0, SARA_R5_PSD_ACTION_LOAD) != SARA_R5_SUCCESS)
122+
{
123+
Serial.println(F("performPDPaction (load from NVM) failed! Freezing..."));
124+
while (1)
125+
; // Do nothing more
126+
}
127+
128+
// Activate the profile
129+
if (mySARA.performPDPaction(0, SARA_R5_PSD_ACTION_ACTIVATE) != SARA_R5_SUCCESS)
130+
{
131+
Serial.println(F("performPDPaction (activate profile) failed! Freezing..."));
132+
while (1)
133+
; // Do nothing more
134+
}
135+
136+
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
137+
138+
//Get the time from an NTP server and use it to set the clock. See SARA-R5_NTP.ino
139+
uint8_t y, mo, d, h, min, s;
140+
bool success = getNTPTime(&y, &mo, &d, &h, &min, &s);
141+
if (!success)
142+
{
143+
Serial.println(F("getNTPTime failed! Freezing..."));
144+
while (1)
145+
; // Do nothing more
146+
}
147+
148+
//Set the SARA's RTC. Set the time zone to zero so the clock uses UTC
149+
if (mySARA.setClock(y, mo, d, h, min, s, 0) != SARA_R5_SUCCESS)
150+
{
151+
Serial.println(F("setClock failed! Freezing..."));
152+
while (1)
153+
; // Do nothing more
154+
}
155+
156+
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
157+
158+
// Read and print the clock as a String
159+
Serial.print(F("The UTC time is: "));
160+
String theTime = mySARA.clock();
161+
Serial.println(theTime);
162+
}
163+
164+
void loop()
165+
{
166+
// Nothing to do here
167+
}
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
2+
#include <time.h> // Note: this is the standard c time library, not Time.h
3+
4+
// Get the time from NTP
5+
// This code is based heavily on:
6+
// https://docs.arduino.cc/tutorials/mkr-nb-1500/mkr-nb-library-examples#mkr-nb-gprs-udp-ntp-client
7+
// Many thanks to: Michael Margolis, Tom Igoe, Arturo Guadalupi, et al
8+
9+
// NTP Server
10+
//const char* ntpServer = "africa.pool.ntp.org"; // The Network Time Protocol Server
11+
//const char* ntpServer = "asia.pool.ntp.org"; // The Network Time Protocol Server
12+
//const char* ntpServer = "europe.pool.ntp.org"; // The Network Time Protocol Server
13+
const char* ntpServer = "north-america.pool.ntp.org"; // The Network Time Protocol Server
14+
//const char* ntpServer = "oceania.pool.ntp.org"; // The Network Time Protocol Server
15+
//const char* ntpServer = "south-america.pool.ntp.org"; // The Network Time Protocol Server
16+
17+
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
18+
19+
bool getNTPTime(uint8_t *y, uint8_t *mo, uint8_t *d, uint8_t *h, uint8_t *min, uint8_t *s)
20+
{
21+
int serverPort = 123; //NTP requests are to port 123
22+
23+
// Set up the packetBuffer for the NTP request
24+
const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message
25+
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets
26+
27+
// set all bytes in the buffer to 0
28+
memset(packetBuffer, 0, NTP_PACKET_SIZE);
29+
30+
// Initialize values needed to form NTP request
31+
packetBuffer[0] = 0b11100011; // LI, Version, Mode
32+
packetBuffer[1] = 0; // Stratum, or type of clock
33+
packetBuffer[2] = 6; // Polling Interval
34+
packetBuffer[3] = 0xEC; // Peer Clock Precision
35+
// 8 bytes of zero for Root Delay & Root Dispersion
36+
packetBuffer[12] = 49;
37+
packetBuffer[13] = 0x4E;
38+
packetBuffer[14] = 49;
39+
packetBuffer[15] = 52;
40+
41+
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
42+
43+
//Open a socket to the NTP server
44+
45+
int socketNum = mySARA.socketOpen(SARA_R5_UDP);
46+
if (socketNum == -1)
47+
{
48+
Serial.println(F("getNTPTime: socketOpen failed!"));
49+
return (false);
50+
}
51+
52+
Serial.print(F("getNTPTime: using socket "));
53+
Serial.println(socketNum);
54+
55+
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
56+
57+
// Send the request - NTP uses UDP
58+
59+
if (mySARA.socketWriteUDP(socketNum, ntpServer, serverPort, (const char *)&packetBuffer, NTP_PACKET_SIZE) != SARA_R5_SUCCESS) // Send the request
60+
{
61+
Serial.println(F("getNTPTime: socketWrite failed!"));
62+
mySARA.socketClose(socketNum); // Be nice. Close the socket
63+
return (false);
64+
}
65+
66+
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
67+
68+
// Wait up to 10 seconds for the response
69+
unsigned long requestTime = millis();
70+
71+
while (millis() < (requestTime + 10000))
72+
{
73+
// We could use the Socket Read Callback to get the data, but, just for giggles,
74+
// and to prove it works, let's poll the arrival of the data manually...
75+
int avail = 0;
76+
if (mySARA.socketReadAvailableUDP(socketNum, &avail) != SARA_R5_SUCCESS)
77+
{
78+
Serial.println(F("getNTPTime: socketReadAvailable failed!"));
79+
mySARA.socketClose(socketNum); // Be nice. Close the socket
80+
return (false);
81+
}
82+
83+
if (avail >= NTP_PACKET_SIZE) // Is enough data available?
84+
{
85+
if (avail > NTP_PACKET_SIZE) // Too much data?
86+
{
87+
Serial.print(F("getNTPTime: too much data received! Length: "));
88+
Serial.print(avail);
89+
Serial.print(F(". Reading "));
90+
Serial.print(NTP_PACKET_SIZE);
91+
Serial.println(F(" bytes..."));
92+
}
93+
94+
if (mySARA.socketReadUDP(socketNum, NTP_PACKET_SIZE, (char *)&packetBuffer) != SARA_R5_SUCCESS)
95+
{
96+
Serial.println(F("getNTPTime: socketRead failed!"));
97+
mySARA.socketClose(socketNum); // Be nice. Close the socket
98+
return (false);
99+
}
100+
101+
// Extract the time from the reply
102+
103+
Serial.print(F("getNTPTime: received "));
104+
Serial.print(avail);
105+
Serial.println(F(" bytes. Extracting the time..."));
106+
107+
//the timestamp starts at byte 40 of the received packet and is four bytes,
108+
// or two words, long. First, esxtract the two words:
109+
unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
110+
unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
111+
112+
// combine the four bytes (two words) into a long integer
113+
// this is NTP time (seconds since Jan 1 1900):
114+
unsigned long secsSince1900 = highWord << 16 | lowWord;
115+
116+
Serial.print(F("getNTPTime: seconds since Jan 1 1900 = "));
117+
Serial.println(secsSince1900);
118+
119+
// now convert NTP time into everyday time:
120+
Serial.print(F("getNTPTime: Unix time = "));
121+
122+
// Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
123+
const unsigned long seventyYears = 2208988800UL;
124+
125+
// subtract seventy years:
126+
unsigned long epoch = secsSince1900 - seventyYears;
127+
128+
// print Unix time:
129+
Serial.println(epoch);
130+
131+
// Instead of calculating the year, month, day, etc. manually, let's use time_t and tm to do it for us!
132+
time_t dateTime = epoch;
133+
tm *theTime = gmtime(&dateTime);
134+
135+
// Load the time into y, mo, d, h, min, s
136+
*y = theTime->tm_year - 100; // tm_year is years since 1900. Convert to years since 2000.
137+
*mo = theTime->tm_mon + 1; //tm_mon starts at zero. Add 1 for January.
138+
*d = theTime->tm_mday;
139+
*h = theTime->tm_hour;
140+
*min = theTime->tm_min;
141+
*s = theTime->tm_sec;
142+
143+
// Finish off by printing the time
144+
Serial.print(F("getNTPTime: YY/MM/DD HH:MM:SS : "));
145+
if (*y < 10) Serial.print(F("0"));
146+
Serial.print(*y);
147+
Serial.print(F("/"));
148+
if (*mo < 10) Serial.print(F("0"));
149+
Serial.print(*mo);
150+
Serial.print(F("/"));
151+
if (*d < 10) Serial.print(F("0"));
152+
Serial.print(*d);
153+
Serial.print(F(" "));
154+
if (*h < 10) Serial.print(F("0"));
155+
Serial.print(*h);
156+
Serial.print(F(":"));
157+
if (*min < 10) Serial.print(F("0"));
158+
Serial.print(*min);
159+
Serial.print(F(":"));
160+
if (*s < 10) Serial.print(F("0"));
161+
Serial.println(*s);
162+
163+
mySARA.socketClose(socketNum); // Be nice. Close the socket
164+
return (true); // We are done!
165+
}
166+
167+
delay(100); // Wait before trying again
168+
}
169+
170+
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
171+
172+
Serial.println(F("getNTPTime: no NTP data received!"));
173+
mySARA.socketClose(socketNum); // Be nice. Close the socket
174+
return (false);
175+
}

keywords.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ getSubscriberNo KEYWORD2
7272
getCapabilities KEYWORD2
7373
reset KEYWORD2
7474
clock KEYWORD2
75+
setClock KEYWORD2
76+
autoTimeZoneForBegin KEYWORD2
7577
autoTimeZone KEYWORD2
7678
setUtimeMode KEYWORD2
7779
getUtimeMode KEYWORD2

0 commit comments

Comments
 (0)