Hardware components | ||||||
| × | 1 | ||||
| × | 9 | ||||
| × | 1 | ||||
| × | 60 | ||||
| × | 12 | ||||
| × | 72 | ||||
| × | 1 | ||||
| × | 5 | ||||
| × | 1 | ||||
| × | 4 | ||||
Software apps and online services | ||||||
|
This is my first clock I made in 2004. I made the clock with digital ic's.
I used 4 bit shift registers, so I had to use 33 of them. And to debounce 4 switches I used NAND gates to do the job. Also to make 1 Hz clock, I used several divider ic's to slow down the 1 MHz crystal. My father in law engraved the front.
But the clock went to the attic.
Now I am retired and I rebuild it with arduino. The original clock is shown in the photo below.
I rebuild the clock and used all the 60 + 12 connections of the leds, so now I need 9 shifregisters (8 bit). Somehow I got a MM5451 35 bit shiftregister mounted on a printboard with 5 displays (7-segment led). I made a hole in the front and placed the displays in it. See photo below.
I made my own routines to read and set the RTC, so there is no need to load a RTC library. I am using the RTC 1 Hz SQW puls via interrupt pin 2 on the arduino. In the main loop the program is checking the state of the 4 switches. With 4 switches there are 16 functions.
The 16 functions are:
Function 1111:
Display: blank
Leds: time
Function 1110:
Display: time
Leds : time and moonage (see video below).
The blinking led is at position 46. Divide it by 2 = 23. The moon is 23 days old.
The blinking led moves two led positions a day.
So the four phases of the moon are:
When the led blinks at zero, it means: new moon
at 15 (divide by two = 7.5 days) = first quarter
at 30 (divide by two = 15 days) = full moon
at 45 (divide by two = 22.5 days) = last quarter
From new moon till the next new moon are 29.5 days.
All the next functions for the leds are: time and moonage. (except function 1011) So I only mention in the next functions what the display indicates.
Function 1101:
Date
Function 1100:
Maximum elevation of the sun (this depends of the latitude)
Function 1011:
Seconds
Function 1010:
Amount of days since januari first
Function 1001:
Sun rise (this depends of the latitude)
Function 1000:
Day Of Week
Function 0111:
Year
Function 0110:
Length of the day in hours
Function 0101:
Tilt of the earth
Function 0100:
Adjust (time, date, timesaving and aging register of the RTC)
Function 0011:
Moonage in days
Function 0010:
Seconds since midnight (max = 86400)
Function 0001:
Sun set (this depends of the latitude)
Function 0000:
Actual elevation of the sun (this depends of the latitude)
#define PI 3.141592653589793
#define DEG_TO_RAD 0.0174532925
#define RAD_TO_DEG 57.2957795130
#include <Wire.h>
#define CLK 5
#define Latch 6
#define dataBit 7// serial data
#define CLKMM 4 // to MM5451 pin 21
#define dataBitMM 3 // to MM5451 pin 22
#define DecPunt 8 // dot display
#define SW1 12
#define SW2 11
#define SW3 10
#define SW4 9
#include "Button2.h"; // https://github.com/LennartHennigs/Button2
#include "Rotary.h";
#define ROTARY_PIN1 A0
#define ROTARY_PIN2 A1
#define BUTTON_PIN A2
#define CLICKS_PER_STEP 4 // this number depends on your rotary encoder
#define MIN_POS -100
#define MAX_POS 100
#define START_POS 0
#define INCREMENT 1 // this number is the counter increment on each step
Button2 bt;
Rotary rt;
//------------------------------------------------
// 7-segment display code array MM5451
byte segCode[18] = {63, 6, 91, 79, 102, 109, 125, 7, 127, 111,
0b0001001, 0b1000000,
0b1011110, 0b0111001, 0b1011100,
0b1000000, 0b0000000, 0b0001000
};
//-----------------------------------------------
byte segCode2[12] = {
0b1000000, 0b0001001, 0b1011110,
0b1110111, 0b1101110, 0b0000000,
0b0100011, 0b0100111, 0b1001001,
0b0000000, 0b0111000, 0b1010100
};
//-------------------------------------------
byte bindec[10] = {
16,
8,
4,
2,
1,
16,
8,
4,
2,
1,
};
byte Maan[20] = { 2, 13, 24, 5, 16, 27, 8, 19, 30, 11, 22, 3, 14, 25, 6, 17, 29, 10, 21 };
// epacta getallen
//eerste getal 2 is het jaar 2017, maan is dan 2 dagen oud op 1 januari.
// volgende getal is 2018, maan is dan 13 dagen oud op 1 januari.
//elk jaar verschuift 11, behalve eens in de 19 jaar, dan 12.
// laatste was in 2014 dan in 2033, en in 2052, en in 2071 enz.
//
//----------------------english-------------------------------------------
//epacta numbers
// first number of array Maan[20] is 2. This number is the year 2017, the moon age in days is 2 on januari first
//The next number is 2018, the moon age in days is 13 also on januari first, etc..
// every year ads 11, except once in 19 years, then it wil be 12
// latest was in 2014, then in 2033 etc...
// moonage = 0 >> new moon, moonage = 15 >> full moon
// moonage = 7.5 >> first quarter, moonage = 22.5 >> last quarter
// from new moon to the next new moon = 29.5 days
byte Schrikkel = 0;
int Dagtotaal[12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
int DagtotaalS[12] = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
byte AR;
byte second;
int minute;
int hour;
byte weekday;
byte monthDay;
byte month;
byte Test;
byte test1;
byte test2;
byte test3;
byte test4;
int year;
byte Sjaar;
byte a = 0;
byte b = 0;
byte c = 0;
byte d = 0;
byte e = 0;
byte f = 0;
byte g = 0;
byte h = 0;
byte i = 0;
byte j = 0;
byte k = 0;
byte m = 0;
byte CodeSec[15];
byte CodeMin[15];
byte CodeLedMS[15];
byte Codemaan[15];
byte Lentepunt;
int Dagen;
float ZonOp;
float ZonOnder;
float MoonAge;
float DagLengte;
byte WT = 1;
// The variables HDT,TDT,DT,HT,TT and EH are used in the subroutine Factor();
long HDT;// hundred thousand ( when number is 123456, HDT = 1)
long TDT;// ten thousand ( when number is 123456, TDT = 2)
long DT;//thousand ( when number is 123456, DT = 3)
long HT;// hundred ( when number is 123456, HT = 4)
long TT;// tens ( when the number is 123456, TT = 5)
long EH;// unity (when the number is 123456, EH = 6)
byte cc;
volatile int encoderPos = 0;
boolean buttonPressed = 0; // a flag variabl
volatile byte secondsInterrupt = 0;
const byte interruptPin = 2;
int counter = 0;
//-------------------------------------------------------
void setup() {
pinMode(SW1, INPUT);
pinMode(SW2, INPUT);
pinMode(SW3, INPUT);
pinMode(SW4, INPUT);
pinMode(DecPunt, OUTPUT);
pinMode(CLK, OUTPUT);
pinMode(Latch, OUTPUT);
pinMode(dataBit, OUTPUT);
pinMode(CLKMM, OUTPUT);
pinMode(dataBitMM, OUTPUT);
pinMode(interruptPin, INPUT_PULLUP);
Serial.begin(9600);
Wire.begin();
attachInterrupt(digitalPinToInterrupt(interruptPin), secondsRTC, FALLING);
bt.begin(BUTTON_PIN);
bt.setPressedHandler(pressed);
bt.setReleasedHandler(released);
rt.begin(ROTARY_PIN1, ROTARY_PIN2, CLICKS_PER_STEP, MIN_POS, MAX_POS, START_POS, INCREMENT);
rt.setLeftRotationHandler(showDirection);
rt.setRightRotationHandler(showDirection);
zet_24uurmode();
SQW1hzOn();
digitalWrite(DecPunt, 1);
digitalWrite(dataBitMM, 1);
TijdUitlezen();
pulseCLKMM();
zeroWrite(35);
Reset60Led();
Displaytest();
Led60Test();
}
//------------------------------------------------------------------------
byte AgingRead() {
return leesroutine(16);
}
//------------------------------------------------------------------------
void zet_24uurmode() {// set 24 hour mode
byte uurreg;
uurreg = leesroutine(2);
if (uurreg > 64) { // bit 6 = 64, set to zero
uurreg = uurreg - 64;
instelroutine(2, uurreg);
}
}
//------------------------------------------------------------------------
byte lees_seconde() { // read seconds
return BcdToDec(leesroutine(0));
}
//------------------------------------------------------------------------
byte lees_minuut() { //read minute
return BcdToDec(leesroutine(1));
}
//------------------------------------------------------------------------
byte lees_uur() { // read hour
return BcdToDec(leesroutine(2));
}
//------------------------------------------------------------------------
byte lees_dagweek() { // read DOW
return BcdToDec(leesroutine(3));
}
//------------------------------------------------------------------------
byte lees_datum() { // read day of month
return BcdToDec(leesroutine(4));
}
//------------------------------------------------------------------------
byte lees_maand() { // read month
return BcdToDec(leesroutine(5));
}
//------------------------------------------------------------------------
byte lees_jaar() { // read year
return BcdToDec(leesroutine(6));
}
//------------------------------------------------------------------------
byte BcdToDec(byte val) {
return (val / 16 * 10) + (val % 16);// bcd to decimal
}
//------------------------------------------------------------------------
byte leesroutine(byte adres) {// read register of RTC
Wire.beginTransmission(0x68); // adress RTC DS1307 or DS3231
Wire.write(adres); // address register DS3231
Wire.endTransmission(); // einde I2C routine
Wire.requestFrom(0x68, 1);
return Wire.read();
}
//------------------------------------------------------------------------
void instelroutine(byte adres, byte data1) {// set register of RTC
Wire.beginTransmission(0x68); // adress RTC DS3231
Wire.write(adres); // address register DS3231
Wire.write(data1);
Wire.endTransmission(); // einde I2C routine
}
//------------------------------------------------------------------------
byte decToBcd(byte val) {
return ((val / 10 * 16) + (val % 10));
}
//------------------------------------------------------------------------
void Agingadjust(byte data1) {// fine adjust the frequency of the RTC
instelroutine(16, data1);
/*
Positive aging values add capacitance to the array, slowing the
oscillator frequency. Negative values remove capacitance from the array,
increasing the oscillator frequency. The change in ppm per LSB is different
at different temperatures. The frequency vs. temperature curve is shifted by
the values used in this registert. At +25C, one LSB typically
provides about 0.1ppm change in frequency.
*/
}
//------------------------------------------------------------------------
void SQW1hzOn() {// switch the 1 Hz SQW on
instelroutine(14, 0);
}
//------------------------------------------------------------------------
void zet_jaar(byte data1) { // set year
instelroutine(6, decToBcd(data1));
}
//------------------------------------------------------------------------
void zet_maand(byte data1) { // set month
instelroutine(5, decToBcd(data1));
}
//------------------------------------------------------------------------
void zet_datum(byte data1) { // set day of month
instelroutine(4, decToBcd(data1));
}
//------------------------------------------------------------------------
void zet_dagweek(byte data1) { // set DOW
instelroutine(3, decToBcd(data1));
}
//------------------------------------------------------------------------
void zet_uur(byte data1) { // set hour
instelroutine(2, decToBcd(data1));
}
//------------------------------------------------------------------------
void zet_minuut(byte data1) { // set minute
instelroutine(1, decToBcd(data1));
}
//------------------------------------------------------------------------
void zet_seconde(byte data1) { // set second
instelroutine(0, decToBcd(data1));
}
//----------------------------------------------------------
void TijdUitlezen() {
second = lees_seconde();
minute = lees_minuut();
hour = lees_uur();
weekday = lees_dagweek(); //0-6 -> sunday - Saturday
monthDay = lees_datum();
month = lees_maand();
year = lees_jaar();
// Serial.println(year);
Sjaar = year;
// seconde uitlezen///
Factor(second, false);
a = EH;
b = TT;
Factor(minute, false);
c = EH;
d = TT;
// uur uitlezen///
Factor(hour, false);
e = EH;
f = TT;
// dag uitlezen///
Factor(monthDay, false);
g = EH;
h = TT;
// maand uitlezen///
Factor(month, false);
i = EH;
j = TT;
// jaar uitlezen///
Factor(year, false);
k = EH;
m = TT;
//Serial.println(second);
}
// --------------------------------------------------------
void Schrikkeljaar() {
Sjaar %= 4; // %= is remainder --------
if (Sjaar == 0) {
Schrikkel = 1;
Lentepunt = 81;
Dagen = 366;
} else {
Schrikkel = 0;
Lentepunt = 80;
Dagen = 365;
}
}
// ------------------------------------------------------------------
void showDirection(Rotary& rt) {
//Serial.println(rt.getDirection());
counter = rt.getDirection();
if (counter == 255)
{
counter = -1;
}
else
{
counter = 1;
}
encoderPos += counter;
//Serial.println(encoderPos);
}
//--------------------------------------------------------
void pressed(Button2& btn) {
//Serial.print("pressed ");
buttonPressed = 1;
//Serial.println(buttonPressed);
}
void released(Button2& btn) {
// Serial.print("released: ");
buttonPressed = 0;
//Serial.println(buttonPressed);
}
//---------------------------------------------
void Factor(long Getal, bool graden) {
long Test;
//Serial.println(Getal);
Test = Getal;
HDT = Test / 100000;
Test = Test - (HDT * 100000);
TDT = Test / 10000;
Test = Test - (TDT * 10000);
DT = Test / 1000;
Test = Test - (DT * 1000);
HT = Test / 100;
Test = Test - (HT * 100);
if (graden == true) {// if true : decimaal to degree conversion
Test = Test * 0.6;
}
TT = Test / 10;
Test = Test - (TT * 10);
EH = Test;
}
//--------------------------------------------------------------------------------
void secondsRTC(void) { // *** ISR iedere seconde ***
secondsInterrupt = 1; // ISR vlag = 1 : er was een 'seconds' interrupt.
}
//------------------------------------------------------------------------
void readtime() {
second = lees_seconde();// read seconds
// seconde uitlezen///
Factor(second, false);
a = EH;
b = TT;
if (second == 0) {
minute = lees_minuut();// read minutes
// minuut uitlezen///
Factor(minute, false);
c = EH;
d = TT;
}
if (minute == 0 & second == 0) {
hour = lees_uur();// read hour
// uur uitlezen///
Factor(hour, false);
e = EH;
f = TT;
}
if (hour == 0 & second == 0) {
weekday = lees_dagweek(); //0-6 -> sunday - Saturday
monthDay = lees_datum();// read day of month
month = lees_maand();// read month
year = lees_jaar();// read year
// dag uitlezen///
Factor(monthDay, false);
g = EH;
h = TT;
// maand uitlezen///
Factor(month, false);
i = EH;
j = TT;
Factor(year, false);
k = EH;
m = TT;
}
}
//---------------------------------------------------------
void loop() {
test1 = digitalRead(SW1); // read the switch
test2 = digitalRead(SW2);
test3 = digitalRead(SW3);
test4 = digitalRead(SW4);
Test = test4 * 8;
Test += test3 * 4;
Test += test2 * 2;
Test += test1;
if (secondsInterrupt == 1) { // **** doe als ISR vlag = 1 ****
readtime(); // de subroutine die iedere seconde de tijd registers leest.
if (Test == 4) {
Reset60Led();
} else {
Led60AanSturen();// update 60 + 12 leds
}
secondsInterrupt = 0; // zet ISR vlag terug naar '0'
}
switch (Test) {
case 15: //1111
digitalWrite(DecPunt, 1); // DecPunt = display dot >> 1 = ON and 0 = OFF
LEDDisplayBLANK(); // regel 872
break;
case 14: //1110
digitalWrite(DecPunt, 1);
LedTijd(); // time
break;
case 13: //1101
digitalWrite(DecPunt, 1);
Leddatum(); // date
break;
case 12: //1100
digitalWrite(DecPunt, 0);
LCDAzimuth(); // elevation of the sun
break;
case 11: //1011
digitalWrite(DecPunt, 1);
LedSeconde(); // seconds
break;
case 10: //1010
digitalWrite(DecPunt, 1);
DagNR(); // amount of days since januari first
break;
case 9: //1001
digitalWrite(DecPunt, 1);
Zonsopgang(); // sun rise
break;
case 8: //1000
digitalWrite(DecPunt, 1);
LedDOW(); // Dau Of Week
break;
case 7: //0111
digitalWrite(DecPunt, 1);
Ledjaar(); // year
break;
case 6: //0110
digitalWrite(DecPunt, 0);
DagDuur(); // Length of day in hours
break;
case 5: //0101
digitalWrite(DecPunt, 0);
SchStand(); // tilt of earth
break;
case 4: //0100
digitalWrite(DecPunt, 1);
Adjust(); // adjust
break;
case 3: //0011
digitalWrite(DecPunt, 0);
LedMaanOuderdom(); // moon age in days
break;
case 2: //0010
digitalWrite(DecPunt, 1);
DagSEC(); // seconds since midnight
break;
case 1: //0001
digitalWrite(DecPunt, 1);
Zonsondergang(); // sun set
break;
case 0: //0000
digitalWrite(DecPunt, 0);
HzonNU(); // present elevation of the sun
break;
}
}
// -------------end loop -----------------------
//------------------------------------------------------------------------------------
void Adjust() {
rt.loop();
bt.loop();
if (encoderPos < 0) {
encoderPos = 0;
}
if (encoderPos > 8) {
encoderPos = 8;
}
switch (encoderPos) {
case 0:
DisplayAjust();
break;
case 1:
Displaykeuze1(64);
if (encoderPos == 1 && buttonPressed == 1) {
encoderPos = 0;
AdjustUUR();
}
break;
case 2:
DisplaykeuzeWT(64);
if (encoderPos == 2 && buttonPressed == 1) {
encoderPos = 0;
AdjustWT();
}
break;
case 3:
Displaykeuze3(64);
if (encoderPos == 3 && buttonPressed == 1) {
encoderPos = 0;
AdjustMIN();
}
break;
case 4:
Displaykeuze4(64);
if (encoderPos == 4 && buttonPressed == 1) {
encoderPos = 0;
AdjustDAG();
}
break;
case 5:
Displaykeuze5(64);
if (encoderPos == 5 && buttonPressed == 1) {
encoderPos = 0;
AdjustMND();
}
break;
case 6:
Displaykeuze6(64);
if (encoderPos == 6 && buttonPressed == 1) {
encoderPos = 0;
AdjustYR();
}
break;
case 7:
Displaykeuze7(64);
if (encoderPos == 7 && buttonPressed == 1) {
encoderPos = 0;
AdjustDOW();
}
break;
case 8:
AR = AgingRead();
Displaykeuze8(AR);
if (encoderPos == 8 && buttonPressed == 1) {
encoderPos = 0;
AdjustAging();
}
break;
}
}
// ------------------------------------------------------
void DisplayAjust() {
DDMM(120, 109, 30, 94, 119);
}
//-------------------------------------------------------------
void AdjustUUR() {
int exx = 0;
Displaykeuze1(73);
encoderPos = 0;
buttonPressed = 0;
while (exx == 0) {
rt.loop();
bt.loop();
if (encoderPos == 0) {
Factor(hour, false);
e = EH;
f = TT;
Displaykeuze1(64); // uur
}
//-----------------
if (encoderPos > 1) {
hour = hour + 1;
if (hour == 24) {
hour = 0;
}
Factor(hour, false);
e = EH;
f = TT;
Displaykeuze1(1); // uur
encoderPos = 1;
}
// --------------------------
if (encoderPos < -1) {
hour = hour - 1;
if (hour < 0) {
hour = 23;
}
Factor(hour, false);
e = EH;
f = TT;
Displaykeuze1(8); // uur
encoderPos = -1;
}
if (buttonPressed == 1 & encoderPos != 0) {
zet_uur(hour);// set hour
Displaykeuze1(9); // uur
encoderPos = 0;
exx = 1;
}
}
}
// ------------------------------------------------------
void Displaykeuze1(int x) {
DDMM(segCode[e], segCode[f], x, 80, 116);
}
//-------------------------------------------------------------
void AdjustWT() {//daylight saving time >> 1 = summer time, 0 = winter time
int exx = 0;
encoderPos = 0;
buttonPressed = 0;
DisplaykeuzeWT(73);
while (exx == 0) {
rt.loop();
bt.loop();
if (encoderPos == 0) {
DisplaykeuzeWT(64);
}
//-----------------
if (encoderPos > 1) {
WT = 1;
DisplaykeuzeWT(1);
encoderPos = 1;
}
// --------------------------
if (encoderPos < -1) {
WT = 0;
DisplaykeuzeWT(8);
encoderPos = -1;
}
if (buttonPressed == 1 & encoderPos != 0) {
DisplaykeuzeWT(9);
encoderPos = 0;
exx = 1;
}
}
}
// ------------------------------------------------------
void DisplaykeuzeWT(int x) {
DDMM(segCode[WT], 0, x, 120, 120);
}
//-----------------------------------------------------------
void AdjustMIN() {
int exx = 0;
Displaykeuze3(73);
encoderPos = 0;
buttonPressed = 0;
while (exx == 0) {
rt.loop();
bt.loop();
if (encoderPos == 0) {
Displaykeuze3(64); // min
}
//-----------------
if (encoderPos > 1) {
minute = minute + 1;
if (minute == 60) {
minute = 0;
}
Factor(minute, false);
c = EH;
d = TT;
Displaykeuze3(1); // min
encoderPos = 1;
}
// --------------------------
if (encoderPos < -1) {
minute = minute - 1;
if (minute < 0) {
minute = 59;
}
Factor(minute, false);
c = EH;
d = TT;
Displaykeuze3(8); // uur
encoderPos = -1;
}
if (buttonPressed == 1 & encoderPos != 0) {
zet_seconde(0);// set second
zet_minuut(minute);// set minute
Displaykeuze3(9); // min
encoderPos = 0;
exx = 1;
}
}
}
// ------------------------------------------------------
void Displaykeuze3(int x) {
DDMM(segCode[c], segCode[d], x, 84, 55);
}
//----------------------------------------------------------
void AdjustDAG() {
int exx = 0;
Displaykeuze4(73);
encoderPos = 0;
buttonPressed = 0;
while (exx == 0) {
rt.loop();
bt.loop();
if (encoderPos == 0) {
Displaykeuze4(64); // min
}
//-----------------
if (encoderPos > 1) {
monthDay = monthDay + 1;
if (monthDay == 32) {
monthDay = 1;
}
Factor(monthDay, false);
g = EH;
h = TT;
Displaykeuze4(1); // min
encoderPos = 1;
}
// --------------------------
if (encoderPos < -1) {
monthDay = monthDay - 1;
if (monthDay == 0) {
monthDay = 31;
}
Factor(monthDay, false);
g = EH;
h = TT;
Displaykeuze4(8); // uur
encoderPos = -1;
}
if (buttonPressed == 1 & encoderPos != 0) {
zet_datum(monthDay);// set monthday
Displaykeuze4(9); // min
encoderPos = 0;
buttonPressed = 0;
exx = 1;
}
}
}
// ------------------------------------------------------
void Displaykeuze4(int x) {
DDMM(segCode[g], segCode[h], x, 110, 94);
}
//-------------------------------------------------------
void AdjustMND() {
int exx = 0;
Displaykeuze5(73);
encoderPos = 0;
buttonPressed = 0;
while (exx == 0) {
rt.loop();
bt.loop();
if (encoderPos == 0) {
Displaykeuze5(64);
}
//-----------------
if (encoderPos > 1) {
month = month + 1;
if (month > 12) {
month = 1;
}
Factor(month, false);
i = EH;
j = TT;
Displaykeuze5(1);
encoderPos = 1;
}
// --------------------------
if (encoderPos < -1) {
month = month - 1;
if (month == 0) {
month = 12;
}
Factor(month, false);
i = EH;
j = TT;
Displaykeuze5(8);
encoderPos = -1;
}
if (buttonPressed == 1 & encoderPos != 0) {
zet_maand(month);// set month
Displaykeuze5(9);
encoderPos = 0;
exx = 1;
}
}
}
// ------------------------------------------------------
void Displaykeuze5(int x) {
DDMM(segCode[i], segCode[j], x, 94, 55);
}
//------------------------------------------------------
void AdjustYR() {
int exx = 0;
encoderPos = 0;
buttonPressed = 0;
Displaykeuze6(73);
if (year > 2000) {
year = year - 2000;
}
while (exx == 0) {
rt.loop();
bt.loop();
if (encoderPos == 0) {
Displaykeuze6(64); // min
}
//-----------------
if (encoderPos > 1) {
year = year + 1;
if (year > 99) {
year = 0;
}
Factor(year, false);
k = EH;
m = TT;
Displaykeuze6(1); // min
encoderPos = 1;
}
// --------------------------
if (encoderPos < -1) {
year = year - 1;
if (year < 0) {
year = 99;
}
Factor(year, false);
k = EH;
m = TT;
Displaykeuze6(8); // uur
encoderPos = -1;
}
if (buttonPressed == 1 & encoderPos != 0) {
zet_jaar(year);// set year
Displaykeuze6(9); // min
encoderPos = 0;
exx = 1;
}
}
}
// ------------------------------------------------------
void Displaykeuze6(int x) {
DDMM(segCode[k], segCode[m], x, 80, 110);
}
//------------------------------------------------------
void AdjustDOW() {
int exx = 0;
encoderPos = 0;
buttonPressed = 0;
Displaykeuze7(73);
while (exx == 0) {
rt.loop();
bt.loop();
if (encoderPos == 0) {
Displaykeuze7(64); //
}
//-----------------
if (encoderPos > 1) {
weekday = weekday + 1;
if (weekday > 7) {
weekday = 7; // 1 = maandag , 2 = dinsdag enz.
}
Displaykeuze7(1); //
encoderPos = 1;
}
// --------------------------
if (encoderPos < -1) {
weekday = weekday - 1;
if (weekday < 1) {
weekday = 1;
}
Displaykeuze7(8); //
encoderPos = -1;
}
if (buttonPressed == 1 & encoderPos != 0) {
zet_dagweek(weekday);// setDOW
Displaykeuze7(9); //
encoderPos = 0;
exx = 1;
}
}
}
// ------------------------------------------------------
void Displaykeuze7(int x) {
DDMM(segCode[weekday], x, 110, 119, 94);
}
//------------------------------------------------------
void AdjustAging() {
int exx = 0;
encoderPos = 0;
buttonPressed = 0;
Displaykeuze8(AR);
AR = AgingRead();
while (exx == 0) {
Displaykeuze8(AR);
rt.loop();
bt.loop();
if (encoderPos == 0) {
Displaykeuze8(AR);
}
//-----------------
if (encoderPos > 1) {
AR = AR + 1;
if (AR > 127) {
AR = 0;
}
Displaykeuze8(AR);
encoderPos = 1;
}
// --------------------------
if (encoderPos < -1) {
AR = AR - 1;
if (AR < -128) {
AR = 0;
}
Displaykeuze8(AR);
encoderPos = -1;
}
if (buttonPressed == 1 & encoderPos != 0) {
Agingadjust(AR);
Displaykeuze8(AR);
encoderPos = 0;
buttonPressed = 0;
exx = 1;
}
}
}
// ------------------------------------------------------
void Displaykeuze8(byte ARR) {
int RR;
// aging register of RTC uses two's complement, a negative number is from 128 to 255
RR = ARR;
if (RR >= 0 & RR < 128) {
Factor(RR, false);
DDMM(segCode[EH], segCode[TT], segCode[HT], 0, 119);
}
else
{
RR = RR - 256;
RR = abs(RR);
Factor(RR, false);
DDMM(segCode[EH], segCode[TT], segCode[HT], 64, 119);
}
}
//----------------------------------------------
void pulseCLK() {
digitalWrite(CLK, 1);
digitalWrite(CLK, 0);
}
//-------------------------------------------------
void pulseCLKMM() {
digitalWrite(CLKMM, 1);
digitalWrite(CLKMM, 0);
}
//-------------------------------------------------------------
// LSB out first!
void ssrWriteLSB(byte value) {
for (int x = 0; x < 5; x++) {
byte temp = value & 0x01;
if (temp == 0x01) {
digitalWrite(dataBit, 1); // data bit HIGH
} else {
digitalWrite(dataBit, 0); // data bit LOW
}
pulseCLK();
value = value >> 0x01; // shift right
}
}
//----------------------------------------------------------
void DDMM(byte D1, byte D2, byte D3, byte D4, byte D5) {
digitalWrite(dataBitMM, 1);
pulseCLKMM();
ssrWriteLSBMM(D1);
ssrWriteLSBMM(D2);
ssrWriteLSBMM(D3);
ssrWriteLSBMM(D4);
ssrWriteLSBMM(D5);
zeroWrite(1); // pad remaining bits with 0s (35-35)+1
}
//----------------------------------------------------------
void ssrWriteLSBMM(byte value) {
for (int x = 0; x < 7; x++) {
byte temp = value & 0x01;
if (temp == 0x01) {
digitalWrite(dataBitMM, 1); // data bit HIGH
} else {
digitalWrite(dataBitMM, 0); // data bit LOW
}
pulseCLKMM();
value = value >> 0x01; // shift right
}
}
//------------------------------------------------------------------
// MSB out first!
void ssrWriteMSB(byte value) {
for (int x = 0; x < 5; x++) {
byte temp = value & 0x80;
if (temp == 0x80) digitalWrite(dataBit, 1); // data bit HIGH
else
digitalWrite(dataBit, 0); // data bit LOW
pulseCLK();
value = value << 0x01; // shift left
}
}
//---------------------------------------------------------
void zeroWrite(byte num1) {
digitalWrite(dataBitMM, 0); // data bit LOW
for (int x = 0; x < num1; x++)
pulseCLKMM();
}
//---------------------------------------------------------
void LedSeconde() {
DDMM(segCode[a], segCode[b], 64, 64, 64);
}
//--------------------------------------------------------
void LedTijd() {
int test = second;
test %= 2; //%= is remainder ----
if (test == 1) {
DDMM(segCode[c], segCode[d], 9, segCode[e], segCode[f]);
} else {
DDMM(segCode[c], segCode[d], 64, segCode[e], segCode[f]);
}
}
//-----------------------------------------------------------------
void Led60AanSturen() {
SecondenAansturen();// update seconds
if (second == 0) {
MinutenAanSturen();// update minutes
}
if (minute == 0 & second == 0) {
UrenAansturen();// update hours
LEDMaan();// update moon
}
if (CodeLedMS[0] == 0 & CodeLedMS[1] == 0 & CodeLedMS[2] == 0) {
MinutenAanSturen();
UrenAansturen();
LEDMaan();
}
CodeOR();
digitalWrite(Latch, 1);
for (int x = 0; x < 15; x++) {
ssrWriteLSB(CodeLedMS[x]);
}
digitalWrite(Latch, 0);
}
//---------------------------------------------------------------
void SecondenAansturen() {
// b = seconds tenth
//a = seconds unity
for (byte x = 0; x < 15; x++) {
CodeSec[x] = 0; // 15 nullen in codeSec zetten
}
// a = 0 .... 9
// b = 0,1,2,3,4 or 5
// cc = segment 14 t/m 3
//segment 14 = led 0 t/m 4, segment 13 = led 5 t/m 9
//segment 12 = led 10 t/m 14, segment 11 = led 15 t/m 19
//segment 10 = led 20 t/m 24, segment 9 = led 25 t/m 29
//segment 8 = led 30 t/m 34, segment 7 = led 35 t/m 39
//segment 6 = led 40 t/m 44, segment 5 = led 45 t/m 49
//segment 4 = led 50 t/m 54, segment 3 = led 55 t/m 59
//b=0, led 0 t/m 9,
//b=1, led 10 t/m 19
//b=2, led 20 t/m 29
//b=3, led 30 t/m 39
//b=4, led 40 t/m 49
//b=5, led 50 t/m 59
cc = 14 - (b * 2);
if (a < 5) {
CodeSec[cc] = bindec[a];
} else {
CodeSec[cc - 1] = bindec[a];
}
/*
switch (b)// b = seconden tientallen
{
case 0:// ------ van 0 tot/m 9 seconden----------------
if (a < 5) // a = seconden eenheden
{
CodeSec[14] = bindec[a]; //1 x data
}
else
{
CodeSec[13] = bindec[a]; //1 x data
}
break;
case 1: // van 10 tot/m 19 seconden------------------------
if (a < 5) // a = seconden eenheden
{
CodeSec[12] = bindec[a]; //1 x data
}
else
{
CodeSec[11] = bindec[a]; //1 x data
}
break;
case 2: // van 20 tot 29 seconden--------------------
if (a < 5) // a = seconden eenheden
{
CodeSec[10] = bindec[a]; //1 x data
}
else
{
CodeSec[9] = bindec[a]; //1 x data
}
break;
case 3:// van 30 tot 39 seconden---------------------
if (a < 5) // a = seconden eenheden
{
CodeSec[8] = bindec[a]; //1 x data
}
else
{
CodeSec[7] = bindec[a]; //1 x data
}
break;
case 4: // van 40 tot 49 seconden-------------------------
if (a < 5) // a = seconden eenheden
{
CodeSec[6] = bindec[a]; //1 x data
}
else
{
CodeSec[5] = bindec[a]; //1 x data
}
break;
case 5: // van 50 tot 59 seconden-------------------------
if (a < 5) // a = seconden eenheden
{
CodeSec[4] = bindec[a]; //1 x data
}
else
{
CodeSec[3] = bindec[a]; //1 x data
}
break;
}
*/
}
//-----------------------------------------------------------------------------------
void MinutenAanSturen() {
for (byte x = 0; x < 15; x++) {
CodeMin[x] = 0; // 15 nullen in codeMin zetten
}
// d = 0,1,2,3,4 of 5
//cc = ledcode[d];
cc = 14 - (d * 2);
if (c < 5) {
CodeMin[cc] = bindec[c];
} else {
CodeMin[cc - 1] = bindec[c];
}
}
//-----------------------------------------------------------------------
void UrenAansturen() {
byte ee;
byte ff;
byte uur;
uur = hour;
//uur = 0;
if (uur >= 12) {
uur = uur - 12;
}
// uur uitlezen///
Factor(uur, false);
ee = EH; // eenheden
ff = TT; // tientallen
//f=1;
//e=1;
CodeLedMS[0] = 0;
CodeLedMS[1] = 0;
CodeLedMS[2] = 0;
switch (ff) {
case 0:
if (ee < 5) // ee = uren eenheden
{
CodeLedMS[2] = bindec[ee]; //1 x data
} else {
CodeLedMS[1] = bindec[ee]; //1 x data
}
break;
case 1:
CodeLedMS[0] = bindec[ee]; //1 x data
break;
}
}
//--------------------------------------------------------------
void CodeOR() {
for (byte aa = 3; aa < 15; aa++) {
// minuten met seconden OR bewerking ------------------------------
CodeLedMS[aa] = CodeMin[aa] | CodeSec[aa]; // "|" = OR functie
}
switch (Test) {
case 15: //1111
// do nothing
break;
default:
byte testsec = second;
testsec %= 2;
if (testsec == 0) {
// minuten en seconden met maan OR bewerking -------------------
for (byte aa = 3; aa < 15; aa++) {
CodeLedMS[aa] = Codemaan[aa] | CodeLedMS[aa];
}
}
break;
}
//for (int x = 0; x < 15; x++) {
// Serial.print("CodeMS: ");
// Serial.print(x);
// Serial.print(" ");
// Serial.println(CodeLedMS[x]);
// }
}
//--------------------------------------------------------------
void Reset60Led() {
for (byte x = 0; x < 15; x++) {
CodeLedMS[x] = 0;
}
for (byte x = 0; x < 15; x++) {
ssrWriteLSB(CodeLedMS[x]);
}
}
// ---------------------------------------------------------------------
void Led60Test() {
byte aa;
byte bb;
byte cc1;
for (byte x = 0; x < 60; x++) {
Factor(x, false);
aa = EH;
bb = TT;
cc1 = 14 - (bb * 2);
if (aa < 5) {
CodeLedMS[cc1] = bindec[aa];
} else {
CodeLedMS[cc1 - 1] = bindec[aa];
}
digitalWrite(Latch, 1);
for (int xx = 3; xx < 15; xx++) {
ssrWriteLSB(CodeLedMS[xx]);
}
digitalWrite(Latch, 0);
delay(100);
for (byte x = 0; x < 15; x++) {
CodeLedMS[x] = 0; // 15 nullen in codeledMS zetten
}
}
}
//--------------------------------------------------------------
void Leddatum() {
DDMM(segCode[i], segCode[j], 64, segCode[g], segCode[h]);
}
// ---------------------------------------------------------
void Ledjaar() {
DDMM(segCode[k], segCode[m], segCode[0], segCode[2], segCode[16]);
}
//------------------------------------------------------------
void LedDOW() {
DDMM(segCode[weekday], segCode2[5], segCode2[4], segCode2[3], segCode2[2]);
}
//--------------------------------------------------------------
void LedMaanOuderdom() {
LEDMaan();
float Oud;
Oud = MoonAge;
Factor(Oud * 100, false);
DDMM(segCode[EH], segCode[TT], segCode[HT], segCode[DT], segCode2[6]);
}
// -----------------------------------------------------------
void LEDDisplayBLANK() {
DDMM(segCode[16], segCode[16], segCode[16], segCode[16], segCode[16]);
}
//--------------------------------------------------------------
byte segCode1[24] = {
0b0000001, 0b0000010, 0b0000100,
0b0001000, 0b0010000, 0b0100000,
0b1000000, 0b1001001, 0b1000000,
0b1001001, 0b1000000, 0b1001001,
0b1000000, 0b0111111, 0b0000110,
0b1011011, 0b1001111, 0b1100110,
0b1101101, 0b1111101, 0b0000111,
0b1111111, 0b1101111, 0b1110110
};
//--------------------------------------------------------------
void Displaytest() {
// start bit
for (int x = 0; x < 23; x++) {
DDMM(segCode1[x], segCode1[x], segCode1[x], segCode1[x], segCode1[x]);
delay(300);
}
delay(1000);
}
//-----------------------------------------------------------------
void LEDMaan() {
float Uur1;
float Min1;
float MOud;
int Index;
float AZ;
int v = 0;
int w = 0;
int Jaar;
Schrikkeljaar();
AZ = TotaalDagen(month);
Min1 = minute;
Uur1 = hour + (Min1 / 60);
AZ = AZ + monthDay;
AZ = AZ + (Uur1 / 24);
Jaar = year;
if (year > 2000) {
year = year - 2000;
}
Index = year - 17; // epactagetal ophalen
while (Index > 18) {
Index = Index - 19;
}
//Serial.println(Index);
MOud = Maan[Index];
//Serial.println(MOud);
MOud = MOud + AZ;
//Serial.println(MOud);
while (MOud >= 29.5305885) {
MOud -= 29.5305885;
}
for (int x = 0; x < 15; x++) {
Codemaan[x] = 0; // 15 nullen in codemaan zetten
}
//MOud = 0;
MoonAge = MOud;
MOud *= 2;
MOud *= 1.0158896; // = 30/29.5305885
MOud = int(MOud);
//Serial.print("MOud: ");
//Serial.println(MOud);
Factor(MOud, false);
v = EH;
w = TT;
//cc = ledcode[w];
cc = 14 - (w * 2);
if (v < 5) {
Codemaan[cc] = bindec[v];
} else {
Codemaan[cc - 1] = bindec[v];
}
}
// ------------------------------------------------
void DagDuur() {
float BB;
float AZ;
float Decc;
Schrikkeljaar();
AZ = TotaalDagen(month);
AZ = AZ - Lentepunt + monthDay;
Decc = Declinatie(AZ, Dagen);
ZonOpOnder(Decc, 52.9); // aanroepen routine JaarDagen();
BB = DagLengte;
Factor(BB * 100, true);
digitalWrite(dataBitMM, 1);
DDMM(segCode[EH], segCode[TT], segCode[HT], segCode[DT], segCode2[10]);
}
//----------------------------------------------------------------
void SchStand() {
float BB;
float BB2;
float AZ;
Schrikkeljaar();
AZ = TotaalDagen(month);
//AZ = 345;
AZ = (AZ - Lentepunt) + monthDay;
BB = Declinatie(AZ, Dagen);
BB2 = BB;
BB2 = abs(BB2); // fabs = absoluut
Factor(BB2 * 100, true);
if (BB >= 0) {
DDMM(segCode[EH], segCode[TT], segCode[HT], segCode[DT], segCode[16]);
} else {
DDMM(segCode[EH], segCode[TT], segCode[HT], segCode[DT], segCode[15]);
}
}
//--------------------------------------------------------------------------
void LCDAzimuth() {
float BB;
float AZ;
float Decc;
Schrikkeljaar();
AZ = TotaalDagen(month);
//AZ = 180;
AZ = (AZ - Lentepunt) + monthDay;
Decc = Declinatie(AZ, Dagen);
BB = Hoogte(Decc, 52.9);
Factor(BB * 100, true);
DDMM(segCode[EH], segCode[TT], segCode[HT], segCode[DT], segCode1[23]);
}
//-------------------------------------------------
float Tijdvereffening(float dd) {
float Tijd;
float TVV;
Tijd = (7.56 * SINUS((2 * 180 * (dd - 2.7)) / Dagen));
Tijd = Tijd + (9.85 * (SINUS((4 * 180 * (10.5 + dd)) / Dagen)));
TVV = (Tijd / 60);
return TVV;
}
//---------------------------------------------------------
void Zonsondergang() {
float BB;
float AZ;
float Decc;
float ZZ;
float TVE;
float DM;
Schrikkeljaar();
AZ = TotaalDagen(month);
AZ = AZ - Lentepunt + monthDay;
Decc = Declinatie(AZ, Dagen);
ZonOpOnder(Decc, 52.9); // aanroepen routine
ZZ = ZonOnder + 0.683333;
ZZ += WT;
AZ += Lentepunt;
TVE = Tijdvereffening(AZ);
ZZ += TVE;
Factor(ZZ * 100, true);
DDMM(segCode[EH], segCode[TT], segCode2[1], segCode[HT], segCode[DT]);
}
//---------------------------------------------------------
void Zonsopgang() {
float BB;
float AZ;
float Decc;
float ZZ;
float TVE;
float DM;
Schrikkeljaar();
AZ = TotaalDagen(month);
AZ = AZ - Lentepunt + monthDay;
Decc = Declinatie(AZ, Dagen);
ZonOpOnder(Decc, 52.9); // aanroepen routine
ZZ = ZonOp + 0.683333;
ZZ += WT;
AZ += Lentepunt;
TVE = Tijdvereffening(AZ);
ZZ += TVE;
Factor(ZZ * 100, true);
DDMM(segCode[EH], segCode[TT], segCode2[1], segCode[HT], segCode[DT]);
}
//------------------------------------------------------
void DagSEC() {
long DS;
long uur;
uur = hour;
DS = (uur * 3600);
DS += (minute * 60);
DS += second;
Factor(DS, false);
DDMM(segCode[EH], segCode[TT], segCode[HT], segCode[DT], segCode[TDT]);
}
// --------------------------------------------------------------
void DagNR() {
long DR;
int AA;
int HB;
int LB;
int HSB;
int LSB;
Schrikkeljaar();
DR = TotaalDagen(month) + monthDay;
Factor(DR, false);
DDMM(segCode[EH], segCode[TT], segCode[HT], segCode2[1], segCode2[2]);
}
// -------------------------------------------------------------------
int TotaalDagen(int maand) { // dit is een functie
int Dagen;
int dag1 = maand - 1;
if (Schrikkel == 1) {
Dagen = DagtotaalS[dag1];
} else {
Dagen = Dagtotaal[dag1];
}
return Dagen;
}
//-----------------------------------------------
float Hoogte(float decl, float brg) {
float HGT;
float HGT2;
HGT = (SINUS(brg) * SINUS(decl)) + (COSINUS(brg) * COSINUS(decl));
HGT2 = ARCSINUS(HGT);
return HGT2;
}
// ------------------------------------------------
void HzonNU() {
float Tijd1;
float AZ;
float Decc;
float TVE;
float Tijd2;
float HGTE;
float Hoogte;
float ZZ;
Tijd1 = hour + (minute / 60.0);
Tijd1 = Tijd1 + (second / 3600.0);
Tijd1 = Tijd1 - WT - 0.683333;
Schrikkeljaar();
AZ = TotaalDagen(month);
AZ = AZ - Lentepunt + monthDay;
Decc = Declinatie(AZ, Dagen);
AZ = AZ + Lentepunt;
TVE = Tijdvereffening(AZ);
Tijd1 = Tijd1 - TVE;
Tijd2 = (Tijd1 * 15.0) - 180.0;
HGTE = (SINUS(52.9) * SINUS(Decc)) + (COSINUS(52.9) * COSINUS(Decc) * COSINUS(Tijd2));
Hoogte = ARCSINUS(HGTE);
// Serial.print("hoogte: ");
//Serial.println(Hoogte);
ZZ = Hoogte;
ZZ = abs(ZZ); // fabs = absoluut
Factor(ZZ * 100, true);
if (Hoogte >= 0) {
DDMM(segCode[EH], segCode[TT], segCode[HT], segCode[DT], segCode[16]);
} else {
DDMM(segCode[EH], segCode[TT], segCode[HT], segCode[DT], segCode[15]);
}
}
//-------------------------------------------------
double ARCTANGENS(double x) {
double XX;
XX = x;
return atan(XX) * RAD_TO_DEG;
}
//-------------------------------------------------
double ARCCOSINUS(double x) {
double XX;
XX = x;
return acos(XX) * RAD_TO_DEG;
}
//-------------------------------------------------
double ARCSINUS(double x) {
double XX;
XX = x;
return asin(XX) * RAD_TO_DEG;
}
//-------------------------------------------------
double TANGENS(double x) {
double XX;
XX = x * DEG_TO_RAD;
return tan(XX);
}
//-------------------------------------------------
double COSINUS(double x) {
double XX;
XX = x * DEG_TO_RAD;
return cos(XX);
}
//-------------------------------------------------
double SINUS(double x) {
double XX;
XX = x * DEG_TO_RAD;
return sin(XX);
}
// -----------------------------------------------
double Declinatie(float dag, float Jaardag) {
double DECL;
DECL = (dag * 360.0 / Jaardag);
DECL = SINUS(DECL);
return DECL = DECL * 23.5;
}
//--------------------------------------------------
void ZonOpOnder(float decl, float brg) {
float ZON;
float ZonOpOn;
float AA2 = 180.0;
float BB2 = 15.0;
float gr = -1.25;
ZON = (SINUS(gr) - (SINUS(brg) * (SINUS(decl)))) / (COSINUS(brg) * COSINUS(decl));
ZonOpOn = ARCCOSINUS(ZON);
ZonOp = (AA2 - ZonOpOn) / BB2;
ZonOnder = (AA2 + ZonOpOn) / BB2;
DagLengte = ZonOnder - ZonOp;
}
//----------------------------------------------------
Comments