网站首页
minecraft
资源共享
个人随笔
科技圈
杂七杂八
豆丁wiki
您的位置:首页 > 笔记 > ESP8266+1602时钟(简单版)
ESP8266+1602时钟(简单版)
2018-8-5    4523    0

之前做的那些1602时钟虽然使用了DS3231来走时,误差不算太大, 但始终会有点误差。加上上次因为DS3231模块设计问题,导致给纽扣电池的电压达到了5V,最终把电池给弄炸了,威力还不小,让我有点害怕,所以决定做一个基于WiFi自动校时的程序。

上网找了一会,没有现成的方案和代码,但是找到了一个WiFi对时的程序,参见:https://github.com/YFROBOT-TM/YFRobot-NTPClock_OneNet,我的1602时钟也是基于这个WiFi授时改动来的。

硬件连接:

这个版本用的1602是那种带按键的模块式的,直接插上板子即可。

代码:

#include <ESP8266WiFi.h>
#include <Time.h>
#include <Timezone.h>
#include "NTP.h"
#include <LiquidCrystal.h>

// Set your WiFi login credentials
#define WIFI_SSID "XXX"       // 使用时请修改为当前你的 wifi ssid
#define WIFI_PASS "XXX"   // 使用时请修改为当前你的 wifi 密码

#define ledPin 14                          // 定义ledPin连接到GPIO14
LiquidCrystal lcd(0, 2, 4, 14, 12, 13);
//年
byte Nian[8] = {0b01000,0b01111,0b10010, 0b01111, 0b01010, 0b11111, 0b00010, 0b00010};
//月
byte Yue[8] = {0b01111, 0b01001, 0b01111, 0b01001, 0b01111, 0b01001, 0b10011, 0b00001};
//日
byte Ri[8] = {0b01111, 0b01001, 0b01001, 0b01111, 0b01001, 0b01001, 0b01111, 0b00000};
// This clock is in the Mountain Time Zone
// Change this for your timezone
// 北京时间时区
#define STD_TIMEZONE_OFFSET +8    // Standard Time offset (-7 is mountain time)

// ***************************************************************
// TimeZone and Daylight Savings Time Rules
// ***************************************************************

// Define daylight savings time rules for the China
TimeChangeRule mySTD = {"", First,  Sun, Jan, 0, STD_TIMEZONE_OFFSET * 60};
Timezone myTZ(mySTD, mySTD);

WiFiClient client;

// This function is called once a second
void updateDisplay(void) {

  TimeChangeRule *tcr;        // Pointer to the time change rule

  // Read the current UTC time from the NTP provider
  time_t utc = now();

  // Convert to local time taking DST into consideration
  time_t localTime = myTZ.toLocal(utc, &tcr);

  // Map time to pixel positions
  int weekdays=   weekday(localTime);
  int days    =   day(localTime);
  int months  =   month(localTime);
  int years   =   year(localTime);
  int seconds =   second(localTime);
  int minutes =   minute(localTime);
  int hours   =   hour(localTime) ;   //12 hour format use : hourFormat12(localTime)  isPM()/isAM()
  Serial.println("");
  Serial.print("Current local time:");
  Serial.print(days);
  Serial.print("/");
  Serial.print(months);
  Serial.print("/");
  Serial.print(years);
  Serial.print(" - ");
  Serial.print(hours);
  Serial.print(":");
  Serial.print(minutes);
  Serial.print(":");
  Serial.print(seconds);
  Serial.print(" - ");
  Serial.print(dayStr(weekdays));
  Serial.println("");
  
 lcd.clear();
 lcd.setCursor(0,0);
 lcd.print("Time:");
 if(hours<10)
        {
          lcd.print("0");
        }
 lcd.print(hours);
 lcd.print(":");
 if(minutes<10)
        {
          lcd.print("0");
        }
 lcd.print(minutes);
 lcd.print(":");
 if(seconds<10)
        {
          lcd.print("0");
        }
 lcd.print(seconds);
 lcd.print(" W");
 printWeek(weekdays);
  
 
 lcd.setCursor(0,1);
 lcd.print("Date:");
 lcd.print(years);
 lcd.write(byte(0));
 if(months<10)
        {
          lcd.print("0");
        }
 lcd.print(months);
 lcd.write(byte(1));
 if(days<10)
        {
          lcd.print("0");
        }
 lcd.print(days);
 lcd.write(byte(2));
}

void setup() {

  Serial.begin(115200);
  pinMode(ledPin, OUTPUT);
  delay(10);
  lcd.begin(16, 2);
    lcd.createChar(0, Nian);
    lcd.createChar(1, Yue);
    lcd.createChar(2, Ri);
  // We start by connecting to a WiFi network
  initNTP(WIFI_SSID, WIFI_PASS);
}

// Previous seconds value
time_t previousSecond = 0;

void loop() {
  //  Update the display only if time has changed
  if (timeStatus() != timeNotSet) {
    if (second() != previousSecond) {
      previousSecond = second();
      // Update the display
      updateDisplay();
    }
  }
  
 
  delay(1000);
}

void printWeek(int week)
{
  switch(week)
  {
    case 1: lcd.print("7");break;
    case 2: lcd.print("1");break;
    case 3: lcd.print("2");break;
    case 4: lcd.print("3");break;
    case 5: lcd.print("4");break;
    case 6: lcd.print("5");break;
    case 7: lcd.print("6");break;
    default: lcd.print("E");break;
  } 
}
NTP.h 文件:


#ifndef NTP_H
#define NTP_H

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

#define LOCALPORT     5000 // Local port to listen for UDP packets
#define NTP_PACKET_SIZE 48 // NTP time stamp is in the first 48 bytes of the message

// A UDP instance to let us send and receive packets over UDP
WiFiUDP udp;

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

// Don't hardwire the IP address or we won't get the benefits of the time server pool.
const char *ntpServerName ;//= "time.windows.com";//"1.cn.pool.ntp.org";
IPAddress timeServerIP(182,92,12,11);  //ONENET -- NTP


// Send an NTP request to the time server at the given address
unsigned long sendNTPpacket(IPAddress& address) {

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

  // Initialize values needed to form NTP request
  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();
}

// NTP Time Provider Code
time_t getNTPTime() {

  int attempts = 10;

  // Try multiple attempts to return the NTP time
  while (attempts--) {

    // Get a server from the pool
    if(ntpServerName != NULL){
        WiFi.hostByName(ntpServerName, timeServerIP);
    }
    Serial.printf("Time server IP address: ");
    Serial.println(timeServerIP);

    while (udp.parsePacket() > 0); // Discard any previously received packets

    Serial.println("Transmitted NTP Request");
    sendNTPpacket(timeServerIP);

    uint32_t beginWait = millis();
    while (millis() - beginWait < 1500) {
      int size = udp.parsePacket();
      if (size >= NTP_PACKET_SIZE) {
        Serial.println("Received 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];

        Serial.println("Got the time");

        return secsSince1900 - 2208988800UL;
      }
      delay(10);
    }
    Serial.println("Retrying NTP request");
    delay(4000);
  }
  Serial.println("No NTP Response");
  return 0;
}

// Login to WiFi network and assign the time sync provider
void initNTP(const char *ssid, const char *password) {

  // Set station mode
  WiFi.mode(WIFI_STA);   //set work mode:  WIFI_AP /WIFI_STA /WIFI_AP_STA

  // Start by connecting to a WiFi network
  WiFi.begin(ssid, password);

  int i = 0;
  while ((WiFi.status() != WL_CONNECTED) && (i++ < 30)) {
    delay(500);
    Serial.printf(".");
  }
  if (i == 31) {
    Serial.printf("\nCould not connect to: %s\n", ssid);
    return;
  }
  Serial.printf("\nConnected to: %s\n", ssid);
  delay(500);

  // Login suceeded so set UDP local port
  udp.begin(LOCALPORT);

  // Set the time provider to NTP
  setSyncProvider(getNTPTime);
}

#endif

效果图:


微信截图_20180805212745.png
WiFi用到的库文件:

https://github.com/PaulStoffregen/Time

https://github.com/JChristensen/Timezone


上一篇: ESP8266+1602时钟(温湿度版)
下一篇: 自建KMS服务器
发表评论:
您的网名:
个人主页:
编辑内容: