Alarm Clock Design
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);
}