实用经验帖 ESP8266 NODEMCU 获取互联网上面时间服务器的标准...-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 6165|回复: 5

实用经验帖 ESP8266 NODEMCU 获取互联网上面时间服务器的标准...

[复制链接]
发表于 2019-8-21 13:46 | 显示全部楼层 |阅读模式
实用经验帖 ESP8266 NODEMCU 获取互联网上面时间服务器的标准时间

能少用原件尽量少用,所以就不用时间模块,直接用NODEMCU获取标准时间。

硬件:NODEMCU 一块
软件:arduino IDE (配好8266开发板)
所需库:NTPclient   直接在库管理里面用这个关键字,第一个就是。


发代码,不一同发库文件的都是耍流氓

时间会打印到串口。安装好库,复制此代码,仅需要修改WIFI密码和WIFI名称即可
文中变量名,基本都是拼音。我英文考试一直保持15-26分的成绩。

[mw_shl_code=arduino,true]#include <TimeLib.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

const char Wifi_MingCheng[] = "HuiKeDianNaoFuWu";  //  your network Wifi_MingCheng (name)
const char Wifi_MiMa[] = "13488214252";       // your network Wifi_MiMaword

//const char Wifi_MingCheng[] = "DanDan";  //  your network Wifi_MingCheng (name)
//const char Wifi_MiMa[] = "13488214252";       // your network Wifi_MiMaword

// NTP服务器:
static const char NTP_Server_Name[] = "us.pool.ntp.org";
//static const char NTP_Server_Name[] = "time.nist.gov";
//static const char NTP_Server_Name[] = "time-a.timefreq.bldrdoc.gov";
//static const char NTP_Server_Name[] = "time-b.timefreq.bldrdoc.gov";
//static const char NTP_Server_Name[] = "time-c.timefreq.bldrdoc.gov";

const int ShiQu = +8;     //时区 北京时间

WiFiUDP Udp;
unsigned int localPort = 8888;  // 用于侦听UDP数据包的本地端口

time_t HuoQu_NTP_ShiJian();// 获取NTP时间
void XianShiShiJian();      //显示时间
void GeShiHuaShuZi(int ShuZi);//格式化数字
void FaSong_NTP_Bao(IPAddress &address);//发送NTP包

void setup() {
  Serial.begin(9600);
  delay(250);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Udp.begin(localPort);

  setSyncProvider(HuoQu_NTP_ShiJian);//设置同步提供程序
  setSyncInterval(300);              //设置同步间隔
}


time_t ShangYiGeXianShi = 0; // 显示数字时钟时

void loop() {

  if (timeStatus() != timeNotSet) {  //如果 时间状态 不等于 时间未设置 那么
    if (now() != ShangYiGeXianShi) { //如果 当前时间 不等于 上一个时间 那么    仅当时间改变时更新显示
      ShangYiGeXianShi = now();      //上一个时间 等于 当前时间
      XianShiShiJian();              //显示时间
    }
  }
}
















void XianShiShiJian() { // 数字时钟显示时间

  Serial.print(year());
  Serial.print("-");
  GeShiHuaShuZi(month());
  Serial.print("-");
  GeShiHuaShuZi(day());

  Serial.print(" ");

  GeShiHuaShuZi(hour());
  Serial.print(":");
  GeShiHuaShuZi(minute());
  Serial.print(":");
  GeShiHuaShuZi(second());

  Serial.println();
}

void GeShiHuaShuZi(int ShuZi) { // 格式化数字  如果输入数字小于10则在前面加0打印出来   注意:下面语句不能加{}否则时间出不来
  if (ShuZi < 10)
    Serial.print("0");
  Serial.print(ShuZi);

}







/*-------- NTP code ----------*/

const int NTP_Bao_DaXiao = 48;     //NTP包大小        NTP时间在消息的前48个字节中
byte ShuJuBaoHuanChongQu[NTP_Bao_DaXiao]; //数据包缓冲区      用于保存传入和传出数据包的缓冲区

time_t HuoQu_NTP_ShiJian() { //获取NTP时间

  IPAddress NTP_Server_IP; // NTP服务器的IP地址

  while (Udp.parsePacket() > 0) ; //丢弃以前接收的任何数据包

  Serial.println("传输NTP请求");
  // 从池中获取随机服务器
  WiFi.hostByName(NTP_Server_Name, NTP_Server_IP);
  Serial.print(NTP_Server_Name);
  Serial.print(": ");
  Serial.println(NTP_Server_IP);

  FaSong_NTP_Bao(NTP_Server_IP);

  uint32_t ShangCiShiJian = millis();          //开始等待
  while (millis() - ShangCiShiJian < 1500) {  //如果小于这个时间则

    int size = Udp.parsePacket();             //分析数据包
    if (size >= NTP_Bao_DaXiao) {             //如果 获取到的包 大于或等于 NTP包大小
      Serial.println("接收NTP响应");
      Udp.read(ShuJuBaoHuanChongQu, NTP_Bao_DaXiao);  // 将数据包读取到缓冲区

      unsigned long secsSince1900;   //从1900年到现在的秒
      // 将从位置40开始的四个字节转换为长整数
      secsSince1900 =  (unsigned long)ShuJuBaoHuanChongQu[40] << 24;
      secsSince1900 |= (unsigned long)ShuJuBaoHuanChongQu[41] << 16;
      secsSince1900 |= (unsigned long)ShuJuBaoHuanChongQu[42] << 8;
      secsSince1900 |= (unsigned long)ShuJuBaoHuanChongQu[43];
      return secsSince1900 - 2208988800UL + ShiQu * SECS_PER_HOUR;
    }
  }


  Serial.println("无NTP响应");
  return 0; // 如果无法获得时间,则返回0
}

// 向给定地址的时间服务器发送NTP请求
void FaSong_NTP_Bao(IPAddress &address) {

  // 将缓冲区中的所有字节设置为0
  memset(ShuJuBaoHuanChongQu, 0, NTP_Bao_DaXiao);//清零
  //初始化形成NTP请求所需的值
  //(有关数据包的详细信息,请参阅上面的URL)
  ShuJuBaoHuanChongQu[0] = 0b11100011;   // li,版本,模式
  ShuJuBaoHuanChongQu[1] = 0;     // 时钟的层次或类型
  ShuJuBaoHuanChongQu[2] = 6;     // 轮询间隔
  ShuJuBaoHuanChongQu[3] = 0xEC;  // 对等时钟精度
  //根延迟和根分散为8字节零
  ShuJuBaoHuanChongQu[12] = 49;
  ShuJuBaoHuanChongQu[13] = 0x4E;
  ShuJuBaoHuanChongQu[14] = 49;
  ShuJuBaoHuanChongQu[15] = 52;
  //所有ntp字段现在都有值
  //可以发送请求时间戳的数据包:
  Udp.beginPacket(address, 123); //NTP请求到端口123
  Udp.write(ShuJuBaoHuanChongQu, NTP_Bao_DaXiao);
  Udp.endPacket();
}
[/mw_shl_code]
 楼主| 发表于 2019-8-21 14:49 | 显示全部楼层
请大神指点,如何比较获取时间和设定时间的差?

或者说,我设定2019年9月1日 12点32分11秒  打开LED灯。   如何判断获取的时间已经到达我设定的时间。在网上找了N久都没找到怎么弄

Arduino 也没有个时间变量。这怎么搞?
发表于 2019-10-18 15:26 | 显示全部楼层
NTPClient库也可实现
发表于 2020-5-13 11:04 | 显示全部楼层
本帖最后由 从入门到放弃· 于 2020-5-13 11:16 编辑

有人实现过吗?看不懂时间显示和格式化数字函数是怎么实现的。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-12-1 05:45 , Processed in 0.074961 second(s), 15 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表