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);
    udp.endPacket();
}

void setup()
{
    // debug
    Serial.begin(9600);

    // 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)
    {
        delay(200);
    }

    Serial.println("Starting UDP");
    udp.begin(localPort);
    Serial.print("Local port: ");
    Serial.println(udp.localPort());
}

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

    // send an ntp packet to a time server
    sendNTPpacket(timeServerIP);

    // wait to see if a reply is available
    delay(1000);

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

        // 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 = ");
        Serial.println(secsSince1900);

        // 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:
        Serial.println(epoch);

        // 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);
        Serial.print(':');

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

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

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

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

    // wait ten seconds before asking for the time again
    delay(10000);
}