-
Notifications
You must be signed in to change notification settings - Fork 0
/
Character_Clock_V108_328-1284.ino
1942 lines (1850 loc) · 79.8 KB
/
Character_Clock_V108_328-1284.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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// =============================================================================================================================
/*
This Arduino code controls the ATMEGA328 ot ARMEGA1284 chip on the PCB board that controls the LED strips of the Word Clock
This source contains code for the following modules:
- RTC DS3231 ZS-042 clock module
- KY-040 Keyes Rotary Encoder
- LDR light sensor 5528
- Bluetooth RF Transceiver Module HC05
- DCF77 module DCF-2
- FM Stereo Radio Module RDA5807M RRD-102V2.0
- Red_MAX7219_8-Digit_LED_Display
- I2C LCD display
A 74HC595 ULN2803APG combination regulates the LEDs by shifting in bits into the 74HC595 LED are turn On or Off
A FT232RL 5.5V FTDI USB to TTL Serial Module can be attached to program te ATMEGA and read the serial port
The HC05 or HM-10 Bluetooth module is used to read and write information or instructions to the clock
The DCF77 module can be attached to adjust the time to the second with German longwave time signal received by the module
The FM-module can be used to read the RDS-time from radio station or to play FM-radio station from within the clock
Author .: Ed Nieuwenhuys
Changes.: 0.27-->0.40 read clock every second instead of every hour"
Changes.: 0.27-->0.40 Encoder turn writes time directly to clock"
Changes.: 0.42 toggle HetWasIs"
Changes.: 0.43 Added PWM on Pin5 to control dimming "
Changes.: 0.48 Minor changes"
Changes.: 0.49 rotary encoder improved"
Changes.: 0.50 Stable and organised coding"
Changes.: 0.51 (SQRT (long)analog read * 63.5) for less lineair dimming"
Changes.: 0.52 Changed rotary pins"
Changes.: 0.54 Coding voor Klok 3 en 5"
Changes.: 0.60 Nieuwe display format. Hetiswas na 10 sec uit "
Changes.: 0.61 Pinchanges"
Changes.: 0.63 Ebben klok No13"
Changes.: 0.64 Light reducer added"
Changes.: 0.65 Programma aangepast voor standaard front en KY-040 rotary-besturing ingebouwd"
Changes.: 0.66 Random tijd when no RTC signal"
Changes.: 0.67 Source code cleaning"
Changes.: 0.69 Bluetooth added"
Changes.: 0.70 Temperature added"
Changes.: 0.76 Rotary delay 200 ---> 0 ms"
Changes.: 0.78 BT Lightintensity"
Changes.: 0.79 FM-radio time and serial/bluetooth input commands added"
Changes.: 0.81 DCF77 receiver included"
Changes.: 0.84 #ifdef included statements in source file, optimisation of code"
Changes.: 0.86 English display added"
Changes.: 0.87 French display added ---> Failed text does not fit in 11 x 11 character matrix.
Changes.: 0.90 Dutch-English version" myEnc.write(0); at end of rotary function
Changes.: 0.91 Added support for ATMEGA 1284P
https://mcudude.github.io/MightyCore/package_MCUdude_MightyCore_index.json add this in preferences
Changes.: 0.92 Added in Arduino\libraries\Encoder\interrupt_pins.h to facilitate the ATMighty 1284
// Arduino Mighty
#elif defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega1284__)
#define CORE_NUM_INTERRUPT 3
#define CORE_INT0_PIN 10
#define CORE_INT1_PIN 11
#define CORE_INT2_PIN 2
Changes.: 0.93 Added LCD support
Changes.: 0.94 Added toggle lights on EDSOFT at minute 0 for several seconds
Changes.: 0.95 Changed because of compile errors #include Time.h"in #include TimeLib.h"
Changes.: 0.96 Added Red_MAX7219_8-Digit_LED_Display
Changes.: 0.97 Added temperature sensor Dallas DS1820. rotary bounces at start of program
Changes.: 0.98 Fixed Bluetooth not receiving commands bug
Changes.: 0.99 Franse klok verbeterd. Nog niet perfect.
sqrt( (float) 63.5 * constrain(LDR_read,1,1023))); ...LDR_read,10,1023 --> LDR_read,1,1023
Changes.: V100 Show DCF-reception in LEDs of the HET display. Menu entries stored with PROGMEM. Cleaned up: time print functions. #defines HET IS etc
Changes.: V101 PROGMEM for menu items to conserve global variable space
Changes.: V102 PROGMEM Time texts to conserve global variabele space, Added in setup "... enabled"
Changes.: V103 Purperhartklok, Changed menu entries
Changes.: V104 Menu optimised, BT en serial optimised
Changes.: V105 LCD optimised, DCF signal 0-100
Changes.: V106 Selftest in menu. Stable version
Changes.: V107 Rotary bug, "noise on AC line", solved by changing rotary press/rotate options
Changes.: V108 Changed time settings in rotary for Kees Soeters. Time text in ShiftInTime function instead from array
*/
// ===============================================================================================================================
//--------------------------------------------
// ARDUINO Definition of installed modules
//--------------------------------------------
//#define FMRADIOMOD // in development time retrieval works. Needs automatic optimal sender search function
//#define BLUETOOTHMOD
//#define DCFMOD
#define ROTARYMOD
//#define LCDMOD
//#define MAX7219_8DIGIT //Only with 1284
//#define DS1820 //Only with 1284
//--------------------------------------------
// ARDUINO Definition of installed language word clock
//--------------------------------------------
#define NL
// #define UK
// #define DE
// #define FR // in development
//--------------------------------------------
// ARDUINO Includes defines and initialysations
//--------------------------------------------
// Get the LCD I2C Library here:
// https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads
// Move any other LCD libraries to another folder or delete them
// See Library "Docs" folder for possible commands etc.
#include <Wire.h>
#include <avr/pgmspace.h>
#ifdef LCDMOD
#include <LiquidCrystal_I2C.h>
#endif LCDMOD
#include <RTClib.h>
#include <EEPROM.h>
// #ifdef BLUETOOTHMOD
#include <SoftwareSerial.h> // for Bluetooth communication
// #endif BLUETOOTHMOD
#ifdef ROTARYMOD
#include <Encoder.h>
#ifdef defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega1284__)
#define CORE_NUM_INTERRUPT 3
#define CORE_INT0_PIN 10
#define CORE_INT1_PIN 11
#define CORE_INT2_PIN 2
#endif
#endif ROTARYMOD
#ifdef DCFMOD
#include <DCF77.h>
#include <TimeLib.h>
#endif DCFMOD
#ifdef MAX7219_8DIGIT
#include <LedControl.h>
#endif MAX7219_8DIGIT
#ifdef DS1820
#include <DallasTemperature.h>
#endif DS1820
#ifdef NL
#define HET ShiftInTime("Het ", 0, 1,Toggle_HetWasIs,0);
#define IS ShiftInTime("is ", 1, 1,Toggle_HetWasIs,1);
#define WAS ShiftInTime("was ", 2, 1,Toggle_HetWasIs,2);
#define MVIJF ShiftInTime("vijf ", 3, 1, 1,3);
#define MTIEN ShiftInTime("tien ", 4, 1, 1,4);
#define KWART ShiftInTime("kwart ", 5, 1, 1,5);
#define VOOR ShiftInTime("voor ", 6, 1, 1,6);
#define OVER ShiftInTime("over ", 7, 1, 1,7);
#define PRECIES ShiftInTime("precies ",8, 2, 1,0);
#define HALF ShiftInTime("half ", 9, 2, 1,1);
#define ELF ShiftInTime("elf ", 10, 2, 1,2);
#define VIJF ShiftInTime("vijf ", 11, 2, 1,3);
#define TWEE ShiftInTime("twee ", 12, 2, 1,4);
#define EEN ShiftInTime("een ", 13, 2, 1,5);
#define VIER ShiftInTime("vier ", 14, 2, 1,6);
#define TIEN ShiftInTime("tien ", 15, 2, 1,7);
#define TWAALF ShiftInTime("twaalf ",16, 3, 1,0);
#define DRIE ShiftInTime("drie ", 17, 3, 1,1);
#define NEGEN ShiftInTime("negen ", 18, 3, 1,2);
#define ACHT ShiftInTime("acht ", 19, 3, 1,3);
#define ZES ShiftInTime("zes ", 20, 3, 1,4);
#define ZEVEN ShiftInTime("zeven ", 21, 3, 1,5);
#define UUR ShiftInTime("uur ", 22, 3, 1,6);
#define EDSOFT ShiftInTime("Edsoft ",23, 3, ToggleEdsoft ,7);
#endif NL
#ifdef UK
#define HET ShiftInTime("It ", 0, 1,Toggle_HetWasIs,0);
#define IS ShiftInTime("is ", 1, 1,Toggle_HetWasIs,0);
#define WAS ShiftInTime("was ", 2, 1,Toggle_HetWasIs,0);
#define PRECIES ShiftInTime("exact " ,3, 1, 1,3);
#define HALF ShiftInTime("half ", 4, 1, 1,4);
#define TWINTIG ShiftInTime("twenty ", 5, 1, 1,5);
#define MVIJF ShiftInTime("five ", 6, 1, 1,6);
#define KWART ShiftInTime("quarter ",7, 1, 1,7);
#define MTIEN ShiftInTime("ten ", 8, 2, 1,0);
#define OVER ShiftInTime("past ", 9, 2, 1,1);
#define ZES ShiftInTime("six ", 10, 2, 1,2);
#define TWEE ShiftInTime("two ", 11, 2, 1,3);
#define VIJF ShiftInTime("five ", 12, 2, 1,4);
#define TWAALF ShiftInTime("twelve ",13, 2, 1,5);
#define TIEN ShiftInTime("ten ", 14, 2, 1,6);
#define ELF ShiftInTime("eleven ",15, 2, 1,7);
#define VIER ShiftInTime("four ", 16, 3, 1,0);
#define NEGEN ShiftInTime("nine ", 17, 3, 1,1);
#define DRIE ShiftInTime("three ", 18, 3, 1,2);
#define ACHT ShiftInTime("eight ", 19, 3, 1,3);
#define ZEVEN ShiftInTime("seven ", 20, 3, 1,4);
#define EEN ShiftInTime("one "," 21, 3, 1,5);
#define UUR ShiftInTime(O'clock ",22, 3, 1,6);
#define VOOR ShiftInTime("to " 23, 3, ToggleEdsoft ,7);
#endif UK
//--------------------------------------------
// PIN Assigments
//--------------------------------------------
#if defined(__AVR_ATmega328P__)
// Digital hardware constants ATMEGA 328 ----
enum DigitalPinAssignments {
DCF_PIN = 2, // DCFPulse on interrupt pin
encoderPinA = 3, // right (labeled DT on decoder)on interrupt pin
clearButton = 4, // switch (labeled SW on decoder)
PWMpin = 5, // Pin that controle PWM signal on BC327 transistor to dim light
BT_RX = 6, // Bluetooth RX connect to TXD op de BT module
BT_TX = 7, // Bluetooth TX connect to RXD op de BT module
encoderPinB = 8, // left (labeled CLK on decoder)no interrupt pin
DCF_LED_Pin = 9, // define LED pin voor DCF pulse
LEDDataPin = 10, // blauw HC595
LEDStrobePin = 11, // groen HC595
LEDClockPin = 12, // geel HC595
secondsPin = 13,
HeartbeatLED = 13};
// Analogue hardware constants ----
enum AnaloguePinAssignments {
PhotoCellPin = 2, // LDR pin
EmptyA3 = 3, //
SDA_pin = 4, // SDA pin
SCL_pin = 5}; // SCL pin
# endif
//--------------------------------------------//--------------------------------------------
#if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega1284__)
// Digital hardware constants ATMEGA 1284P ----
enum DigitalPinAssignments {
BT_RX = 0, // Bluetooth RX
BT_TX = 1, // Bluetooth TX
DCF_PIN = 2, // DCFPulse on interrupt pin
PWMpin = 3, // Pin that controle PWM signal on BC327 transistor to dim light
MAX7219_DIN = 4, // MAX7219 DIN gr PB4 PWM
MAX7219_CS = 5, // MAX7219 CS ge PB5 digital
MAX7219_CLK = 6, // MAX7219 CLK or PB6 PWM
DS1820Temp = 7, // DS1820 temperature PB7 PWM
PIN08 = 8, // RX1 PD0 digital
PIN09 = 9, // TX1 PD1 digital
LED10 = 10, // LED10 PD2 digital
encoderPinB = 11, // left (labeled CLK on decoder) no interrupt pin PD3 digital
encoderPinA = 12, // right (labeled DT on decoder) no interrupt pin PD4 PWM
clearButton = 13, // switch (labeled SW on decoder) PD5 PWM
DCF_LED_Pin = 14, // define pin voor DCF signal Led PD6 PWM
HeartbeatLED = 15, // LED15 PD7 PWM
SCL_pin = 16, // SCL pin PC0 interrupt
SDA_pin = 17, // SDA pin PC1 interrupt
PIN18 = 18, // Empty PC2 digital
LED19 = 19, // LED19 PC3 digital
LEDDataPin = 20, // blauw HC595 PC4 digital
LEDStrobePin = 21, // groen HC595 PC5 digital
LEDClockPin = 22, // geel HC595 PC6 digital
secondsPin = 23}; // PC7 digital
// Analogue hardware constants ----
enum AnaloguePinAssignments {
EmptyA0 = 24, // Empty
EmptyA1 = 25, // Empty
PhotoCellPin = 26, // LDR pin
EmptyA3 = 27, // Empty
EmptyA4 = 28, // Empty
EmptyA5 = 29, // Empty
EmptyA6 = 30}; // Empty
# endif
//--------------------------------------------
// LED
//--------------------------------------------
byte BrightnessCalcFromLDR = 200; // BRIGHTNESS 0 - 255
int ToggleEdsoft = 1;
//--------------------------------------------
// KY-040 ROTARY
//--------------------------------------------
#ifdef ROTARYMOD
Encoder myEnc(encoderPinA, encoderPinB); // Use digital pin for encoder
#endif ROTARYMOD
unsigned long Looptime = 0;
unsigned long RotaryPressTimer = 0;
byte NoofRotaryPressed = 0;
//--------------------------------------------
// LDR PHOTOCELL
//--------------------------------------------
float LightReducer = 0.80 ; // Factor to dim ledintensity with. Between 0.1 and 1 in steps of 0.05
byte LowerBrightness = 10; // Lower limit of Brightness ( 0 - 255)
int OutPhotocell; // stores reading of photocell;
int MinPhotocell = 1024; // stores minimum reading of photocell;
int MaxPhotocell = 1; // stores maximum reading of photocell;
//--------------------------------------------
// CLOCK
//--------------------------------------------
#define MAXTEXT 50
static unsigned long msTick; // the number of millisecond ticks since we last incremented the second counter
int count;
byte Isecond, Iminute, Ihour , Iday, Imonth, Iyear;
byte Display1 = 0 , Display2 = 0, Display3 = 0;
byte lastminute = 0 , lasthour = 0, sayhour = 0;
int Delaytime = 200;
byte Toggle_HetWasIs = 1; // Turn On/Off HetIsWas lights
int Toggle_HetWasIsUit = 0; // Turn off HetIsWas after 10 sec
byte ChangeTime = false;
byte ChangeLightIntensity = false;
byte SecPulse = 0; // give a pulse to the Isecond led
byte Demo = false;
byte Zelftest = false;
byte hbval = 128;
byte hbdelta = 8;
String SerialString;
const byte MenuItems = 13; // sentences, rows, in menu
const char menu[][MAXTEXT] PROGMEM = {
"Woordklok Ninotska nov 2019",
"Enter time as:hhmm (1321) or hhmmss (132145)",
"Enter A for normal display",
"Enter B to suspress Het Is Was in display",
"Enter C to suspress Het Is Was after 10 seconds",
"Enter D D15122017 for date 15 December 2017",
"Enter G for DCF-signalinfo on display",
"Enter Mnn (M90)Max light intensity (1% - 250%)",
"Enter Lnn (L5) Min light intensity ( 1 - 255)",
"Enter I for info",
"Enter X for Demo mode",
"Enter Z for Self test",
"Ed Nieuwenhuys V108 September 2019" };
//--------------------------------------------
// DS3231 CLOCK MODULE
//--------------------------------------------
#define DS3231_I2C_ADDRESS 0x68
#define DS3231_TEMPERATURE_MSB 0x11
#define DS3231_TEMPERATURE_LSB 0x12
RTC_DS3231 RTC; //RTC_DS1307 RTC;
DateTime Inow;
//--------------------------------------------
// BLUETOOTH
//--------------------------------------------
#ifdef BLUETOOTHMOD // Bluetooth ---------------------
SoftwareSerial Bluetooth(BT_RX, BT_TX); // RX <=> TXD on BT module, TX <=> RXD on BT module
String BluetoothString;
#endif BLUETOOTHMOD
//--------------------------------------------
// RDA5807 FM-RADIO
//--------------------------------------------
#ifdef FMRADIOMOD // FM radio -----------------------
byte RadioUur; // reading from RDS FM-radio
byte RadioMinuut; // reading from RDS FM-radio
float fini = 103.50; //91.60; // 103.50; //98.10; // Start frequency
int ftun; // Selected frequency
float Freq_lower_bandwith = 87.00; // lower Band limit
float Freq_tuned; //
int RDA5807_adrs = 0x10; // I2C-Address RDA Chip for sequential Access
int RDA5807_adrr = 0x11; // I2C-Address RDA Chip for random Access
int RDA5807_adrt = 0x60; // I2C-Address RDA Chip for TEA5767like Access
int sidx = 0; // Counter of frequency array
int vol = 0; // Volume
int rssi = 0; // Signal-Level
unsigned int auRDS[32];
unsigned int auRDA5807_Reg[32];
unsigned int aui_RDA5807_Reg[32];
unsigned int aui_buf[8];
unsigned int auRDA5807_Regdef[10] ={
0x0758, // 00 defaultid
0x0000, // 01 not used
0xD009, // 02 DHIZ,DMUTE,BASS, POWERUPENABLE,RDS
0x0000, // 03
0x1400, // 04 DE ? SOFTMUTE
0x84D0, // 05 INT_MODE, SEEKTH=0110,????, Volume=0
0x4000, // 06 OPENMODE=01
0x0000, // 07 unused ?
0x0000, // 08 unused ?
0x0000 // 09 unused ?
};
#endif FMRADIOMOD // END FM radio ------------------------
//--------------------------------------------
// DCF-2 DCF77 MODULE
//--------------------------------------------
byte DCF_signal = 50; // is a proper time received?
bool SeeDCFsignalInDisplay = false; // if ON then the display line HET IS WAS will show the DCF77-signal received
#ifdef DCFMOD // DCF77 ------------------------------
#if defined(__AVR_ATmega328P__)
#define DCF_INTERRUPT 0 // DCF Interrupt number associated with DCF_PIN
#endif
#if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega1284__)
#define DCF_INTERRUPT 2 // DCF Interrupt number associated with DCF_PIN
#endif
DCF77 DCF = DCF77(DCF_PIN,DCF_INTERRUPT,LOW);
#endif DCFMOD
#ifdef LCDMOD
//--------------------------------------------
// LCD Module
//--------------------------------------------
//LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7); // 0x27 is the I2C bus address for an unmodified backpack
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);// 0x27 or 0x3F is the I2C bus address for an unmodified backpack
#endif LCDMOD
#ifdef MAX7219_8DIGIT
//----------------------------------------
// MAX7219_8DIGIT
//----------------------------------------
// MAX7219_DIN is connected to the DataIn, MAX7219_CLK is connected to the CLK, MAX7219_CS is connected to LOAD We have only a single MAX72XX.
LedControl lc = LedControl( MAX7219_DIN, MAX7219_CLK, MAX7219_CS, 1 );
#endif MAX7219_8DIGIT
//----------------------------------------
// Temperature sensor DS1820
//----------------------------------------
#ifdef DS1820
#define TEMPERATURE_PRECISION 9 // a DS18B20 takes from 94ms (9-bit resolution) to 750ms (12-bit resolution) to convert temperature
OneWire oneWire(DS1820Temp); // Setup a oneWire instance to communicate with any OneWire devices DS1820Temp
DallasTemperature Tempsensors(&oneWire); // Pass our oneWire reference to Dallas Temperature.
DeviceAddress tempDeviceAddress; // We'll use this variable to store a found device address
int numberOfDevices; // Number of temperature devices found
#endif DS1820
//----------------------------------------
// Common
//----------------------------------------
char sptext[MAXTEXT+2]; // for common print use
// End Definitions ---------------------------------------------------------
//--------------------------------------------
// ARDUINO Loop
//--------------------------------------------
void loop(void)
{
SerialCheck();
if(Demo) Demomode();
else if (Zelftest) Selftest();
else
{
#if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega1284__)
heartbeat(); // only heartbeat with ATMEGA1284
#endif
EverySecondCheck();
EveryMinuteUpdate();
#ifdef FMRADIOMOD
FMradioCheck();
#endif FMRADIOMOD
#ifdef BLUETOOTHMOD
BluetoothCheck();
#endif BLUETOOTHMOD
#ifdef DCFMOD
DCF77Check();
#endif DCFMOD
#ifdef ROTARYMOD
RotaryEncoderCheck();
#endif ROTARYMOD
}
}
//--------------------------------------------
// ARDUINO Setup
//--------------------------------------------
void setup()
{ // initialise the hardware // initialize the appropriate pins as outputs:
Serial.begin(9600); // setup the serial port to 9600 baud
Wire.begin(); // start the wire communication I2C
RTC.begin(); // start the RTC-module
pinMode(LEDClockPin, OUTPUT);
pinMode(LEDDataPin, OUTPUT);
pinMode(LEDStrobePin, OUTPUT);
pinMode(PWMpin, OUTPUT);
pinMode(secondsPin, OUTPUT );
#ifdef ROTARYMOD
pinMode(encoderPinA, INPUT_PULLUP);
pinMode(encoderPinB, INPUT_PULLUP);
pinMode(clearButton, INPUT_PULLUP);
Tekstprintln("Rotary enabled");
#endif ROTARYMOD
#if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega1284__)
pinMode(LED10, OUTPUT );
pinMode(HeartbeatLED, OUTPUT );
pinMode(LED19, OUTPUT );
#endif
#ifdef BLUETOOTHMOD
Bluetooth.begin(9600); // setup the Bluetooth port to 9600 baud
Tekstprintln("Bluetooth enabled");
#endif BLUETOOTHMOD
#ifdef FMRADIOMOD
Setup_FMradio(); // start the FM-radio
Tekstprintln("FM-radio enabled");
#endif FMRADIOMOD
#ifdef DS1820
setupDS1820();
#endif DS1820
#ifdef DCFMOD
pinMode(DCF_LED_Pin, OUTPUT);
pinMode(DCF_PIN, INPUT_PULLUP);
DCF.Start(); // start the DCF-module
Tekstprintln("DCF enabled");
#endif DCFMOD
#ifdef LCDMOD
lcd.begin (16,2); // Activate LCD module
lcd.setBacklightPin(3,POSITIVE);
lcd.setBacklight(HIGH);
Tekstprintln("LCD enabled");
#endif LCDMOD
#ifdef MAX7219_8DIGIT
lc.shutdown(0,false);
lc.setIntensity(0,2); // Set the brightness to a medium values
lc.clearDisplay(0); // and clear the display
Tekstprintln("MAX7219 enabled");
#endif MAX7219_8DIGIT
analogWrite(PWMpin, BrightnessCalcFromLDR); // the duty cycle: between 0 (lights off) and 255 (light full on).
GetTijd(1); // Get the time and print it to serial
DateTime now = RTC.now(); // Get the time from the RTC
DateTime compiled = DateTime(__DATE__, __TIME__);
if (now.unixtime() < compiled.unixtime())
{
Tekstprintln("RTC is older than compile time! Updating"); // following line sets the RTC to the date & time this sketch was compiled
RTC.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
if (EEPROM.read(0) <3 || EEPROM.read(0) > 200) EEPROM.write(0,(int)(LightReducer * 100)); // default intensity for this clock
if (EEPROM.read(1) <1 || EEPROM.read(1) > 100) EEPROM.write(1, LowerBrightness); // default Lower Brightness for this clock
LightReducer = ((float)EEPROM.read(0) / 100); // store it is the work variable
LowerBrightness = EEPROM.read(1); // store it is the work variable
Looptime = millis(); // Used in KY-040 rotary
MinPhotocell = MaxPhotocell = analogRead(PhotoCellPin); // Read lightsensor
msTick = Looptime;
SWversion(); // Display the version number of the software
// Selftest(); // Play the selftest
GetTijd(0); // Get the time and print it to serial
#ifdef ROTARYMOD
myEnc.write(0); // Clear Rotary encode buffer
#endif ROTARYMOD
}
// --------------------------- END SETUP
//--------------------------------------------
// CLOCK Version info
//--------------------------------------------
void SWversion(void)
{
for (int n=0; n<39; n++) {Serial.print(F("_"));} Serial.println();
for (int i = 0; i < MenuItems; i++) {strcpy_P(sptext, menu[i]); Tekstprintln(sptext); }
for (int n=0; n<39; n++) {Serial.print(F("_"));} Serial.println();
sprintf(sptext,"Brightness Min: %3d bits Max: %3d%%",LowerBrightness, (int)(LightReducer * 100 )) ;
Tekstprintln(sptext);
sprintf(sptext," LDR read Min: %3d bits Max: %3d bits",MinPhotocell , MaxPhotocell);
Tekstprintln(sptext);
for (int n = 0; n < 39; n++) {Serial.print(F("_"));} Serial.println();
}
//--------------------------------------------
// CLOCK Demo mode
//--------------------------------------------
void Demomode(void)
{
if ( millis() - msTick >50) digitalWrite(secondsPin,LOW); // Turn OFF the second on pin 13
if ( millis() - msTick >999) // Flash the onboard Pin 13 Led so we know something is happening
{
msTick = millis(); // second++;
digitalWrite(secondsPin,HIGH); // turn ON the second on pin 13
++SecPulse; // second routine in function DimLeds
if( ++Iminute >59) { Iminute = 0; Isecond = 0; Ihour++;}
if( Ihour >24) Ihour = 0;
DimLeds(false);
Displaytime();
Tekstprintln("");
}
}
//--------------------------------------------
// CLOCK common print routines
//--------------------------------------------
void Tekstprint(char tekst[])
{
Serial.print(tekst);
#ifdef BLUETOOTHMOD
Bluetooth.print(tekst);
#endif BLUETOOTHMOD
}
void Tekstprintln(char tekst[])
{
Serial.println(tekst);
#ifdef BLUETOOTHMOD
Bluetooth.println(tekst);
#endif BLUETOOTHMOD
}
//--------------------------------------------
// CLOCK Update routine done every second
//--------------------------------------------
void EverySecondCheck(void)
{
if ( millis() - msTick >50) digitalWrite(secondsPin,LOW); // Turn OFF the second on pin 13
if ( millis() - msTick >999) // Flash the onboard Pin 13 Led so we know something is happening
{
msTick = millis(); // second++;
digitalWrite(secondsPin,HIGH); // turn ON the second on pin 13
++SecPulse; // second routine in function DimLeds
GetTijd(0); // synchronize time with RTC clock
#ifdef LCDMOD
Print_tijd_LCD();
#endif LCDMOD
if ((Toggle_HetWasIsUit == 2) && (Isecond > 10)) Toggle_HetWasIs = 0;
else Toggle_HetWasIs = 1; // HET IS WAS is On
if(Isecond % 30 == 0) DimLeds(true); // Led Intensity Control + seconds tick print every 30 seconds
else DimLeds(false);
if ((Toggle_HetWasIsUit == 2) && (Isecond == 11))Displaytime(); // turn Leds OFF on second == 11
if(Iminute == 0 && Isecond <9)
{
ToggleEdsoft = Isecond % 2; // ToggleEdsoft becomes 0 or 1 and turn on and off the first seconds at minute 0 the Edsoft light on pin 24
Serial.println(ToggleEdsoft);
Displaytime();
}
#ifdef DS1820
DS1820read();
#endif DS1820
}
}
//--------------------------------------------
// CLOCK Update routine done every minute
//--------------------------------------------
void EveryMinuteUpdate(void)
{
if (Iminute != lastminute) //show time every minute
{
lastminute = Iminute;
Displaytime();
Print_RTC_tijd();
DCF_signal--;
DCF_signal = constrain( DCF_signal,1,99);
}
if (Ihour != lasthour) {lasthour = Ihour;}
}
#ifdef BLUETOOTHMOD
//--------------------------------------------
// CLOCK check for Bluetooth input
//--------------------------------------------
void BluetoothCheck(void)
{
unsigned long looptimeBT = millis(); //avoid an hangup in this loop
while (Bluetooth.available() and (millis() - looptimeBT < 10000) )
{
delay(3);
char c = Bluetooth.read();
Serial.print(c);
if (c>31 && c<128) BluetoothString += c;
else c = 0; // delete a CR
}
if (BluetoothString.length()>0)
ReworkInputString(BluetoothString); // Rework ReworkInputString();
BluetoothString = "";
}
#endif BLUETOOTHMOD
#ifdef DCFMOD
//--------------------------------------------
// CLOCK check for DCF input
//--------------------------------------------
void DCF77Check(void)
{
time_t DCFtime = DCF.getTime(); // Check if new DCF77 time is available
if (DCFtime!=0)
{
Tekstprint("DCF: Time is updated -----> ");
DCF_signal+=2;
setTime(DCFtime);
RTC.adjust(DCFtime);
// digitalClockDisplay(); *************************
}
bool LHbit = digitalRead(DCF_PIN);
digitalWrite(DCF_LED_Pin, 1 - LHbit ); // write inverted DCF pulse to LED on board
if (SeeDCFsignalInDisplay == true)
{
Toggle_HetWasIs = LHbit;
Display1 |= (Toggle_HetWasIs<<0); // Turn off the HET IS WAS LEDs
Displaytime();
}
DCF_signal = constrain(DCF_signal,0,99); // DCF_signal <100
}
#endif DCFMOD
//--------------------------------------------
// CLOCK check for serial input
//--------------------------------------------
void SerialCheck(void)
{
while (Serial.available())
{
delay(3);
char c = Serial.read();
if (c>31 && c<128) SerialString += c; // allow input from Space - Del
}
if (SerialString.length()>0) ReworkInputString(SerialString); // Rework ReworkInputString();
SerialString = "";
}
//--------------------------------------------
// CLOCK heartbeat
//--------------------------------------------
void heartbeat()
{
static unsigned long last_time = 0;
unsigned long now = millis();
if ((now - last_time) < 40) return;
last_time = now;
if (hbval > 230 || hbval < 20 ) hbdelta = -hbdelta;
hbval += hbdelta;
analogWrite(HeartbeatLED, hbval);
}
//------------------------ KY-040 rotary encoder -------------------------
//--------------------------------------------
// KY-040 ROTARY check if the rotary is moving
//
// Due to AC power spikes the rotary pins on the ATMEGA can detect an erroneous signal
// causing the time to change. Therefore the shaft has to be pressed before settings
// can be changed for a period of 60 seconds.
//--------------------------------------------
#ifdef ROTARYMOD
void RotaryEncoderCheck(void)
{
long encoderPos = myEnc.read();
if ( (unsigned long) (millis() - RotaryPressTimer) > 60000) // After 60 sec after shaft is pressed time of light intensity can not be changed
{
if (ChangeTime || ChangeLightIntensity)
{
Tekstprintln("<-- Changing time is over -->");
NoofRotaryPressed = 0;
}
ChangeTime = false;
ChangeLightIntensity = false;
}
if (ChangeTime || ChangeLightIntensity) // If shaft is pressed time of light intensity can be changed
{
if ( encoderPos && ( (millis() - Looptime) > 200)) // If rotary turned avoid debounce within 0.05 sec
{
Serial.print(F("----> Index:")); Serial.println(encoderPos);
if (encoderPos >0) // Increase MINUTES of light intensity
{
if (ChangeLightIntensity) { WriteLightReducer(0.05); } // If time < 60 sec then adjust light intensity factor
if (ChangeTime)
{
if (NoofRotaryPressed == 1) // Change hours
{
if( ++Ihour >23) { Ihour = 0; }
}
if (NoofRotaryPressed == 2) // Change minutes
{
Isecond = 0;
if( ++Iminute >59) { Iminute = 0; if( ++Ihour >23) { Ihour = 0; } }
}
}
}
if (encoderPos <0) // Increase the HOURS
{
if (ChangeLightIntensity) { WriteLightReducer(-0.05); } // If time < 60 sec then adjust light intensity factor
if (ChangeTime)
{
if (NoofRotaryPressed == 1) // Change hours
{
if( Ihour-- ==0) { Ihour = 23; }
}
if (NoofRotaryPressed == 2) // Change minutes
{
Isecond = 0;
if( Iminute-- == 0) { Iminute = 59; if( Ihour-- == 0) { Ihour = 23; } }
}
}
}
SetRTCTime();
Print_RTC_tijd();
myEnc.write(0); // Set encoder pos back to 0
Looptime = millis();
}
}
if (digitalRead(clearButton) == LOW ) // Set the time by pressing rotary button
{
delay(200);
ChangeTime = false;
ChangeLightIntensity = false;
SeeDCFsignalInDisplay = false;
RotaryPressTimer = millis(); // Record the time the shaft was pressed.
if(++NoofRotaryPressed >4 ) NoofRotaryPressed = 0;
switch (NoofRotaryPressed) // No of times the rotary is pressed
{
case 1: ChangeTime = true; BlinkUUR(3, 70); Displaytime(); break; // Change the hours
case 2: ChangeTime = true; BlinkHETISWAS(3, 70); Displaytime(); break; // Change the hours
case 3: ChangeLightIntensity = true; Display1=Display2=Display3=255; Laatzien(); break; // Turn on all LEDs and change intensity
#ifdef DCFMOD
case 4: SeeDCFsignalInDisplay = true; break; // Show DCF signal
#endif DCFMOD
default: NoofRotaryPressed = 0;
SeeDCFsignalInDisplay = ChangeTime = ChangeLightIntensity = false;
Selftest();
break; // Reset all settings
}
Serial.print(F("NoofRotaryPressed: ")); Serial.println(NoofRotaryPressed);
Toggle_HetWasIs = 1; // Make sure HET IS WAS is on
myEnc.write(0);
Looptime = millis();
}
myEnc.write(0);
}
#endif ROTARYMOD
//--------------------------------------------
// CLOCK Self test sequence
//--------------------------------------------
void Selftest(void)
{
GetTijd(1); //Prints time in Serial monitor
LedsOff();
#ifdef NL
HET; Laatzien(); IS; Laatzien(); WAS; Laatzien();
MVIJF; Laatzien(); MTIEN; Laatzien();
KWART; Laatzien(); VOOR; Laatzien();
OVER; Laatzien(); PRECIES; Laatzien();
HALF; Laatzien(); ELF; Laatzien();
VIJF; Laatzien(); TWEE; Laatzien();
EEN; Laatzien(); VIER; Laatzien();
TIEN; Laatzien(); TWAALF; Laatzien();
DRIE; Laatzien(); NEGEN; Laatzien();
ACHT; Laatzien(); ZES; Laatzien();
ZEVEN; Laatzien(); UUR; Laatzien();
EDSOFT; Laatzien();
#endif NL
#ifdef UK
HET; Laatzien(); IS; Laatzien(); WAS; Laatzien();
PRECIES; Laatzien(); HALF; Laatzien();
TWINTIG; Laatzien(); MVIJF; Laatzien();
KWART; Laatzien(); MTIEN; Laatzien();
OVER; Laatzien(); VOOR; Laatzien();
ZES; Laatzien(); TWEE; Laatzien();
VIJF; Laatzien(); TWAALF; Laatzien();
TIEN; Laatzien(); ELF; Laatzien();
VIER; Laatzien(); NEGEN; Laatzien();
DRIE; Laatzien(); ACHT; Laatzien();
ZEVEN; Laatzien(); EEN; Laatzien();
UUR; Laatzien();
#endif UK
for(int i=0; i<2; i++)
{
Display1=255; Display2=255; Display3=255; Laatzien();
Display1=0; Display2=0; Display3=0; Laatzien();
}
Play_Lights();
Displaytime();
}
// -------------------------- END Selftest
//--------------------------- Time functions --------------------------
//--------------------------------------------
// CLOCK set the LED's for displaying
//--------------------------------------------
void Displaytime(void)
{
LedsOff(); // start by clearing the display to a known state
HET; // HET light is always on
switch (Iminute)
{
#ifdef NL
case 0: IS; PRECIES; break;
case 1: IS; break;
case 2:
case 3: WAS; break;
case 4:
case 5:
case 6: IS; MVIJF; OVER; break;
case 7:
case 8: WAS; MVIJF; OVER; break;
case 9:
case 10:
case 11: IS; MTIEN; OVER; break;
case 12:
case 13: WAS; MTIEN; OVER; break;
case 14:
case 15:
case 16: IS; KWART; OVER; break;
case 17:
case 18: WAS; KWART; OVER; break;
case 19:
case 20:
case 21: IS; MTIEN; VOOR; HALF; break;
case 22:
case 23: WAS; MTIEN; VOOR; HALF; break;
case 24:
case 25:
case 26: IS; MVIJF; VOOR; HALF; break;
case 27:
case 28: WAS; MVIJF; VOOR; HALF; break;
case 29: IS; HALF; break;
case 30: IS; PRECIES; HALF; break;
case 31: IS; HALF; break;
case 32:
case 33: WAS; HALF; break;
case 34:
case 35:
case 36: IS; MVIJF; OVER; HALF; break;
case 37:
case 38: WAS; MVIJF; OVER; HALF; break;
case 39:
case 40:
case 41: IS; MTIEN; OVER; HALF; break;
case 42:
case 43: WAS; MTIEN; OVER; HALF; break;
case 44:
case 45:
case 46: IS; KWART; VOOR; break;
case 47:
case 48: WAS; KWART; VOOR; break;
case 49:
case 50:
case 51: IS; MTIEN; VOOR; break;
case 52:
case 53: WAS; MTIEN; VOOR; break;
case 54:
case 55:
case 56: IS; MVIJF; VOOR; break;
case 57:
case 58: WAS; MVIJF; VOOR; break;
case 59: IS; break;
#endif NL
#ifdef UK
case 0: IS; PRECIES; break;
case 1: IS; break;
case 2:
case 3: WAS; break;
case 4:
case 5:
case 6: IS; MVIJF; OVER; break;
case 7:
case 8: WAS; MVIJF; OVER; break;
case 9:
case 10:
case 11: IS; MTIEN; OVER; break;
case 12:
case 13: WAS; MTIEN; OVER; break;
case 14:
case 15:
case 16: IS; KWART; OVER; break;
case 17:
case 18: WAS; KWART; OVER; break;
case 19:
case 20:
case 21: IS; TWINTIG; OVER; break;
case 22:
case 23: WAS; TWINTIG; OVER; break;
case 24:
case 25:
case 26: IS; TWINTIG; MVIJF; OVER; break;
case 27:
case 28: WAS; TWINTIG; MVIJF; OVER; break;
case 29: IS; HALF; OVER; break;
case 30: IS; PRECIES; HALF; OVER; break;
case 31: IS; HALF; OVER; break;
case 32:
case 33: WAS; HALF; OVER; break;
case 34:
case 35:
case 36: IS; TWINTIG; MVIJF; VOOR; break;
case 37:
case 38: WAS; TWINTIG; MVIJF; VOOR; break;
case 39:
case 40:
case 41: IS; TWINTIG; VOOR; break;
case 42:
case 43: WAS; TWINTIG; VOOR; break;
case 44:
case 45:
case 46: IS; KWART; VOOR; break;
case 47:
case 48: WAS; KWART; VOOR; break;
case 49:
case 50:
case 51: IS; MTIEN; VOOR; break;
case 52:
case 53: WAS; MTIEN; VOOR; break;
case 54:
case 55:
case 56: IS; MVIJF; VOOR; break;
case 57:
case 58: WAS; MVIJF; VOOR; break;
case 59: IS; break;
#endif UK
#ifdef FR
case 0: IS; PRECIES; break;
case 1: IS; break;
case 2:
case 3: WAS; break;
case 4:
case 5:
case 6: IS; MVIJF; OVER; break;
case 7:
case 8: WAS; MVIJF; OVER; break;
case 9:
case 10:
case 11: IS; MTIEN; OVER; break;
case 12:
case 13: WAS; MTIEN; OVER; break;
case 14:
case 15:
case 16: IS; KWART; OVER; break;
case 17:
case 18: WAS; KWART; OVER; break;
case 19:
case 20:
case 21: IS; TWINTIG; OVER; break;
case 22:
case 23: WAS; TWINTIG; OVER; break;
case 24: