I’m thinking of building an alarm clock next, I need something that has bright lights that can be turned on and off, as my wall clock I can’t read at night. I’m probably going to use four MAX7219 controlled 8×8 LED matrices just to display the four digits. I was thinking of a 7-segment display, but that’s a bit small.

Also I’d like it to be NTP synced, so needs wifi. I’ll possibly use a Raspberry Pi Zero with wifi dongle, if I can get my hands on one, otherwise it’ll be an ESP-12; probably powered by a USB mains adaptor as the LED’s need 5v even though the zero/esp8266 are 3.3v

Not sure if its going to be just a clock or an alarm, I don’t think a piezo buzzer will be very good, so maybe a speaker.

I’ve already got a bunch of DS1307 RTC chips and 32.768KHz 12.5pF crystals, just have to power at 5v and use pullup resistors on SDA/SCL to 3.3v

I made a test sketch on the 4tronix ESP-12e breakout, which just prints the NTP time to the serial monitor, its based on the demo from the ESP8266WiFi library:

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

// local port to listen for udp packets
unsigned int localPort = 2390;

// ntp server pool
IPAddress timeServerIP;
const char* ntpServerName = "europe.pool.ntp.org";

// ntp time stamp is in the first 48 bytes of the message
const int NTP_PACKET_SIZE = 48;

// buffer to hold incoming and outgoing packets
byte packetBuffer[NTP_PACKET_SIZE];

// create a udp instance
WiFiUDP udp;

// send an ntp request to the time server at the given address
unsigned long sendNTPpacket(IPAddress& address)
    Serial.println("Sending NTP packet...");

    // set all bytes in the buffer to 0
    memset(packetBuffer, 0, NTP_PACKET_SIZE);

    packetBuffer[0] = 0b11100011;   // li, version, mode
    packetBuffer[1] = 0;            // stratum, or type of clock
    packetBuffer[2] = 6;            // polling interval
    packetBuffer[3] = 0xEC;         // peer clock precision

    // 8 bytes of zero for root delay & root dispersion
    packetBuffer[12] = 49;
    packetBuffer[13] = 0x4E;
    packetBuffer[14] = 49;
    packetBuffer[15] = 52;

    // all ntp fields have been given values, send request
    udp.beginPacket(address, 123);
    udp.write(packetBuffer, NTP_PACKET_SIZE);

void setup()
    // debug

    // connect to wifi network
    WiFi.begin("SSID", "passphrase");

    // static ip, gateway, netmask
    WiFi.config(IPAddress(192, 168, 1, 2), IPAddress(192, 168, 1, 1), IPAddress(255, 255, 255, 0));

    while (WiFi.status() != WL_CONNECTED)

    Serial.println("Starting UDP");
    Serial.print("Local port: ");

void loop()
    // get a random server from the pool
    WiFi.hostByName(ntpServerName, timeServerIP);

    // send an ntp packet to a time server

    // wait to see if a reply is available

    int cb = udp.parsePacket();
    if (!cb)
        Serial.println("No packet yet");
        // we've received a packet, read the data from it
        Serial.print("Packet received, length=");

        // read the packet into the buffer
        udp.read(packetBuffer, NTP_PACKET_SIZE);

        // the timestamp starts at byte 40 of the received packet and is four bytes,
        // or two words, long. first, esxtract the two words:
        unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
        unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);

        // combine the four bytes (two words) into a long integer
        // this is ntp time (seconds since jan 1 1900):
        unsigned long secsSince1900 = highWord << 16 | lowWord;
        Serial.print("Seconds since Jan 1 1900 = ");

        // now convert ntp time into everyday time:
        Serial.print("Unix time = ");

        // unix time starts on jan 1 1970. in seconds, that's 2208988800:
        const unsigned long seventyYears = 2208988800UL;

        // subtract seventy years:
        unsigned long epoch = secsSince1900 - seventyYears;

        // print unix time:

        // utc is the time at gmt
        Serial.print("The UTC time is ");

        // print the hour - 86400 equals secs per day
        Serial.print((epoch % 86400L) / 3600);

        // in the first 10 minutes of each hour, we'll want a leading '0'
        if (((epoch % 3600) / 60) < 10)

        // print the minute (3600 equals secs per minute)
        Serial.print((epoch % 3600) / 60);

        // in the first 10 seconds of each minute, we'll want a leading '0'
        if ((epoch % 60) < 10)

        // print the second
        Serial.println(epoch % 60);

    // wait ten seconds before asking for the time again