Make a Home-made Network Clock with ESP32-E

Introduction 

A few days ago, I heard one of my friends say that he was going to move to a new house. So, I thought about giving him some gifts. I just got a new version of the Firebeetle ESP32 controller from DFRobot. The size of the new version is smaller than the old one, and it uses a type-c port.

Then, I decided to make a network clock. This production will be very simple, getting the time from the internet via the wifi of the ESP32, and then you need to find a screen that displays the time. There are many options for the screen, LCD1602 or LED monochrome dot matrix for splicing. I accidentally saw a VFD fluorescent screen before, it was green-blue when it was lit, and it glowed with white light, which makes the whole screen a mottled beauty. So, I am going to use it here.

 

 

projectImage
projectImage

Material:

 

1. Firebeetle ESP32-E

 

2. VFD fluorescent screen

 

Weld the ESP32 and screen first.

projectImage
projectImage

Build the shell model.

projectImage

Use 3D printing to print out the shell. The cover on the back of the shell uses a 2mm acrylic sheet.

projectImage

Fix the VFD and ESP inside the shell with hot melt glue.

projectImage

Apply a little glue and close the lid.

projectImage

Burn Program

 

Download two library files here first.

 

Time Library: https://github.com/PaulStoffregen/Time

Timezone Library: https://github.com/JChristensen/Timezone

 

Then change the wifi and password in setup () in the code at the end of the article to your own, and click burn.

CODE
#include <Arduino.h>
#include <HardwareSerial.h>
#include<stdlib.h>
#include <TimeLib.h>
#include <WiFi.h>
#include <WiFiMulti.h>
#include <WiFiUdp.h>
#ifdef ARDUINO_AVR_UNO
        SoftwareSerial Serial1( 2, 5 ); //RX, TX
#endif
 
 
static const char ntpServerName[] = "ntp.aliyun.com"; 
const int timeZone = 8;                                     
 
WiFiUDP Udp;
unsigned int localPort = 8888;
 
time_t getNtpTime();
WiFiMulti WiFiMulti; 



uint8_t din   = 25; // DA
uint8_t clk   = 26; // CK
uint8_t cs    = 14; // CS
uint8_t Reset = 13; // RS
uint8_t en    = 21; // EN

void write_6302(unsigned char w_data)
{
  unsigned char i;
  for (i = 0; i < 8; i++)
  {
    digitalWrite(clk, LOW);
    delayMicroseconds(5);
    if ( (w_data & 0x01) == 0x01)
    {
      digitalWrite(din, HIGH);
      delay(1);
    }
    else
    {
      digitalWrite(din, LOW);
      delay(1);
    }
    w_data >>= 1;
    digitalWrite(clk, HIGH);
    delayMicroseconds(5);
  }
}

void VFD_cmd(unsigned char command)
{
  digitalWrite(cs, LOW);
  delayMicroseconds(5);
  write_6302(command);
  digitalWrite(cs, HIGH);
  delayMicroseconds(5);
}

void S1201_show(void)
{
  digitalWrite(cs, LOW);//开始传输
  delayMicroseconds(5);
  write_6302(0xe8);     //地址寄存器起始位置
  digitalWrite(cs, HIGH); //停止传输
  delayMicroseconds(5);
}

void VFD_init()
{
  //SET HOW MANY digtal numbers
  digitalWrite(cs, LOW);
  delayMicroseconds(5);
  write_6302(0xe0);
  delayMicroseconds(5);
  write_6302(0x07);//8 digtal
  digitalWrite(cs, HIGH);
  delayMicroseconds(5);

  //set bright
  digitalWrite(cs, LOW);
  delayMicroseconds(5);
  write_6302(0xe4);
  delayMicroseconds(5);
  write_6302(0xff);//leve 255 max
  digitalWrite(cs, HIGH);
  delayMicroseconds(5);
}

/******************************
  在指定位置打印一个字符(用户自定义,所有CG-ROM中的)
  x:0~11;chr:要显示的字符编码
*******************************/
void S1201_WriteOneChar(unsigned char x, unsigned char chr)
{
  digitalWrite(cs, LOW);  //开始传输
  delayMicroseconds(5);
  write_6302(0x20 + x); //地址寄存器起始位置
  delayMicroseconds(5);
  write_6302(chr + 0x30);
  digitalWrite(cs, HIGH); //停止传输
  delayMicroseconds(5);
  S1201_show();
}
/******************************
  在指定位置打印字符串
  (仅适用于英文,标点,数字)
  x:0~11;str:要显示的字符串
*******************************/
void S1201_WriteStr(unsigned char x, char *str)
{
  digitalWrite(cs, LOW);  //开始传输
  delayMicroseconds(5);
  write_6302(0x20 + x); //地址寄存器起始位置
  delayMicroseconds(5);
  while (*str)
  {
    write_6302(*str); //ascii与对应字符表转换
    str++;
  }
  digitalWrite(cs, HIGH); //停止传输
  delayMicroseconds(5);
  S1201_show();
}




void setup() {
 
 
        Serial.begin( 115200 );
        delay(10);
        pinMode(en, OUTPUT);
        pinMode(clk, OUTPUT);
        pinMode(din, OUTPUT);
        pinMode(cs, OUTPUT);
        pinMode(Reset, OUTPUT);
        digitalWrite(en, HIGH);
        digitalWrite(Reset, LOW);
        delayMicroseconds(5);
        digitalWrite(Reset, HIGH);
        
        VFD_init();
        WiFiMulti.addAP("wifi", "password");
        
        while(WiFiMulti.run() != WL_CONNECTED) {
            Serial.print(".");
            delay(500);
        }
        S1201_WriteStr(0, "wifi...");
        delay(2000);
        Serial.print( "IP number assigned by DHCP is " );
        Serial.println( WiFi.localIP() );
        Serial.println( "Starting UDP" );
        Udp.begin( localPort );
        Serial.print( "Local port: " );
        //Serial.println( Udp.localPort() );
        Serial.println( "waiting for sync" );
        setSyncProvider( getNtpTime );
        setSyncInterval( 300 );
 
}
 
 
time_t prevDisplay = 0;
 
void loop() {
 
 
        if( timeStatus() != timeNotSet ) {
                if( now() != prevDisplay ) {
                        prevDisplay = now();
                        showtime();
                }
        }
 
}
 
void showtime() {
        int Hour = hour();
        int Min = minute();
        int Sec = second();
        int HourHigh,HourLow,MinHigh,MinLow,SecHigh,SecLow;

        Serial.print(Hour);
        Serial.print(":");
        Serial.print(Min);
        Serial.print(":");
        Serial.println(Sec);
        HourHigh=Hour/10;
        if(HourHigh){
        S1201_WriteOneChar(0, HourHigh);
        }
        else{
          S1201_WriteOneChar(0, ' '-0x30);
        }
        HourLow=Hour%10;
        S1201_WriteOneChar(1, HourLow);
        S1201_WriteOneChar(2, ':'-0x30);
        MinHigh=Min/10;
        S1201_WriteOneChar(3, MinHigh);
        MinLow=Min%10;
        S1201_WriteOneChar(4, MinLow);
        S1201_WriteOneChar(5, ':'-0x30);
        SecHigh=Sec/10;
        S1201_WriteOneChar(6, SecHigh);
        SecLow=Sec%10;
        S1201_WriteOneChar(7, SecLow);

}
 
const int NTP_PACKET_SIZE = 48; 
byte packetBuffer[NTP_PACKET_SIZE]; 
 
time_t getNtpTime()
{
        IPAddress ntpServerIP; // NTP server's ip address
 
        while( Udp.parsePacket() > 0 ) ; // discard any previously received packets
        Serial.println( "Transmit NTP Request" );
        // get a random server from the pool
        WiFi.hostByName( ntpServerName, ntpServerIP );
        Serial.print( ntpServerName );
        Serial.print( ": " );
        Serial.println( ntpServerIP );
        sendNTPpacket( ntpServerIP );
        uint32_t beginWait = millis();
        while( millis() - beginWait < 1500 ) {
                int size = Udp.parsePacket();
                if( size >= NTP_PACKET_SIZE ) {
                        Serial.println( "Receive NTP Response" );
                        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;
                }
        }
        Serial.println( "No NTP Response :-(" );
        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();
}
projectImage

Done. Personally, I love the display effect of this VFD very much. If you use a brown acrylic for the faceplate, it will have a display effect close to white. But I like the beauty of being able to see the internal structure, which looks complicated but organized.

projectImage
projectImage
icon 3D Printing Model.rar 108KB Download(1)
License
All Rights
Reserved
licensBg
0