切换到宽版
  • 34843阅读
  • 72回复

ESP8266直驱OLED,做个不用调时间的WiFi钟 [复制链接]

上一主题 下一主题
离线disassembly

发帖
76
M币
359
专家
0
粉丝
7
只看该作者 70楼 发表于: 01-22
回 hubertdong 的帖子
hubertdong:我的也是快一天,
你的问题解决了吗? (2018-01-20 21:29) 回 hubertdong 的帖子

没有去重新改代码,只注释掉一行(while(f){}后面的):
//    Day += 1;  2018年时间不对,日期快一天

暂时能正确显示,不知道2019年是否会正确。
源代码中的计算方法实在有点难懂。
离线elecfunwb

发帖
39
M币
1609
专家
1
粉丝
3
只看该作者 71楼 发表于: 02-20
回 disassembly 的帖子
disassembly:
没有去重新改代码,只注释掉一行(while(f){}后面的):
//    Day += 1;  2018年时间不对,日期快一天
暂时能正确显示,不知道2019年是否会正确。
....... 回 disassembly 的帖子


楼主的算法确实是有问题的,我换了个其它算法,有兴趣可以试下


#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <Adafruit_ssd1306syp.h>

//OLED
// #define SDA_PIN 2//oled_SDA
// #define SCL_PIN 0//oled_SCL
#define SDA_PIN 3//oled_SDA
#define SCL_PIN 1//oled_SCL
Adafruit_ssd1306syp display(SDA_PIN, SCL_PIN);
const byte weekData1[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE,
                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
                         }; /*"一",0*/

const byte weekData2[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
                         };/*"二",0*/
const byte weekData3[] = { 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF8,
                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00
                         }; /*"三",2*/
const byte weekData4[] = { 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFC, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
                           0x48, 0x44, 0x48, 0x3C, 0x50, 0x04, 0x60, 0x04, 0x40, 0x04, 0x7F, 0xFC, 0x40, 0x04, 0x00, 0x00
                         }; /*"四",3*/

const byte weekData5[] = { 0x00, 0x00, 0x7F, 0xFC, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x3F, 0xF0, 0x04, 0x10,
                           0x04, 0x10, 0x04, 0x10, 0x04, 0x10, 0x08, 0x10, 0x08, 0x10, 0x08, 0x10, 0xFF, 0xFE, 0x00, 0x00
                         }; /*"五",4*/
const byte weekData6[] = { 0x02, 0x00, 0x01, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00,
                           0x04, 0x40, 0x04, 0x20, 0x08, 0x10, 0x08, 0x08, 0x10, 0x08, 0x20, 0x04, 0x40, 0x04, 0x00, 0x00
                         }; /*"六",5*/
const byte weekData7[] = { 0x00, 0x00, 0x1F, 0xF0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1F, 0xF0,
                           0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1F, 0xF0, 0x10, 0x10
                         };/*"日",6*/
//WIFI
char ssid[] = "****";  // WiFi名 SSID (name)
char pass[] = "****";       // WiFi密码

//NTP
#define time_zone 8   //时区(要格林尼治时间加减的小时,北京为东八区,要将格林威治时间+8小时)
unsigned int localPort = 2390;      // local port to listen for UDP packets
/* Don't hardwire the IP address or we won't get the benefits of the pool.
    Lookup the IP address for the host name instead */

//IPAddress timeServer(129, 6, 15, 28); // time.nist.gov NTP server
IPAddress timeServerIP; // time.nist.gov NTP server address
const char* ntpServerName = "cn.ntp.org.cn";
const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message
byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets
// A UDP instance to let us send and receive packets over UDP
WiFiUDP udp;

unsigned long sendNTPpacket(IPAddress& address);
unsigned char LY(unsigned int y);

static const int MON1[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};   //平年  
static const int MON2[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};   //闰年  
static const int FOURYEARS = (366 + 365 +365 +365); //每个四年的总天数  
static const int DAYMS = 24*3600;   //每天的秒数  


//ref: http://blog.csdn.net/mill_li/article/details/54599927
void GetMonthAndDay(unsigned int nDays, unsigned int& nMonth, unsigned int& nDay, bool IsLeapYear)  
{  
    int nTemp;
  //循环减去12个月中每个月的天数,直到剩余天数小于等于0,就找到了对应的月份  
  for ( int i=0; i<12; ++i )  
  {  
    if (IsLeapYear)
      nTemp = nDays - MON2[ i ];
    else
      nTemp = nDays - MON1[ i ];
  
    if ( nTemp<=0 )  
    {  
      nMonth = i+1;  
      if ( nTemp == 0 )//表示刚好是这个月的最后一天,那么天数就是这个月的总天数了  
        if (IsLeapYear)
          nDay = MON2[ i ];
        else
          nDay = MON1[ i ];
      else  
          nDay = nDays;  
      break;  
    }  
    nDays = nTemp;  
  }  
}

/* ref: http://blog.csdn.net/mfcing/article/details/48438421
* 功能:
*     根据给定的日期得到对应的星期
* 参数:
*     year:给定的年份
*     month:给定的月份
*     day:给定的天数
*
* 返回值:
*     对应的星期数,0 - 星期天 ... 6 - 星期六
*/

unsigned char applib_dt_dayindex(unsigned int year, unsigned char month, unsigned char day)
{
    char century_code, year_code, month_code, day_code;
    int week = 0;

    century_code = year_code = month_code = day_code = 0;

    if (month == 1 || month == 2) {
        century_code = (year - 1) / 100;
        year_code = (year - 1) % 100;
        month_code = month + 12;
        day_code = day;
    } else {
        century_code = year / 100;
        year_code = year % 100;
        month_code = month;
        day_code = day;
    }

    /* 根据蔡勒公式计算星期 */
    week = year_code + year_code / 4 + century_code / 4 - 2 * century_code + 26 * ( month_code + 1 ) / 10 + day_code - 1;
    week = week > 0 ? (week % 7) : ((week % 7) + 7);

    return week;
}


void setup()
{
  //初始化
  Serial.begin(115200);//串口波特率115200
  Serial.println();
  Serial.println();
  delay(1000);
  display.initialize();//oled初始化

  display.setTextColor(WHITE);//设置oled文字颜色
  display.setTextSize(2);//设置oled文字大小
  display.setCursor(0, 24); //设置oled指针位置
  display.print("WiFi-Clock");//oled显示文字
  display.setTextSize(1);
  display.setCursor(62, 56);
  display.print("Power By LC");
  display.update();
  // We start by connecting to a WiFi network
  delay(1500);
  display.clear();
  display.setCursor(0, 0);
  Serial.print("Connecting to ");
  display.print("Connecting to ");
  Serial.println(ssid);
  display.println(ssid);
  WiFi.begin(ssid, pass);
  display.update();
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
    display.print(".");
    display.update();
  }
  Serial.println("");
  display.println("");
  Serial.println("WiFi connected");
  display.println("WiFi connected");
  Serial.println("IP address: ");
  display.println("IP address: ");
  Serial.println(WiFi.localIP());
  display.println(WiFi.localIP());
  display.update();
  Serial.println("Starting UDP");
  udp.begin(localPort);
  Serial.print("Local port: ");
  Serial.println(udp.localPort());


}
void loop()
{
  if (WiFi.status() != WL_CONNECTED)
  {
    display.clear();
    display.setCursor(0, 0);
    display.setTextSize(4);
    display.print("--:--");
    display.setCursor(0, 48);
    display.setTextSize(2);
    display.print("----/--/--");
    display.update();
  }
  else
  {
    //get a random server from the pool
    WiFi.hostByName(ntpServerName, timeServerIP);

    sendNTPpacket(timeServerIP); // send an NTP packet to a time server
    // wait to see if a reply is available
    delay(5000);

    int cb = udp.parsePacket();
    if (!cb) {
      Serial.println("no packet yet");
      return;
    }
    else {


      //NTP
      Serial.print("packet received, length=");
      Serial.println(cb);
      // We've received a packet, read the data from it
      udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer
      //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);

      unsigned long Time = time_zone * 3600 + epoch;  //北京在东八区
      unsigned int nDays = Time/DAYMS + 1;        //得到天数
      unsigned int nYear4 = nDays/FOURYEARS;      //得到从1970年以来的周期(4年)的次数  
      unsigned int nRemain = nDays%FOURYEARS;     //得到不足一个周期的天数
      unsigned int nDesYear = 1970 + nYear4 * 4;
      unsigned int nDesMonth = 0;
      unsigned int nDesDay = 0;
      bool bLeapYear = false;
      if ( nRemain<365 )//一个周期内,第一年  
      {//平年  
            
      }  
      else if ( nRemain<(365+365) )//一个周期内,第二年  
      {//平年  
          nDesYear += 1;  
          nRemain -= 365;  
      }  
      else if ( nRemain<(365+365+365) )//一个周期内,第三年  
      {//平年  
          nDesYear += 2;  
          nRemain -= (365+365);  
      }  
      else//一个周期内,第四年,这一年是闰年  
      {//润年  
          nDesYear += 3;  
          nRemain -= (365+365+365);  
          bLeapYear = true;  
      }  

      GetMonthAndDay(nRemain, nDesMonth, nDesDay, bLeapYear);


      display.clear();
      display.setCursor(0, 48);
      display.setTextSize(2);
      Serial.print(nDesYear);
      display.print(nDesYear);
      Serial.print("/");
      display.print("/");
      Serial.print(nDesMonth);
      display.print(nDesMonth);
      Serial.print("/");
      display.print("/");
      Serial.println(nDesDay);
      display.print(nDesDay);

      //星期
      switch (applib_dt_dayindex(nDesYear, nDesMonth, nDesDay)) //计算星期
      {
        case 0: display.drawBitmap(112, 48, weekData7, 16, 16, WHITE); break;
        case 1: display.drawBitmap(112, 48, weekData1, 16, 16, WHITE); break;
        case 2: display.drawBitmap(112, 48, weekData2, 16, 16, WHITE); break;
        case 3: display.drawBitmap(112, 48, weekData3, 16, 16, WHITE); break;
        case 4: display.drawBitmap(112, 48, weekData4, 16, 16, WHITE); break;
        case 5: display.drawBitmap(112, 48, weekData5, 16, 16, WHITE); break;
        case 6: display.drawBitmap(112, 48, weekData6, 16, 16, WHITE); break;
      }


      //时间
      display.setCursor(0, 0);
      display.setTextSize(4);
      // print the hour, minute and second:
      if ((Time  % 86400L) / 3600 < 10)
      {
        display.print(' ');
      }
      Serial.print("The time is ");       // UTC is the time at Greenwich Meridian (GMT)
      Serial.print((Time  % 86400L) / 3600); // print the hour (86400 equals secs per day)
      display.print((Time  % 86400L) / 3600);
      Serial.print(':');
      display.print(':');
      if ( ((Time % 3600) / 60) < 10 ) {
        // In the first 10 minutes of each hour, we'll want a leading '0'
        Serial.print('0');
        display.print('0');
      }
      Serial.print((Time  % 3600) / 60); // print the minute (3600 equals secs per minute)
      display.print((Time  % 3600) / 60);
      Serial.print(':');
      if ( (Time % 60) < 10 ) {
        // In the first 10 seconds of each minute, we'll want a leading '0'
        Serial.print('0');
      }
      Serial.println(Time % 60); // print the second

    }
    display.update();
  }
}

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


离线elecfunwb

发帖
39
M币
1609
专家
1
粉丝
3
只看该作者 72楼 发表于: 02-20
71楼换了个算法,有兴趣试一下
快速回复
限80 字节
温馨提示:欢迎交流讨论,请勿发布纯表情、纯引用等灌水帖子;以免被删除
 
上一个 下一个