Browse Source

first commit

pull/2/head
Vladimir Smagin 4 months ago
commit
66f632e0d5
9 changed files with 1709 additions and 0 deletions
  1. 1
    0
      .gitignore
  2. BIN
      IMG_20190204_025627_HDR-01.jpg
  3. 354
    0
      LM1640Display.cpp
  4. 379
    0
      LM1640Display.h
  5. 394
    0
      NTPClientLib.cpp
  6. 430
    0
      NtpClientLib.h
  7. 3
    0
      readme.md
  8. 145
    0
      tm1640-ntp.ino
  9. 3
    0
      wifi.h.sample

+ 1
- 0
.gitignore View File

@@ -0,0 +1 @@
1
+wifi.h

BIN
IMG_20190204_025627_HDR-01.jpg View File


+ 354
- 0
LM1640Display.cpp View File

@@ -0,0 +1,354 @@
1
+//  Inspired by LM1640Display,  Author: avishorp@gmail.com, https://github.com/avishorp/TM1637
2
+//
3
+//  This library is free software; you can redistribute it and/or
4
+//  modify it under the terms of the GNU Lesser General Public
5
+//  License as published by the Free Software Foundation; either
6
+//  version 2.1 of the License, or (at your option) any later version.
7
+//
8
+//  This library is distributed in the hope that it will be useful,
9
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11
+//  Lesser General Public License for more details.
12
+//
13
+//  You should have received a copy of the GNU Lesser General Public
14
+//  License along with this library; if not, write to the Free Software
15
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
16
+
17
+extern "C" {
18
+  #include <stdlib.h>
19
+  #include <string.h>
20
+  #include <inttypes.h>
21
+}
22
+
23
+#include "LM1640Display.h"
24
+#include <Arduino.h>
25
+
26
+#define TM1637_I2C_COMM1    0b01000000
27
+#define TM1637_I2C_COMM2    0b11000000
28
+#define TM1637_I2C_COMM3    0b10000000
29
+#define S7_DP   0x0080 
30
+
31
+//
32
+//      A
33
+//     ---
34
+//  F |   | B
35
+//     -G-
36
+//  E |   | C
37
+//     ---
38
+//      D
39
+
40
+const uint8_t digitToSegment[] = {
41
+ // XGFEDCBA
42
+  0b00111111,    // 0
43
+  0b00000110,    // 1
44
+  0b01011011,    // 2
45
+  0b01001111,    // 3
46
+  0b01100110,    // 4
47
+  0b01101101,    // 5
48
+  0b01111101,    // 6
49
+  0b00000111,    // 7
50
+  0b01111111,    // 8
51
+  0b01101111,    // 9
52
+  0b01110111,    // A
53
+  0b01111100,    // b
54
+  0b00111001,    // C
55
+  0b01011110,    // d
56
+  0b01111001,    // E
57
+  0b01110001     // F
58
+  };
59
+
60
+ const uint8_t clr[] = {
61
+ // XGFEDCBA
62
+  0b00000000,    // 0
63
+  0b00000000,    // 1
64
+  0b00000000,    // 2
65
+  0b00000000,    // 3
66
+  0b00000000,    // 4
67
+  0b00000000,    // 5
68
+  0b00000000,    // 6
69
+  0b00000000,    // 7
70
+  0b00000000,    // 8
71
+  0b00000000,    // 9
72
+  0b00000000,    // A
73
+  0b00000000,    // b
74
+  0b00000000,    // C
75
+  0b00000000,    // d
76
+  0b00000000,    // E
77
+  0b00000000     // F
78
+  };
79
+
80
+const short FONT_7S[]  = { 
81
+                             C7_SPC, //32 0x20, Space
82
+                             C7_EXC,
83
+                             C7_QTE,
84
+                             C7_HSH,
85
+                             C7_DLR,
86
+                             C7_PCT,
87
+                             C7_AMP,
88
+                             C7_ACC,
89
+                             C7_LBR,
90
+                             C7_RBR,                   
91
+                             C7_MLT,                            
92
+                             C7_PLS,
93
+                             C7_CMA,
94
+                             C7_MIN,
95
+                             C7_DPT,                             
96
+                             C7_RS,
97
+                             C7_0,   //48 0x30
98
+                             C7_1,
99
+                             C7_2,
100
+                             C7_3,
101
+                             C7_4,                   
102
+                             C7_5,
103
+                             C7_6,
104
+                             C7_7,
105
+                             C7_8,
106
+                             C7_9,
107
+                             C7_COL, //58 0x3A
108
+                             C7_SCL,
109
+                             C7_LT,
110
+                             C7_EQ,
111
+                             C7_GT,
112
+                             C7_QM,                             
113
+                             C7_AT,  //64 0x40
114
+                             C7_A,   //65 0x41, A
115
+                             C7_B,
116
+                             C7_C,
117
+                             C7_D,
118
+                             C7_E,
119
+                             C7_F,
120
+                             C7_G,
121
+                             C7_H,
122
+                             C7_I,
123
+                             C7_J,                   
124
+                             C7_K,
125
+                             C7_L,
126
+                             C7_M,
127
+                             C7_N,
128
+                             C7_O,
129
+                             C7_P,
130
+                             C7_Q,
131
+                             C7_R,
132
+                             C7_S,
133
+                             C7_T,
134
+                             C7_U,
135
+                             C7_V,
136
+                             C7_W,
137
+                             C7_X,
138
+                             C7_Y,
139
+                             C7_Z,   //90 0x5A, Z
140
+                             C7_SBL, //91 0x5B
141
+                             C7_LS,
142
+                             C7_SBR,
143
+                             C7_PWR,
144
+                             C7_UDS,  
145
+                             C7_ACC,                             
146
+                             C7_A,   //97 0x61, A replacing a
147
+                             C7_B,
148
+                             C7_C,
149
+                             C7_D,
150
+                             C7_E,
151
+                             C7_F,
152
+                             C7_G,
153
+                             C7_H,
154
+                             C7_I,
155
+                             C7_J,                   
156
+                             C7_K,
157
+                             C7_L,
158
+                             C7_M,
159
+                             C7_N,
160
+                             C7_O,
161
+                             C7_P,
162
+                             C7_Q,
163
+                             C7_R,
164
+                             C7_S,
165
+                             C7_T,
166
+                             C7_U,
167
+                             C7_V,
168
+                             C7_W,
169
+                             C7_X,
170
+                             C7_Y,
171
+                             C7_Z,   // 122 0x7A, Z replacing z
172
+                             C7_CBL, // 123 0x7B
173
+                             C7_OR,
174
+                             C7_CBR,
175
+                             C7_TLD,
176
+                             C7_DEL  // 127                             
177
+                        };
178
+ 
179
+
180
+
181
+LM1640Display::LM1640Display(uint8_t pinClk, uint8_t pinDIO)
182
+{
183
+  // Copy the pin numbers
184
+  m_pinClk = pinClk;
185
+  m_pinDIO = pinDIO;
186
+
187
+  // Set the pin direction and default value.
188
+  // Both pins are set as inputs, allowing the pull-up resistors to pull them up
189
+  pinMode(m_pinClk, INPUT);
190
+  pinMode(m_pinDIO,INPUT);
191
+  digitalWrite(m_pinClk, LOW);
192
+  digitalWrite(m_pinDIO, LOW);
193
+}
194
+
195
+
196
+
197
+void LM1640Display::setBrightness(uint8_t brightness, bool on)
198
+{
199
+  m_brightness = (brightness & 0x7) | (on? 0x08 : 0x00);
200
+}
201
+
202
+void LM1640Display::clear(uint8_t length)
203
+{
204
+  setSegments(clr, length, 0);
205
+}
206
+
207
+void LM1640Display::setSegments(const uint8_t segments[], uint8_t length, uint8_t pos)
208
+{
209
+    // Write COMM1
210
+  start();
211
+  writeByte(TM1637_I2C_COMM1);
212
+  stop();
213
+
214
+  // Write COMM2 + first digit address
215
+  start();
216
+  writeByte(TM1637_I2C_COMM2 + (pos & 0x03));
217
+
218
+  // Write the data bytes
219
+  for (uint8_t k=0; k < length; k++)
220
+    writeByte(segments[k]);
221
+
222
+  stop();
223
+
224
+  // Write COMM3 + brightness
225
+  start();
226
+  writeByte(TM1637_I2C_COMM3 + (m_brightness & 0x0f));
227
+  stop();
228
+}
229
+
230
+//void LM1640Display::showNumberDec(int num, bool leading_zero, uint8_t length, uint8_t pos)
231
+
232
+
233
+void LM1640Display::showString(char str[]){
234
+  // ensure str is 16 chars long
235
+  uint8_t digits[SIZE];
236
+  
237
+  int to = strlen(str);
238
+  for(int8_t k = 0; k < to; k++) {
239
+   digits[k] = encodeChar(str[k]);
240
+  }
241
+  if (to < 16){
242
+    for(int8_t k = to; k < 16; k++) {
243
+      digits[k] = 0;
244
+    }
245
+  }
246
+  setSegments(digits, 16, 0);
247
+}
248
+
249
+void LM1640Display::showNumberDec(int num, bool leading_zero, uint8_t length, uint8_t pos)
250
+{
251
+  uint8_t digits[length];
252
+  const static int divisors[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000};
253
+  bool leading = true;
254
+
255
+  for(int8_t k = 0; k < length; k++) {
256
+    if (leading_zero){
257
+      digits[k] = encodeDigit(0);
258
+    }
259
+    else{
260
+      digits[k] = 0;
261
+    }
262
+  }
263
+
264
+  for(int8_t k = 5; k < 16; k++) {
265
+    int divisor = divisors[16 - k - 1];
266
+    int d = num / divisor;
267
+    uint8_t digit = 0;
268
+
269
+    if (d == 0) {
270
+      if (leading_zero || !leading)
271
+          digit = encodeDigit(d);
272
+        else
273
+          digit = 0;
274
+    }
275
+    else {
276
+      digit = encodeDigit(d);
277
+      num -= d * divisor;
278
+      leading = false;
279
+    }
280
+    digits[k] = digit;
281
+  }
282
+  setSegments(digits, length, pos);
283
+}
284
+
285
+
286
+void LM1640Display::bitDelay()
287
+{
288
+  delayMicroseconds(100);
289
+}
290
+
291
+void LM1640Display::start()
292
+{
293
+  pinMode(m_pinDIO, OUTPUT);
294
+  bitDelay();
295
+}
296
+
297
+void LM1640Display::stop()
298
+{
299
+  pinMode(m_pinDIO, OUTPUT);  //LOW
300
+  bitDelay();
301
+  pinMode(m_pinClk, INPUT);  // HIGH
302
+  bitDelay();
303
+  pinMode(m_pinDIO, INPUT);   // HIGH
304
+  bitDelay();
305
+}
306
+
307
+bool LM1640Display::writeByte(uint8_t b)
308
+{
309
+  uint8_t data = b;
310
+
311
+  //Serial.print("DATA: ");
312
+  //Serial.println(data);
313
+
314
+  // 8 Data Bits
315
+  for(uint8_t i = 0; i < 8; i++) {
316
+    // CLK low
317
+    pinMode(m_pinClk, OUTPUT);
318
+    bitDelay();
319
+
320
+    uint8_t heisan = data & 0x01;
321
+   
322
+  // Set data bit
323
+    if (heisan)  // HIGH
324
+      pinMode(m_pinDIO, INPUT);
325
+    else  //LOW
326
+      pinMode(m_pinDIO, OUTPUT);
327
+
328
+    bitDelay();
329
+
330
+    // CLK high
331
+    pinMode(m_pinClk, INPUT);
332
+    bitDelay();
333
+    data = data >> 1;
334
+  }
335
+
336
+  // CLK to zero
337
+  pinMode(m_pinClk, OUTPUT);  // LOW
338
+  bitDelay();
339
+  return true;
340
+}
341
+
342
+uint8_t LM1640Display::encodeDigit(uint8_t digit)
343
+{
344
+  return digitToSegment[digit];
345
+}
346
+
347
+uint8_t LM1640Display::encodeChar(char ch)
348
+{
349
+  return FONT_7S[ch-32];
350
+}
351
+
352
+
353
+
354
+

+ 379
- 0
LM1640Display.h View File

@@ -0,0 +1,379 @@
1
+//  lib for JY-LM1640 - inspired by: https://github.com/avishorp/TM1637
2
+//
3
+//  This library is free software; you can redistribute it and/or
4
+//  modify it under the terms of the GNU Lesser General Public
5
+//  License as published by the Free Software Foundation; either
6
+//  version 2.1 of the License, or (at your option) any later version.
7
+//
8
+//  This library is distributed in the hope that it will be useful,
9
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11
+//  Lesser General Public License for more details.
12
+//
13
+//  You should have received a copy of the GNU Lesser General Public
14
+//  License along with this library; if not, write to the Free Software
15
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
16
+
17
+#ifndef __LM1640DISPLAY__
18
+#define __LM1640DISPLAY__
19
+
20
+#include <inttypes.h>
21
+
22
+//            A
23
+//          -----
24
+//         |     |     
25
+//       F |     | B    
26
+//         |  G  |     
27
+//          -----
28
+//         |     |     
29
+//       E |     | C    
30
+//         |     |     
31
+//          -----   * DP
32
+//            D  
33
+//
34
+#define S7_A    0x0001
35
+#define S7_B    0x0002
36
+#define S7_C    0x0004
37
+#define S7_D    0x0008
38
+#define S7_E    0x0010
39
+#define S7_F    0x0020
40
+#define S7_G    0x0040 
41
+#define S7_DP   0x0080 
42
+
43
+
44
+
45
+
46
+// Segment bit positions for 7 Segment display using the CATALEX and ROBOTDYN mapping for TM1637
47
+// Modify this table for different 'bit-to-segment' mappings. The ASCII character defines and the FONT_7S const table below 
48
+// will be adapted automatically according to the bit-to-segment mapping. Obviously this will only work when the segment
49
+// mapping is identical for every digit position. This will be the case unless the hardware designer really hates software developers.
50
+//
51
+//            A
52
+//          -----
53
+//         |     |     
54
+//       F |     | B    
55
+//         |  G  |     
56
+//          -----
57
+//         |     |     
58
+//       E |     | C    
59
+//         |     |     
60
+//          -----   * DP
61
+//            D  
62
+//
63
+#define S7_A    0x0001
64
+#define S7_B    0x0002
65
+#define S7_C    0x0004
66
+#define S7_D    0x0008
67
+#define S7_E    0x0010
68
+#define S7_F    0x0020
69
+#define S7_G    0x0040 
70
+#define S7_DP   0x0080 
71
+ 
72
+#define SIZE   16
73
+ 
74
+//Mask for blending out and setting 7 segments digits
75
+#define MASK_7S_ALL = (S7_A | S7_B | S7_C | S7_D | S7_E | S7_F | S7_G}
76
+ 
77
+//The CATALAX mapping between Digit positions or Columns (Left to Right) and Grids (ie memory address) are:
78
+//The column numbers are:
79
+//   0   1   2   3
80
+//The Grids are:
81
+//  GR1 GR2 GR3 GR4
82
+//The memory addresses are:
83
+//   0   1   2   3
84
+ 
85
+ 
86
+//The ROBOTDYN mapping between Digit positions or columns (Left to Right) and Grids (ie memory address) are:
87
+//The column numbers are:
88
+//   0   1   2   3   4   5
89
+//The Grids are:
90
+//  GR3 GR2 GR1 GR6 GR5 GR4
91
+//The memory addresses are:
92
+//   2   1   0   5   4   3
93
+ 
94
+ 
95
+//The EYEWINK mapping between Digit positions or columns (Left to Right) and Grids (ie memory address) are:
96
+//The column numbers are:
97
+//   0   1   2   3   4   5
98
+//The Grids are:
99
+//  GR1 GR2 GR3 GR4 GR5 GR6
100
+//The memory addresses are:
101
+//   0   1   2   3   4   5
102
+ 
103
+ 
104
+//Icons Grid 1
105
+#define S7_DP1  0x0080
106
+#define S7_ICON_GR1 (0x0000)
107
+//#define S7_ICON_GR1 (S7_DP1)
108
+ 
109
+//Icons Grid 2
110
+#define S7_DP2  0x0080
111
+#define S7_COL2 0x0080
112
+#define S7_ICON_GR2 (0x0000)
113
+//#define S7_ICON_GR2 (S7_DP2)
114
+ 
115
+//Icons Grid 3
116
+#define S7_DP3  0x0080
117
+#define S7_ICON_GR3 (0x0000)
118
+//#define S7_ICON_GR3 (S7_DP3)
119
+ 
120
+//Icons Grid 4
121
+#define S7_DP4  0x0080
122
+#define S7_ICON_GR4 (0x0000)
123
+//#define S7_ICON_GR4 (S7_DP4)
124
+ 
125
+//Icons Grid 5
126
+#define S7_DP5  0x0080
127
+#define S7_ICON_GR5 (0x0000)
128
+//#define S7_ICON_GR5 (S7_DP5)
129
+ 
130
+//Icons Grid 6
131
+#define S7_DP6  0x0080
132
+#define S7_ICON_GR6 (0x0000)
133
+//#define S7_ICON_GR6 (S7_DP6)
134
+ 
135
+ 
136
+//Mask for blending out and restoring Icons
137
+extern const char MASK_ICON_GRID[]; 
138
+ 
139
+ 
140
+// ASCII Font definitions for segments in each character
141
+//
142
+//32 0x20  Symbols
143
+#define C7_SPC  (0x0000)
144
+#define C7_EXC  (S7_B | S7_C) //!
145
+#define C7_QTE  (S7_B | S7_F) //"
146
+#define C7_HSH  (S7_C | S7_D | S7_E | S7_G) //#
147
+#define C7_DLR  (S7_A | S7_C | S7_D | S7_F | S7_G) //$
148
+#define C7_PCT  (S7_C | S7_F) //%
149
+#define C7_AMP  (S7_A | S7_C | S7_D | S7_E | S7_F | S7_G) //&
150
+#define C7_ACC  (S7_B) //'
151
+#define C7_LBR  (S7_A | S7_D | S7_E | S7_F) //(
152
+#define C7_RBR  (S7_A | S7_B | S7_C | S7_D) //)
153
+#define C7_MLT  (S7_B | S7_C | S7_E | S7_F | S7_G)  //*
154
+#define C7_PLS  (S7_B | S7_C | S7_G) //+
155
+#define C7_CMA  (S7_DP)
156
+#define C7_MIN  (S7_G)
157
+#define C7_DPT  (S7_DP)
158
+#define C7_RS   (S7_B | S7_E  | S7_G)  // /
159
+ 
160
+//48 0x30  Digits
161
+#define C7_0    (S7_A | S7_B | S7_C | S7_D | S7_E | S7_F)
162
+#define C7_1    (S7_B | S7_C)
163
+#define C7_2    (S7_A | S7_B | S7_D | S7_E | S7_G)
164
+#define C7_3    (S7_A | S7_B | S7_C | S7_D | S7_G)
165
+#define C7_4    (S7_B | S7_C | S7_F | S7_G)
166
+#define C7_5    (S7_A | S7_C | S7_D | S7_F | S7_G)
167
+#define C7_6    (S7_A | S7_C | S7_D | S7_E | S7_F | S7_G)
168
+#define C7_7    (S7_A | S7_B | S7_C)
169
+#define C7_8    (S7_A | S7_B | S7_C | S7_D | S7_E | S7_F | S7_G)
170
+#define C7_9    (S7_A | S7_B | S7_C | S7_D | S7_F | S7_G)
171
+ 
172
+//58 0x3A
173
+#define C7_COL  (S7_D | S7_G) // :
174
+#define C7_SCL  (S7_D | S7_G) // ;
175
+#define C7_LT   (S7_D | S7_E | S7_G)             // <
176
+#define C7_EQ   (S7_D | S7_G)                    // =
177
+#define C7_GT   (S7_C | S7_D | S7_G)             // >   
178
+#define C7_QM   (S7_A | S7_B | S7_E | S7_G)      // ?
179
+#define C7_AT   (S7_A | S7_B | S7_C | S7_D | S7_E  | S7_G)  // @
180
+ 
181
+//65 0x41  Upper case alphabet
182
+#define C7_A    (S7_A | S7_B | S7_C | S7_E | S7_F | S7_G )
183
+#define C7_B    (S7_C | S7_D | S7_E | S7_F | S7_G)
184
+#define C7_C    (S7_A | S7_D | S7_E | S7_F)
185
+#define C7_D    (S7_B | S7_C | S7_D | S7_E | S7_G)
186
+#define C7_E    (S7_A | S7_D | S7_E | S7_F | S7_G)
187
+#define C7_F    (S7_A | S7_E | S7_F | S7_G)
188
+ 
189
+#define C7_G    (S7_A | S7_C | S7_D | S7_E | S7_F)
190
+#define C7_H    (S7_B | S7_C | S7_E | S7_F | S7_G)
191
+#define C7_I    (S7_B | S7_C)
192
+#define C7_J    (S7_B | S7_C | S7_D | S7_E)
193
+#define C7_K    (S7_B | S7_C | S7_E | S7_F | S7_G)
194
+#define C7_L    (S7_D | S7_E | S7_F)
195
+#define C7_M    (S7_A | S7_C | S7_E)
196
+#define C7_N    (S7_A | S7_B | S7_C | S7_E | S7_F)
197
+#define C7_O    (S7_A | S7_B | S7_C | S7_D | S7_E | S7_F)
198
+#define C7_P    (S7_A | S7_B | S7_E | S7_F | S7_G)
199
+#define C7_Q    (S7_A | S7_B | S7_C | S7_F | S7_G)
200
+#define C7_R    (S7_E | S7_G )
201
+#define C7_S    (S7_A | S7_C | S7_D | S7_F | S7_G)
202
+#define C7_T    (S7_D | S7_E | S7_F | S7_G)
203
+#define C7_U    (S7_B | S7_C | S7_D | S7_E | S7_F)
204
+#define C7_V    (S7_B | S7_C | S7_D | S7_E | S7_F)
205
+#define C7_W    (S7_B | S7_D | S7_F)
206
+#define C7_X    (S7_B | S7_C | S7_E | S7_F | S7_G)
207
+#define C7_Y    (S7_B | S7_C | S7_D | S7_F | S7_G)
208
+#define C7_Z    (S7_A | S7_B | S7_D | S7_E | S7_G)
209
+ 
210
+//91 0x5B
211
+#define C7_SBL  (S7_A | S7_D | S7_E | S7_F) // [
212
+#define C7_LS   (S7_C | S7_F | S7_G)        // left slash
213
+#define C7_SBR  (S7_A | S7_B | S7_C | S7_D) // ]
214
+#define C7_PWR  (S7_A | S7_B | S7_F)        // ^
215
+#define C7_UDS  (S7_D)                      // _
216
+#define C7_DSH  (S7_F)                      // `  
217
+ 
218
+//97 0x61  Lower case alphabet
219
+#define C7_a     C7_A
220
+#define C7_b     C7_B
221
+#define C7_c     C7_C
222
+#define C7_d     C7_D
223
+#define C7_e     C7_E
224
+#define C7_f     C7_H
225
+ 
226
+#define C7_g     C7_G
227
+#define C7_h     C7_H
228
+#define C7_i     C7_I
229
+#define C7_j     C7_J
230
+#define C7_k     C7_K
231
+#define C7_l     C7_L
232
+#define C7_m     C7_M
233
+//#define C7_n     C7_N
234
+#define C7_n    (S7_C | S7_E | S7_G)
235
+//#define C7_o     C7_O
236
+#define C7_o    (S7_C | S7_D | S7_E | S7_G)
237
+#define C7_p     C7_P
238
+#define C7_q     C7_Q
239
+//#define C7_r     C7_R
240
+#define C7_r    (S7_E | S7_G)
241
+#define C7_s     C7_S
242
+#define C7_t     C7_T
243
+#define C7_u     C7_U
244
+#define C7_v     C7_V
245
+#define C7_w     C7_W
246
+#define C7_x     C7_X
247
+#define C7_y     C7_Y
248
+#define C7_z     C7_Z
249
+ 
250
+//123 0x7B
251
+#define C7_CBL  (S7_A | S7_D | S7_E | S7_F)        // {
252
+#define C7_OR   (S7_B | S7_C)                      // |
253
+#define C7_CBR  (S7_A | S7_B | S7_C | S7_D)        // }
254
+#define C7_TLD  (S7_B | S7_E | S7_G )              // ~
255
+#define C7_DEL  (0x0000)
256
+ 
257
+ 
258
+//User Defined Characters (some examples)
259
+#define C7_DGR   (S7_A | S7_B | S7_F | S7_G)  //Degrees
260
+                                                                         
261
+// Font data selection for transmission to TM1637 memory
262
+#define LO(x)  ( x & 0xFF)
263
+#define HI(x)  ((x >> 8) & 0xFF)
264
+ 
265
+ 
266
+// ASCII Font definition table
267
+//
268
+#define FONT_7S_START     0x20
269
+#define FONT_7S_END       0x7F
270
+//#define FONT_7S_NR_CHARS (FONT_7S_END - FONT_7S_START + 1)
271
+
272
+
273
+
274
+
275
+class LM1640Display {
276
+
277
+public:
278
+  //! Initialize a LM1640Display object, setting the clock and
279
+  //! data pins.
280
+  //!
281
+  //! @param pinClk - The number of the digital pin connected to the clock pin of the module
282
+  //! @param pinDIO - The number of the digital pin connected to the DIO pin of the module
283
+  LM1640Display(uint8_t pinClk, uint8_t pinDIO);
284
+
285
+  //! Sets the brightness of the display.
286
+  //!
287
+  //! The setting takes effect when a command is given to change the data being
288
+  //! displayed.
289
+  //!
290
+  //! @param brightness A number from 0 (lowes brightness) to 7 (highest brightness)
291
+  //! @param on Turn display on or off
292
+  void setBrightness(uint8_t brightness, bool on = true);
293
+
294
+  //! Display arbitrary data on the module
295
+  //!
296
+  //! This function receives raw segment values as input and displays them. The segment data
297
+  //! is given as a byte array, each byte corresponding to a single digit. Within each byte,
298
+  //! bit 0 is segment A, bit 1 is segment B etc.
299
+  //! The function may either set the entire display or any desirable part on its own. The first
300
+  //! digit is given by the @ref pos argument with 0 being the leftmost digit. The @ref length
301
+  //! argument is the number of digits to be set. Other digits are not affected.
302
+  //!
303
+  //! @param segments An array of size @ref length containing the raw segment values
304
+  //! @param length The number of digits to be modified
305
+  //! @param pos The position from which to start the modification (0 - leftmost, 3 - rightmost)
306
+  void setSegments(const uint8_t segments[], uint8_t length = 16, uint8_t pos = 0);
307
+
308
+  //! Displayes a decimal number
309
+  //!
310
+  //! Dispalyes the given argument as a decimal number
311
+  //!
312
+  //! @param num The number to be shown
313
+  //! @param leading_zero When true, leading zeros are displayed. Otherwise unnecessary digits are
314
+  //!        blank
315
+  //! @param length The number of digits to set. The user must ensure that the number to be shown
316
+  //!        fits to the number of digits requested (for example, if two digits are to be displayed,
317
+  //!        the number must be between 0 to 99)
318
+  //! @param pos The position most significant digit (0 - leftmost, 3 - rightmost)
319
+  void showNumberDec(int num, bool leading_zero = false, uint8_t length = 16, uint8_t pos = 0);
320
+
321
+  //! Displayes a decimal number, with dot control
322
+  //!
323
+  //! Dispalyes the given argument as a decimal number. The dots between the digits (or colon)
324
+  //! can be individually controlled
325
+  //!
326
+  //! @param num The number to be shown
327
+  //! @param dots Dot/Colon enable. The argument is a bitmask, with each bit corresponding to a dot
328
+  //!        between the digits (or colon mark, as implemented by each module). i.e.
329
+  //!        For displays with dots between each digit:
330
+  //!        * 0.000 (0b10000000)
331
+  //!        * 00.00 (0b01000000)
332
+  //!        * 000.0 (0b00100000)
333
+  //!        * 0.0.0.0 (0b11100000)
334
+  //!        For displays with just a colon:
335
+  //!        * 00:00 (0b01000000)
336
+  //!        For displays with dots and colons colon:
337
+  //!        * 0.0:0.0 (0b11100000)
338
+  //! @param leading_zero When true, leading zeros are displayed. Otherwise unnecessary digits are
339
+  //!        blank
340
+  //! @param length The number of digits to set. The user must ensure that the number to be shown
341
+  //!        fits to the number of digits requested (for example, if two digits are to be displayed,
342
+  //!        the number must be between 0 to 99)
343
+  //! @param pos The position least significant digit (0 - leftmost, 3 - rightmost)
344
+  void showNumberDecEx(int num, uint8_t dots = 0, bool leading_zero = false, uint8_t length = 16, uint8_t pos = 0);
345
+
346
+
347
+  void clear(uint8_t length = 16);
348
+
349
+  //! Translate a single digit into 7 segment code
350
+  //!
351
+  //! The method accepts a number between 0 - 15 and converts it to the
352
+  //! code required to display the number on a 7 segment display.
353
+  //! Numbers between 10-15 are converted to hexadecimal digits (A-F)
354
+  //!
355
+  //! @param digit A number between 0 to 15
356
+  //! @return A code representing the 7 segment image of the digit (LSB - segment A;
357
+  //!         bit 6 - segment G; bit 7 - always zero)
358
+  uint8_t encodeDigit(uint8_t digit);
359
+
360
+  uint8_t encodeChar(char ch);
361
+    
362
+  void showString(char str[]);
363
+    
364
+protected:
365
+   void bitDelay();
366
+
367
+   void start();
368
+
369
+   void stop();
370
+
371
+   bool writeByte(uint8_t b);
372
+
373
+private:
374
+  uint8_t m_pinClk;
375
+  uint8_t m_pinDIO;
376
+  uint8_t m_brightness;
377
+};
378
+
379
+#endif // __LM1640Display__

+ 394
- 0
NTPClientLib.cpp View File

@@ -0,0 +1,394 @@
1
+/*
2
+Copyright 2016 German Martin (gmag11@gmail.com). All rights reserved.
3
+
4
+Redistribution and use in source and binary forms, with or without modification, are
5
+permitted provided that the following conditions are met :
6
+
7
+1. Redistributions of source code must retain the above copyright notice, this list of
8
+conditions and the following disclaimer.
9
+
10
+2. Redistributions in binary form must reproduce the above copyright notice, this list
11
+of conditions and the following disclaimer in the documentation and / or other materials
12
+provided with the distribution.
13
+
14
+THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY EXPRESS OR IMPLIED
15
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
17
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18
+CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING
21
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
+
24
+The views and conclusions contained in the software and documentation are those of the
25
+authors and should not be interpreted as representing official policies, either expressed
26
+or implied, of German Martin
27
+*/
28
+// 
29
+// 
30
+// 
31
+
32
+#include "NtpClientLib.h"
33
+
34
+#define DBG_PORT Serial
35
+
36
+#ifdef DEBUG_NTPCLIENT
37
+#define DEBUGLOG(...) DBG_PORT.printf(__VA_ARGS__)
38
+#else
39
+#define DEBUGLOG(...)
40
+#endif
41
+
42
+
43
+NTPClient::NTPClient () {
44
+}
45
+
46
+bool NTPClient::setNtpServerName (String ntpServerName) {
47
+    char * name = (char *)malloc ((ntpServerName.length () + 1) * sizeof (char));
48
+    if (!name)
49
+        return false;
50
+    ntpServerName.toCharArray (name, ntpServerName.length () + 1);
51
+    DEBUGLOG ("NTP server set to %s\n", name);
52
+    free (_ntpServerName);
53
+    _ntpServerName = name;
54
+    return true;
55
+}
56
+
57
+bool NTPClient::setNtpServerName (char* ntpServerName) {
58
+    char *name = ntpServerName;
59
+    if (name == NULL)
60
+        return false;
61
+    DEBUGLOG ("NTP server set to %s\n", name);
62
+    free (_ntpServerName);
63
+    _ntpServerName = name;
64
+    return true;
65
+}
66
+
67
+String NTPClient::getNtpServerName () {
68
+    return String (_ntpServerName);
69
+}
70
+
71
+char* NTPClient::getNtpServerNamePtr () {
72
+    return _ntpServerName;
73
+}
74
+
75
+bool NTPClient::setTimeZone (int8_t timeZone, int8_t minutes) {
76
+    if ((timeZone >= -12) && (timeZone <= 14) && (minutes >= -59) && (minutes <= 59)) {
77
+        // Temporarily set time to new time zone, before trying to synchronize
78
+        int8_t timeDiff = timeZone - _timeZone;
79
+        _timeZone = timeZone;
80
+        _minutesOffset = minutes;
81
+        setTime (now () + timeDiff * SECS_PER_HOUR + minutes * SECS_PER_MIN);
82
+        if (udp && (timeStatus () != timeNotSet)) {
83
+            setTime (getTime ());
84
+        }
85
+        DEBUGLOG ("NTP time zone set to: %d\r\n", timeZone);
86
+        return true;
87
+    }
88
+    return false;
89
+}
90
+
91
+boolean sendNTPpacket (const char* address, UDP *udp) {
92
+    uint8_t ntpPacketBuffer[NTP_PACKET_SIZE]; //Buffer to store request message
93
+
94
+                                           // set all bytes in the buffer to 0
95
+    memset (ntpPacketBuffer, 0, NTP_PACKET_SIZE);
96
+    // Initialize values needed to form NTP request
97
+    // (see URL above for details on the packets)
98
+    ntpPacketBuffer[0] = 0b11100011;   // LI, Version, Mode
99
+    ntpPacketBuffer[1] = 0;     // Stratum, or type of clock
100
+    ntpPacketBuffer[2] = 6;     // Polling Interval
101
+    ntpPacketBuffer[3] = 0xEC;  // Peer Clock Precision
102
+                                // 8 bytes of zero for Root Delay & Root Dispersion
103
+    ntpPacketBuffer[12] = 49;
104
+    ntpPacketBuffer[13] = 0x4E;
105
+    ntpPacketBuffer[14] = 49;
106
+    ntpPacketBuffer[15] = 52;
107
+    // all NTP fields have been given values, now
108
+    // you can send a packet requesting a timestamp:
109
+    udp->beginPacket (address, DEFAULT_NTP_PORT); //NTP requests are to port 123
110
+    udp->write (ntpPacketBuffer, NTP_PACKET_SIZE);
111
+    udp->endPacket ();
112
+    return true;
113
+}
114
+
115
+time_t NTPClient::getTime () {
116
+    //DNSClient dns;
117
+    //WiFiUDP *udpClient = new WiFiUDP(*udp);
118
+    IPAddress timeServerIP; //NTP server IP address
119
+    char ntpPacketBuffer[NTP_PACKET_SIZE]; //Buffer to store response message
120
+
121
+
122
+    DEBUGLOG ("Starting UDP\n");
123
+    udp->begin (DEFAULT_NTP_PORT);
124
+    //DEBUGLOG ("UDP port: %d\n",udp->localPort());
125
+    while (udp->parsePacket () > 0); // discard any previously received packets
126
+                                    /*dns.begin(WiFi.dnsServerIP());
127
+                                    uint8_t dnsResult = dns.getHostByName(NTP.getNtpServerName().c_str(), timeServerIP);
128
+                                    DEBUGLOG(F("NTP Server hostname: "));
129
+                                    DEBUGLOGCR(NTP.getNtpServerName());
130
+                                    DEBUGLOG(F("NTP Server IP address: "));
131
+                                    DEBUGLOGCR(timeServerIP);
132
+                                    DEBUGLOG(F("Result code: "));
133
+                                    DEBUGLOG(dnsResult);
134
+                                    DEBUGLOG(" ");
135
+                                    DEBUGLOGCR(F("-- IP Connected. Waiting for sync"));
136
+                                    DEBUGLOGCR(F("-- Transmit NTP Request"));*/
137
+
138
+                                    //if (dnsResult == 1) { //If DNS lookup resulted ok
139
+    sendNTPpacket (getNtpServerName ().c_str (), udp);
140
+    uint32_t beginWait = millis ();
141
+    while (millis () - beginWait < NTP_TIMEOUT) {
142
+        int size = udp->parsePacket ();
143
+        if (size >= NTP_PACKET_SIZE) {
144
+            DEBUGLOG ("-- Receive NTP Response\n");
145
+            udp->read (ntpPacketBuffer, NTP_PACKET_SIZE);  // read packet into the buffer
146
+            time_t timeValue = decodeNtpMessage (ntpPacketBuffer);
147
+            setSyncInterval (getLongInterval ());
148
+            if (!_firstSync) {
149
+                //    if (timeStatus () == timeSet)
150
+                _firstSync = timeValue;
151
+            }
152
+            //getFirstSync (); // Set firstSync value if not set before
153
+            DEBUGLOG ("Sync frequency set low\n");
154
+            udp->stop ();
155
+            setLastNTPSync (timeValue);
156
+            DEBUGLOG ("Successful NTP sync at %s", getTimeDateString (getLastNTPSync ()).c_str ());
157
+
158
+            if (onSyncEvent)
159
+                onSyncEvent (timeSyncd);
160
+            return timeValue;
161
+        }
162
+#ifdef ARDUINO_ARCH_ESP8266
163
+        ESP.wdtFeed ();
164
+#endif
165
+    }
166
+    DEBUGLOG ("-- No NTP Response :-(\n");
167
+    udp->stop ();
168
+    setSyncInterval (getShortInterval ()); // Retry connection more often
169
+    if (onSyncEvent)
170
+        onSyncEvent (noResponse);
171
+    return 0; // return 0 if unable to get the time
172
+}
173
+
174
+int8_t NTPClient::getTimeZone () {
175
+    return _timeZone;
176
+}
177
+
178
+int8_t NTPClient::getTimeZoneMinutes () {
179
+    return _minutesOffset;
180
+}
181
+
182
+/*void NTPClient::setLastNTPSync(time_t moment) {
183
+    _lastSyncd = moment;
184
+}*/
185
+
186
+time_t NTPClient::s_getTime () {
187
+    return NTP.getTime ();
188
+}
189
+
190
+#if NETWORK_TYPE == NETWORK_W5100
191
+bool NTPClient::begin (String ntpServerName, int8_t timeZone, bool daylight, int8_t minutes, EthernetUDP* udp_conn) {
192
+#elif NETWORK_TYPE == NETWORK_ESP8266 || NETWORK_TYPE == NETWORK_WIFI101 || NETWORK_TYPE == NETWORK_ESP32
193
+bool NTPClient::begin (String ntpServerName, int8_t timeZone, bool daylight, int8_t minutes, WiFiUDP* udp_conn) {
194
+#endif
195
+    if (!setNtpServerName (ntpServerName)) {
196
+        DEBUGLOG ("Time sync not started\r\n");
197
+        return false;
198
+    }
199
+    if (!setTimeZone (timeZone, minutes)) {
200
+        DEBUGLOG ("Time sync not started\r\n");
201
+        return false;
202
+    }
203
+    if (udp_conn)
204
+        udp = udp_conn;
205
+    else
206
+#if NETWORK_TYPE == NETWORK_W5100
207
+        udp = new EthernetUDP ();
208
+#else
209
+        udp = new WiFiUDP ();
210
+#endif
211
+
212
+    //_timeZone = timeZone;
213
+    setDayLight (daylight);
214
+    _lastSyncd = 0;
215
+
216
+    if (!setInterval (DEFAULT_NTP_SHORTINTERVAL, DEFAULT_NTP_INTERVAL)) {
217
+        DEBUGLOG ("Time sync not started\r\n");
218
+        return false;
219
+    }
220
+    DEBUGLOG ("Time sync started\r\n");
221
+
222
+    setSyncInterval (getShortInterval ());
223
+    setSyncProvider (s_getTime);
224
+
225
+    return true;
226
+}
227
+
228
+bool NTPClient::stop () {
229
+    setSyncProvider (NULL);
230
+    DEBUGLOG ("Time sync disabled\n");
231
+
232
+    return true;
233
+}
234
+
235
+bool NTPClient::setInterval (int interval) {
236
+    if (interval >= 10) {
237
+        if (_longInterval != interval) {
238
+            _longInterval = interval;
239
+            DEBUGLOG ("Sync interval set to %d\n", interval);
240
+            if (timeStatus () == timeSet)
241
+                setSyncInterval (interval);
242
+        }
243
+        return true;
244
+    } else
245
+        return false;
246
+}
247
+
248
+bool NTPClient::setInterval (int shortInterval, int longInterval) {
249
+    if (shortInterval >= 10 && longInterval >= 10) {
250
+        _shortInterval = shortInterval;
251
+        _longInterval = longInterval;
252
+        if (timeStatus () != timeSet) {
253
+            setSyncInterval (shortInterval);
254
+        } else {
255
+            setSyncInterval (longInterval);
256
+        }
257
+        DEBUGLOG ("Short sync interval set to %d\n", shortInterval);
258
+        DEBUGLOG ("Long sync interval set to %d\n", longInterval);
259
+        return true;
260
+    } else
261
+        return false;
262
+}
263
+
264
+int NTPClient::getInterval () {
265
+    return _longInterval;
266
+}
267
+
268
+int NTPClient::getShortInterval () {
269
+    return _shortInterval;
270
+}
271
+
272
+void NTPClient::setDayLight (bool daylight) {
273
+    _daylight = daylight;
274
+    DEBUGLOG ("--Set daylight saving %s\n", daylight ? "ON" : "OFF");
275
+    setTime (getTime ());
276
+}
277
+
278
+bool NTPClient::getDayLight () {
279
+    return _daylight;
280
+}
281
+
282
+String NTPClient::getTimeStr (time_t moment) {
283
+    char timeStr[10];
284
+    sprintf (timeStr, "%02d:%02d:%02d", hour (moment), minute (moment), second (moment));
285
+
286
+    return timeStr;
287
+}
288
+
289
+String NTPClient::getDateStr (time_t moment) {
290
+    char dateStr[12];
291
+    sprintf (dateStr, "/ %02d-%02d", day (moment), month (moment), year (moment));
292
+
293
+    return dateStr;
294
+}
295
+
296
+String NTPClient::getTimeDateString (time_t moment) {
297
+    return getTimeStr (moment) + " " + getDateStr (moment);
298
+}
299
+
300
+time_t NTPClient::getLastNTPSync () {
301
+    return _lastSyncd;
302
+}
303
+
304
+void NTPClient::onNTPSyncEvent (onSyncEvent_t handler) {
305
+    onSyncEvent = handler;
306
+}
307
+
308
+time_t NTPClient::getUptime () {
309
+    _uptime = _uptime + (millis () - _uptime);
310
+    return _uptime / 1000;
311
+}
312
+
313
+String NTPClient::getUptimeString () {
314
+    uint16_t days;
315
+    uint8_t hours;
316
+    uint8_t minutes;
317
+    uint8_t seconds;
318
+
319
+    time_t uptime = getUptime ();
320
+
321
+    seconds = uptime % SECS_PER_MIN;
322
+    uptime -= seconds;
323
+    minutes = (uptime % SECS_PER_HOUR) / SECS_PER_MIN;
324
+    uptime -= minutes * SECS_PER_MIN;
325
+    hours = (uptime % SECS_PER_DAY) / SECS_PER_HOUR;
326
+    uptime -= hours * SECS_PER_HOUR;
327
+    days = uptime / SECS_PER_DAY;
328
+
329
+    char uptimeStr[20];
330
+    sprintf (uptimeStr, "%4u days %02d:%02d:%02d", days, hours, minutes, seconds);
331
+
332
+    return uptimeStr;
333
+}
334
+
335
+time_t NTPClient::getLastBootTime () {
336
+    if (timeStatus () == timeSet) {
337
+        return (now () - getUptime ());
338
+    }
339
+    return 0;
340
+}
341
+
342
+time_t NTPClient::getFirstSync () {
343
+    /*if (!_firstSync) {
344
+        if (timeStatus () == timeSet) {
345
+            _firstSync = now () - getUptime ();
346
+        }
347
+    }*/
348
+    return _firstSync;
349
+}
350
+
351
+bool NTPClient::summertime (int year, byte month, byte day, byte hour, byte tzHours)
352
+// input parameters: "normal time" for year, month, day, hour and tzHours (0=UTC, 1=MEZ)
353
+{
354
+    if ((month < 3) || (month > 10)) return false; // keine Sommerzeit in Jan, Feb, Nov, Dez
355
+    if ((month > 3) && (month < 10)) return true; // Sommerzeit in Apr, Mai, Jun, Jul, Aug, Sep
356
+    if ((month == 3 && (hour + 24 * day) >= (1 + tzHours + 24 * (31 - (5 * year / 4 + 4) % 7))) || (month == 10 && (hour + 24 * day) < (1 + tzHours + 24 * (31 - (5 * year / 4 + 1) % 7))))
357
+        return true;
358
+    else
359
+        return false;
360
+}
361
+
362
+boolean NTPClient::isSummerTimePeriod (time_t moment) {
363
+    return summertime (year (), month (), day (), hour (), getTimeZone ());
364
+}
365
+
366
+void NTPClient::setLastNTPSync (time_t moment) {
367
+    _lastSyncd = moment;
368
+}
369
+
370
+time_t NTPClient::decodeNtpMessage (char *messageBuffer) {
371
+    unsigned long secsSince1900;
372
+    // convert four bytes starting at location 40 to a long integer
373
+    secsSince1900 = (unsigned long)messageBuffer[40] << 24;
374
+    secsSince1900 |= (unsigned long)messageBuffer[41] << 16;
375
+    secsSince1900 |= (unsigned long)messageBuffer[42] << 8;
376
+    secsSince1900 |= (unsigned long)messageBuffer[43];
377
+
378
+#define SEVENTY_YEARS 2208988800UL
379
+    time_t timeTemp = secsSince1900 - SEVENTY_YEARS + _timeZone * SECS_PER_HOUR + _minutesOffset * SECS_PER_MIN;
380
+
381
+    if (_daylight) {
382
+        if (summertime (year (timeTemp), month (timeTemp), day (timeTemp), hour (timeTemp), _timeZone)) {
383
+            timeTemp += SECS_PER_HOUR;
384
+            DEBUGLOG ("Summer Time\n");
385
+        } else {
386
+            DEBUGLOG ("Winter Time\n");
387
+        }
388
+    } else {
389
+        DEBUGLOG ("No daylight\n");
390
+    }
391
+    return timeTemp;
392
+}
393
+
394
+NTPClient NTP;

+ 430
- 0
NtpClientLib.h View File

@@ -0,0 +1,430 @@
1
+/*
2
+Copyright 2016 German Martin (gmag11@gmail.com). All rights reserved.
3
+
4
+Redistribution and use in source and binary forms, with or without modification, are
5
+permitted provided that the following conditions are met :
6
+
7
+1. Redistributions of source code must retain the above copyright notice, this list of
8
+conditions and the following disclaimer.
9
+
10
+2. Redistributions in binary form must reproduce the above copyright notice, this list
11
+of conditions and the following disclaimer in the documentation and / or other materials
12
+provided with the distribution.
13
+
14
+THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY EXPRESS OR IMPLIED
15
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
17
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18
+CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING
21
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
+
24
+The views and conclusions contained in the software and documentation are those of the
25
+authors and should not be interpreted as representing official policies, either expressed
26
+or implied, of German Martin
27
+*/
28
+/*
29
+ Name:		NtpClientLib
30
+ Created:	17/08/2016
31
+ Author:	Germán Martín (gmag11@gmail.com)
32
+ Maintainer:Germán Martín (gmag11@gmail.com)
33
+ Editor:	http://www.visualmicro.com
34
+
35
+ Library to get system sync from a NTP server
36
+*/
37
+
38
+#ifndef _NtpClientLib_h
39
+#define _NtpClientLib_h
40
+
41
+//#define DEBUG_NTPCLIENT //Uncomment this to enable debug messages over serial port
42
+
43
+#ifdef ESP8266
44
+//extern "C" {
45
+//#include "user_interface.h"
46
+//#include "sntp.h"
47
+//}
48
+#include <functional>
49
+using namespace std;
50
+using namespace placeholders;
51
+#endif
52
+
53
+#include <TimeLib.h>
54
+
55
+#if defined(ARDUINO) && ARDUINO >= 100
56
+#include "Arduino.h"
57
+#else
58
+#include "WProgram.h"
59
+#endif
60
+
61
+#define NETWORK_W5100           (1) // Arduino Ethernet Shield
62
+#define NETWORK_ENC28J60        (2) // Alternate Ethernet Shield
63
+#define NETWORK_WIFI101			(3) // WiFi Shield 101 or MKR1000
64
+#define NETWORK_ESP8266			(100) // ESP8266 boards, not for Arduino using AT firmware
65
+#define NETWORK_ESP32           (101) // ESP32 boards
66
+
67
+#define DEFAULT_NTP_SERVER "pool.ntp.org" // Default international NTP server. I recommend you to select a closer server to get better accuracy
68
+#define DEFAULT_NTP_PORT 123 // Default local udp port. Select a different one if neccesary (usually not needed)
69
+#define NTP_TIMEOUT 1500 // Response timeout for NTP requests
70
+#define DEFAULT_NTP_INTERVAL 1800 // Default sync interval 30 minutes 
71
+#define DEFAULT_NTP_SHORTINTERVAL 15 // Sync interval when sync has not been achieved. 15 seconds
72
+#define DEFAULT_NTP_TIMEZONE 0 // Select your local time offset. 0 if UTC time has to be used
73
+
74
+const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
75
+
76
+#ifdef ARDUINO_ARCH_ESP8266
77
+#define NETWORK_TYPE NETWORK_ESP8266
78
+#elif defined ARDUINO_ARCH_SAMD || defined ARDUINO_ARCH_ARC32
79
+#define NETWORK_TYPE NETWORK_WIFI101 // SET YOUR NETWORK INTERFACE
80
+#elif defined ARDUINO_ARCH_AVR
81
+#define NETWORK_TYPE NETWORK_W5100
82
+#elif defined ARDUINO_ARCH_ESP32 || defined ESP32
83
+#define NETWORK_TYPE NETWORK_ESP32
84
+#endif
85
+
86
+#if NETWORK_TYPE == NETWORK_W5100
87
+//#include <SPI.h>
88
+#include <EthernetUdp.h>
89
+#include <Ethernet.h>
90
+//#include <Dns.h>
91
+//#include <Dhcp.h>
92
+#elif NETWORK_TYPE == NETWORK_WIFI101
93
+#include <WiFiClient.h>
94
+#include <WiFiUdp.h>
95
+#include <WiFi101.h>
96
+#elif NETWORK_TYPE == NETWORK_ESP8266
97
+#include <ESP8266WiFi.h>
98
+#include <WiFiUdp.h>
99
+#include <Udp.h>
100
+#elif NETWORK_TYPE == NETWORK_ESP32
101
+#include <WiFi.h>
102
+#include <WiFiUdp.h>
103
+#include <Udp.h>
104
+#else
105
+#error "Incorrect platform. Only ARDUINO and ESP8266 MCUs are valid."
106
+#endif // NETWORK_TYPE
107
+
108
+typedef enum {
109
+    timeSyncd, // Time successfully got from NTP server
110
+    noResponse, // No response from server
111
+    invalidAddress // Address not reachable
112
+} NTPSyncEvent_t;
113
+
114
+#if defined ARDUINO_ARCH_ESP8266 || defined ARDUINO_ARCH_ESP32
115
+#include <functional>
116
+typedef std::function<void (NTPSyncEvent_t)> onSyncEvent_t;
117
+#else
118
+typedef void (*onSyncEvent_t)(NTPSyncEvent_t);
119
+#endif
120
+
121
+class NTPClient {
122
+public:
123
+    /**
124
+    * Construct NTP client.
125
+    */
126
+    NTPClient ();
127
+
128
+    /**
129
+    * Starts time synchronization.
130
+    * @param[in] NTP server name as String.
131
+    * @param[in] Time offset from UTC.
132
+    * @param[in] true if this time zone has dayligth saving.
133
+    * @param[in] Minutes offset added to hourly offset (optional).
134
+    * @param[in] UDP connection instance (optional).
135
+    * @param[out] true if everything went ok.
136
+    */
137
+#if NETWORK_TYPE == NETWORK_W5100
138
+    bool begin (String ntpServerName = DEFAULT_NTP_SERVER, int8_t timeOffset = DEFAULT_NTP_TIMEZONE, bool daylight = false, int8_t minutes = 0, EthernetUDP* udp_conn = NULL);
139
+#elif NETWORK_TYPE == NETWORK_ESP8266 || NETWORK_TYPE == NETWORK_WIFI101 || NETWORK_TYPE == NETWORK_ESP32
140
+    bool begin (String ntpServerName = DEFAULT_NTP_SERVER, int8_t timeOffset = DEFAULT_NTP_TIMEZONE, bool daylight = false, int8_t minutes = 0, WiFiUDP* udp_conn = NULL);
141
+#endif
142
+
143
+    /**
144
+    * Sets NTP server name.
145
+    * @param[in] New NTP server name.
146
+    * @param[out] True if everything went ok.
147
+    */
148
+    bool setNtpServerName (String ntpServerName);
149
+    bool setNtpServerName (char* ntpServerName);
150
+
151
+    /**
152
+    * Sets NTP server name. DEPRECATED, only for compatibility with older versions
153
+    * @param[in] New NTP server name.
154
+    * @param[in] Server index (0-2).
155
+    * @param[out] True if everything went ok.
156
+    */
157
+    bool setNtpServerName (String ntpServerName, int idx) {
158
+        if (idx < 0 || idx > 2)
159
+            return false;
160
+        return setNtpServerName (ntpServerName);
161
+    }
162
+
163
+    /**
164
+    * Gets NTP server name
165
+    * @param[out] NTP server name.
166
+    */
167
+    String getNtpServerName ();
168
+    char* getNtpServerNamePtr ();
169
+
170
+    /**
171
+    * Gets NTP server name. DEPRECATED, only for compatibility with older versions
172
+    * @param[in] Server index (0-2).
173
+    * @param[out] NTP server name.
174
+    */
175
+    String getNtpServerName (int idx) {
176
+        if (idx < 0 || idx > 2)
177
+            return "";
178
+        return getNtpServerName ();
179
+    }
180
+
181
+    /**
182
+    * Starts a NTP time request to server. Returns a time in UNIX time format. Normally only called from library.
183
+    * Kept in public section to allow direct NTP request.
184
+    * @param[out] Time in UNIX time format.
185
+    */
186
+    time_t getTime ();
187
+
188
+    /**
189
+    * Sets timezone.
190
+    * @param[in] New time offset in hours (-11 <= timeZone <= +13).
191
+    * @param[out] True if everything went ok.
192
+    */
193
+    bool setTimeZone (int8_t timeZone, int8_t minutes = 0);
194
+
195
+    /**
196
+    * Gets timezone.
197
+    * @param[out] Time offset in hours (plus or minus).
198
+    */
199
+    int8_t getTimeZone ();
200
+
201
+    /**
202
+    * Gets minutes fraction of timezone.
203
+    * @param[out] Minutes offset (plus or minus) added to hourly offset.
204
+    */
205
+    int8_t getTimeZoneMinutes ();
206
+
207
+    /**
208
+    * Stops time synchronization.
209
+    * @param[out] True if everything went ok.
210
+    */
211
+    bool stop ();
212
+
213
+    /**
214
+    * Changes sync period.
215
+    * @param[in] New interval in seconds.
216
+    * @param[out] True if everything went ok.
217
+    */
218
+    bool setInterval (int interval);
219
+
220
+    /**
221
+    * Changes sync period in sync'd and not sync'd status.
222
+    * @param[in] New interval while time is not first adjusted yet, in seconds.
223
+    * @param[in] New interval for normal operation, in seconds.
224
+    * @param[out] True if everything went ok.
225
+    */
226
+    bool setInterval (int shortInterval, int longInterval);
227
+
228
+    /**
229
+    * Gets sync period.
230
+    * @param[out] Interval for normal operation, in seconds.
231
+    */
232
+    int getInterval ();
233
+
234
+    /**
235
+    * Changes sync period not sync'd status.
236
+    * @param[out] Interval while time is not first adjusted yet, in seconds.
237
+    */
238
+    int	getShortInterval ();
239
+
240
+    /**
241
+    * Gets sync period.
242
+    * @param[out] Interval for normal operation in seconds.
243
+    */
244
+    int	getLongInterval () { return getInterval (); }
245
+
246
+    /**
247
+    * Set daylight time saving option.
248
+    * @param[in] true is daylight time savings apply.
249
+    */
250
+    void setDayLight (bool daylight);
251
+
252
+    /**
253
+    * Get daylight time saving option.
254
+    * @param[out] true is daylight time savings apply.
255
+    */
256
+    bool getDayLight ();
257
+
258
+    /**
259
+    * Convert current time to a String.
260
+    * @param[out] String constructed from current time.
261
+    * TODO: Add internationalization support
262
+    */
263
+    String getTimeStr () { return getTimeStr (now ()); }
264
+
265
+    /**
266
+    * Convert a time in UNIX format to a String representing time.
267
+    * @param[out] String constructed from current time.
268
+    * @param[in] time_t object to convert to extract time.
269
+    * TODO: Add internationalization support
270
+    */
271
+    String getTimeStr (time_t moment);
272
+
273
+    /**
274
+    * Convert current date to a String.
275
+    * @param[out] String constructed from current date.
276
+    * TODO: Add internationalization support
277
+    */
278
+    String getDateStr () { return getDateStr (now ()); }
279
+
280
+    /**
281
+    * Convert a time in UNIX format to a String representing its date.
282
+    * @param[out] String constructed from current date.
283
+    * @param[in] time_t object to convert to extract date.
284
+    * TODO: Add internationalization support
285
+    */
286
+    String getDateStr (time_t moment);
287
+
288
+    /**
289
+    * Convert current time and date to a String.
290
+    * @param[out] String constructed from current time.
291
+    * TODO: Add internationalization support
292
+    */
293
+    String getTimeDateString () { return getTimeDateString (now ()); }
294
+
295
+    /**
296
+    * Convert current time and date to a String.
297
+    * @param[in] time_t object to convert to String.
298
+    * @param[out] String constructed from current time.
299
+    * TODO: Add internationalization support
300
+    */
301
+    String getTimeDateString (time_t moment);
302
+
303
+    /**
304
+    * Gets last successful sync time in UNIX format.
305
+    * @param[out] Last successful sync time. 0 equals never.
306
+    */
307
+    time_t getLastNTPSync ();
308
+
309
+    /**
310
+    * Get uptime in human readable String format.
311
+    * @param[out] Uptime.
312
+    */
313
+    String getUptimeString ();
314
+
315
+    /**
316
+    * Get uptime in UNIX format, time since MCU was last rebooted.
317
+    * @param[out] Uptime. 0 equals never.
318
+    */
319
+    time_t getUptime ();
320
+
321
+    /**
322
+    * Get first boot time in UNIX format, time when MCU was last rebooted.
323
+    * @param[out] Uptime. 0 equals never.
324
+    */
325
+    time_t getLastBootTime ();
326
+
327
+    /**
328
+    * Get first successful synchronization time after boot.
329
+    * @param[out] First sync time.
330
+    */
331
+    time_t getFirstSync ();
332
+
333
+    /**
334
+    * Set a callback that triggers after a sync trial.
335
+    * @param[in] function with void(NTPSyncEvent_t) or std::function<void(NTPSyncEvent_t)> (only for ESP8266)
336
+    *				NTPSyncEvent_t equals 0 is there is no error
337
+    */
338
+    void onNTPSyncEvent (onSyncEvent_t handler);
339
+
340
+    /**
341
+    * True if current time is inside DST period (aka. summer time). False otherwise of if NTP object has DST
342
+    * calculation disabled
343
+    * @param[out] True = summertime enabled and time in summertime period
344
+    *			  False = sumertime disabled or time ouside summertime period
345
+    */
346
+    boolean isSummerTime () {
347
+        if (_daylight)
348
+            return isSummerTimePeriod (now ());
349
+        else
350
+            return false;
351
+    }
352
+
353
+    /**
354
+    * True if given time is inside DST period (aka. summer time). False otherwise.
355
+    * @param[in] time to make the calculation with
356
+    * @param[out] True = time in summertime period
357
+    *			  False = time ouside summertime period
358
+    */
359
+    boolean isSummerTimePeriod (time_t moment);
360
+
361
+protected:
362
+
363
+#if NETWORK_TYPE == NETWORK_W5100
364
+    EthernetUDP *udp;
365
+#elif NETWORK_TYPE == NETWORK_ESP8266 || NETWORK_TYPE == NETWORK_WIFI101 || NETWORK_TYPE == NETWORK_ESP32
366
+    WiFiUDP *udp;
367
+#endif
368
+    bool _daylight;             ///< Does this time zone have daylight saving?
369
+    int8_t _timeZone = 0;       ///< Keep track of set time zone offset
370
+    int8_t _minutesOffset = 0;   ///< Minutes offset for time zones with decimal numbers
371
+    char* _ntpServerName;       ///< Name of NTP server on Internet or LAN
372
+    int _shortInterval;         ///< Interval to set periodic time sync until first synchronization.
373
+    int _longInterval;          ///< Interval to set periodic time sync
374
+    time_t _lastSyncd = 0;      ///< Stored time of last successful sync
375
+    time_t _firstSync = 0;      ///< Stored time of first successful sync after boot
376
+    unsigned long _uptime = 0;  ///< Time since boot
377
+    onSyncEvent_t onSyncEvent;  ///< Event handler callback
378
+
379
+    /**
380
+    * Function that gets time from NTP server and convert it to Unix time format
381
+    * @param[out] Time form NTP in Unix Time Format.
382
+    */
383
+    static time_t s_getTime ();
384
+
385
+    /**
386
+    * Calculates the daylight saving for a given date.
387
+    * @param[in] Year.
388
+    * @param[in] Month.
389
+    * @param[in] Day.
390
+    * @param[in] Hour.
391
+    * @param[in] Time zone offset.
392
+    * @param[out] true if date and time are inside summertime period.
393
+    */
394
+    bool summertime (int year, byte month, byte day, byte hour, byte tzHours);
395
+
396
+    /**
397
+    * Helper function to add leading 0 to hour, minutes or seconds if < 10.
398
+    * @param[in] Digit to evaluate the need of leading 0.
399
+    * @param[out] Result digit with leading 0 if needed.
400
+    */
401
+    //String printDigits(int digits);
402
+
403
+
404
+public:
405
+    /**
406
+    * Decode NTP response contained in buffer.
407
+    * @param[in] Pointer to message buffer.
408
+    * @param[out] Decoded time from message, 0 if error ocurred.
409
+    */
410
+    time_t decodeNtpMessage (char *messageBuffer);
411
+
412
+    /**
413
+    * Set last successful synchronization time.
414
+    * @param[out] Last sync time.
415
+    */
416
+    void setLastNTPSync (time_t moment);
417
+
418
+private:
419
+    /**
420
+    * Sends NTP request packet to given IP address.
421
+    * @param[in] NTP server's IP address.
422
+    * @param[out] True if everything went ok.
423
+    */
424
+    //bool sendNTPpacket(IPAddress &address);
425
+//#endif
426
+};
427
+
428
+extern NTPClient NTP;
429
+
430
+#endif // _NtpClientLib_h

+ 3
- 0
readme.md View File

@@ -0,0 +1,3 @@
1
+# ESP8266 NTP driven clock on TM1640
2
+
3
+Rename `wifi.h.sample` to `wifi.h`, change NTP server to nearest to you, set timezone shift.

+ 145
- 0
tm1640-ntp.ino View File

@@ -0,0 +1,145 @@
1
+#include <Wire.h>
2
+#include "LM1640Display.h"
3
+
4
+#include <TimeLib.h>
5
+#include "NtpClientLib.h"
6
+#include <ESP8266WiFi.h>
7
+#include <ESP8266HTTPClient.h>
8
+
9
+#include "wifi.h"
10
+
11
+#define ONBOARDLED 2 // Built in LED on ESP-12/ESP-07
12
+
13
+#define CLK D2
14
+#define DIO D3
15
+
16
+LM1640Display display(CLK, DIO);
17
+
18
+//set timezone
19
+static const int8_t timeZone = 7;
20
+bool wifiFirstConnected = false;
21
+bool ntp_online = false;
22
+
23
+void onSTAConnected (WiFiEventStationModeConnected ipInfo) {
24
+  Serial.printf ("Connected to %s\r\n", ipInfo.ssid.c_str ());
25
+}
26
+
27
+// Start NTP only after IP network is connected
28
+void onSTAGotIP(WiFiEventStationModeGotIP ipInfo) {
29
+  Serial.printf("Got IP: %s\r\n", ipInfo.ip.toString().c_str());
30
+  wifiFirstConnected = true;
31
+  //digitalWrite(ONBOARDLED, LOW); // Turn on LED
32
+}
33
+
34
+// Manage network disconnection
35
+void onSTADisconnected(WiFiEventStationModeDisconnected event_info) {
36
+  Serial.printf("Disconnected from SSID: %s\n", event_info.ssid.c_str());
37
+  Serial.printf("Reason: %d\n", event_info.reason);
38
+  digitalWrite(ONBOARDLED, HIGH); // Turn off LED
39
+  //NTP.stop(); // NTP sync can be disabled to avoid sync errors
40
+  ntp_online = false;
41
+}
42
+
43
+void processSyncEvent(NTPSyncEvent_t ntpEvent) {
44
+  if (ntpEvent) {
45
+    Serial.print("Time Sync error: ");
46
+    if (ntpEvent == noResponse) {
47
+      Serial.println("NTP server not reachable");
48
+      ntp_online = false;
49
+    }
50
+    else if (ntpEvent == invalidAddress) {
51
+      Serial.println("Invalid NTP server address");
52
+      ntp_online = false;
53
+    }
54
+  }
55
+  else {
56
+    Serial.print("Got NTP time: ");
57
+    ntp_online = true;
58
+    Serial.println(NTP.getTimeDateString(NTP.getLastNTPSync()));
59
+  }
60
+}
61
+
62
+boolean syncEventTriggered = false;
63
+NTPSyncEvent_t ntpEvent;
64
+
65
+void setup() {
66
+  static WiFiEventHandler e1, e2, e3;
67
+  Wire.begin();
68
+
69
+  //Serial.begin(115200);
70
+  WiFi.mode(WIFI_STA);
71
+  WiFi.hostname("clock16");
72
+  WiFi.begin(YOUR_WIFI_SSID, YOUR_WIFI_PASSWD);
73
+
74
+  pinMode(ONBOARDLED, OUTPUT); // Onboard LED
75
+  digitalWrite(ONBOARDLED, HIGH); // Switch off LED
76
+
77
+  NTP.onNTPSyncEvent([](NTPSyncEvent_t event) {
78
+    ntpEvent = event;
79
+    syncEventTriggered = true;
80
+  });
81
+
82
+  e1 = WiFi.onStationModeGotIP(onSTAGotIP);// As soon WiFi is connected, start NTP Client
83
+  e2 = WiFi.onStationModeDisconnected(onSTADisconnected);
84
+  e3 = WiFi.onStationModeConnected (onSTAConnected);
85
+  digitalWrite(ONBOARDLED, HIGH); // Switch off LED
86
+}
87
+
88
+void starting() {
89
+
90
+  NTP.begin("ntp.tomtel.ru", timeZone, true);
91
+  NTP.setInterval(10, 600);
92
+
93
+  display.clear();
94
+ 
95
+  //Serial.println("Starting NTP client");
96
+  
97
+  while (ntp_online == false) {
98
+    if (syncEventTriggered) {
99
+      processSyncEvent (ntpEvent);
100
+      syncEventTriggered = true;
101
+    }
102
+    display.setBrightness(7);
103
+    display.showString("connecting...");
104
+    //Serial.println("Connecting");
105
+    delay(1000);
106
+  }
107
+
108
+  display.clear();
109
+
110
+  for (uint8_t l = 0; l <= 7; l++) {
111
+    display.setBrightness(l); //set the diplay to maximum brightness
112
+    display.showString("hello int 21h");
113
+    delay(200);
114
+  }
115
+
116
+  display.clear();
117
+}
118
+
119
+char timebuff[17];
120
+
121
+void loop() {  
122
+  if (ntp_online == true) {
123
+    if (syncEventTriggered) {
124
+      processSyncEvent (ntpEvent);
125
+      syncEventTriggered = false;
126
+    }
127
+
128
+    String timestamp = NTP.getTimeDateString();
129
+
130
+    //Serial.print(timestamp + "\n");
131
+
132
+    timestamp.toCharArray(timebuff, 17);
133
+    
134
+    display.showString( timebuff );
135
+
136
+    delay(1000);
137
+  } else {
138
+    starting();
139
+  }
140
+}
141
+
142
+
143
+
144
+
145
+

+ 3
- 0
wifi.h.sample View File

@@ -0,0 +1,3 @@
1
+#define YOUR_WIFI_SSID "supapupamegawifi"
2
+#define YOUR_WIFI_PASSWD "sexdrugsrickroll"
3
+

Loading…
Cancel
Save