//4 Digit 7 Segment VFD Arduino Based Clock w/o LED Seconds Circle
//by Frank Zheng, REV 1.1 - based on niq_ro
//Alle Pins ausser Shift-Register-Steuerpins sind Active Low!
//Modified for BCD decoder (such as 74LS48) and active high output to UDN6118A.
//May also be used with neon gas discharge displays.
//Anzeigenpin-Zuweisung
int digit1 =
9; //Arduino Pin D6~, PWM, Pin 12, T9 (tens hours)
int digit2 =
8; //Arduino Pin D9~, PWM, Pin 15, T10 (hours)
int digit3 =
7; //Arduino Pin D10~, PWM, Pin 16, T11 (tens minutes)
int digit4 =
6; //Arduino Pin D11~, PWM, Pin 17, T12 (minutes)
//Segmentpin-Zuweisung
int segA =
2; //Arduino Pin D2, Pin 4, T1 (1's bit)
int segB =
3; //Arduino Pin D3, Pin 5, T2 (2's bit)
int segC =
4; //Arduino Pin D4, Pin 6, T3 (4's bit)
int segD =
5; //Arduino Pin D5, Pin 11, T4 (8's bit)
//Einstellknopf-Zuweisung
byte SW0 = A0;
byte SW1 = A1;
byte SW2 = A2;
//Praeprozessor
#include <Wire.h>
#include "RTClib.h"
#include "TimerOne.h"
RTC_DS1307 RTC;
//Globale Sekundendefinition
//int alle_x_sekunden = 1;
//int secondreset = 0;
//Aktuelle Sekunde definieren
//int sekaktuell = 0;
//Hex-Dec-Konversion (niq_ro)
int zh,
uh, ore;
int zm,
um, miniti;
//Initialisierung
void setup() {
//Initialisierung RTC
//Serial wird fuer Shift-Register verwendet
//Serial.begin(57600);
Wire.begin();
RTC.begin();
//RTC.adjust(DateTime(__DATE__, __TIME__));
//LED-Blink/PWM-Modulation
Wire.beginTransmission(0x68);
Wire.write(0x07);
//Pointer uebertragen, PWM
//Wire.write(0x00); //PWM Ausschalten
Wire.write(0x10);
//0x10 (h) 00010000 (b) an Kontrollregister: 1Hz Blink
//Wire.write(0x13); //0x13 (h) 00010011 (b) 32kHz
Wire.endTransmission();
//RTC-Aktiv?
if (! RTC.isrunning()) {
//Serial.println("RTC is not running!");
//Nein -> Schreibe Systemzeit in RTC
RTC.adjust(DateTime(__DATE__,
__TIME__));
}
// dht.begin();
//Pin-I/O-Zuweisung
pinMode(segA,
OUTPUT);
pinMode(segB,
OUTPUT);
pinMode(segC,
OUTPUT);
pinMode(segD,
OUTPUT);
pinMode(digit1,
OUTPUT);
pinMode(digit2,
OUTPUT);
pinMode(digit3,
OUTPUT);
pinMode(digit4,
OUTPUT);
pinMode(SW0,
INPUT);
pinMode(SW1,
INPUT);
pinMode(SW2,
INPUT);
//Digital-Pull-Up
digitalWrite(SW0,
HIGH);
digitalWrite(SW1,
HIGH);
digitalWrite(SW2,
HIGH);
// Serial.begin(9600);
// Serial.println("HARDWARECOP VFD Clock - Welcome");
}
//Routine
void loop() {
//DP-Anzeige einschalten
//Zeitabgleich
DateTime now =
RTC.now();
//Zeit = Stunde * 100 + Minute (14h * 100 + 25 min) = 1425
int timp =
now.hour()*100+now.minute();
//int timp = (now.minute(), DEC);
//displayNumber(12);
//int timp = 1234;
// display parts
for(int
i = 150 ;
i >0 ;
i--) {
if
(timp >= 1000)
displayNumber01(timp);
//e.g. 2142 -> timp = 2, 1, 4, 2 -> GOTO
displayNumber01(2142)
else displayNumber02(timp);
//e.g. 0943 -> timp = 0, 9, 4, 3 -> GOTO
displayNumber02(0943)
//Leading zero is blanked out by new code, e.g. " 943"
}
for(int
i = 150 ;
i >0 ;
i--) {
if
(timp >= 1000)
displayNumber03(timp);
else
displayNumber04(timp);
}
//Einstellknopf gedrueckt?
if
(!(digitalRead(SW0)))
set_time(); //Waehrend SW0 Low: Zeit
einstellen!
}
//Zeit einstellen (niq_ro)
void set_time() {
byte minutes1 =
0;
byte hours1 =
0;
byte minutes =
0;
byte hours =
0;
while (!digitalRead(SW0))
{
minutes1=minutes;
hours1=hours;
while
(!digitalRead(SW1))
// set minutes
{
minutes++;
// converting hexa in zecimal:
zh =
hours / 16;
uh =
hours - 16 *
zh ;
ore =
10 * zh +
uh;
zm =
minutes / 16;
um =
minutes - 16 *
zm ;
miniti =
10 * zm +
um;
for(int
i = 20 ;
i >0 ;
i--) {
displayNumber01(ore*100+miniti);
}
if
((minutes & 0x0f) >
9) minutes =
minutes + 6;
if
(minutes > 0x59)
minutes = 0;
//Serial.print("Minutes = ");
//if (minutes >= 9) Serial.print("0");
//Serial.println(minutes, HEX);
delay(150);
}
while
(!digitalRead(SW2))
// set hours
{
hours++;
// converting hexa in zecimal:
zh =
hours / 16;
uh =
hours - 16 *
zh ;
ore =
10 * zh +
uh;
zm =
minutes / 16;
um =
minutes - 16 *
zm ;
miniti =
10 * zm +
um;
for(int
i = 20 ;
i >0 ;
i--) {
displayNumber01(ore*100+miniti);
}
if
((hours & 0x0f) >
9) hours =
hours + 6;
if
(hours > 0x23)
hours = 0;
//Serial.print("Hours = ");
//if (hours <= 9) Serial.print("0");
//Serial.println(hours, HEX);
delay(150);
}
Wire.beginTransmission(0x68);
// activate DS1307
Wire.write(0);
// where to begin
Wire.write(0x00);
//seconds
Wire.write(minutes);
//minutes
Wire.write(0x80 |
hours); //hours (24hr time)
Wire.write(0x06);
// Day 01-07
Wire.write(0x01);
// Date 0-31
Wire.write(0x05);
// month 0-12
Wire.write(0x09);
// Year 00-99
Wire.write(0x10);
// Control 0x10 produces a 1 HZ square wave on pin 7.
Wire.endTransmission();
// converting hexa in zecimal:
zh =
hours / 16;
uh =
hours - 16 *
zh ;
ore =
10 * zh +
uh;
zm =
minutes / 16;
um =
minutes - 16 *
zm ;
miniti =
10 * zm +
um;
for(int
i = 20 ;
i >0 ;
i--) {
displayNumber01(ore*100+miniti);
}
// delay(150);
}
}
//Anzeige 1:
void displayNumber01(int
toDisplay) {
#define DISPLAY_BRIGHTNESS 1500
#define DIGIT_ON HIGH
#define DIGIT_OFF LOW
for(int digit =
4 ; digit >
0 ; digit--) {
//PWM: Kurz einschalten
switch(digit) {
case
1:
digitalWrite(digit1,
DIGIT_ON);
break;
case
2:
digitalWrite(digit2,
DIGIT_ON);
break;
case
3:
digitalWrite(digit3,
DIGIT_ON);
break;
case
4:
digitalWrite(digit4,
DIGIT_ON);
break;
}
lightNumber(toDisplay %
10);
toDisplay /=
10;
delayMicroseconds(DISPLAY_BRIGHTNESS);
//Segmente ausschalten
lightNumber(10);
//Anzeigen ausschalten
digitalWrite(digit1,
DIGIT_OFF);
digitalWrite(digit2,
DIGIT_OFF);
digitalWrite(digit3,
DIGIT_OFF);
digitalWrite(digit4,
DIGIT_OFF);
}
}
//Anzeige 2:
void displayNumber02(int
toDisplay) {
#define DISPLAY_BRIGHTNESS 1500
#define DIGIT_ON HIGH
#define DIGIT_OFF LOW
for(int
digit = 4 ;
digit > 0 ;
digit--) {
//PWM: Kurz einschalten
switch(digit) {
case
1:
digitalWrite(digit1,
DIGIT_OFF); //blank leading zero
break;
case
2:
digitalWrite(digit2,
DIGIT_ON);
break;
case
3:
digitalWrite(digit3,
DIGIT_ON);
break;
case
4:
digitalWrite(digit4,
DIGIT_ON);
break;
}
lightNumber(toDisplay %
10);
toDisplay /=
10;
delayMicroseconds(DISPLAY_BRIGHTNESS);
//Segmente ausschalten
lightNumber(10);
//Anzeigen ausschalten
digitalWrite(digit1,
DIGIT_OFF);
digitalWrite(digit2,
DIGIT_OFF);
digitalWrite(digit3,
DIGIT_OFF);
digitalWrite(digit4,
DIGIT_OFF);
}
}
//Anzeige 3:
void displayNumber03(int
toDisplay) {
#define DISPLAY_BRIGHTNESS 1500
#define DIGIT_ON HIGH
#define DIGIT_OFF LOW
for(int digit =
4 ; digit >
0 ; digit--) {
//PWM: Kurz einschalten
switch(digit) {
case
1:
digitalWrite(digit1,
DIGIT_ON);
break;
case
2:
digitalWrite(digit2,
DIGIT_ON);
break;
case
3:
digitalWrite(digit3,
DIGIT_ON);
break;
case
4:
digitalWrite(digit4,
DIGIT_ON);
break;
}
lightNumber(toDisplay %
10);
toDisplay /=
10;
delayMicroseconds(DISPLAY_BRIGHTNESS);
//Segmente ausschalten
lightNumber(10);
//Anzeigen ausschalten
digitalWrite(digit1,
DIGIT_OFF);
digitalWrite(digit2,
DIGIT_OFF);
digitalWrite(digit3,
DIGIT_OFF);
digitalWrite(digit4,
DIGIT_OFF);
}
}
//Anzeige 4:
void displayNumber04(int
toDisplay) {
#define DISPLAY_BRIGHTNESS 1500
#define DIGIT_ON HIGH
#define DIGIT_OFF LOW
for(int
digit = 4 ;
digit > 0 ;
digit--) {
//PWM: Kurz einschalten
switch(digit) {
case
1:
digitalWrite(digit1,
DIGIT_OFF); //blank leading zero
break;
case
2:
digitalWrite(digit2,
DIGIT_ON);
break;
case
3:
digitalWrite(digit3,
DIGIT_ON);
break;
case
4:
digitalWrite(digit4,
DIGIT_ON);
break;
}
lightNumber(toDisplay %
10);
toDisplay /=
10;
delayMicroseconds(DISPLAY_BRIGHTNESS);
//Segmente ausschalten
lightNumber(10);
//Anzeigen ausschalten
digitalWrite(digit1,
DIGIT_OFF);
digitalWrite(digit2,
DIGIT_OFF);
digitalWrite(digit3,
DIGIT_OFF);
digitalWrite(digit4,
DIGIT_OFF);
}
}
//Zeichenbedingungen:
//Fuerr case 10 ist Anzeige mit allen Segmenten eingeschaltet
void lightNumber(int
numberToDisplay) {
#define SEGMENT_ON HIGH
//bit = 1
#define SEGMENT_OFF LOW
//bit = 0
switch
(numberToDisplay){
//Zahl 0
//BCD data
case
0: //BCD 0000
digitalWrite(segA,
SEGMENT_OFF);
digitalWrite(segB,
SEGMENT_OFF);
digitalWrite(segC,
SEGMENT_OFF);
digitalWrite(segD,
SEGMENT_OFF);
break;
case
1: //BCD 0001
digitalWrite(segA,
SEGMENT_ON);
digitalWrite(segB,
SEGMENT_OFF);
digitalWrite(segC,
SEGMENT_OFF);
digitalWrite(segD,
SEGMENT_OFF);
break;
case
2: //BCD 0010
digitalWrite(segA,
SEGMENT_OFF);
digitalWrite(segB,
SEGMENT_ON);
digitalWrite(segC,
SEGMENT_OFF);
digitalWrite(segD,
SEGMENT_OFF);
break;
case
3: //BCD 0011
digitalWrite(segA,
SEGMENT_ON);
digitalWrite(segB,
SEGMENT_ON);
digitalWrite(segC,
SEGMENT_OFF);
digitalWrite(segD,
SEGMENT_OFF);
break;
case
4: //BCD 0100
digitalWrite(segA,
SEGMENT_OFF);
digitalWrite(segB,
SEGMENT_OFF);
digitalWrite(segC,
SEGMENT_ON);
digitalWrite(segD,
SEGMENT_OFF);
break;
case
5: //BCD 0101
digitalWrite(segA,
SEGMENT_ON);
digitalWrite(segB,
SEGMENT_OFF);
digitalWrite(segC,
SEGMENT_ON);
digitalWrite(segD,
SEGMENT_OFF);
break;
case
6: //BCD 0110
digitalWrite(segA,
SEGMENT_OFF);
digitalWrite(segB,
SEGMENT_ON);
digitalWrite(segC,
SEGMENT_ON);
digitalWrite(segD,
SEGMENT_OFF);
break;
case
7: //BCD 0111
digitalWrite(segA,
SEGMENT_ON);
digitalWrite(segB,
SEGMENT_ON);
digitalWrite(segC,
SEGMENT_ON);
digitalWrite(segD,
SEGMENT_OFF);
break;
case
8: //BCD 1000
digitalWrite(segA,
SEGMENT_OFF);
digitalWrite(segB,
SEGMENT_OFF);
digitalWrite(segC,
SEGMENT_OFF);
digitalWrite(segD,
SEGMENT_ON);
break;
case
9: //BCD 1001
digitalWrite(segA,
SEGMENT_ON);
digitalWrite(segB,
SEGMENT_OFF);
digitalWrite(segC,
SEGMENT_OFF);
digitalWrite(segD,
SEGMENT_ON);
break;
//Alles ein
case
10: //illegal BCD value 1111 blanks display
digitalWrite(segA,
SEGMENT_ON);
digitalWrite(segB,
SEGMENT_ON);
digitalWrite(segC,
SEGMENT_ON);
digitalWrite(segD,
SEGMENT_ON);
break;
}
}