数码之家

 找回密码
 立即注册
搜索
查看: 999|回复: 15

[Arduino] 使用ESP01模块实现通过Wifi联网从NTP服务器获取时间

[复制链接]
发表于 2025-3-10 17:02:17 | 显示全部楼层 |阅读模式
本帖最后由 mmxx2015 于 2025-3-10 17:33 编辑

这个ESP01模块在ESP8266模块里是最低配的:1MB Flash,没有屏蔽罩,板载天线。开始还担心Flash空间不够,完全实现后发现只需要350KB左右空间。
程序是从网上搜的程序改的,我就是做了整合,然后按需修改少量功能,实现:网页配网(保存和加载);联网获取时间然后串口输出。

参考源:
(1)ESP8266热点配网-Arduino代码分享
使用其中的AP配网程序(搜索wifi,选择ssid即可,不需要输入)
https://blog.csdn.net/qq_31878883/article/details/124070546
(2)ESP8266 AP模式 网页配网 arduino ide
使用其中的配网参数保存、加载。
https://blog.csdn.net/qq_66771136/article/details/145156914
(3)STM32F103时间戳与常用时间格式互换算法
使用其中的UTC时间转常规日期、时间
https://www.cnblogs.com/pantttian/articles/12826298.html

程序在Arduino IDE 2.3.4编译通过,需要安装库:NTPClient。

程序存在问题:有时无法获取时间,估计重启可以解决;好像时间慢1秒左右,即使频繁调用timeClient.update()也没用,即使不联网调用也要用时1秒左右;程序使用固定的NTP服务器和设置,如果能在配网设置界面加个NTP服务器设置就好了。

源程序(开头长长的类似乱码的东西是配网网页源代码,因为网页关键字和论坛代码模板冲突,只能以附件方式上传):


使用效果:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

打赏

参与人数 2家元 +60 收起 理由
jf201006 + 30 謝謝分享
不长叶子的树 + 30

查看全部打赏

发表于 2025-3-10 17:53:53 | 显示全部楼层
用esphome更简单
回复 支持 反对

使用道具 举报

发表于 2025-3-10 22:06:34 来自手机浏览器 | 显示全部楼层
可以做时钟用了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-3-11 01:19:10 | 显示全部楼层

  不熟悉esphome,搜到esphome获取时间的例子很少。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-3-11 01:27:40 | 显示全部楼层

只是用来对时而已,走时还是要用更省电的方式。
回复 支持 反对

使用道具 举报

发表于 2025-3-11 09:19:12 | 显示全部楼层
厉害啊~
这个芯片功能很强大。只是低功耗很难做到啊
回复 支持 反对

使用道具 举报

发表于 2025-3-11 10:26:49 | 显示全部楼层
huakeha 发表于 2025-3-11 09:19
厉害啊~
这个芯片功能很强大。只是低功耗很难做到啊

RST连接GPIO16,deepsleep,功耗uA级的。
回复 支持 反对

使用道具 举报

发表于 2025-3-11 11:39:31 | 显示全部楼层
kindzhon 发表于 2025-3-11 10:26
RST连接GPIO16,deepsleep,功耗uA级的。

1分钟唤醒一次,也不是不可以
回复 支持 反对

使用道具 举报

发表于 2025-4-5 09:19:12 | 显示全部楼层
编译下载后,运行能够搜到热点,连接后一直不出登录界面,这是什么问题
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-4-5 10:25:38 来自手机浏览器 | 显示全部楼层
zheng_wei339 发表于 2025-4-5 09:19
编译下载后,运行能够搜到热点,连接后一直不出登录界面,这是什么问题

试试用浏览器打开192.168.4.1。
回复 支持 反对

使用道具 举报

发表于 2025-4-5 23:25:59 | 显示全部楼层
192.168.4.1网页拒绝访问
回复 支持 反对

使用道具 举报

发表于 2025-4-6 07:59:52 | 显示全部楼层
串口打印信息,文件系统初始化失败
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-4-6 09:15:23 | 显示全部楼层
本帖最后由 mmxx2015 于 2025-4-6 09:24 编辑
zheng_wei339 发表于 2025-4-5 23:25
192.168.4.1网页拒绝访问

试试关闭其它网络连接,如果是手机连接热点,关闭手机数据网络,如果是电脑连接,禁用有线网络连接。
我这边测试,如果打开手机数据网络,浏览器打开192.168.4.1也打不开配网界面,但从跳出配置界面可以打开。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-4-6 09:41:07 | 显示全部楼层
本帖最后由 mmxx2015 于 2025-4-6 09:46 编辑
zheng_wei339 发表于 2025-4-6 07:59
串口打印信息,文件系统初始化失败

你的模块是哪种?

ai提供的解决方法:
SPIFFS.begin()失败的主要原因及解决方法

1.格式化失败:如果SPIFFS.begin()失败,可能是因为SPIFFS分区未正确格式化。可以在初始化代码中添加格式化逻辑,如:

if (!SPIFFS.begin())
{
    Serial.println("SPIFFS: An error occurred while mounting SPIFFS");
    if (SPIFFS.format())
    {
        Serial.println("SPIFFS partition formatted successfully");
        ESP.restart();
    }
    else
    {
        Serial.println("SPIFFS partition format failed");
    }
}

这段代码会在挂载失败时尝试格式化SPIFFS分区,如果格式化成功则重启设备。


2.参数设置问题:在调用SPIFFS.begin()时,可以设置一些参数来控制行为,例如在挂载失败时是否自动格式化。例如:

SPIFFS.begin(true, "/spiffs", 10);    // 打开失败时自动格式化,根目录为"/spiffs",最大打开文件数为10

样可以避免因挂载失败而导致的程序异常。

3.错误代码-10025:错误代码-10025通常表示SPIFFS挂载失败。这可能是由于分区表不正确或SPIFFS分区未正确设置。确保在分区表中为SPIFFS分配了正确的分区,并且该分区的类型设置为spi_flash_partition_config。

建议尝试第1种:
修改这段程序:
  1.         // 初始化SPIFFS文件系统
  2.         if (!SPIFFS.begin())
  3.         {
  4.                 Serial.println("文件系统初始化失败!");
  5.                 return;
  6.         }
复制代码
修改为:
  1.         // 初始化SPIFFS文件系统
  2.         if (!SPIFFS.begin())
  3.         {
  4.                 //Serial.println("文件系统初始化失败!");
  5.                 //return;
  6.                
  7.                 Serial.println("SPIFFS: An error occurred while mounting SPIFFS");
  8.                 if (SPIFFS.format())
  9.                 {
  10.                         Serial.println("SPIFFS partition formatted successfully");
  11.                         ESP.restart();
  12.                 }
  13.                 else
  14.                 {
  15.                         Serial.println("SPIFFS partition format failed");
  16.                 }
  17.         }
复制代码

如果问题仍未解决,可以先屏蔽初始化SPIFS程序,直接填写wifi ssid和密码:
  1.         // 初始化SPIFFS文件系统
  2.         //if (!SPIFFS.begin())
  3.         //{
  4.         //        Serial.println("文件系统初始化失败!");
  5.         //        return;
  6.         //}

  7.         // 检查Wi-Fi凭据
  8.         //if (isWiFiConfigured())
  9.         {
  10.                 //Serial.println("找到Wi-Fi凭据,尝试连接Wi-Fi...");

  11.                 //String ssid = loadWiFiSSID();
  12.                 //String pass = loadWiFiPassword();

  13.                 WiFi.begin("你的wifi ssid", "你的wifi密码");
复制代码


回复 支持 反对

使用道具 举报

发表于 2025-4-6 15:27:30 | 显示全部楼层
已经成功,编译时需要设置一下
回复 支持 反对

使用道具 举报

 楼主| 发表于 3 天前 | 显示全部楼层
(似乎可以)提高时间精度的版本:

(1)不使用NTPClient库。NTPClient库有2个问题影响精度:没有使用NTP服务器返回时间秒的小数部分(返回时间=4字节秒+4字节秒小数);第一次发送对时包不成功后再尝试时服务器返回的可能是响应第一次请求的数据。虽然NTPClient库的作者写了据称有毫秒精度的ESPNtpClient库,但我一直未能正常使用,Wifi连接后ESP8266就复位了。
(2)直接发送对时请求包(参考这篇文章:https://blog.csdn.net/qq_31878883/article/details/121373888),使用服务器完整的时间数据,并考虑返回数据与发送请求的时间差。因为这个程序主要是为了时钟对时而做的了,所有,仅从NTP服务器获取一次时间,之后根据系统时间累计时间(NTPClient是获取一次时间后经过一个设置时间间隔后才再次获取)。

程序使用文本或十六进制方式发送时间数据,通过条件编译选择。文本方式方便串口调试查看,十六进制方式方便授时客户端处理。
  1. #define        TIME_SEND_MODE_HEX                1                        //发送时间格式=Hex
  2. #define        TIME_SEND_MODE_TEXT                2                        //发送时间格式=文本
  3. #define        TIME_SEND_MODE                TIME_SEND_MODE_TEXT
复制代码
十六进制方式发送时间数据格式
  1. //发送时间数据结构体(1字节对齐)
  2. typedef struct __attribute__((packed))
  3. {
  4.         unsigned char Header_1;                //帧头1
  5.         unsigned char Header_2;                //帧头2
  6.         unsigned char Length;                //帧字节数
  7.         unsigned char Status;                //状态代码
  8.         unsigned char Year_High;        //年份高字节(双字节拆分为2个字节旨在防止地址对齐问题导致实际分配字节数多于预期)
  9.         unsigned char Year_Low;                //年份低字节
  10.         unsigned char Month;
  11.         unsigned char Date;
  12.         unsigned char WeekDay;
  13.         unsigned char Hour;
  14.         unsigned char Minute;
  15.         unsigned char Second;
  16.         unsigned char Milli_Second_High;//秒小数转成毫秒高字节
  17.         unsigned char Milli_Second_Low;
  18.         unsigned char CRC_16_High;        //CRC校验码高字节
  19.         unsigned char CRC_16_Low;        //CRC校验码低字节
  20. } Time_Send_Typedef;
复制代码
程序使用腾讯NTP服务器,因为它的ping延时比较低,可以按需修改
  1. const char *ntpServerName = "ntp.tencent.com";
复制代码
程序输出的是东8区的时间,如果要输出其它时区的时间,修改
  1. NTP_Epoch_Second = (T_32Bit_Temp1 - 2208988800UL + 28800UL);
复制代码
中的28800UL为其它值,东部时区加,西部时区减,值=(时区*60*60)。


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2025-5-1 18:44 , Processed in 0.109200 second(s), 10 queries , Redis On.

Powered by Discuz!

© 2006-2025 MyDigit.Net

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