-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathGPS2RTC.ino
139 lines (118 loc) · 4.3 KB
/
GPS2RTC.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// Set RTC DS3231 with GPS date and time
#include <Wire.h>
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
#define DS3231_I2C_ADDRESS 0x68
#define LEAP_YEAR(Y) ((Y>0) && !(Y%4) && ( (Y%100) || !(Y%400) )) // from time-lib
static const int RXPin = 4, TXPin = 3;
static const uint32_t GPSBaud = 9600;
TinyGPSPlus gps;
SoftwareSerial ss(RXPin, TXPin);
byte second, minute, hour, dayOfWeek, day, month, year;
void setup () {
Serial.begin(9600);
// Read and display the current date & time of the RTC
readDS3231time(&second, &minute, &hour, &dayOfWeek, &day, &month, &year);
Serial.print("RTC Time: ");
Serial.print(day < 10 ? "0" : "");
Serial.print(day);
Serial.print("/");
Serial.print(month < 10 ? "0" : "");
Serial.print(month);
Serial.print("/");
Serial.print(2000 + year);
Serial.print(" ");
Serial.print(hour < 10 ? "0" : "");
Serial.print(hour);
Serial.print(":");
Serial.print(minute < 10 ? "0" : "");
Serial.print(minute);
Serial.print(":");
Serial.print(second < 10 ? "0" : "");
Serial.println(second);
ss.begin(GPSBaud);
}
void loop () {
while (ss.available() > 0)
if (gps.encode(ss.read()))
{
// When date & time of the GPS are valid set the RTC
if (gps.date.isValid() && gps.time.isValid())
{
// Calculate the day of the week
dayOfWeek = CalculateDayOfWeek(gps.date.year() + 2000, gps.date.month(), gps.date.day());
Serial.println(dayOfWeek);
// set the RTC date & time
setDS3231time(gps.time.second(), gps.time.minute(), gps.time.hour() + 2, dayOfWeek, gps.date.day(), gps.date.month(), gps.date.year() - 2000);
// Display the date & time of the RTC
Serial.print("GPS Time: ");
if (gps.date.day() < 10) Serial.print(F("0"));
Serial.print(gps.date.day());
Serial.print(F("/"));
if (gps.date.month() < 10) Serial.print(F("0"));
Serial.print(gps.date.month());
Serial.print(F("/"));
Serial.print(gps.date.year());
Serial.print(F(" "));
if (gps.time.hour() < 10) Serial.print(F("0"));
Serial.print(gps.time.hour());
Serial.print(F(":"));
if (gps.time.minute() < 10) Serial.print(F("0"));
Serial.print(gps.time.minute());
Serial.print(F(":"));
if (gps.time.second() < 10) Serial.print(F("0"));
Serial.println(gps.time.second());
// Done
while (true);
}
}
if (millis() > 5000 && gps.charsProcessed() < 10)
{
Serial.println(F("No GPS detected: check wiring."));
while (true);
}
}
byte decToBcd(byte val)
{
return ((val / 10 * 16) + (val % 10));
}
byte bcdToDec(byte val)
{
return ((val / 16 * 10) + (val % 16));
}
void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte dayOfMonth, byte month, byte year)
{
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0);
Wire.write(decToBcd(second));
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour));
Wire.write(decToBcd(dayOfWeek));
Wire.write(decToBcd(dayOfMonth));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.endTransmission();
}
void readDS3231time(byte *second, byte *minute, byte *hour, byte *dayOfWeek, byte *dayOfMonth, byte *month, byte *year)
{
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0);
Wire.endTransmission();
Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
*second = bcdToDec(Wire.read() & 0x7f);
*minute = bcdToDec(Wire.read());
*hour = bcdToDec(Wire.read() & 0x3f);
*dayOfWeek = bcdToDec(Wire.read());
*dayOfMonth = bcdToDec(Wire.read());
*month = bcdToDec(Wire.read());
*year = bcdToDec(Wire.read());
}
byte CalculateDayOfWeek(byte year, byte month, byte day)
{
int months[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; // days until 1st of month
uint32_t days = year * 365; // days until year
for (int i = 4; i < year; i += 4) if (LEAP_YEAR(i) ) days++; // adjust leap years, test only multiple of 4 of course
days += months[month - 1] + day; // add the days of this year
if ((month > 2) && LEAP_YEAR(year)) days++; // adjust 1 if this year is a leap year, but only after february
return days % 7; // remove all multiples of 7
}