-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathClockSpin.ino
156 lines (130 loc) · 3.79 KB
/
ClockSpin.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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/*
* Clockulator
* Matthew (mnuck) Nuckolls <[email protected]>
*
* Setup:
* 1. Plug into USB for power.
* 2. Grab any device with wifi and a browser.
* 3. Connect to wifi access point named Clockulator.
* 4. Go to any website, get redirected.
* 5. Add your Wifi connection to this device.
*
* If you need to re-run the config workflow, unplug the device,
* then press the rotary knob while plugging it back in.
*
* Theory of Operation:
* This device connects to pool.ntp.org every 60 seconds
* to synchronize its internal clock. Local time is displayed
* on one 4-digit display. UTC time is displayed on the other.
* The rotary knob offsets both displays to show time in the
* past or future. Press the rotary knob button to return to
* present time. If the knob is not touched for 10 seconds,
* offset automatically returns to present time.
*
* But Why?
* This device answers four common questions.
* 1. What time is right now?
* 2. What time is it UTC right now?
* 3. When it is timeX here, what time is it UTC?
* 4. When it is timeX UTC, what time is it here?
*
* ESP-12E microcontroller board (ESP8266 module)
* Two TM1637 4-digit clock displays
* One rotary encoder with button
*
* Libraries Used:
* Wifi Manager
* NTPClient
* Time
* Timezone
* ESPRotary
* Button2
* Grove 4-Digit Display
*/
#include <Button2.h>
#include <ESP8266WiFi.h>
#include <ESPRotary.h>
#include <NTPClient.h>
#include <Timezone.h>
#include <TM1637.h>
#include <WiFiUdp.h>
#include <WiFiManager.h>
#define CLK1 5
#define DIO1 4
#define CLK2 0
#define DIO2 2
#define ROTARY_PIN_CLOCK 14
#define ROTARY_PIN_DT 12
#define ROTARY_BUTTON 13
#define ROTARY_STEPS_PER_CLICK 4
#define AP_NAME "Clockulator"
const TimeChangeRule PDT = {"PDT", Second, Sun, Mar, 2, -7 * 60};
const TimeChangeRule PST = {"PST", Second, Sun, Nov, 2, -8 * 60};
Timezone Pacific(PDT, PST);
const int brightness = 4; // 0 - 7
const int auto_reset_delay = 10; // seconds
const int rotary_increment = -600; // seconds
ESPRotary rotary(ROTARY_PIN_CLOCK, ROTARY_PIN_DT);
Button2 button;
TM1637 tm1637_local(CLK1, DIO1);
TM1637 tm1637_utc(CLK2, DIO2);
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org");
int dial_offset = 0;
unsigned long last_touch = 0;
void setup_display(TM1637* display) {
display->init();
display->set(brightness);
display->point(POINT_ON);
}
void update_display(TM1637* display, const time_t moment) {
const int h = hour(moment);
const int m = minute(moment);
display->display(0, h / 10);
display->display(1, h % 10);
display->display(2, m / 10);
display->display(3, m % 10);
}
void reset_offset(Button2& b) {
dial_offset = 0;
}
void auto_reset_offset() {
unsigned long now = timeClient.getEpochTime();
if (last_touch + auto_reset_delay < now) {
dial_offset = 0;
}
}
void decrement_offset(ESPRotary& r) {
dial_offset -= rotary_increment;
last_touch = timeClient.getEpochTime();
}
void increment_offset(ESPRotary& r) {
dial_offset += rotary_increment;
last_touch = timeClient.getEpochTime();
}
void setup(){
setup_display(&tm1637_local);
setup_display(&tm1637_utc);
rotary.setLeftRotationHandler(decrement_offset);
rotary.setRightRotationHandler(increment_offset);
WiFiManager wm;
pinMode(ROTARY_BUTTON, INPUT_PULLUP);
if (digitalRead(ROTARY_BUTTON) == LOW) {
wm.startConfigPortal(AP_NAME);
} else {
wm.autoConnect(AP_NAME);
}
button.begin(ROTARY_BUTTON);
button.setTapHandler(reset_offset);
timeClient.begin();
}
void loop() {
timeClient.update();
rotary.loop();
button.loop();
auto_reset_offset();
time_t utc = dial_offset + timeClient.getEpochTime();
time_t local = Pacific.toLocal(utc);
update_display(&tm1637_utc, utc);
update_display(&tm1637_local, local);
}