aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoruser@node5.net <user@node5.net>2025-08-25 20:21:51 +0200
committeruser@node5.net <user@node5.net>2025-08-25 20:21:51 +0200
commit213554538fac9abe4e161f434fb0e156ec52f26e (patch)
treecf4fed8d7ada9b2bd45151c1d78e587e50e3490b
parentbf1ba0980d4bbef0e1b90d00e5e57b0bc159ca89 (diff)
VFD works
-rw-r--r--README.md6
-rw-r--r--include/header.h11
-rw-r--r--include/user_settings.h8
-rw-r--r--src/main.cpp272
4 files changed, 30 insertions, 267 deletions
diff --git a/README.md b/README.md
index d397a1f..e69de29 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +0,0 @@
-# 7 Segment display
-Big 3D printed RGB LED seven segment display clock
-
-Read more here: [blog.node5.net - Seven segment display](https://blog.node5.net/Seven%20segment%20display/)
-
-[Main code file](../tree/src/main.cpp)
diff --git a/include/header.h b/include/header.h
deleted file mode 100644
index 18d92a4..0000000
--- a/include/header.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#define LED_PIN 2 // Pin the LED strip is connected to
-#define PHOTORESISTOR_PIN 3 // Used for dimming the LEDs based on light level
-#define SEGMENT_COUNT 7 // 7 segment display
-#define DIGIT_COUNT 4 // Number of digits 4 for a clock
-#define START_OFFSET 1 // First segment flickers, voltage level shifter?
-#define LED_COUNT (DIGIT_COUNT * SEGMENT_COUNT) + START_OFFSET
-#define LED_TYPE WS2811
-#define COLOR_ORDER GRB
-#define SATURATION 255
-#define WIFI_CONN_ANI_TIMEOUT 1000 * 60 // Stop WiFi connection animation after one minute
-
diff --git a/include/user_settings.h b/include/user_settings.h
index f44c952..30304f0 100644
--- a/include/user_settings.h
+++ b/include/user_settings.h
@@ -1,10 +1,10 @@
-// #define WIFI_SSID ""
-// #define WIFI_PASSWORD ""
+#define WIFI_SSID ""
+#define WIFI_PASSWORD ""
-// #define NTP_SERVER "pool.ntp.org" // Don't do a D-Link
+#define NTP_SERVER "pool.ntp.org" // Don't do a D-Link
#define NTP_UPDATE_INTERVAL 60000
-#define HOSTNAME "7-segment-esp-ws2811"
+#define HOSTNAME "VFD-clock"
#ifndef WIFI_SSID
#error You must specify a WiFi SSID above, remember to uncomment the line
diff --git a/src/main.cpp b/src/main.cpp
index 5aecda2..9158336 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,273 +1,53 @@
#include <user_settings.h>
-#include <header.h>
#include <FastLED.h>
#include <ESP8266WiFi.h>
#include <ezTime.h>
-// Define the array of leds
-CRGB leds[LED_COUNT];
-
Timezone CopenhagenTime;
-// Used for hue shift each minute
-// https://github.com/FastLED/FastLED/wiki/FastLED-HSV-Colors
-int hue = 0;
-int max_brightness = 255;
-// Hold state if an led is on, to check if it should be faded on / off, or if it already is in desired state
-bool on_state[SEGMENT_COUNT * DIGIT_COUNT] = {false};
-
-// Segment naming scheme, corresponds to LED strip soldering order, standardized on Wikipeadia
-// https://en.wikipedia.org/wiki/Seven-segment_display#/media/File:7_Segment_Display_with_Labeled_Segments.svg
-// Last bit unused
-typedef enum : uint8_t {
- seg_a = 1<<0, // 00000001
- seg_b = 1<<1, // 00000010
- seg_c = 1<<2, // 00000100
- seg_d = 1<<3, // ...
- seg_e = 1<<4,
- seg_f = 1<<5,
- seg_g = 1<<6
-} segments;
-
-//
-uint8_t symbols[] = {
- /* 0 */ seg_a | seg_b | seg_c | seg_d | seg_e | seg_f, // 00111111
- /* 1 */ seg_b | seg_c, // 00000110
- /* 2 */ seg_a | seg_b | seg_g | seg_e | seg_d, // ...
- /* 3 */ seg_a | seg_b | seg_g | seg_c | seg_d,
- /* 4 */ seg_f | seg_g | seg_c | seg_b,
- /* 5 */ seg_a | seg_f | seg_g | seg_c | seg_d,
- /* 6 */ seg_a | seg_f | seg_g | seg_c | seg_d | seg_e,
- /* 7 */ seg_a | seg_b | seg_c,
- /* 8 */ seg_a | seg_b | seg_c | seg_d | seg_e | seg_f | seg_g,
- /* 9 */ seg_g | seg_f | seg_a | seg_b | seg_c | seg_d,
- /* ° */ seg_a | seg_b | seg_g | seg_f,
- /* C */ seg_a | seg_f | seg_e | seg_d
-};
-
-// Which segments should change color in this frame of the animation
-uint8_t spin_animation[] = {
- seg_a,
- seg_b,
- seg_c,
- seg_d,
- seg_e,
- seg_f,
-};
-
-
-uint8_t dual_spin_animation[] = {
- seg_a | seg_d,
- seg_b | seg_e,
- seg_c | seg_f,
- seg_d | seg_a,
- seg_e | seg_b,
- seg_f | seg_c,
-};
-
-// Fades all at once
-void display_symbols(uint8_t *symbols_mask) {
- // Loop over each brightness state and apply it to all elements if it's not already the desired state
- for (int brightness = 0; brightness <= max_brightness; brightness ++) {
- for (uint8_t digit_index = 0; digit_index < DIGIT_COUNT; digit_index++) {
- // Counts up by bitshifting
- uint8_t seg_counter = 1;
-
- for (int segment_index = 0; segment_index < SEGMENT_COUNT; segment_index++) {
- int digit_offset = digit_index * SEGMENT_COUNT;
- // LEDS can be offsed by START_INDEX, state array isn't
- int led_raw_index = digit_offset + segment_index;
- int led_index = START_OFFSET + led_raw_index;
- // Get this LEDs previous state to see if it should be changed
- bool previously_on = on_state[led_raw_index];
- // Compare the current segment bit with the mask for the symbol
- bool turn_on = symbols_mask[digit_index] & seg_counter;
-
- if (turn_on) {
- // Turn on LED
- if(previously_on){
- // Previously on, allow hue change
- leds[led_index] = CHSV(hue, SATURATION, max_brightness);
- } else {
- // Previously off, gradually increase brightness with loop e.g. 0-255
- leds[led_index] = CHSV(hue, SATURATION, brightness);
- }
- } else {
- // Turn off LED
- if(previously_on) {
- // Previously on, gradually decrease brightness with a negative of the loop e.g. 255-0
- leds[led_index] = CHSV(hue, SATURATION, max_brightness - brightness);
- }
- }
-
- // Last loop itteration, save current LED state
- if (brightness == max_brightness) {
- on_state[led_raw_index] = turn_on;
- }
-
- // Increment segment counter used with bit mask comparison by bitshifting
- seg_counter = seg_counter<<1;
- }
- }
-
- // Push changes of entire LED array to LEDs
- FastLED.show();
- delay(2);
- }
-}
-
-// Show a four digit number, by fading on LEDs
-void display_number(int number) {
- // Build up entire bit mask, so all can be faded on at once
- uint8_t symbols_mask[DIGIT_COUNT];
- // Start from the last digit
- for (int digit_index = DIGIT_COUNT - 1; digit_index >= 0; digit_index--) {
- // Get only last digit
- symbols_mask[digit_index] = symbols[number % 10];
- // Pop last digit
- number /= 10;
- }
- display_symbols(symbols_mask);
-}
-
-// Instantly changes. Binary, no fade
-void display_symbol(int digit_index, uint8_t symbol) {
- // Counts up by bitshifting
- uint8_t seg_counter = 1;
- for (int segment_index = 0; segment_index < SEGMENT_COUNT; segment_index++) {
- int offset = digit_index * SEGMENT_COUNT;
- int led_index = START_OFFSET + offset + segment_index;
-
- // Compare the current segment bit with the bit mask for the symbol
- if (symbol & seg_counter) {
- // Turn on LED
- leds[led_index] = CHSV(hue, SATURATION, max_brightness);
- FastLED.show();
- }
-
- // Increment segment counter used with bit mask comparison by bitshifting
- seg_counter = seg_counter<<1;
- }
-}
-
-// Change hue of 0-7 segments per frame each digit displays the same
-void play_animation(uint8_t *animation, int animation_size, int segment_delay) {
- for (int i = 0; i < animation_size; i++){
- for (int digit_index = 0; digit_index < 4; digit_index++) {
- display_symbol(digit_index, animation[i]);
- }
-
- hue += 16; // Increment HSV hue a lot for rainbow vomit
- FastLED.show();
- delay(segment_delay);
- }
-}
-
-// Check the time, and display it on the clock
-void update_clock() {
- // Set hue to a value derived from the time of day, doing 1 loop per day
- int hour = CopenhagenTime.dateTime("G").toInt();
- int minute = CopenhagenTime.dateTime("i").toInt();
- int minute_of_day = (hour * 60) + minute;
- hue = map(minute_of_day, 0, 1440, 0, 255);
-
- Serial.println("Minute of day:");
- Serial.println(minute_of_day);
- Serial.println("Hue:");
- Serial.println(hue);
-
- // Format the time as a 4-digit integer
- int timeInt = CopenhagenTime.dateTime("Hi").toInt(); // Sadly string format
- display_number(timeInt);
- //hue++; // Increment HSV hue
-}
-
void setup() {
- // Setup LEDs
- FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, LED_COUNT).setCorrection( TypicalLEDStrip );
- FastLED.addLeds<NEOPIXEL, LED_PIN>(leds, LED_COUNT); // GRB ordering is assumed
+ Serial.begin(9600);
- // Turn off all LEDs
- FastLED.clear();
-
- Serial.begin(9600);
-
- setServer(NTP_SERVER);
+ Serial.write(0x0C); // Clear display
+ Serial.print("VFD display\n");
+ Serial.print("Starting\n");
WiFi.setHostname(HOSTNAME);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
- Serial.print("Connecting");
+
+ Serial.write(0x0C); // Clear display
+ Serial.printf("Hostname: %s\n", HOSTNAME);
+ Serial.printf("Connecting to: %s\n", WIFI_SSID);
while (WiFi.status() != WL_CONNECTED)
{
- // Play animation untill connected to WiFi, or animation timeout is reached
- // Will continue attempting to connect to WiFi
- if (millis() < WIFI_CONN_ANI_TIMEOUT) {
- play_animation(spin_animation, sizeof(spin_animation), 100);
- } else {
- // Turn off all LEDs
- FastLED.clear();
- }
+ delay(1000);
+ Serial.print('.');
}
-
- delay(100);
- hue = 0;
- // Turn off all LEDs
- FastLED.clear();
-
- Serial.println();
- Serial.print("Connected, IP address: ");
+ Serial.write(0x0C); // Clear display
+ Serial.println("Connected, IP address: ");
Serial.println(WiFi.localIP());
+ delay(1000);
waitForSync();
- Serial.println("UTC: " + UTC.dateTime());
CopenhagenTime.setLocation("Europe/Copenhagen");
- Serial.println("Copenhagen time: " + CopenhagenTime.dateTime());
-
- update_clock();
-}
-
-/*
-// Test each segment
-int i = 0;
-
-void loop() {
- leds[i] = CRGB::Red;
- FastLED.show();
- delay(500);
- leds[i] = CRGB::Black;
- FastLED.show();
- delay(500);
- i++;
- if (i > LED_COUNT - 1) {
- i = 0;
- }
+ Serial.write(0x0C); // Clear display
}
-*/
void loop() {
- // Only update on each hole minute to avoid flickering
- int seconds = CopenhagenTime.dateTime("s").toInt();
- int minutes = CopenhagenTime.dateTime("i").toInt();
-
- // Play animation 5 seconds before hour change
- if(minutes == 59 && seconds >= 55) {
- play_animation(dual_spin_animation, sizeof(spin_animation), 50);
- FastLED.clear();
- }
+ // Get Unix epoch timestamp
+ char buffer [3];
+ sprintf(buffer,"%03d",ms());
+ String milliEpoch = String(now()) + buffer;
+ Serial.println(milliEpoch);
- // Do nothing untill minute change
- if(seconds != 0) {
- delay(10);
- return;
- }
-
- // Minute changed
- update_clock();
-
- // Wait untill minute change check won't be triggered again
- delay(1000);
-}
+ delay(50);
+ // https://github.com/ropg/ezTime#getting-date-and-time
+ // 16;36;15 Sat 16 Aug 33
+ String time_formatted = CopenhagenTime.dateTime("H:i:s D d M");
+ Serial.println(time_formatted);
+ events(); // Needed to update time continuously
+}