Vacuum Fluorescent Display Clock
March 2019

 

The Arduino Sketch

DS1307/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;
}




 

Back to Index | Page 1 | Page 2 | Page 3