Основным контроллером в этой сборке является ESP8266, входящий в состав мини-модуля Wemos D1. Благодаря встроенному Wi-Fi позволяет выполнять многие задачи. Один из них - создание часов с использованием сетевого протокола NTP (Network Time Protocol). NTP можно использовать для синхронизации всех сетевых устройств с временем UTC за несколько миллисекунд. При использовании NTP для создания часов не требуется дополнительный модуль DS1307 для получения данных времени.
Эти часы состоят из 4-х модулей. 2 модуля показывают час, еще 2 модуля - минуты. На секунду указывают 2 светодиода, которые находятся между цифрами часа и минуты. Каждый модуль состоит из 7 сегментов.
Сначала мастер разработал схему и эскиз печатной платы.
Файлы можно скачать ниже.
Дальше распечатывает схему, затем переносит на печатную плату.
Помещает плату в травильный раствор. После травления промывает плату, протирает. Сверлит отверстия.
Собирает согласно ранее приведенной схемы.
При разработке кода мастер использует программу Visual Studio Code + Platformio. Перед установкой кода нужно установить библиотеку:
Загружает код.
#include <Arduino.h>
/************************************************************** /
Made by : Mr. Sottong
****************************************************************/
#include <TimeLib.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include "Ticker.h"
Ticker Timer500ms;
//WiFi variables............................................................
const char ssid[] = "xxx"; //your network SSID (name)
const char pass[] = "yyy"; // your network password
// NTP Servers:
static const char ntpServerName[] = "us.pool.ntp.org";
//static const char ntpServerName[] = "time-b.timefreq.bldrdoc.gov";//static const char ntpServerName[] = "time-a.timefreq.bldrdoc.gov";
// static const char ntpServerName[] = "server 0.id.pool.ntp.org";
float timeZone = 7; //+7 GMT
WiFiUDP Udp;
unsigned int localPort = 8888; // local port to listen for UDP packets
time_t getNtpTime();
void sendNTPpacket(IPAddress &address);
//OTHER variables................................................................
//Pin connected to ST_CP / Pin 12 of 74HC595
int latchPin = 0; //D3
//Pin connected to SH_CP / Pin 11 of 74HC595
int clockPin = 5; //D1
////Pin connected to DS / Pin 14 of 74HC595
int dataPin = 4; //D2
//Pin connected to LED
int LEDpin = 2; //D4
//Seven Segment
unsigned long d1[10] = {0x8140,0xcf40,0x9240,0x8640,0xcc40,0xa440,0xa040,0x8f40,0x8040,0x8440};
unsigned long d2[10] = {0x8120,0xcf20,0x9220,0x8620,0xcc20,0xa420,0xa020,0x8f20,0x8020,0x8420};
unsigned long d3[10] = {0x8110,0xcf10,0x9210,0x8610,0xcc10,0xa410,0xa010,0x8f10,0x8010,0x8410};
unsigned long d4[10] = {0x8108,0xcf08,0x9208,0x8608,0xcc08,0xa408,0xa008,0x8f08,0x8008,0x8408};
bool Led = 0;
/*-------- NTP code ----------*/
const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets
time_t getNtpTime() {
IPAddress ntpServerIP; // NTP server's ip address
while (Udp.parsePacket() > 0) ; // discard any previously received packets
// get a random server from the pool
WiFi.hostByName(ntpServerName, ntpServerIP);
sendNTPpacket(ntpServerIP);
uint32_t beginWait = millis();
while (millis() - beginWait < 1600) {
int size = Udp.parsePacket();
if (size >= NTP_PACKET_SIZE) {
Udp.read(packetBuffer, NTP_PACKET_SIZE); // read packet into the buffer
unsigned long secsSince1900;
// convert four bytes starting at location 40 to a long integer
secsSince1900 = (unsigned long)packetBuffer[40] << 24;
secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
secsSince1900 |= (unsigned long)packetBuffer[43];
return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
}
}
return 0; // return 0 if unable to get the time
}
// send an NTP request to the time server at the given address
void sendNTPpacket(IPAddress &address) {
// set all bytes in the buffer to 0
memset(packetBuffer, 0, NTP_PACKET_SIZE);
// Initialize values needed to form NTP request
// (see URL above for details on the packets)
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, now
// you can send a packet requesting a timestamp:
Udp.beginPacket(address, 123); //NTP requests are to port 123
Udp.write(packetBuffer, NTP_PACKET_SIZE);
Udp.endPacket();
}
void printDigits(int value) {
int th = value / 1000;
int hun = value / 100;
int tens = value / 10;
// if (th == 0) {
// thByte = 0;
// }
// else {
// thByte = th % 10;
// }
digitalWrite(latchPin, LOW); //THOUSANDS - Ribuan - jam
shiftOut(dataPin, clockPin, LSBFIRST, d4[th]);
shiftOut(dataPin, clockPin, LSBFIRST, d4[th]>>8);
digitalWrite(latchPin, HIGH);
delay(1);
digitalWrite(latchPin, LOW); //HUNDREDS - Ratusan - jam
shiftOut(dataPin, clockPin, LSBFIRST, d3[hun % 10]);
shiftOut(dataPin, clockPin, LSBFIRST, d3[hun % 10]>>8);
digitalWrite(latchPin, HIGH);
delay(1);
digitalWrite(latchPin, LOW); //TENS - Puluhan - menit
shiftOut(dataPin, clockPin, LSBFIRST, d2[tens % 10]);
shiftOut(dataPin, clockPin, LSBFIRST, d2[tens % 10]>>8);
digitalWrite(latchPin, HIGH);
delay(1);
digitalWrite(latchPin, LOW); //ONES - satuan - menit
shiftOut(dataPin, clockPin, LSBFIRST, d1[(value % 10)]);
shiftOut(dataPin, clockPin, LSBFIRST, d1[(value % 10)]>>8);
digitalWrite(latchPin, HIGH);
delay(1);
}
void wifinc(){
//animation when wifi is not connected
int on = 0b0000000001111000;
int off = 0b0000000000000000;
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, LSBFIRST, on);
shiftOut(dataPin, clockPin, LSBFIRST, on>>8);
digitalWrite(latchPin, HIGH);
delay(100);
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, LSBFIRST, off);
shiftOut(dataPin, clockPin, LSBFIRST, off>>8);
digitalWrite(latchPin, HIGH);
delay(100);
}
void Setiap500ms(){
Led = !Led;
}
void setup() {
//Serial begin
Serial.begin(115200);
//set pins to output so you can control the shift register
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(LEDpin, OUTPUT);
Udp.begin(localPort);
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED) {
delay ( 500 );
Serial.print ( "." );
wifinc();
}
setSyncProvider(getNtpTime);
setSyncInterval(360);
if (hour() == 0 && second() < 3) {
setSyncProvider(getNtpTime);
}
Timer500ms.attach_ms (500,Setiap500ms);
}
void loop() {
printDigits(int(hour() * 100 + minute()));
digitalWrite(LEDpin,Led); //Led Detik
if(Led == 1){
Serial.println(int(hour() * 100 + minute()));
}
}
Для установки часов в горизонтальном положении мастер напечатал подставку. Файлы для печати можно скачать ниже.
Все готово.
Весь процесс по изготовлению таких часов можно посмотреть на видео.