• DS3231

    Rhea Rae5 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 Rae3 days ago 0 comments

    If screen is scrambled switch pin D13 and D11.

    -RR

  • ST7920 Pin-Out

    Rhea Rae3 days ago 0 comments

    Use EXP 3 Header!

    -RR

  • Ender Clock-Duino current Sketch

    Rhea Rae3 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 »