Alarm clock for 4 digit display

Alarm clock for 7 segment 4 digit display.
1
5
0
35
updated April 23, 2025

Description

PDF

I use a dfrobot firebeetle 2 esp-c6 but you can use anything with wifi, a MAX7219 4 digit 7 segment display, a 18650 battery, a push button, a buzzer and a switch for the battery.

The battery is connected directly to the builtin li-ion charger on the board, but if your doesnt have one you can just connect it to the VIN pin and GND and charge it using a external charging board.

 

Pinout:

ESPComponents
GPIO8MAX7219 DIN
GPIO7MAX7219 CLK
GPIO6MAX7219 CS
GPIO5Buzzer (+)
GPIO4Button (one side)
3.3VMAX7219 VCC
GNDMAX7219 GND + Buzzer (-) + Button (other side)

 

 

#include <WiFi.h>
#include <WiFiUdp.h>
#include <NTPClient.h>

// WiFi Settings
const char* ssid = "WIFI-SSID";
const char* password = "WIFI-PASS";

// NTP Client (UTC+1: 3600 seconds)
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", 10800, 60000);

// MAX7219 Pins
#define DIN_PIN 8
#define CLK_PIN 7
#define CS_PIN 6

// Alarm Components
#define BUZZER_PIN 5
#define BUTTON_PIN 4
bool alarmTriggered = false;
bool alarmActive = false;
unsigned long lastBeep = 0;
unsigned long lastDebounce = 0;
const int debounceDelay = 50;

byte reverseSegments(byte original) {
  return ((original & 0x01) << 6) |  // Bit 0 → Bit 6 (A↔G)
         ((original & 0x02) << 4) |  // Bit 1 → Bit 5 (B↔F)
         ((original & 0x04) << 2) |  // Bit 2 → Bit 4 (C↔E)
         ((original & 0x08) << 0) |  // Bit 3 → Bit 3 (D stays)
         ((original & 0x10) >> 2) |  // Bit 4 → Bit 2 (E↔C)
         ((original & 0x20) >> 4) |  // Bit 5 → Bit 1 (F↔B)
         ((original & 0x40) >> 6);    // Bit 6 → Bit 0 (G↔A)
}

const byte SEGMENT_MAP[10] = {
  reverseSegments(0x3F), // 0
  reverseSegments(0x06), // 1
  reverseSegments(0x5B), // 2
  reverseSegments(0x4F), // 3
  reverseSegments(0x66), // 4
  reverseSegments(0x6D), // 5
  reverseSegments(0x7D), // 6
  reverseSegments(0x07), // 7
  reverseSegments(0x7F), // 8
  reverseSegments(0x6F)  // 9
};

void sendCommand(uint8_t address, uint8_t data) {
  digitalWrite(CS_PIN, LOW);
  shiftOut(DIN_PIN, CLK_PIN, MSBFIRST, address);
  shiftOut(DIN_PIN, CLK_PIN, MSBFIRST, data);
  digitalWrite(CS_PIN, HIGH);
}

void initMAX7219() {
  pinMode(DIN_PIN, OUTPUT);
  pinMode(CLK_PIN, OUTPUT);
  pinMode(CS_PIN, OUTPUT);
  digitalWrite(CS_PIN, HIGH);

  sendCommand(0x0C, 0x01);  // Power ON
  sendCommand(0x09, 0x00);  // No decoding
  sendCommand(0x0A, 0x0F);  // Max brightness
  sendCommand(0x0B, 0x03);  // Scan 4 digits
  for(int i = 1; i <= 4; i++) sendCommand(i, 0x00); // Clear
}

void displayTime(int hours, int minutes) {
  sendCommand(4, SEGMENT_MAP[minutes % 10]);  // Rightmost digit
  sendCommand(3, SEGMENT_MAP[minutes / 10]);
  sendCommand(2, SEGMENT_MAP[hours % 10]);
  sendCommand(1, SEGMENT_MAP[hours / 10]);    // Leftmost digit
}

void setup() {
  Serial.begin(115200);
  initMAX7219();
  
  // Alarm components
  pinMode(BUZZER_PIN, OUTPUT);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  digitalWrite(BUZZER_PIN, LOW);

  WiFi.begin(ssid, password);
  while(WiFi.status() != WL_CONNECTED) delay(500);
  
  timeClient.begin();
  timeClient.update();
}

void loop() {
  timeClient.update();
  int hours = timeClient.getHours();
  int minutes = timeClient.getMinutes();
  Serial.print(hours);
  Serial.println(minutes);
  // Update display
  displayTime(hours, minutes);

  // Alarm Logic (6:00 AM)
  if (!alarmTriggered && hours == 6 && minutes == 0) {
    alarmActive = true;
    alarmTriggered = true;
    Serial.println("ALARM ACTIVATED!");
  }

  // Handle active alarm
  if (alarmActive) {
    // Non-blocking beeper (500ms on/off)
    if (millis() - lastBeep >= 500) {
      digitalWrite(BUZZER_PIN, !digitalRead(BUZZER_PIN));
      lastBeep = millis();
    }

    // Button press with debounce
    if (digitalRead(BUTTON_PIN) == LOW && 
       (millis() - lastDebounce) > debounceDelay) {
      alarmActive = false;
      digitalWrite(BUZZER_PIN, LOW);
      lastDebounce = millis();
      Serial.println("ALARM STOPPED");
    }
  }
  // Hourly NTP sync
  static unsigned long lastUpdate = 0;
  if(millis() - lastUpdate >= 3600000) {
    timeClient.forceUpdate();
    lastUpdate = millis();
  }
  
  delay(1000);
}

If you want to change your timezone change the third parameter of the function (in my case 10800 for UTC+3) to 3600*x (your timezone is UTC+x)

NTPClient timeClient(ntpUDP, "pool.ntp.org", 10800, 60000);

Tags



Model origin

The author marked this model as their own original creation.

License


Highlighted models from creator

View more