怎么用esp8266制作wifi时钟(单片机通过WIFI模块)

前几天发布了开源4.3寸触摸屏的文章,里面有WIFI获取时间和天气预报相关的功能,今天就来介绍一下这个功能是怎样实现的。

1.底层驱动

首先,硬件上,单片机通过串口AT指令访问WIFI模块(ESP8266)。具体AT指令怎样写,可以参考之前的文章《单片机裸机环境下编写AT指令程序》。上电后,先配置WIFI模块的工作模式等,用到的AT指令如下:

1. 关闭回显

ATE0

2. 设置为STA模式

AT CWMODE_DEF=1

3. 设置WIFI名称和密码

AT CWJAP_DEF=”SSID”,”Password”

4. 开启DHCP

AT CWDHCP_DEF=1,1

5. 设置为单连接模式

AT CIPMUX=0

6. 设置为透传模式

AT CIPMODE=1

2.获取网络时间

获取网络时间的方式有两种,对于较新版本的固件,可以直接通过AT指令来获取。(可以通过AT GMR指令来查询固件的版本。)

AT CIPSNTPTIME?

对于较老版本的固件,不支持该AT指令,只能通过自己连接网络服务器来获取当前时间。具体需要的AT指令如下:

1.建立TCP链接

AT CIPSTART="TCP","www.beijing-time.org",80

2.打开传透模式

AT CIPSEND

3.收到‘>’符号后,随便发送个数据

4.等待接收数据

接收的数据可以先用网络调试助手来测试,如下,可以看到,数据中包含了当前的日期和时间信息,我们可以先找到字符串中“Data”的位置,再解析后面的数据。数据格式固定,直接按照字符位置解析就行。

需要注意的是,获取的这个时间是格林威治时间,与北京时间相差8个小时。

当然,也可以通过连接其它NTP时间服务器来获取时间,步骤是类似的。

怎么用esp8266制作wifi时钟(单片机通过WIFI模块)(1)

3.获取天气预报

天气的获取就要比时间稍复杂一些,网上有很多可以提供天气预报的服务器,有些可以免费使用,一般都需要注册一个账号,这里以“心知天气”为例进行介绍。步骤如下:

1.注册账号。在该网站注册一个账号:https://www.seniverse.com/。注册之后就可以通过其开放的API来获取天气预报。有免费版和付费版,区别在于访问频次和获取的天气信息内容不同。如下:

怎么用esp8266制作wifi时钟(单片机通过WIFI模块)(2)

2.查看私钥。在控制台查看账号的私钥,这个在程序中要用。

怎么用esp8266制作wifi时钟(单片机通过WIFI模块)(3)

3.API。有了这个私钥,我们就可以通过API来获取天气预报了,相关的API说明可以在这里查询:

https://seniverse.yuque.com/books/share/f4f9bf1a-d3d9-4a68-8996-950f8c88400e/sl6gvt#d29hl

先用网络调试助手测试一下:

怎么用esp8266制作wifi时钟(单片机通过WIFI模块)(4)

可以看到,通过TCP连接服务器后,发送GET请求就可以收到天气预报数据,接下来就是解析数据了。

嵌入式物联网需要学的东西真的非常多,千万不要学错了路线和内容,导致工资要不上去!

无偿分享大家一个资料包,差不多150多G。里面学习内容、面经、项目都比较新也比较全!某鱼上买估计至少要好几十。

点击这里找小助理0元领取:点击文中蓝色字体领取吖

怎么用esp8266制作wifi时钟(单片机通过WIFI模块)(5)

怎么用esp8266制作wifi时钟(单片机通过WIFI模块)(6)

4.解析数据。接收的数据是JSON格式的字符串,在单片机中我们可以移植cJSON来进行解析。cJSON是一个开源的C语音解析库,只有cjson.c、cJSON.h两个文件,直接添加到工程中就可以使用相关函数。程序如下:

void Weather_JSON( ) { char *data; cJSON *root; cJSON *results; cJSON *last_update; cJSON *loc_json, *daily_json; cJSON *forecast_json; char *loc_tmp, *weather_tmp; int i = 0; data = (char*)(Uart1.RxBuf);//接受到的数据 root = cJSON_Parse(data); if(root) { //printf("JSON格式正确:\n%s\n\n",cJSON_Print(root)); //输出json字符串 results = cJSON_GetObjectItem(root, "results"); results = cJSON_GetArrayItem(results,0); if(results) { loc_json = cJSON_GetObjectItem(results, "location"); //得到location键对应的值,是一个对象 loc_tmp = cJSON_GetObjectItem(loc_json, "id") -> valuestring; //printf("城市ID:%s\n",loc_tmp); loc_tmp = cJSON_GetObjectItem(loc_json, "name") -> valuestring; memset(loc_str,0,20); memcpy(loc_str,loc_tmp,strlen(loc_tmp)); loc_tmp = cJSON_GetObjectItem(loc_json, "timezone") -> valuestring; //printf("城市时区:%s\n\n",loc_tmp); daily_json = cJSON_GetObjectItem(results, "daily"); if(daily_json) { Weather_Dat[0].Flag = 1; for(i = 0; i < 3; i ) { forecast_json = cJSON_GetArrayItem(daily_json, i); //weather_tmp = cJSON_GetObjectItem(forecast_json, "date") -> valuestring;//日期 weather_tmp = cJSON_GetObjectItem(forecast_json, "code_day") -> valuestring;//白天天气代码 Weather_Dat[i].Weathcode = atoi(weather_tmp); //weather_tmp = cJSON_GetObjectItem(forecast_json, "code_night") -> valuestring;//晚上天气代码 weather_tmp = cJSON_GetObjectItem(forecast_json, "high") -> valuestring;//最高温度 memset(Weather_Dat[i].HighT,0,4); memcpy(Weather_Dat[i].HighT,weather_tmp,strlen(weather_tmp)); weather_tmp = cJSON_GetObjectItem(forecast_json, "low") -> valuestring;//最低温度 memset(Weather_Dat[i].LowT,0,4); memcpy(Weather_Dat[i].LowT,weather_tmp,strlen(weather_tmp)); weather_tmp = cJSON_GetObjectItem(forecast_json, "wind_direction") -> valuestring;//风向 memset(Weather_Dat[i].Wind_Dir,0,10); memcpy(Weather_Dat[i].Wind_Dir,weather_tmp,strlen(weather_tmp)); weather_tmp = cJSON_GetObjectItem(forecast_json, "wind_scale") -> valuestring;//风力 memset(Weather_Dat[i].WindScale,0,4); memcpy(Weather_Dat[i].WindScale,weather_tmp,strlen(weather_tmp)); weather_tmp = cJSON_GetObjectItem(forecast_json, "humidity") -> valuestring;//湿度 memset(Weather_Dat[i].Humi,0,4); memcpy(Weather_Dat[i].Humi,weather_tmp,strlen(weather_tmp)); } } else { //printf("daily json格式错误\r\n"); Weather_Dat[0].Flag = 0; } } else { Weather_Dat[0].Flag = 0; //printf("results格式错误:%s\r\n", cJSON_GetErrorPtr()); } } else { Weather_Dat[0].Flag = 0; //printf("JSON格式错误\r\n"); } cJSON_Delete(root); }

解析后,将有用数据转换为自己想要的格式存储在变量中。需要注意的是,cJSON可能占用较大的堆栈,因此堆栈需要设大一些。

总结一下,获取天气预报的步骤如下:

1.注册账号。

2.获取私钥。

3.连接服务器。

AT CIPSTART="TCP”,” api.seniverse.com”,80

4..打开传透模式。

AT CIPSEND

5..收到‘>’符号后,发送GET请求

GET https://api.seniverse.com/v3/weather/daily.json?key=your_key&location=ip&language=zh-Hans&unit=c&start=0&days=3

6.等待接收数据,并解析。

以上就是单片机通过AT指令访问WIFI模块获取网络时间和天气预报的方法,需要注意的是上述所有指令后面别忘了加回车换行符。

文章链接:https://mp.weixin.qq.com/s/Xy1FJBqAF_ByP4GyznkLxw

转载自:Mr张工 嵌入式技术开发

文章来源:单片机通过WIFI模块(ESP8266)获取网络时间与天气预报

版权申明:本文来源于网络,免费传达知识,版权归原作者所有。如涉及作品版权问题,请联系我进行删除。

,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页