Skip to content

Commit 8231f1f

Browse files
committed
main.cpp
1 parent 5db353e commit 8231f1f

File tree

1 file changed

+250
-0
lines changed

1 file changed

+250
-0
lines changed

src/main.cpp

Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
#include <Arduino.h>
2+
#include <WiFi.h>
3+
4+
// Mode configuration - uncomment to run in bare bone mode
5+
// will advance the tile every 2.5 sec.
6+
//#define BARE_BONE_MODE
7+
8+
// Log configuration - comment out to get rid of any serial out
9+
#define DEBUG_ENABLED
10+
#ifdef DEBUG_ENABLED
11+
#define DEBUG_PRINTLN(x) Serial.println(x)
12+
#define DEBUG_PRINT(x) Serial.print(x)
13+
#else
14+
#define DEBUG_PRINTLN(x)
15+
#define DEBUG_PRINT(x)
16+
#endif
17+
18+
// Board parameters
19+
static const int enable_pin = 21;
20+
static const int input1_pin = 23;
21+
static const int input2_pin = 22;
22+
23+
// WiFi parameters
24+
static const char *ssid = "WLAN SSID";
25+
static const char *password = "secret";
26+
27+
// NTP parameters
28+
static const char *ntp_pool = "de.pool.ntp.org";
29+
static const char *cet_tz = "CET-1CEST,M3.5.0/02,M10.5.0/03";
30+
31+
/** Global varibales */
32+
bool setup_completed = false;
33+
// used to alternate DC flow
34+
bool direction = false;
35+
// Keeps the number of flips to perform on the minute tile to adjust for DST changes.
36+
// Values can be positive, 0, or negativ.
37+
// It is assumed that the main loop is performed at a higher frequency than a minute (e.g. once every 500ms)
38+
// Positive values indicate the number of minutes to advance the clock.
39+
// A 0 indicates that the clock does not need to get changed.
40+
// Negative values indicate that the clock must be paused for -n minutes.
41+
// Positive values larger than one and negative values can be used to perform summer/winter time adjustment.
42+
int dst_adjustment = 0;
43+
// keeps the last time assumed to be displayed on clock
44+
struct tm clock_time;
45+
46+
/**
47+
* Setup NTP and set local time zone
48+
*/
49+
void initTime(String timezone)
50+
{
51+
struct tm timeinfo;
52+
53+
DEBUG_PRINTLN("Setting up time");
54+
// First connect to NTP server, with 0 TZ offset
55+
configTime(0, 0, ntp_pool);
56+
int ntp_retries = 3;
57+
while (ntp_retries > 0)
58+
{
59+
if (!getLocalTime(&timeinfo))
60+
{
61+
#ifdef DEBUG_ENABLED
62+
Serial.println(" Failed to obtain time");
63+
Serial.print(" Retry attempts left: ");
64+
Serial.println(ntp_retries);
65+
#endif
66+
ntp_retries -= 1;
67+
}
68+
else
69+
{
70+
#ifdef DEBUG_ENABLED
71+
Serial.println(" Got time from NTP");
72+
Serial.printf(" Setting Timezone to %s\n", timezone.c_str());
73+
#endif
74+
// Set the timezone
75+
setenv("TZ", timezone.c_str(), 1);
76+
tzset();
77+
break;
78+
}
79+
}
80+
}
81+
82+
// Function to alternate the direction of current to drive the clock motor
83+
void advanceMinuteTile()
84+
{
85+
direction = !direction;
86+
#ifdef DEBUG_ENABLED
87+
if (direction)
88+
{
89+
Serial.println("DC >>>");
90+
}
91+
else
92+
{
93+
Serial.println("DC <<<");
94+
}
95+
#endif
96+
digitalWrite(input1_pin, direction);
97+
digitalWrite(input2_pin, !direction);
98+
digitalWrite(enable_pin, HIGH); // Enable the motor
99+
}
100+
101+
/**
102+
* Setup Bodet Clock Driver
103+
*/
104+
// cppcheck-suppress unusedFunction
105+
void setup()
106+
{
107+
Serial.begin(115200);
108+
// Initializte the GPIO pins as output and set voltage
109+
pinMode(enable_pin, OUTPUT);
110+
pinMode(input1_pin, OUTPUT);
111+
pinMode(input2_pin, OUTPUT);
112+
//better without? advanceMinuteTile();
113+
// just plugin in clock a few seconds after the minute switched to what is shown on the clock.
114+
115+
#ifdef BARE_BONE_MODE
116+
return;
117+
#endif
118+
119+
// Connect to WiFi network
120+
WiFi.begin(ssid, password);
121+
DEBUG_PRINT("Connecting to WiFi.");
122+
while (WiFi.status() != WL_CONNECTED)
123+
{
124+
delay(200);
125+
DEBUG_PRINT(".");
126+
}
127+
DEBUG_PRINTLN("");
128+
DEBUG_PRINTLN("Connected to WiFi.");
129+
DEBUG_PRINT("IP Address: ");
130+
DEBUG_PRINTLN(WiFi.localIP());
131+
132+
// Configure NTP and clock time
133+
initTime(cet_tz);
134+
if (!getLocalTime(&clock_time))
135+
{
136+
DEBUG_PRINTLN("Failed to obtain clock time");
137+
return;
138+
}
139+
140+
#ifdef DEBUG_ENABLED
141+
Serial.print("Clock time is: ");
142+
Serial.println(&clock_time, "%A, %B %d %Y %H:%M zone %Z %z ");
143+
Serial.println("Setup completed.");
144+
#endif
145+
146+
setup_completed = true;
147+
}
148+
149+
/**
150+
* Loop for bare bone testing mode.
151+
*/
152+
void bare_bone_loop()
153+
{
154+
DEBUG_PRINT("Advance Tile in bare bone mode.");
155+
advanceMinuteTile();
156+
delay(500);
157+
}
158+
159+
/**
160+
* Main loop driving the minute tile flip. This loop should be run more often than once per minute.
161+
* Otherwise the calcuation of minutes to flip will not work.
162+
*/
163+
void main_loop()
164+
{
165+
// check if time advanced by a minute
166+
bool advanced_by_minute = false;
167+
struct tm system_time;
168+
if (!getLocalTime(&system_time))
169+
{
170+
DEBUG_PRINTLN("Failed to obtain new system time. Using last clock time.");
171+
system_time = clock_time;
172+
}
173+
if (system_time.tm_min != clock_time.tm_min)
174+
{
175+
advanced_by_minute = true;
176+
}
177+
178+
// check for DST change
179+
if (system_time.tm_isdst && !clock_time.tm_isdst)
180+
{
181+
// switch to summer time (DST / CEST)
182+
dst_adjustment += 60;
183+
}
184+
else if (!system_time.tm_isdst && clock_time.tm_isdst)
185+
{
186+
// switch to winter time (non-DST / CET)
187+
dst_adjustment -= 60;
188+
}
189+
190+
// advance the clock per minute or to catch up after switch to DST
191+
if (advanced_by_minute)
192+
{
193+
#ifdef DEBUG_ENABLED
194+
Serial.print("System time: ");
195+
Serial.println(&system_time, "%A, %B %d %Y %H:%M:%S zone %Z %z ");
196+
Serial.print("Clock time : ");
197+
Serial.println(&clock_time, "%A, %B %d %Y %H:%M:%S zone %Z %z ");
198+
Serial.print("Advance minute: ");
199+
Serial.print(advanced_by_minute);
200+
Serial.print("DST adjustments: ");
201+
Serial.println(dst_adjustment);
202+
#endif
203+
// set clock time to system time
204+
clock_time = system_time;
205+
206+
if (dst_adjustment < 0)
207+
{
208+
// clock time is ahead of system time (DST to normal), do not flip minute tile.
209+
dst_adjustment += 1;
210+
#ifdef DEBUG_ENABLED
211+
Serial.print(" > DST adjustment: *not* advancing minute, left: ");
212+
Serial.println(dst_adjustment);
213+
#endif
214+
}
215+
else
216+
{
217+
// clock time is in sync (normal) or behind system time, flip minute tile.
218+
advanceMinuteTile();
219+
// do not reduce dst_adjustment as this is a regular minute
220+
}
221+
}
222+
else if (dst_adjustment > 0)
223+
{
224+
// if clock time is running behind (DST change), catch up
225+
advanceMinuteTile();
226+
dst_adjustment -= 1;
227+
#ifdef DEBUG_ENABLED
228+
Serial.print(" > DST adjustment: advancing minute, delta left: ");
229+
Serial.println(dst_adjustment);
230+
#endif
231+
}
232+
233+
// 500ms delay is the result of tests with the clock.
234+
// This results in tiles quickly for testing or during DST switch.
235+
delay(500);
236+
}
237+
238+
// cppcheck-suppress unusedFunction
239+
void loop()
240+
{
241+
// To allow testing without WiFi and/or NTP
242+
if (!setup_completed)
243+
{
244+
bare_bone_loop();
245+
return;
246+
}
247+
else {
248+
main_loop();
249+
}
250+
}

0 commit comments

Comments
 (0)