| Vacuum Fluorescent Display Clock | |
|
March 2019
The Arduino SketchDS1307/DS3231 RTC Library
/* Vacuum Fluorescent Display (VFD) Real Time Clock - vwlowen.co.uk *
*/
#include <Wire.h>
#include "RTClib.h" // https://github.com/adafruit/RTClib
//RTC_DS1307 rtc; // Choose the RTC clock module here.
RTC_DS3231 rtc;
const int filament_pin1 = 2;
const int filament_pin2 = 4;
const int dp_pin = 3;
const int setHours_pin = A2;
const int setMins_pin = A3;
// Define Arduino pins used for the grids.
const int grid_pins[5] {8, 7, 6, 5}; // Hours x 10, Hours, Mins x 10, Mins
// Define Arduino pins used for the segments (anodes).
const int segment_pins[8] {A1, A0, 13, 12, 11, 10, 9}; // Segments (Anodes) a b c d e f
int theTime[4] {0, 0, 0, 0}; // Each read of the RTC is stored here.
// gfedcba
const int numbers[10] = { // Define which segments are lit for each number.
B0111111, // 0
B0000110, // 1
B1011011, // 2
B1001111, // 3
B1100110, // 4
B1101101, // 5
B1111101, // 6
B0000111, // 7
B1111111, // 8
B1101111 // 9
};
byte hours, mins, secs;
unsigned long settingHours = 0; // Timer for incrementing hours when the button is pressed.
unsigned long settingMinutes = 0; // Timer for incrementing minutes when its button is pressed.
bool filament_flag = false; // Display filament is powered from two IO pins which alternate.
int grid = 0; // Define first grid to be activated/updated (grid 0 is Hours x 10).
void setup() {
Serial.begin(9600);
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
pinMode(filament_pin1, OUTPUT);
pinMode(filament_pin2, OUTPUT);
pinMode(dp_pin, OUTPUT); // Decimal point is not multiplexed so is too bright when fully
analogWrite(dp_pin, 30); // powered with logic HIGH, so set PWM value to match brightness.
pinMode(setHours_pin, INPUT_PULLUP);
pinMode(setMins_pin, INPUT_PULLUP);
for (int i = 0; i < 8; i++) { // Make all display segments LOW
pinMode(segment_pins[i], OUTPUT);
digitalWrite(segment_pins[i], LOW);
}
for (int i = 0; i < 5; i++) { // Make all grids LOW (grids are Hx10, H, Mx10, M).
pinMode(grid_pins[i], OUTPUT);
digitalWrite(grid_pins[i], LOW);
}
}
void loop() {
digitalWrite(filament_pin1, filament_flag); // Power display filament with one polatity.
digitalWrite(filament_pin2, !filament_flag);
filament_flag = !filament_flag; // Swap polarity next time around the loop.
DateTime now = rtc.now(); // Get time from RTC.
hours = now.hour();
mins = now.minute();
secs = now.second(); // Seconds will be needed if we set the time.
theTime[0] = hours / 10; // Store the time so all digits can be recalled from the
theTime[1] = hours % 10; // same RTC reading.
theTime[2] = mins / 10;
theTime[3] = mins % 10;
// If pressed, only allow time-setting buttons to change the time once every 250 millisec.
if ((digitalRead(setHours_pin) == LOW) && (millis() > (settingHours + 250))) { //Set Hours
hours++;
if (hours >= 24) hours = 0;
theTime[0] = hours / 10;
theTime[1] = hours % 10;
rtc.adjust(DateTime(2019, 2, 15, hours, mins, secs)); // Retain existing seconds value.
settingHours = millis(); // Reset the Hours button timer.
}
if ((digitalRead(setMins_pin) == LOW) && (millis() > (settingMinutes + 250))) { // Set Minutes
mins++;
if (mins >= 60) mins = 0;
theTime[2] = mins / 10;
theTime[3] = mins % 10;
rtc.adjust(DateTime(2019, 2, 15, hours, mins, 0)); // Reset seconds to zero when minutes are set.
settingMinutes = millis(); // Reset the Minutes button timer.
}
// Display the segments for one grid.
for (int i = 0; i < 5; i++) { // Turn all grids off.
digitalWrite(grid_pins[i], LOW);
}
// For the current grid, turn on the segments for which the number's bits are '1' (HIGH).
for (int i = 0; i < 8; i++) {
digitalWrite(segment_pins[i], numbers[theTime[grid]] & (1 << i));
}
digitalWrite(grid_pins[grid], HIGH); // Turn the current grid on.
grid++; // Advance to the next grid next time around.
if (grid >= 4) grid = 0;
}
| |