/***************************************************************************************************************
***************************************************************************************************************
VFD Clock Main Sketch
Version 0.3.5
Tested with: Arduino IDE 1.8.16 - Arduino AVR Boards 1.8.4 - MD_DS3231 1.3.1 - Adafruit_NeoPixel 1.7.0 -
MD_KeySwitch 1.4.2 - DHT sensor library 1.4.3 - ATMega328P-PU with Arduino UNO R3 bootloader
(for uploading code with the FTDI board select Tools-> Board:-> "Ardruino Uno")
17-05-2022
Leon
**************************************************************************************************************/
// Libraries needed:
#include <MD_DS3231.h> // Pre-existing object named RTC (SCL to pin A5, SDA to pin A4)
#include <Adafruit_NeoPixel.h>
#include <MD_KeySwitch.h>
#include "DHT.h"
#include <SPI.h>
// Turn debugging on and off:
#define DEBUG 1
#if DEBUG
#define PRINTS(s) { Serial.print (F(s));} // Print a string
#define PRINT(s, v) { Serial.print (F(s)); Serial.print (v);} // Print string then value (dec)
#include <MemoryFree.h> // Library for printing free memory on runtime
#else
#define PRINTS(s) // Print a string
#define PRINT(s, v) // Print a string followed by a value (decimal)
#endif
// General universal variables:
byte currentHours = 0; // variable to hold the value of the current hour
byte currentSeconds = 0; // variable to hold the value of the current seconds
// Variables for holding the individual digits of time:
byte hoursFirstDigit = 0;
byte hoursSecondDigit = 0;
byte minutesFirstDigit = 0;
byte minutesSecondDigit = 0;
// VFD tubes:
#define NUM_DIGITS 2 // define number of display digits.
const byte Blank = 9; // Output to HV5812P-G 'BLANK' input
const byte strobe = 10; // Output to HV5812P-G 'STROBE' input
byte timeBuffer [4]; // array to hold the time digits
byte vfdDisplayMode = 0;
// mode 0 = 24h time display
// mode 1 = 12h time display
// mode 2 = temperature & humidity only display (without time)
// mode 3 = display temp & humidity once (used when turning tempDisplayOn to true)
// mode 4 = set time in 24h mode
// mode 5 = set time in 12h mode
bool previousDisplayMode = 0; // variable to hold the previous display mode
bool tempDisplayOn = true; // show temp and humidity periodically on modes 0 and 1
bool vfdCycleEffectOn = false; // trigger for vfd cycle effect
bool vfdDashEffectOn = false; // trigger for vfd dash effect - used to indicate "OFF"
bool vfdDotEffectOn = false; // trigger for vfd dot effect - used to indicate "ON"
byte effectBuffer [4]; // array to hold the effects digits
bool setTimeModeFlag = false; // flag for checking if setTimeMode is running
bool timeSetModeReset = true; // used to reset variables at the first run of timeSetMode function
byte tempTimeHolder = 0; // hold the time that is displayed currently on setTimeMode
bool setTimeStageArray [3] = {false}; // array that holds which steps of the time setting are completed
bool setTimeAm = false; // if am = true, if pm = false - used in 12h set time mode
// Array with the bit-pattern for each tube Grid - the grids are MULTIPLEXED: 1 and 3 VFDs are on
// together while 2 and 4 VFDs are off and in reverse:
const byte grids [2] =
{
B00000101,
B00001010,
};
// Array with the bit-pattern for each and 7-segment number character:
const byte symbols [25] =
{
B01110111, // 0
B00100100, // 1
B01011101, // 2
B01101101, // 3
B00101110, // 4
B01101011, // 5
B01111011, // 6
B00100101, // 7
B01111111, // 8
B01101111, // 9
B00000000, // 10 (Blank)
B01011000, // 11 (c celsius)
B01010011, // 12 (C Celsius)
B00001111, // 13 (top half on)
B01111000, // 14 (bottom half on)
B10000000, // 15 (. dot - used to signal ON)
B11111111, // 16 (all segments on)
B00001000, // 17 (- dash used to signal OFF)
B00100000, // 18 (from 18 to 24 are the cycle effect bit-patterns)
B01000000, // 19
B00010000, // 20
B00000010, // 21
B00000001, // 22
B00000100, // 23
B00100000, // 24
};
// DHT11 temperature and humidity sensor:
#define DHTPIN 7 // pin the sensor is connected to
DHT dht (DHTPIN, DHT11);
byte tempFirstDigit = 0;
byte tempSecondDigit = 0;
byte tempThirdDigit = 0;
byte tempBuffer [4]; // array to hold the temp digits
byte humidityFirstDigit = 0;
byte humiditySecondDigit = 0;
byte humidityBuffer [4]; // array to hold the humidity digits
float originalTemp = 0; // hold the temperature before compensating for electronics heat
float compensatedTemp = 0; // hold temperature after compensating for electronics
const float tempCompensation = 1.80; // degrees in c to compensate for electronics heat
// Dots:
#define DOTS_PIN A1
#define DOTS_NUM 2
Adafruit_NeoPixel dots (DOTS_NUM, DOTS_PIN, NEO_RGB + NEO_KHZ800);
#define AM_LED 12
#define PM_LED A2
// WS LEDs:
#define WS_PIN 2
#define WS_NUM 4
Adafruit_NeoPixel ws (WS_NUM, WS_PIN, NEO_RGB + NEO_KHZ800);
byte wsMode = 1; // variable to hold the WS2911 LEDs mode - default is 1
byte wsModeNum = 5; // variable to hold the number (sum) of WS2911 LEDs modes
bool wsTransition = false; // true if mode transition is on, false if not
#define WSTRANSTIME 1800UL // transition duration in milliseconds
bool wsOff = false; // true if the WS2911 LEDs are off, false if they are on
bool wsWasOn = false; // true if the LEDs were on, false if not
bool rainbowEffectTrigger = false; // flag for triggering the rainbow effect
bool colorWipeEffectTrigger = false; // flag for triggering the color wipe effect
bool colorWheelEffectTrigger = false; // flag for triggering the colorWheel effect
int redLedArray [4] = {0}; // array to hold the values of the red WS2911 LEDs
int greenLedArray [4] = {0}; // array to hold the values of the green WS2911 LEDs
int blueLedArray [4] = {0}; // array to hold the values of the blue WS2911 LEDs
unsigned long tempColorArray [4] = {0}; // array to hold the values of rainbow or wheel colors
// LDR Photoresistor:
#define LDRPIN A3 // analog pin that the LDR photoresistor is connected on the Arduino
#define VFD_BRIGHT_MAX 0 // full brightness
#define VFD_BRIGHT_MIN 250 // fully dimmed
byte vfdBrightness = 120; // startup brightness of VFDs (half brightness)
#define WS_BRIGHT_MAX 100 // maximum brightness the LEDs will go depending on room light
#define WS_BRIGHT_MIN 10 // minimum brightness the LEDs will go depending on room light
byte wsBrightness = 44; // startup brightness of the WS2811 LEDs (half brightness)
#define DOTS_BRIGHT_MAX 60 // maximum brightness the dots will go depending on room light
#define DOTS_BRIGHT_MIN 10 // minimum brightness the dots will go depending on room light
byte dotsBrightness = 24; // startup brightness of the dots (half brightness)
// Buttons:
MD_KeySwitch button1 (3, LOW); // set button 1 to pin 3
MD_KeySwitch button2 (4, LOW); // set button 2 to pin 4
MD_KeySwitch button3 (5, LOW); // set button 3 to pin 5
MD_KeySwitch button4 (6, LOW); // set button 4 to pin 6
bool repeatOn = false; // true if repeat button pressed
// Functions with default values declaration:
void vfdHandler (bool reset = false);
void displayTime (bool mode12hours = false);
void colorWipeEffect (bool resetTrigger = false);
/*-------------------------------------------------- SETUP: --------------------------------------------------*/
void setup ()
{
// Debug setup:
#if DEBUG
Serial.begin (9600);
PRINTS ("\n[VFD Clock]");
#endif
// Set Fast PWM frequency on pin 9 [and 10] (for dimming display):
TCCR1B = (TCCR1B & 0b11111000) | 0x1;
// start SPI:
SPI.begin ();
// VFDs setup:
pinMode (strobe, OUTPUT);
pinMode (Blank, OUTPUT);
analogWrite (Blank, 255); // Set vfd brightness to zero at startup
// DHT11 temperature and humidity sensor:
dht.begin ();
// Dots setup:
dots.begin (); // INITIALIZE NeoPixel strip object (REQUIRED)
dots.setBrightness (dotsBrightness); // set default brightness
dots.clear (); // set all pixel colors to 'off'
dots.show (); // send the updated pixel colors to the hardware
// WS LEDs setup:
ws.begin (); // initialize NeoPixel strip object
ws.show (); // turn OFF all pixels ASAP
ws.setBrightness (wsBrightness); // Set the brightness
wsHandler ();
// AM-PM LEDs setup:
pinMode (AM_LED, OUTPUT);
pinMode (PM_LED, OUTPUT);
digitalWrite (AM_LED, LOW);
digitalWrite (PM_LED, LOW);
// LDR Photoresistor setup:
pinMode (LDRPIN, INPUT);
// Buttons setup:
// Keep in mind library restriction: debounce time < Long Press Time < Repeat time
// Button 1:
button1.begin();
button1.enableDoublePress (false);
button1.enableLongPress (true);
button1.enableRepeat (false);
button1.enableRepeatResult (false);
button1.setDebounceTime (160);
button1.setLongPressTime (2000); // set long press time to 2 seconds
// Button 2:
button2.begin();
button2.enableDoublePress (false);
button2.enableLongPress (true);
button2.enableRepeat (false);
button2.enableRepeatResult (false);
button2.setDebounceTime (160);
button2.setLongPressTime (2000); // set long press time to 2 seconds
// Button 3:
button3.begin();
button3.enableDoublePress (false);
button3.enableLongPress (false);
button3.enableRepeat (true);
button3.enableRepeatResult (true);
button3.setRepeatTime (180);
button3.setDebounceTime (160);
// Button 4:
button4.begin();
button4.enableDoublePress (false);
button4.enableLongPress (true);
button4.enableRepeat (false);
button4.enableRepeatResult (false);
button4.setDebounceTime (160);
button4.setLongPressTime (2000); // set long press time to 2 seconds
}
/*------------------------------------------------- LOOP: ----------------------------------------------------*/
void loop ()
{
// Run the handlers:
vfdHandler ();
buttonsHandler ();
photoresistorHandler ();
// Run the color wipe effect if it is on:
if (colorWipeEffectTrigger == true)
{
colorWipeEffect ();
}
// Run the rainbow effect if it is on:
if (rainbowEffectTrigger == true)
{
rainbowEffect ();
}
// Run the color wheel effect if it is on:
if (colorWheelEffectTrigger == true)
{
colorWheelEffect ();
}
}
/*---------------------------------------------- END OF LOOP -------------------------------------------------*/
/*------------------------------------------------------------------------------------------------------------*/
/* Function for handling what is displayed in the VFD tubes including timing of events and set time modes.
When called with reset = true, variables are reset:
*/
void vfdHandler (bool reset = false)
{
// Local variables declaration:
static unsigned long lastTime = 0; // time keeping for time display
static unsigned long lastTimeCyrcleEffect = 0; // time keeping for cycle effect
static unsigned long lastTimeDashEffect = 0; // time keeping for dash effect
static unsigned long lastTimeDotEffect = 0; // time keeping for dot effect
static unsigned long startTime = millis (); // time keeping for blinking digits on set time modes
static bool dashEffectFirstRun = true;
static bool dotEffectFirstRun = true;
static bool tempFirstRun = true; // used to read temperature only once per cycle
static bool humidityFirstRun = true; // used to read humidity only once per cycle
unsigned long DELAY = 4400; // time that the temp and humidity will be displayed
static byte effectCounter = 0; // keep track of the stage of the cycle effect
// Main code:
RTC.readTime (); // get the time from the module
// Reset variables and exit:
if (reset == true)
{
lastTime = millis ();
reset = false;
tempFirstRun = true;
humidityFirstRun = true;
digitalWrite (AM_LED, LOW);
digitalWrite (PM_LED, LOW);
return;
}
// Execute effects:
if (vfdCycleEffectOn == true) // dot effect
{
if (millis () - lastTimeCyrcleEffect < 60UL) // run for X seconds
{
effectBuffer [0] = 18 + effectCounter;
effectBuffer [1] = 18 + effectCounter;
effectBuffer [2] = 18 + effectCounter;
effectBuffer [3] = 18 + effectCounter;
updateDisplay (effectBuffer);
}
else
{
lastTimeCyrcleEffect = millis ();
effectCounter++;
}
if (effectCounter == 7)
{
effectCounter = 0;
vfdCycleEffectOn = false;
}
return;
}
else if (vfdDashEffectOn == true) // dash effect, only one effect active simultaneously
{
if (dashEffectFirstRun == true)
{
lastTimeDashEffect = millis ();
dashEffectFirstRun = false;
}
if (millis () - lastTimeDashEffect < 1000UL) // run for X seconds
{
effectBuffer [0] = 17;
effectBuffer [1] = 17;
effectBuffer [2] = 17;
effectBuffer [3] = 17;
updateDisplay (effectBuffer);
}
else
{
vfdDashEffectOn = false;
dashEffectFirstRun = true;
}
return;
}
else if (vfdDotEffectOn == true) // dot effect, only one effect active simultaneously
{
if (dotEffectFirstRun == true)
{
lastTimeDotEffect = millis ();
dotEffectFirstRun = false;
}
if (millis () - lastTimeDotEffect < 1000UL) // run for X seconds
{
effectBuffer [0] = 15;
effectBuffer [1] = 15;
effectBuffer [2] = 15;
effectBuffer [3] = 15;
updateDisplay (effectBuffer);
}
else
{
vfdDotEffectOn = false;
dotEffectFirstRun = true;
}
return;
}
switch (vfdDisplayMode)
{
case 0: // -------------------------------- 24h time display: --------------------------------
if (tempDisplayOn == false) // display only time
{
displayTime ();
}
else // display temperature and humidity at DELAY intervals
{
if (RTC.s > 10 && RTC.s <= 10 + (DELAY / 1000) * 2 || RTC.s > 30 && RTC.s <= 30 + (DELAY / 1000) * 2)
{
if (millis () - lastTime < DELAY) // run for delay seconds
{
if (tempFirstRun == true)
{
tempFirstRun = false;
displayTemp (true);
vfdCycleEffectOn = true;
}
else
{
displayTemp (false);
}
}
else if (millis () - lastTime < DELAY * 2)
{
if (humidityFirstRun == true)
{
humidityFirstRun = false;
displayHumidity (true);
vfdCycleEffectOn = true;
}
else
{
displayHumidity (false);
}
}
else
{
lastTime = millis ();
tempFirstRun = true;
humidityFirstRun = true;
}
}
else
{
displayTime ();
}
}
break;
case 1: // -------------------------------- 12h time display: --------------------------------
if (tempDisplayOn == false) // just display time
{
displayTime (true);
}
else // display temperature and humidity at DELAY intervals
{
if (RTC.s > 10 && RTC.s <= 10 + (DELAY / 1000) * 2 || RTC.s > 40 && RTC.s <= 40 + (DELAY / 1000) * 2)
{
if (millis () - lastTime < DELAY) // run for DELAY seconds
{
if (tempFirstRun == true)
{
tempFirstRun = false;
displayTemp (true);
vfdCycleEffectOn = true;
}
else
{
displayTemp (false);
}
}
else if (millis () - lastTime < DELAY * 2)
{
if (humidityFirstRun == true)
{
humidityFirstRun = false;
displayHumidity (true);
vfdCycleEffectOn = true;
}
else
{
displayHumidity (false);
}
}
else
{
lastTime = millis ();
tempFirstRun = true;
humidityFirstRun = true;
}
}
else
{
displayTime (true);
}
}
break;
case 2: // ---------------------- Temperature and humidity only display mode: ------------------------
if (millis () - lastTime < DELAY) // run for DELAY seconds
{
if (tempFirstRun == true)
{
tempFirstRun = false;
displayTemp (true);
vfdCycleEffectOn = true;
}
else
{
displayTemp (false);
}
}
else if (millis () - lastTime < DELAY * 2)
{
if (humidityFirstRun == true)
{
humidityFirstRun = false;
displayHumidity (true);
vfdCycleEffectOn = true;
}
else
{
displayHumidity (false);
}
}
else
{
lastTime = millis ();
tempFirstRun = true;
humidityFirstRun = true;
}
break;
case 3: // ---------------------------- Display temp and humidity once: ----------------------------
if (millis () - lastTime < DELAY + 1000UL) // run for DELAY + 1 seconds
{
if (tempFirstRun == true)
{
tempFirstRun = false;
displayTemp (true);
vfdCycleEffectOn = true;
}
else
{
displayTemp (false);
}
}
else if (millis () - lastTime < (DELAY + 1000UL) * 2)
{
if (humidityFirstRun == true)
{
humidityFirstRun = false;
displayHumidity (true);
vfdCycleEffectOn = true;
}
else
{
displayHumidity (false);
}
}
else
{
tempFirstRun = true;
humidityFirstRun = true;
// to prevent showing temperature two times in a row, skip showing it if it is to close to
// previous display:
if (RTC.s > 6 && RTC.s <= 12 + ((DELAY + 1000) / 1000) * 2
|| RTC.s > 36 && RTC.s <= 42 + ((DELAY + 1000) / 1000) * 2)
{
if (previousDisplayMode == 0)
{
displayTime ();
}
else
{
displayTime (true);
}
}
else
{
vfdDisplayMode = previousDisplayMode;
}
}
break;
case 4: // -------------------------------- 24h set time mode: --------------------------------
if (timeSetModeReset == true) // check if it's the first run of set time
{
timeSetModeReset = false;
for (int i = 0; i < 3; i++) // reset array
{
setTimeStageArray [i] = false;
}
tempTimeHolder = RTC.h; // pass current time to temp variable for manipulation with buttons
dots.clear (); // set off dots
dots.show ();
}
else if (setTimeStageArray [0] == false) // blink hours except when on repeat
{
// Hours:
if (repeatOn == false)
{
separateDoubleDigits (tempTimeHolder, hoursFirstDigit, hoursSecondDigit);
if (millis () - startTime < 500UL)
{
timeBuffer [0] = hoursFirstDigit;
timeBuffer [1] = hoursSecondDigit;
}
else if (millis () - startTime < 1000UL)
{
timeBuffer [0] = 10; // 10 = blank
timeBuffer [1] = 10; // 10 = blank
}
else
{
startTime = millis ();
}
}
else // on repeat button press don't blink
{
separateDoubleDigits (tempTimeHolder, hoursFirstDigit, hoursSecondDigit);
timeBuffer [0] = hoursFirstDigit;
timeBuffer [1] = hoursSecondDigit;
repeatOn = false;
startTime = millis ();
}
// Minutes:
separateDoubleDigits (RTC.m, minutesFirstDigit, minutesSecondDigit);
timeBuffer [2] = minutesFirstDigit;
timeBuffer [3] = minutesSecondDigit;
}
else if (setTimeStageArray [1] == false) // if hours set, blink minutes except on repeat
{
// Hours:
separateDoubleDigits (RTC.h, hoursFirstDigit, hoursSecondDigit);
timeBuffer [0] = hoursFirstDigit;
timeBuffer [1] = hoursSecondDigit;
// Minutes:
if (repeatOn == false)
{
separateDoubleDigits (tempTimeHolder, minutesFirstDigit, minutesSecondDigit);
if (millis () - startTime < 500UL)
{
timeBuffer [2] = minutesFirstDigit;
timeBuffer [3] = minutesSecondDigit;
}
else if (millis () - startTime < 1000UL)
{
timeBuffer [2] = 10; // 10 = blank
timeBuffer [3] = 10; // 10 = blank
}
else
{
startTime = millis ();
}
}
else // on repeat button press don't blink
{
separateDoubleDigits (tempTimeHolder, minutesFirstDigit, minutesSecondDigit);
timeBuffer [2] = minutesFirstDigit;
timeBuffer [3] = minutesSecondDigit;
repeatOn = false;
startTime = millis ();
}
}
updateDisplay (timeBuffer); // update the display
break;
case 5: // -------------------------------- 12h set time mode: --------------------------------
if (timeSetModeReset == true) // check if it's the first run of set time
{
timeSetModeReset = false;
for (int i = 0; i < 3; i++) // reset array
{
setTimeStageArray [i] = false;
}
// Keep the status of the am/pm LEDs for consistency when setting them and translate the
// time from 24h to 12h to display correctly:
if (RTC.h == 0)
{
tempTimeHolder = 12; // pass current time to temp variable for manipulation with buttons
setTimeAm = true;
}
else if (RTC.h < 12)
{
tempTimeHolder = RTC.h; // pass current time to temp variable for manipulation with buttons
setTimeAm = true;
}
else if (RTC.h == 12)
{
tempTimeHolder = RTC.h; // pass current time to temp variable for manipulation with buttons
setTimeAm = false;
}
else
{
tempTimeHolder = RTC.h - 12; // pass current time to temp variable for manipulation with buttons
setTimeAm = false;
}
dots.clear (); // turn off dots
dots.show ();
}
else if (setTimeStageArray [0] == false) // blink hours except when on repeat
{
// Hours:
if (repeatOn == false)
{
separateDoubleDigits (tempTimeHolder, hoursFirstDigit, hoursSecondDigit);
if (millis () - startTime < 500UL)
{
if (hoursFirstDigit == 0) // don't show zero
{
timeBuffer [0] = 10; // 10 = blank
}
else
{
timeBuffer [0] = hoursFirstDigit;
}
timeBuffer [1] = hoursSecondDigit;
}
else if (millis () - startTime < 1000UL)
{
timeBuffer [0] = 10; // 10 = blank
timeBuffer [1] = 10; // 10 = blank
}
else
{
startTime = millis ();
}
}
else // on repeat button press don't blink
{
separateDoubleDigits (tempTimeHolder, hoursFirstDigit, hoursSecondDigit);
if (hoursFirstDigit == 0) // don't show zero
{
timeBuffer [0] = 10; // 10 = blank
}
else
{
timeBuffer [0] = hoursFirstDigit;
}
timeBuffer [1] = hoursSecondDigit;
repeatOn = false;
startTime = millis ();
}
// Minutes:
separateDoubleDigits (RTC.m, minutesFirstDigit, minutesSecondDigit);
timeBuffer [2] = minutesFirstDigit;
timeBuffer [3] = minutesSecondDigit;
}
else if (setTimeStageArray [1] == false) // if hours set, blink minutes except on repeat
{
// Hours:
if (RTC.h == 0) // convert 24h to 12h for displaying properly
{
separateDoubleDigits (12, hoursFirstDigit, hoursSecondDigit);
}
else if (RTC.h > 12)
{
separateDoubleDigits (RTC.h - 12, hoursFirstDigit, hoursSecondDigit);
}
else
{
separateDoubleDigits (RTC.h, hoursFirstDigit, hoursSecondDigit);
}
if (hoursFirstDigit == 0) // don't show zero
{
timeBuffer [0] = 10; // 10 = blank
}
else
{
timeBuffer [0] = hoursFirstDigit;
}
timeBuffer [1] = hoursSecondDigit;
// Minutes:
if (repeatOn == false)
{
separateDoubleDigits (tempTimeHolder, minutesFirstDigit, minutesSecondDigit);
if (millis () - startTime < 500UL)
{
timeBuffer [2] = minutesFirstDigit;
timeBuffer [3] = minutesSecondDigit;
}
else if (millis () - startTime < 1000UL)
{
timeBuffer [2] = 10; // 10 = blank
timeBuffer [3] = 10; // 10 = blank
}
else
{
startTime = millis ();
}
}
else // if on repeat button press don't blink
{
separateDoubleDigits (tempTimeHolder, minutesFirstDigit, minutesSecondDigit);
timeBuffer [2] = minutesFirstDigit;
timeBuffer [3] = minutesSecondDigit;
repeatOn = false;
startTime = millis ();
}
}
else if (setTimeStageArray [2] == false) // if minutes set, blink AM/PM
{
// Hours:
if (RTC.h == 0) // convert 24h to 12h for displaying properly
{
separateDoubleDigits (12, hoursFirstDigit, hoursSecondDigit);
}
else if (RTC.h > 12)
{
separateDoubleDigits (RTC.h - 12, hoursFirstDigit, hoursSecondDigit);
}
else
{
separateDoubleDigits (RTC.h, hoursFirstDigit, hoursSecondDigit);
}
if (hoursFirstDigit == 0) // don't show zero
{
timeBuffer [0] = 10; // 10 = blank
}
else
{
timeBuffer [0] = hoursFirstDigit;
}
timeBuffer [1] = hoursSecondDigit;
// Minutes:
separateDoubleDigits (RTC.m, minutesFirstDigit, minutesSecondDigit);
timeBuffer [2] = minutesFirstDigit;
timeBuffer [3] = minutesSecondDigit;
// AM/PM LEDs:
if (millis () - startTime < 500UL)
{
if (setTimeAm == true)
{
digitalWrite (AM_LED, HIGH);
digitalWrite (PM_LED, LOW);
}
else
{
digitalWrite (AM_LED, LOW);
digitalWrite (PM_LED, HIGH);
}
}
else if (millis () - startTime < 1000UL)
{
digitalWrite (AM_LED, LOW);
digitalWrite (PM_LED, LOW);
}
else
{
startTime = millis ();
}
}
updateDisplay (timeBuffer); // update the display
break;
default:
break;
}
}
/*------------------------------------------------------------------------------------------------------------*/
/* Function for displaing the time on the VFD tubes and blinking the dots. When called with true, the time
is displayed with 12 hours:
*/
void displayTime (bool mode12hours = false)
{
// Local variables declaration:
// Main code:
// Hours:
currentHours = RTC.h;
if (mode12hours == false)
{
separateDoubleDigits (currentHours, hoursFirstDigit, hoursSecondDigit);
timeBuffer [0] = hoursFirstDigit;
timeBuffer [1] = hoursSecondDigit;
}
else
{
if (currentHours < 12)
{
switch (currentHours)
{
case 0:
currentHours = 12;
separateDoubleDigits (currentHours, hoursFirstDigit, hoursSecondDigit);
timeBuffer [0] = hoursFirstDigit;
timeBuffer [1] = hoursSecondDigit;
break;
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
separateDoubleDigits (currentHours, hoursFirstDigit, hoursSecondDigit);
timeBuffer [0] = 10; // blank
timeBuffer [1] = hoursSecondDigit;
break;
case 10:
case 11:
separateDoubleDigits (currentHours, hoursFirstDigit, hoursSecondDigit);
timeBuffer [0] = hoursFirstDigit;
timeBuffer [1] = hoursSecondDigit;
break;
default:
break;
}
digitalWrite (AM_LED, HIGH);
digitalWrite (PM_LED, LOW);
}
else
{
switch (currentHours)
{
case 12:
separateDoubleDigits (currentHours, hoursFirstDigit, hoursSecondDigit);
timeBuffer [0] = hoursFirstDigit;
timeBuffer [1] = hoursSecondDigit;
break;
case 13:
case 14:
case 15:
case 16:
case 17:
case 18:
case 19:
case 20:
case 21:
currentHours = currentHours - 12;
separateDoubleDigits (currentHours, hoursFirstDigit, hoursSecondDigit);
timeBuffer [0] = 10; // blank
timeBuffer [1] = hoursSecondDigit;
break;
case 22:
case 23:
currentHours = currentHours - 12;
separateDoubleDigits (currentHours, hoursFirstDigit, hoursSecondDigit);
timeBuffer [0] = hoursFirstDigit;
timeBuffer [1] = hoursSecondDigit;
break;
default:
break;
}
digitalWrite (AM_LED, LOW);
digitalWrite (PM_LED, HIGH);
}
}
// Minutes:
separateDoubleDigits (RTC.m, minutesFirstDigit, minutesSecondDigit);
timeBuffer [2] = minutesFirstDigit;
timeBuffer [3] = minutesSecondDigit;
// Blinking dots every second:
currentSeconds = RTC.s;
if (currentSeconds % 2 == 0) // if the seconds are even turn off dots
{
dots.clear (); // Set all pixel colors to 'off'
dots.show (); // Send the updated pixel colors to the hardware
}
else // if the seconds are even turn on dots
{
dots.setPixelColor (0, 28, 200, 52);
dots.setPixelColor (1, 28, 200, 52);
dots.show (); // Send the updated pixel colors to the hardware
}
updateDisplay (timeBuffer);
}
/*------------------------------------------------------------------------------------------------------------*/
/* Function for displaying the temperature on the VFDs. When called with firstRun true the reading of the
temperature and the compensation happens:
*/
void displayTemp (bool firstRun)
{
// Local variables declaration:
int intTemp = 0;
static unsigned long lastTime = 0;
// Main code:
if (firstRun == true) // run every DELAY seconds
{
digitalWrite (AM_LED, LOW);
digitalWrite (PM_LED, LOW);
originalTemp = dht.readTemperature ();
compensatedTemp = originalTemp - tempCompensation;
intTemp = compensatedTemp * 10;
separateThreeDigits (intTemp, tempFirstDigit, tempSecondDigit, tempThirdDigit);
tempBuffer [0] = tempFirstDigit;
tempBuffer [1] = tempSecondDigit;
tempBuffer [2] = tempThirdDigit;
tempBuffer [3] = 11; // c symbol
dots.setPixelColor (0, 28, 205, 52);
dots.setPixelColor (1, 0, 0, 0);
dots.show(); // send the updated pixel colors to the hardware
return; // skip first display update for effects to end
}
updateDisplay (tempBuffer);
}
/*------------------------------------------------------------------------------------------------------------*/
/* Function for displaying on the VFDs. When called with firstRun true the reading of the
temperature and the compensation happens:
*/
void displayHumidity (bool firstRun)
{
// Local variables declaration:
static unsigned long lastTime = 0;
float dewPointTemp = 0;
int originalHumidity = 0;
int compensatedHumidity = 0;
// Main code:
...
This file has been truncated, please download it to see its full contents.
Comments