Nixie clock
- Войдите на сайт для отправки комментариев
Втр, 27/09/2016 - 09:26
При настройке имеено часов перескок 05 часов до 12часов.
В чем проблема?
#include <EEPROM.h>
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 RTC;
// K155ID1 : Truth Table
//D C B A #
//L,L,L,L 0
//L,L,L,H 1
//L,L,H,L 2
//L,L,H,H 3
//L,H,L,L 4
//L,H,L,H 5
//L,H,H,L 6
//L,H,H,H 7
//H,L,L,L 8
//H,L,L,H 9
// K155ID1 (1)
int ledPin_0_a = 2;
int ledPin_0_b = 3;
int ledPin_0_c = 4;
int ledPin_0_d = 5;
// K155ID1 (2)
int ledPin_1_a = 6;
int ledPin_1_b = 7;
int ledPin_1_c = 8;
int ledPin_1_d = 9;
// anode pins
int ledPin_a_1 = 10;
int ledPin_a_2 = 11;
int ledPin_a_3 = 12;
int ledPin_a_4 = 13;
void setup()
{
Serial.begin(57600);
Wire.begin();
RTC.begin();
if (! RTC.isrunning()){
Serial.println("RTC is NOT running!");
// following line sets the RTC to the date & time this sketch was compiled.
RTC.adjust(DateTime(__DATE__, __TIME__));
}
pinMode(ledPin_0_a, OUTPUT);
pinMode(ledPin_0_b, OUTPUT);
pinMode(ledPin_0_c, OUTPUT);
pinMode(ledPin_0_d, OUTPUT);
pinMode(ledPin_1_a, OUTPUT);
pinMode(ledPin_1_b, OUTPUT);
pinMode(ledPin_1_c, OUTPUT);
pinMode(ledPin_1_d, OUTPUT);
pinMode(ledPin_a_1, OUTPUT);
pinMode(ledPin_a_2, OUTPUT);
pinMode(ledPin_a_3, OUTPUT);
pinMode(ledPin_a_4, OUTPUT);
// NOTE: All analog pins as digital inputs with pull-up resistor activated.
pinMode(A0, INPUT_PULLUP); // Set (Press for > 1sec)
pinMode(A1, INPUT_PULLUP); // Mode switch
pinMode(A2, INPUT_PULLUP); // Pair selection
pinMode(A3, INPUT_PULLUP); // Increase switch
pinMode(A6, INPUT_PULLUP); // Decrease switch
pinMode(A7, OUTPUT); // Alarm tone will be sent there
}
void SetSN74141Chips( int num2, int num1 )
{
int a,b,c,d;
// set defaults.
a=0;b=0;c=0;d=0; // will display a zero.
// Load the a,b,c,d.. to send to the SN74141 IC (1)
switch( num1 )
{
case 0: a=0;b=0;c=0;d=0;break;
case 1: a=1;b=0;c=0;d=0;break;
case 2: a=0;b=1;c=0;d=0;break;
case 3: a=1;b=1;c=0;d=0;break;
case 4: a=0;b=0;c=1;d=0;break;
case 5: a=1;b=0;c=1;d=0;break;
case 6: a=0;b=1;c=1;d=0;break;
case 7: a=1;b=1;c=1;d=0;break;
case 8: a=0;b=0;c=0;d=1;break;
case 9: a=1;b=0;c=0;d=1;break;
default: a=1;b=1;c=1;d=1;
break;
}
// Write to output pins.
digitalWrite(ledPin_0_d, d);
digitalWrite(ledPin_0_c, c);
digitalWrite(ledPin_0_b, b);
digitalWrite(ledPin_0_a, a);
// Load the a,b,c,d.. to send to the SN74141 IC (2)
switch( num2 )
{
case 0: a=0;b=0;c=0;d=0;break;
case 1: a=1;b=0;c=0;d=0;break;
case 2: a=0;b=1;c=0;d=0;break;
case 3: a=1;b=1;c=0;d=0;break;
case 4: a=0;b=0;c=1;d=0;break;
case 5: a=1;b=0;c=1;d=0;break;
case 6: a=0;b=1;c=1;d=0;break;
case 7: a=1;b=1;c=1;d=0;break;
case 8: a=0;b=0;c=0;d=1;break;
case 9: a=1;b=0;c=0;d=1;break;
default: a=1;b=1;c=1;d=1;
break;
}
// Write to output pins
digitalWrite(ledPin_1_d, d);
digitalWrite(ledPin_1_c, c);
digitalWrite(ledPin_1_b, b);
digitalWrite(ledPin_1_a, a);
}
float fadeMax = 5.0f;
float fadeStep = 1.0f;
int NumberArray[6]={0,0,0,0,0,0};
int currNumberArray[6]={0,0,0,0,0,0};
float NumberArrayFadeInValue[6]={0.0f,0.0f,0.0f,0.0f,0.0f,0.0f};
float NumberArrayFadeOutValue[6]={8.0f,8.0f,8.0f,8.0f,8.0f,8.0f};
void DisplayFadeNumberString()
{
// Anode channel 1 - numerals 0,3
SetSN74141Chips(currNumberArray[0],currNumberArray[3]);
digitalWrite(ledPin_a_2, HIGH);
delay(NumberArrayFadeOutValue[0]);
SetSN74141Chips(NumberArray[0],NumberArray[3]);
delay(NumberArrayFadeInValue[0]);
digitalWrite(ledPin_a_2, LOW);
// Anode channel 2 - numerals 1,4
SetSN74141Chips(currNumberArray[1],currNumberArray[4]);
digitalWrite(ledPin_a_3, HIGH);
delay(NumberArrayFadeOutValue[1]);
SetSN74141Chips(NumberArray[1],NumberArray[4]);
delay(NumberArrayFadeInValue[1]);
digitalWrite(ledPin_a_3, LOW);
// Anode channel 3 - numerals 2,5
SetSN74141Chips(currNumberArray[2],currNumberArray[5]);
digitalWrite(ledPin_a_4, HIGH);
delay(NumberArrayFadeOutValue[2]);
SetSN74141Chips(NumberArray[2],NumberArray[5]);
delay(NumberArrayFadeInValue[2]);
digitalWrite(ledPin_a_4, LOW);
// Loop thru and update all the arrays, and fades.
for( int i = 0 ; i < 6 ; i ++ )
{
if( NumberArray[i] != currNumberArray[i] )
{
NumberArrayFadeInValue[i] += fadeStep;
NumberArrayFadeOutValue[i] -= fadeStep;
if( NumberArrayFadeInValue[i] >= fadeMax )
{
NumberArrayFadeInValue[i] = 0.0f;
NumberArrayFadeOutValue[i] = fadeMax;
currNumberArray[i] = NumberArray[i];
}
}
}
}
//Read the EEPROM just at switch-on.
int ClockHourSet = word(EEPROM.read(1), EEPROM.read(0)); //Reconstruction the integer form the two bytes saved on the EEPROM.
int ClockMinSet = word(EEPROM.read(3), EEPROM.read(2));
int ClockSecSet = word(EEPROM.read(5), EEPROM.read(4));
int ClockDaySet = word(EEPROM.read(7), EEPROM.read(6));
int ClockMonthSet = word(EEPROM.read(9), EEPROM.read(8));
int ClockYearSet = word(EEPROM.read(11), EEPROM.read(10));
int AlmHours = word(EEPROM.read(13), EEPROM.read(12));
int AlmMins = word(EEPROM.read(15), EEPROM.read(14));
byte AlmArmed= EEPROM.read(16); // Used as flag as well as indicator on the tube themselves (0 or 1).
byte Mode = 1; //1: time, 2: date, 3: alarm
byte ModeButtonPressed = false;
byte Set = 1; //1: left, 2: middle, 3: right
long SetTimer = 0;
byte SETMODE = false;
byte SETMODEentered = false;
byte SetButtonPressed = false;
byte IncreaseButtonPressed = false;
byte DecreaseButtonPressed = false;
byte AlmButtonPressed = false;
int nixState = HIGH;
int toneState = LOW;
long previousTimeBlink = 0;
long previousTimeTone= 0;
byte AlmPlaying=false;
void loop(){
// Get milliseconds.
unsigned long runTime = millis();
// MODE SELECTION ///////////////////////////////////
/////////////////////////////////////////////////////
byte ModeInput = digitalRead(A1);
if(ModeInput==0) ModeButtonPressed = true;
if (Mode==1 && ModeButtonPressed==true && ModeInput==1)
{
Mode = 2; //Switching from Time to Date mode
ModeButtonPressed = false;
}
if (Mode==2 && ModeButtonPressed==true && ModeInput==1)
{
Mode = 3; //Switching from Date to Alarm mode
ModeButtonPressed = false;
}
if (Mode==3 && ModeButtonPressed==true && ModeInput==1)
{
Mode = 1; //Switching from Alarm to Time mode
ModeButtonPressed = false;
}
// ALARM ARMING /////////////////////////////////////
/////////////////////////////////////////////////////
if(Mode==3 && AlmPlaying==false){
int AlmInput = analogRead(A6);
if(AlmInput==0) AlmButtonPressed = true;
if(AlmButtonPressed==true && AlmInput>250){
if(AlmArmed==true) AlmArmed=false;
else AlmArmed=true;
AlmButtonPressed = false;
}
}
// SETTING //////////////////////////////////////////
/////////////////////////////////////////////////////
byte SetInput = digitalRead(A0);
if(SetInput==0) SetButtonPressed = true;
while(SetInput==0){
SetTimer++;
delay(10);
SetInput = digitalRead(A0);
}
if(SetTimer>=70){
if(SETMODE==false) SETMODE=true; //A long press will either enter or exit the setting mode option.
else SETMODE=false;
}
SetTimer=0; //Reinitializing.
if(SETMODE==true){
SETMODEentered=true;
if (Set==1 && SetButtonPressed==true && SetInput==1)
{
Set = 2; //Switching from left to middle pair available for setting.
SetButtonPressed = false;
}
if (Set==2 && SetButtonPressed==true && SetInput==1)
{
Set = 3; //Switching from middle to right pair available for setting.
SetButtonPressed = false;
}
if (Set==3 && SetButtonPressed==true && SetInput==1)
{
Set = 1; //Switching from right to left pair available for setting.
SetButtonPressed = false;
}
//Now we set the selected the pair of tube, let's modify its value:
int DecreaseInput = digitalRead(A3);
int IncreaseInput = digitalRead(A2);
if(DecreaseInput==0) DecreaseButtonPressed = true;
if(IncreaseInput==0) IncreaseButtonPressed = true;
if(DecreaseButtonPressed==true && DecreaseInput==1)
{
if(Set==1){
if(Mode==1) ClockHourSet--;
if(Mode==2) ClockDaySet--;
if(Mode==3) AlmHours--;
}
if(Set==2){
if(Mode==1) ClockMinSet--;
if(Mode==2) ClockMonthSet--;
if(Mode==3) AlmMins--;
}
if(Set==3){
if(Mode==1) ClockSecSet--;
if(Mode==2) ClockYearSet--;
}
DecreaseButtonPressed = false;
}
if(IncreaseButtonPressed==true && IncreaseInput==1)
{
if(Set==1){
if(Mode==1) ClockHourSet++;
if(Mode==2) ClockDaySet++;
if(Mode==3) AlmHours++;
}
if(Set==2){
if(Mode==1) ClockMinSet++;
if(Mode==2) ClockMonthSet++;
if(Mode==3) AlmMins++;
}
if(Set==3){
if(Mode==1) ClockSecSet++;
if(Mode==2) ClockYearSet++;
}
IncreaseButtonPressed = false;
}
}
long TimeShift = ClockSecSet + 60*ClockMinSet + 3600*ClockHourSet + 86400*ClockDaySet + 2678400*ClockMonthSet + 31536000*ClockYearSet;
//Saving to EEPROM after exiting the SETMODE
if(SETMODE==false && SETMODEentered==true){
SETMODEentered=false;
byte lowCHS = lowByte(ClockHourSet); //Split the 2-bytes integer into the respecting "high" and "low" parts in order to save them on the EEPROM.
byte highCHS = highByte(ClockHourSet);
byte lowCMS = lowByte(ClockMinSet);
byte highCMS = highByte(ClockMinSet);
byte lowCSS = lowByte(ClockSecSet);
byte highCSS = highByte(ClockSecSet);
byte lowCDS = lowByte(ClockDaySet);
byte highCDS = highByte(ClockDaySet);
byte lowCOS = lowByte(ClockMonthSet);
byte highCOS = highByte(ClockMonthSet);
byte lowCYS = lowByte(ClockYearSet);
byte highCYS = highByte(ClockYearSet);
byte lowAH = lowByte(AlmHours);
byte highAH = highByte(AlmHours);
byte lowAM = lowByte(AlmMins);
byte highAM = highByte(AlmMins);
EEPROM.write(0, lowCHS); EEPROM.write(1, highCHS); //Saving
EEPROM.write(2, lowCMS); EEPROM.write(3, highCMS);
EEPROM.write(4, lowCSS); EEPROM.write(5, highCSS);
EEPROM.write(6, lowCDS); EEPROM.write(7, highCDS);
EEPROM.write(8, lowCOS); EEPROM.write(9, highCOS);
EEPROM.write(10, lowCYS); EEPROM.write(11, highCYS);
EEPROM.write(12, lowAH); EEPROM.write(13, highAH);
EEPROM.write(14, lowAM); EEPROM.write(15, highAM);
EEPROM.write(16, AlmArmed);
}
// TIME RETRIEVING //////////////////////////////////
/////////////////////////////////////////////////////
DateTime now = RTC.now();
DateTime future = (now.unixtime() + TimeShift);
// Convert time to days,hours,mins,seconds
long Year = future.year()%100;
long Month = future.month();
long Day = future.day();
long hours = future.hour();
long minutes = future.minute();
long seconds = future.second();
// Get the high and low order values for hours,min,seconds.
byte lowerHours = hours % 10;
byte upperHours = hours - lowerHours;
byte lowerMins = minutes % 10;
byte upperMins = minutes - lowerMins;
byte lowerSeconds = seconds % 10;
byte upperSeconds = seconds - lowerSeconds;
if( upperSeconds >= 10 ) upperSeconds = upperSeconds / 10;
if( upperMins >= 10 ) upperMins = upperMins / 10;
if( upperHours >= 10 ) upperHours = upperHours / 10;
// Same for date.
byte lowerYears = Year % 10;
byte upperYears = Year - lowerYears;
byte lowerMonths = Month % 10;
byte upperMonths = Month - lowerMonths;
byte lowerDays = Day % 10;
byte upperDays = Day - lowerDays;
if( upperDays >= 10 ) upperDays = upperDays / 10;
if( upperMonths >= 10 ) upperMonths = upperMonths / 10;
if( upperYears >= 10 ) upperYears = upperYears / 10;
// ALM RULES /////////////////////////////////
//////////////////////////////////////////////
if(AlmHours>23) AlmHours=AlmHours-24; //After 23:00 comes 00:00
if(AlmHours<0) AlmHours=AlmHours+23; //vice-versa
if(AlmMins>59) AlmMins=AlmMins-60; //same thing
if(AlmMins<0) AlmMins=AlmMins+59;
// Splitting.
byte lowerAlmHours = AlmHours % 10;
byte upperAlmHours = AlmHours - lowerAlmHours;
byte lowerAlmMins = AlmMins % 10;
byte upperAlmMins = AlmMins - lowerAlmMins;
if( upperAlmMins >= 10 ) upperAlmMins = upperAlmMins / 10;
if( upperAlmHours >= 10 ) upperAlmHours = upperAlmHours / 10;
//Alm actions:
if(AlmArmed==true){
if(upperAlmHours==upperHours && lowerAlmHours==lowerHours && upperAlmMins==upperMins && lowerAlmMins==lowerMins && upperSeconds==0 && lowerSeconds==0){
AlmPlaying = true; //Alarm rings when the time matches the pre-entered alarm values.
}
}
if(AlmPlaying==true){
if(runTime-previousTimeTone > 500){ //Play an intermittent (1s period) tune.
previousTimeTone = runTime;
if(toneState == HIGH){
tone(10, 200); //Tune is 200Hz.
toneState=LOW;
}
else{
noTone(10);
toneState=HIGH;
}
}
if(digitalRead(A0)==LOW || digitalRead(A1)==LOW || digitalRead(A2)==LOW || digitalRead(A3)==LOW) AlmPlaying=false; //Press anything to stop it.
}
else noTone(10);
// SHOWTIME /////////////////////////////////////////
/////////////////////////////////////////////////////
// Fill in the Number array used to display on the tubes following the Mode.
if(Mode==1){
if(SETMODE==true){
if(Set==1){
if(runTime-previousTimeBlink > 500){ //Blinking these digits while in setmode.
previousTimeBlink = runTime;
if(nixState == LOW){
NumberArray[5] = 11; //Turning this pair off.
NumberArray[1] = 11;
nixState = HIGH;
}
else{
NumberArray[5] = upperHours; //Turning this pair on again.
NumberArray[1] = lowerHours;
nixState = LOW;
}
}
NumberArray[3] = upperMins; //Makes sure no pair stays off even if left in that state in the previous set mode.
NumberArray[2] = lowerMins;
NumberArray[4] = upperSeconds;
NumberArray[0] = lowerSeconds;
}
if(Set==2){
if(runTime-previousTimeBlink > 500){ //Blinking these digits while in setmode.
previousTimeBlink = runTime;
if(nixState == LOW){
NumberArray[3] = 11;
NumberArray[2] = 11;
nixState = HIGH;
}
else{
NumberArray[3] = upperMins;
NumberArray[2] = lowerMins;
nixState = LOW;
}
}
NumberArray[5] = upperHours;
NumberArray[1] = lowerHours;
NumberArray[4] = upperSeconds;
NumberArray[0] = lowerSeconds;
}
if(Set==3){
if(runTime-previousTimeBlink > 500){ //Blinking these digits while in setmode.
previousTimeBlink = runTime;
if(nixState == LOW){
NumberArray[4] = 11;
NumberArray[0] = 11;
nixState = HIGH;
}
else{
NumberArray[4] = upperSeconds;
NumberArray[0] = lowerSeconds;
nixState = LOW;
}
}
NumberArray[5] = upperHours;
NumberArray[1] = lowerHours;
NumberArray[3] = upperMins;
NumberArray[2] = lowerMins;
}
}
else{ //Fill the digits normally.
NumberArray[5] = upperHours;
NumberArray[1] = lowerHours;
NumberArray[3] = upperMins;
NumberArray[2] = lowerMins;
NumberArray[4] = upperSeconds;
NumberArray[0] = lowerSeconds;
}
DisplayFadeNumberString();// Display time.
if((lowerMins==5)&&upperSeconds==0&&lowerSeconds==1)//lighting all the numbers every 10min to prevent cathode poisoning.
{
for(int j=-1; j<11; j++){//alternating to make it more beautiful. the -1 and 11 value will turn the digits off to mark a short pause.
NumberArray[5] = j;
NumberArray[1] = 9-j;
NumberArray[3] = j;
NumberArray[2] = 9-j;
NumberArray[4] = j;
NumberArray[0] = 9-j;
int k = 0;
while(k<10){
DisplayFadeNumberString();// Clean each nixie digits for 2 seconds.
k++;
delay(1);
}
}
}
if(lowerMins==3 && upperSeconds==0 && lowerSeconds==1){ //Display date only on every (03,13,23,33) mins.
NumberArray[5] = upperDays;
NumberArray[1] = lowerDays;
NumberArray[3] = upperMonths;
NumberArray[2] = lowerMonths;
NumberArray[4] = upperYears;
NumberArray[0] = lowerYears;
int k = 0;
while(k<550){ // Display date for 10 seconds (50 = 1sec).
DisplayFadeNumberString(); // Display date.
k++;
delay(1);
}
}
}
if(Mode==2){
if(SETMODE==true){
if(Set==1){
if(runTime-previousTimeBlink > 500){ //Blinking these digits while in setmode.
previousTimeBlink = runTime;
if(nixState == LOW){
NumberArray[5] = 11; //Turning this pair off.
NumberArray[1] = 11;
nixState = HIGH;
}
else{
NumberArray[5] = upperDays;
NumberArray[1] = lowerDays;
nixState = LOW;
}
}
NumberArray[3] = upperMonths;
NumberArray[2] = lowerMonths;
NumberArray[4] = upperYears;
NumberArray[0] = lowerYears;
}
if(Set==2){
if(runTime-previousTimeBlink > 500){ //Blinking these digits while in setmode.
previousTimeBlink = runTime;
if(nixState == LOW){
NumberArray[3] = 11;
NumberArray[2] = 11;
nixState = HIGH;
}
else{
NumberArray[3] = upperMonths;
NumberArray[2] = lowerMonths;
nixState = LOW;
}
}
NumberArray[5] = upperDays;
NumberArray[1] = lowerDays;
NumberArray[4] = upperYears;
NumberArray[0] = lowerYears;
}
if(Set==3){
if(runTime-previousTimeBlink > 500){ //Blinking these digits while in setmode.
previousTimeBlink = runTime;
if(nixState == LOW){
NumberArray[4] = 11;
NumberArray[0] = 11;
nixState = HIGH;
}
else{
NumberArray[4] = upperYears;
NumberArray[0] = lowerYears;
nixState = LOW;
}
}
NumberArray[5] = upperDays;
NumberArray[1] = lowerDays;
NumberArray[3] = upperMonths;
NumberArray[2] = lowerMonths;
}
}
else{ //Fill the digits normally.
NumberArray[5] = upperDays;
NumberArray[1] = lowerDays;
NumberArray[3] = upperMonths;
NumberArray[2] = lowerMonths;
NumberArray[4] = upperYears;
NumberArray[0] = lowerYears;
}
DisplayFadeNumberString(); // Display date.
}
if(Mode==3){
if(SETMODE==true){
if(Set==1){
if(runTime-previousTimeBlink > 500){ //Blinking these digits while in setmode.
previousTimeBlink = runTime;
if(nixState == LOW){
NumberArray[5] = 11; //Turning this pair off.
NumberArray[1] = 11;
nixState = HIGH;
}
else{
NumberArray[5] = upperAlmHours;
NumberArray[1] = lowerAlmHours;
nixState = LOW;
}
}
NumberArray[3] = upperAlmMins;
NumberArray[2] = lowerAlmMins;
NumberArray[0] = AlmArmed; //1: armed, 0: not armed
}
if(Set==2){
if(runTime-previousTimeBlink > 500){ //Blinking these digits while in setmode.
previousTimeBlink = runTime;
if(nixState == LOW){
NumberArray[3] = 11;
NumberArray[2] = 11;
nixState = HIGH;
}
else{
NumberArray[3] = upperAlmMins;
NumberArray[2] = lowerAlmMins;
nixState = LOW;
}
}
NumberArray[5] = upperAlmHours;
NumberArray[1] = lowerAlmHours;
NumberArray[0] = AlmArmed;
}
if(Set==3) Set=1; //Dirty fix to convert a 3-cycle into a 2-cycle.
}
else{ //Fill the digits normally.
NumberArray[5] = upperAlmHours;
NumberArray[1] = lowerAlmHours;
NumberArray[3] = upperAlmMins;
NumberArray[2] = lowerAlmMins;
NumberArray[0] = AlmArmed;
}
NumberArray[4] = 11; //Eleven will turn off the tube
DisplayFadeNumberString(); // Display alarm.
}
}
вы суровый чел
заставляете смотреть 660 строк кода
таких героев здесь не много))))
Могу другой скинуть, там ошибка не правильно показывает дату. Только год и месец.
#include "pitches.h" #include <EEPROM.h> #include <Wire.h> #include <RTClib.h> RTC_DS1307 RTC; // SN74141 : Truth Table //D C B A # //L,L,L,L 0 //L,L,L,H 1 //L,L,H,L 2 //L,L,H,H 3 //L,H,L,L 4 //L,H,L,H 5 //L,H,H,L 6 //L,H,H,H 7 //H,L,L,L 8 //H,L,L,H 9 // SN74141 (1) int ledPin_0_a = 2; int ledPin_0_b = 3; int ledPin_0_c = 4; int ledPin_0_d = 5; // SN74141 (2) int ledPin_1_a = 6; int ledPin_1_b = 7; int ledPin_1_c = 8; int ledPin_1_d = 9; // anode pins //int ledPin_a_1 = 10; now used for Alarm output int ledPin_a_2 = 11; int ledPin_a_3 = 12; int ledPin_a_4 = 13; // notes in the melody int melody[] = { NOTE_C7, NOTE_C7, NOTE_C7, NOTE_C7, NOTE_C7 }; // note duration: 4 =quater note, 8 = eight note, ect.: int noteDurations[] = { 2, 2, 2, 2, 2 }; void setup() { Serial.begin(57600); Wire.begin(); RTC.begin(); if (! RTC.isrunning()){ Serial.println("RTC is NOT running!"); // following line sets the RTC to the date & time this sketch was compiled RTC.adjust(DateTime(__DATE__, __TIME__)); } pinMode(ledPin_0_a, OUTPUT); pinMode(ledPin_0_b, OUTPUT); pinMode(ledPin_0_c, OUTPUT); pinMode(ledPin_0_d, OUTPUT); pinMode(ledPin_1_a, OUTPUT); pinMode(ledPin_1_b, OUTPUT); pinMode(ledPin_1_c, OUTPUT); pinMode(ledPin_1_d, OUTPUT); pinMode(ledPin_a_2, OUTPUT); pinMode(ledPin_a_3, OUTPUT); pinMode(ledPin_a_4, OUTPUT); // NOTE: All analog pins as digital inputs with pull-up resistor activated. pinMode(A1, INPUT_PULLUP); // Mode swicth pinMode(A0, INPUT_PULLUP); // Set (Press for >3sec) pinMode(A6, INPUT_PULLUP); // Alarm arming pinMode(A3, INPUT_PULLUP); // increase pinMode(A2, INPUT_PULLUP); // decrease pinMode(10, OUTPUT); // Alarm tone will be sent there } void SetSN74141Chips( int num2, int num1 ) { int a,b,c,d; // set defaults. a=0;b=0;c=0;d=0; // will display a zero. // Load the a,b,c,d.. to send to the SN74141 IC (1) switch( num1 ) { case 0: a=0;b=0;c=0;d=0;break; case 1: a=1;b=0;c=0;d=0;break; case 2: a=0;b=1;c=0;d=0;break; case 3: a=1;b=1;c=0;d=0;break; case 4: a=0;b=0;c=1;d=0;break; case 5: a=1;b=0;c=1;d=0;break; case 6: a=0;b=1;c=1;d=0;break; case 7: a=1;b=1;c=1;d=0;break; case 8: a=0;b=0;c=0;d=1;break; case 9: a=1;b=0;c=0;d=1;break; default: a=1;b=1;c=1;d=1; break; } // Write to output pins. digitalWrite(ledPin_0_d, d); digitalWrite(ledPin_0_c, c); digitalWrite(ledPin_0_b, b); digitalWrite(ledPin_0_a, a); // Load the a,b,c,d.. to send to the SN74141 IC (2) switch( num2 ) { case 0: a=0;b=0;c=0;d=0;break; case 1: a=1;b=0;c=0;d=0;break; case 2: a=0;b=1;c=0;d=0;break; case 3: a=1;b=1;c=0;d=0;break; case 4: a=0;b=0;c=1;d=0;break; case 5: a=1;b=0;c=1;d=0;break; case 6: a=0;b=1;c=1;d=0;break; case 7: a=1;b=1;c=1;d=0;break; case 8: a=0;b=0;c=0;d=1;break; case 9: a=1;b=0;c=0;d=1;break; default: a=1;b=1;c=1;d=1; break; } // Write to output pins digitalWrite(ledPin_1_d, d); digitalWrite(ledPin_1_c, c); digitalWrite(ledPin_1_b, b); digitalWrite(ledPin_1_a, a); } float fadeMax = 5.0f; float fadeStep = 1.0f; int NumberArray[6]={0,0,0,0,0,0}; int currNumberArray[6]={0,0,0,0,0,0}; float NumberArrayFadeInValue[6]={0.0f,0.0f,0.0f,0.0f,0.0f,0.0f}; float NumberArrayFadeOutValue[6]={8.0f,8.0f,8.0f,8.0f,8.0f,8.0f}; void DisplayFadeNumberString() { // Anode channel 1 - numerals 0,3 SetSN74141Chips(currNumberArray[0],currNumberArray[3]); digitalWrite(ledPin_a_2, HIGH); delay(NumberArrayFadeOutValue[0]); SetSN74141Chips(NumberArray[0],NumberArray[3]); delay(NumberArrayFadeInValue[0]); digitalWrite(ledPin_a_2, LOW); // Anode channel 2 - numerals 1,4 SetSN74141Chips(currNumberArray[1],currNumberArray[4]); digitalWrite(ledPin_a_3, HIGH); delay(NumberArrayFadeOutValue[1]); SetSN74141Chips(NumberArray[1],NumberArray[4]); delay(NumberArrayFadeInValue[1]); digitalWrite(ledPin_a_3, LOW); // Anode channel 3 - numerals 2,5 SetSN74141Chips(currNumberArray[2],currNumberArray[5]); digitalWrite(ledPin_a_4, HIGH); delay(NumberArrayFadeOutValue[2]); SetSN74141Chips(NumberArray[2],NumberArray[5]); delay(NumberArrayFadeInValue[2]); digitalWrite(ledPin_a_4, LOW); // Loop thru and update all the arrays, and fades. for( int i = 0 ; i < 6 ; i ++ ) { if( NumberArray[i] != currNumberArray[i] ) { NumberArrayFadeInValue[i] += fadeStep; NumberArrayFadeOutValue[i] -= fadeStep; if( NumberArrayFadeInValue[i] >= fadeMax ) { NumberArrayFadeInValue[i] = 0.0f; NumberArrayFadeOutValue[i] = fadeMax; currNumberArray[i] = NumberArray[i]; } } } } //Read the EEPROM just at switch-on. int ClockHourSet = word(EEPROM.read(1), EEPROM.read(0)); //Reconstruction the integer form the two bytes saved on the EEPROM. int ClockMinSet = word(EEPROM.read(3), EEPROM.read(2)); int ClockSecSet = word(EEPROM.read(5), EEPROM.read(4)); int ClockDaySet = word(EEPROM.read(7), EEPROM.read(6)); int ClockMonthSet = word(EEPROM.read(9), EEPROM.read(8)); int ClockYearSet = word(EEPROM.read(11), EEPROM.read(10)); int AlmHours = word(EEPROM.read(13), EEPROM.read(12)); int AlmMins = word(EEPROM.read(15), EEPROM.read(14)); byte Mode = 1; //1: time, 2: date, 3: alarm byte ModeButtonPressed = false; byte Set = 1; //1: left, 2: middle, 3: right long SetTimer = 0; byte SETMODE = false; byte SETMODEentered = false; byte SetButtonPressed = false; byte IncreaseButtonPressed = false; byte DecreaseButtonPressed = false; byte AlmButtonPressed = false; int nixState = HIGH; int toneState = LOW; long previousTimeBlink = 0; long previousTimeTone= 0; byte AlmArmed=false; // Used as flag as well as indicator on the tube themselves (0 or 1). byte AlmPlaying=false; void loop(){ // Get milliseconds. unsigned long runTime = millis(); // MODE SELECTION /////////////////////////////////// ///////////////////////////////////////////////////// byte ModeInput = digitalRead(A1); if(ModeInput==0) ModeButtonPressed = true; if (Mode==1 && ModeButtonPressed==true && ModeInput==1) { Mode = 2; //Switching from Time to Date mode ModeButtonPressed = false; } if (Mode==2 && ModeButtonPressed==true && ModeInput==1) { Mode = 3; //Switching from Date to Alarm mode ModeButtonPressed = false; } if (Mode==3 && ModeButtonPressed==true && ModeInput==1) { Mode = 1; //Switching from Alarm to Time mode ModeButtonPressed = false; } // SETTING ////////////////////////////////////////// ///////////////////////////////////////////////////// byte SetInput = digitalRead(A0); if(SetInput==0) SetButtonPressed = true; while(SetInput==0){ SetTimer++; delay(10); SetInput = digitalRead(A0); } if(SetTimer>=70){ if(SETMODE==false) SETMODE=true; //A long press will either enter or exit the setting mode option. else SETMODE=false; } SetTimer=0; //Reinitializing. if(SETMODE==true){ SETMODEentered=true; if (Set==1 && SetButtonPressed==true && SetInput==1) { Set = 2; //Switching from left to middle pair available for setting. SetButtonPressed = false; } if (Set==2 && SetButtonPressed==true && SetInput==1) { Set = 3; //Switching from middle to right pair available for setting. SetButtonPressed = false; } if (Set==3 && SetButtonPressed==true && SetInput==1) { Set = 1; //Switching from right to left pair available for setting. SetButtonPressed = false; } //Now we set the selected the pair of tube, let's modify its value: int IncreaseInput = digitalRead(A3); int DecreaseInput = digitalRead(A2); if(DecreaseInput==0) DecreaseButtonPressed = true; if(IncreaseInput==0) IncreaseButtonPressed = true; if(DecreaseButtonPressed==true && DecreaseInput==1) { if(Set==1){ if(Mode==1) ClockHourSet--; if(Mode==2) ClockDaySet--; if(Mode==3) AlmHours--; } if(Set==2){ if(Mode==1) ClockMinSet--; if(Mode==2) ClockMonthSet--; if(Mode==3) AlmMins--; } if(Set==3){ if(Mode==1) ClockSecSet--; if(Mode==2) ClockYearSet--; } DecreaseButtonPressed = false; } if(IncreaseButtonPressed==true && IncreaseInput==1) { if(Set==1){ if(Mode==1) ClockHourSet++; if(Mode==2) ClockDaySet++; if(Mode==3) AlmHours++; } if(Set==2){ if(Mode==1) ClockMinSet++; if(Mode==2) ClockMonthSet++; if(Mode==3) AlmMins++; } if(Set==3){ if(Mode==1) ClockSecSet++; if(Mode==2) ClockYearSet++; } IncreaseButtonPressed = false; } } //Saving to EEPROM after exiting the SETMODE if(SETMODE==false && SETMODEentered==true){ SETMODEentered=false; byte lowCHS = lowByte(ClockHourSet); //Split the 2-bytes integer into the respecting "high" and "low" parts in order to save them on the EEPROM. byte highCHS = highByte(ClockHourSet); byte lowCMS = lowByte(ClockMinSet); byte highCMS = highByte(ClockMinSet); byte lowCSS = lowByte(ClockSecSet); byte highCSS = highByte(ClockSecSet); byte lowCDS = lowByte(ClockDaySet); byte highCDS = highByte(ClockDaySet); byte lowCOS = lowByte(ClockMonthSet); byte highCOS = highByte(ClockMonthSet); byte lowCYS = lowByte(ClockYearSet); byte highCYS = highByte(ClockYearSet); byte lowAH = lowByte(AlmHours); byte highAH = highByte(AlmHours); byte lowAM = lowByte(AlmMins); byte highAM = highByte(AlmMins); EEPROM.write(0, lowCHS); EEPROM.write(1, highCHS); //Saving EEPROM.write(2, lowCMS); EEPROM.write(3, highCMS); EEPROM.write(4, lowCSS); EEPROM.write(5, highCSS); EEPROM.write(6, lowCDS); EEPROM.write(7, highCDS); EEPROM.write(8, lowCOS); EEPROM.write(9, highCOS); EEPROM.write(10, lowCYS); EEPROM.write(11, highCYS); EEPROM.write(12, lowAH); EEPROM.write(13, highAH); EEPROM.write(14, lowAM); EEPROM.write(15, highAM); } // ALARM ARMING ///////////////////////////////////// ///////////////////////////////////////////////////// if(Mode==3 && AlmPlaying==false){ int AlmInput = analogRead(A6); if(AlmInput==0) AlmButtonPressed = true; if(AlmButtonPressed==true && AlmInput>250){ if(AlmArmed==true) AlmArmed=false; else AlmArmed=true; AlmButtonPressed = false; } } // TIME CALCULATION ///////////////////////////////// ///////////////////////////////////////////////////// DateTime now = RTC.now(); unsigned long time = now.unixtime() - 1401000000; time += (long) ClockSecSet + 60* (long) ClockMinSet + 3600* (long) ClockHourSet + 86400* (long) ClockDaySet; //time in seconds, based on offset // Convert time to days,hours,mins,seconds long days = time / 86400; time -= days * 86400; long hours = time / 3600; time -= hours * 3600; long minutes = time / 60; time -= minutes * 60; long seconds = time; // Get the high and low order values for hours,min,seconds. byte lowerHours = hours % 10; byte upperHours = hours - lowerHours; byte lowerMins = minutes % 10; byte upperMins = minutes - lowerMins; byte lowerSeconds = seconds % 10; byte upperSeconds = seconds - lowerSeconds; if( upperSeconds >= 10 ) upperSeconds = upperSeconds / 10; if( upperMins >= 10 ) upperMins = upperMins / 10; if( upperHours >= 10 ) upperHours = upperHours / 10; // DATE CALCULATION ///////////////////////////////// ///////////////////////////////////////////////////// int Day = days; int Month = ClockMonthSet; int Year = abs(ClockYearSet%100); //Defining years incrementation. if(Month>=13){ Year++; Month=Month-12; } if(Month<=0){ Year--; Month=Month+12; } //Number of days in a month: byte February; if(Year%4==0) February=29; else February=28; byte MonthArray[13] = {0,31,February,31,30,31,30,31,31,30,31,30,31}; //we'll skip the first entry, so we can use the array's index directly. //Defining Month incrementation. for(byte i=1;i<13;i++){ if(Month==i){ if(Day>MonthArray[i]){ //If "Day" exceeds the number of days in the present month, it is resetted to 1 and we step into the next month. Day -= MonthArray[i]; Month++; } if(Day<1){ //Similarly if "Day" is to become 0. if(i-1==0) i=13; //Before January comes December. Day += MonthArray[i-1]; Month--; } } } // Splitting date. byte lowerYears = Year % 10; byte upperYears = Year - lowerYears; byte lowerMonths = Month % 10; byte upperMonths = Month - lowerMonths; byte lowerDays = Day % 10; byte upperDays = Day - lowerDays; if( upperDays >= 10 ) upperDays = upperDays / 10; if( upperMonths >= 10 ) upperMonths = upperMonths / 10; if( upperYears >= 10 ) upperYears = upperYears / 10; // ALM RULES ///////////////////////////////// ////////////////////////////////////////////// if(AlmHours>23) AlmHours=AlmHours-24; //After 23:00 comes 00:00 if(AlmHours<0) AlmHours=AlmHours+23; //vice-versa if(AlmMins>59) AlmMins=AlmMins-60; //same thing if(AlmMins<0) AlmMins=AlmMins+59; // Splitting. byte lowerAlmHours = AlmHours % 10; byte upperAlmHours = AlmHours - lowerAlmHours; byte lowerAlmMins = AlmMins % 10; byte upperAlmMins = AlmMins - lowerAlmMins; if( upperAlmMins >= 10 ) upperAlmMins = upperAlmMins / 10; if( upperAlmHours >= 10 ) upperAlmHours = upperAlmHours / 10; //Alm actions: if(AlmArmed==true){ if(upperAlmHours==upperHours && lowerAlmHours==lowerHours && upperAlmMins==upperMins && lowerAlmMins==lowerMins && upperSeconds==0 && lowerSeconds==0){ AlmPlaying = true; //Alarm rings when the time matches the pre-entered alarm values. } } if(AlmPlaying==true){ if(runTime-previousTimeTone > 2000){ //Play an intermitten (1s period) tune. previousTimeTone = runTime; if(toneState == HIGH){ for (int thisNote = 0; thisNote < 5; thisNote++) { int noteDuration = 1000/noteDurations[thisNote]; tone(10, melody[thisNote], noteDuration); int pauseBetweenNotes = noteDuration * 1.30; delay(pauseBetweenNotes); toneState=LOW; } } else{ noTone(10); toneState=HIGH; } } if(digitalRead(A0)==LOW || digitalRead(A1)==LOW || digitalRead(A2)==LOW || digitalRead(A3)==LOW) AlmPlaying=false; //Press anything to stop it. } else noTone(10); // SHOWTIME ///////////////////////////////////////// ///////////////////////////////////////////////////// // Fill in the Number array used to display on the tubes following the Mode. if(Mode==1){ if(SETMODE==true){ if(Set==1){ if(runTime-previousTimeBlink > 500){ //Blinking these digits while in setmode. previousTimeBlink = runTime; if(nixState == LOW){ NumberArray[5] = 11; //Turning this pair off. NumberArray[1] = 11; nixState = HIGH; } else{ NumberArray[5] = upperHours; //Turning this pair on again. NumberArray[1] = lowerHours; nixState = LOW; } } NumberArray[3] = upperMins; //Makes sure no pair stays off even if left in that state in the previous set mode. NumberArray[2] = lowerMins; NumberArray[4] = upperSeconds; NumberArray[0] = lowerSeconds; } if(Set==2){ if(runTime-previousTimeBlink > 500){ //Blinking these digits while in setmode. previousTimeBlink = runTime; if(nixState == LOW){ NumberArray[3] = 11; NumberArray[2] = 11; nixState = HIGH; } else{ NumberArray[3] = upperMins; NumberArray[2] = lowerMins; nixState = LOW; } } NumberArray[5] = upperHours; NumberArray[1] = lowerHours; NumberArray[4] = upperSeconds; NumberArray[0] = lowerSeconds; } if(Set==3){ if(runTime-previousTimeBlink > 500){ //Blinking these digits while in setmode. previousTimeBlink = runTime; if(nixState == LOW){ NumberArray[4] = 11; NumberArray[0] = 11; nixState = HIGH; } else{ NumberArray[4] = upperSeconds; NumberArray[0] = lowerSeconds; nixState = LOW; } } NumberArray[5] = upperHours; NumberArray[1] = lowerHours; NumberArray[3] = upperMins; NumberArray[2] = lowerMins; } } else{ //Fill the digits normally. NumberArray[5] = upperHours; NumberArray[1] = lowerHours; NumberArray[3] = upperMins; NumberArray[2] = lowerMins; NumberArray[4] = upperSeconds; NumberArray[0] = lowerSeconds; } DisplayFadeNumberString();// Display time. if((lowerMins==5)&&upperSeconds==0&&lowerSeconds==1)//lighting all the numbers every 10min to prevent cathode poisining. { for(int j=-1; j<11; j++){//alternating to make it more beautiful. the -1 and 11 value will turn the digits off to mark a short pause. NumberArray[5] = j; NumberArray[1] = 9-j; NumberArray[3] = j; NumberArray[2] = 9-j; NumberArray[4] = j; NumberArray[0] = 9-j; int k = 0; while(k<10){ DisplayFadeNumberString();// Clean each nixie digits for 2 seconds. k++; delay(1); } } } if(lowerMins==3 && upperSeconds==0 && lowerSeconds==1){ //Display date only on every (03,13,23,33) mins. NumberArray[5] = upperDays; NumberArray[1] = lowerDays; NumberArray[3] = upperMonths; NumberArray[2] = lowerMonths; NumberArray[4] = upperYears; NumberArray[0] = lowerYears; int k = 0; while(k<550){ // Display date for 10 seconds (50 = 1sec). DisplayFadeNumberString(); // Display date. k++; delay(1); } } } if(Mode==2){ if(SETMODE==true){ if(Set==1){ if(runTime-previousTimeBlink > 500){ //Blinking these digits while in setmode. previousTimeBlink = runTime; if(nixState == LOW){ NumberArray[5] = 11; //Turning this pair off. NumberArray[1] = 11; nixState = HIGH; } else{ NumberArray[5] = upperDays; NumberArray[1] = lowerDays; nixState = LOW; } } NumberArray[3] = upperMonths; NumberArray[2] = lowerMonths; NumberArray[4] = upperYears; NumberArray[0] = lowerYears; } if(Set==2){ if(runTime-previousTimeBlink > 500){ //Blinking these digits while in setmode. previousTimeBlink = runTime; if(nixState == LOW){ NumberArray[3] = 11; NumberArray[2] = 11; nixState = HIGH; } else{ NumberArray[3] = upperMonths; NumberArray[2] = lowerMonths; nixState = LOW; } } NumberArray[5] = upperDays; NumberArray[1] = lowerDays; NumberArray[4] = upperYears; NumberArray[0] = lowerYears; } if(Set==3){ if(runTime-previousTimeBlink > 500){ //Blinking these digits while in setmode. previousTimeBlink = runTime; if(nixState == LOW){ NumberArray[4] = 11; NumberArray[0] = 11; nixState = HIGH; } else{ NumberArray[4] = upperYears; NumberArray[0] = lowerYears; nixState = LOW; } } NumberArray[5] = upperDays; NumberArray[1] = lowerDays; NumberArray[3] = upperMonths; NumberArray[2] = lowerMonths; } } else{ //Fill the digits normally. NumberArray[5] = upperDays; NumberArray[1] = lowerDays; NumberArray[3] = upperMonths; NumberArray[2] = lowerMonths; NumberArray[4] = upperYears; NumberArray[0] = lowerYears; } DisplayFadeNumberString(); // Display date. } if(Mode==3){ if(SETMODE==true){ if(Set==1){ if(runTime-previousTimeBlink > 500){ //Blinking these digits while in setmode. previousTimeBlink = runTime; if(nixState == LOW){ NumberArray[5] = 11; //Turning this pair off. NumberArray[1] = 11; nixState = HIGH; } else{ NumberArray[5] = upperAlmHours; NumberArray[1] = lowerAlmHours; nixState = LOW; } } NumberArray[3] = upperAlmMins; NumberArray[2] = lowerAlmMins; NumberArray[0] = AlmArmed; //1: armed, 0: not armed } if(Set==2){ if(runTime-previousTimeBlink > 500){ //Blinking these digits while in setmode. previousTimeBlink = runTime; if(nixState == LOW){ NumberArray[3] = 11; NumberArray[2] = 11; nixState = HIGH; } else{ NumberArray[3] = upperAlmMins; NumberArray[2] = lowerAlmMins; nixState = LOW; } } NumberArray[5] = upperAlmHours; NumberArray[1] = lowerAlmHours; NumberArray[0] = AlmArmed; } if(Set==3) Set=1; //Dirty fix to convert a 3-cycle into a 2-cycle. } else{ //Fill the digits normally. NumberArray[5] = upperAlmHours; NumberArray[1] = lowerAlmHours; NumberArray[3] = upperAlmMins; NumberArray[2] = lowerAlmMins; NumberArray[0] = AlmArmed; } NumberArray[4] = 11; //Eleven will turn off the tube DisplayFadeNumberString(); // Display alarm. } }