0%
0%

Ender_Clock_Duino

Arduino Clock

rhea-raeRhea Rae

Become a Hackaday.io member

Not a member? You should Sign up.

Already have an account? Log in.

Just one more thing

To make the experience fit your profile, pick a username and tell us what interests you.

Pick an awesome username
hackaday.io/
Your profile's URL: hackaday.io/username. Max 25 alphanumeric characters.
Pick a few interests
Projects that share your interests
People that share your interests
Similar projects worth following
0 followers
0 likes
View Gallery
Hello World! This project is an Arduino-based clock that repurposes an Ender-3 Pro printer display and rotary encoder into a permanent, appliance-style timepiece. The ST7920 LCD is driven over hardware SPI using U8g2, and the encoder is handled through interrupts for responsive and accurate input. Timekeeping is provided by a DS3231 RTC module, ensuring long-term accuracy and retention across resets and power loss, while EEPROM is used to store user settings so configuration persists without reentry. The interface uses a 12-hour time format with a clear AM and PM indicator and provides audible feedback through a piezo buzzer using tone variation rather than simulated volume control. The system is designed to be stable, predictable, and capable of running unattended for extended periods, treating reclaimed hardware as functional hardware rather than obsolete part's.

This project uses an Arduino Uno R3 board with an original Ender 3 Pro control panel LCD. The Arduino is driving the ST7920 LCD over hardware SPI and handling the integrated rotary encoder via interrupts for reliable input. Timekeeping is provided by a DS3231 RTC module to maintain accuracy across power loss, while user settings are stored in EEPROM so configuration persists without reentry. Audible feedback is implemented with a piezo buzzer using distinct tone patterns for interaction cues. 

  • 1 ×ばつ Elegoo Uno R3 Arduino R3 Clone
  • 1 ×ばつ ST7920 Display Spare Stock Ender 3 LCD Display
  • 1 ×ばつ Ender Clock-Duino Stand See links to download .stl file
  • 1 ×ばつ Breadboard Electronic Components / Misc. Electronic Components
  • 1 ×ばつ Assorted Jumpers

View all 6 components

  • DS3231

    Rhea Rae 18 hours ago 0 comments

    This DS3231 RTC module includes a charge path intended for a rechargeable LIR2032, implemented using a small series resistor and a glass diode feeding the VBAT node. Since I am using a standard CR2032 (non-rechargeable), I disabled the charging path.

    To do this, I identified the resistor located directly next to the glass diode associated with the battery circuit (both resistors on this board are marked “102”). I lifted one leg of the resistor that feeds the diode, effectively opening the VCC → VBAT charging path while leaving the battery connected to the DS3231’s VBAT pin.

    After lifting the resistor, I installed a CR2032 coin cell, set the time, unplugged the clock for several minutes, and then re-applied power. The RTC retained the correct time, confirming that VBAT backup is functioning normally and that the coin cell is no longer being charged from VCC.

    This modification prevents unintended charging of a non-rechargeable coin cell while preserving full RTC backup operation.

    -RR

  • Scrambled

    Rhea Rae 4 days ago 0 comments

    If screen is scrambled switch pin D13 and D11.

    -RR

  • ST7920 Pin-Out

    Rhea Rae 4 days ago 0 comments

    Use EXP 3 Header!

    -RR

  • Ender Clock-Duino current Sketch

    Rhea Rae 4 days ago 0 comments

    #include <Arduino.h>
    #include <U8g2lib.h>
    #include <EEPROM.h>
    #include <Wire.h>
    #include <RTClib.h>

    // ================= LCD =================
    const uint8_t PIN_LCD_CS = 10; // CS/RS
    U8G2_ST7920_128X64_1_HW_SPI u8g2(U8G2_R0, PIN_LCD_CS, U8X8_PIN_NONE);

    // ================= ENCODER =================
    const uint8_t PIN_ENC_A   = 2;
    const uint8_t PIN_ENC_B   = 3;
    const uint8_t PIN_ENC_BTN = 4;

    // If your encoder changes 2 numbers per click, set this to 2.
    // If it changes 1 per click, leave at 4.
    const int8_t TRANSITIONS_PER_DETENT = 4;

    // ================= UI TIMING =================
    const uint16_t LONG_MS     = 700;
    const uint16_t DEBOUNCE_MS = 25;

    // ================= EEPROM =================
    const int EEPROM_SIG_ADDR    = 0;
    const int EEPROM_TIME_ADDR   = 1;                  // (legacy; not used now, kept for spacing)
    const int EEPROM_CHIME_ADDR  = EEPROM_TIME_ADDR + 4; // uint8_t
    const int EEPROM_TONE_ADDR   = EEPROM_CHIME_ADDR + 1; // uint8_t
    const int EEPROM_FMT_ADDR    = EEPROM_TONE_ADDR + 1;  // uint8_t (0=12h,1=24h)
    const uint8_t EEPROM_SIG     = 0xA5;

    // ================= BUZZER =================
    const uint8_t PIN_BUZZER = 8;

    // Settings (editable, saved)
    bool    chime_enabled = true;
    uint8_t tone_amount   = 18;    // 0..100 (0 = silent)
    bool    fmt_24h       = false; // false=12h, true=24h

    // ================= RTC =================
    RTC_DS3231 rtc;

    // Throttle RTC reads so we don't spam I2C
    DateTime rtc_cached;
    uint32_t last_rtc_read_ms = 0;

    // ================= SET MODE FIELDS =================
    bool set_mode = false;

    // Editing fields
    uint8_t edit_hour12 = 12;  // 1..12
    bool    edit_pm     = false;
    uint8_t edit_hour24 = 0;   // 0..23
    uint8_t edit_min    = 0;   // 0..59

    bool    edit_chime_enabled = true;
    uint8_t edit_tone_amount   = 18;
    bool    edit_fmt_24h       = false;

    enum Sel : uint8_t { SEL_HOUR, SEL_MIN, SEL_AMPM, SEL_FMT, SEL_CHIME, SEL_TONE, SEL_TEST };
    Sel sel = SEL_HOUR;

    uint32_t saved_banner_until_ms = 0;
    int8_t last_chimed_h24 = -1;

    // ================= ENCODER ISR =================
    volatile int16_t enc_delta = 0;
    volatile uint8_t enc_prev  = 0;

    static const int8_t ENC_TAB[16] = {
      0, -1,  1,  0,
      1,  0,  0, -1,
     -1,  0,  0,  1,
      0,  1, -1,  0
    };

    void enc_isr() {
      uint8_t a = digitalRead(PIN_ENC_A) ? 1 : 0;
      uint8_t b = digitalRead(PIN_ENC_B) ? 1 : 0;
      uint8_t cur = (a << 1) | b;
      uint8_t idx = (enc_prev << 2) | cur;
      enc_prev = cur;
      enc_delta += ENC_TAB[idx];
    }

    // ================= BUTTON =================
    bool btn_last_raw = true;
    bool btn_stable   = true;
    uint32_t btn_change_ms = 0;
    uint32_t btn_down_ms   = 0;
    bool long_fired = false;

    static void poll_button(bool &short_press, bool &long_press) {
      short_press = false;
      long_press  = false;

      bool raw = digitalRead(PIN_ENC_BTN); // HIGH idle, LOW pressed
      uint32_t now = millis();

      if (raw != btn_last_raw) {
        btn_last_raw = raw;
        btn_change_ms = now;
      }

      if ((now - btn_change_ms) > DEBOUNCE_MS) {
        if (btn_stable != raw) {
          btn_stable = raw;
          if (btn_stable == LOW) {
            btn_down_ms = now;
            long_fired = false;
          } else {
            if (!long_fired) short_press = true;
          }
        }
      }

      if (btn_stable == LOW && !long_fired && (now - btn_down_ms) >= LONG_MS) {
        long_fired = true;
        long_press = true;
      }
    }

    // ================= HELPERS =================
    static const char* ampm_str(bool pm) { return pm...

    Read more »

View all 4 project logs

Enjoy this project?

Share

Discussions

Log In/Sign up to comment

Become a Hackaday.io Member

Create an account to leave a comment. Already have an account? Log In.

Similar Projects

Project Owner Contributor

UV Exposure Unit

alex365Alex365

Does this project spark your interest?

to follow this project and never miss any updates

Cancel

AltStyle によって変換されたページ (->オリジナル) /