当前位置:网站首页 > 云服务教程 > 正文

esp8266oled制作天气时钟(esp8266天气时钟教程)



1. 导论

先来看看别人是怎么实现的:利用ESP8266+OLED(I2C)打造智能时钟(网络校时+实时天气+天气预报)

我们要分析这篇文章中的代码并加以改造。可以点击上面的链接去原帖膜拜一下。

同时,本文也会探讨一些方法和原理(通式通法),包括:

  • ArduinoJson的使用
  • 字体的使用
  • U8g2的使用

等一些其他内容,希望能够有所帮助。

(没想到能写这么多)

2. 连接WiFi

WiFi的连接与前面的示例是基本一致的,ssid和password分别是WiFi的名称和密码。

可以像示例中一样写,也可以像这篇文章的作者一样:

这一块是定义常量,应该写在前面,注意还要导入相关库:

3. 获取天气

获取实时天气的函数为:

其中的reqRes是要请求的地址,作者使用了心知天气,这里先简单介绍一下心知天气。

3.1 心知天气

心知天气的官网地址为:心知天气

点击上面的链接跳转官网后,点击右上角注册/登录。

根据说明注册并登录后,点击控制台,然后点击产品管理->添加产品,选择免费版。

免费版可以使用V3版3项数据,具体配置可以都可以在官网中找到。

V3版的使用手册为:心知天气使用手册(V3版)

3.2 实时天气

实时天气在手册的这一页:天气实况

接口地址为:

https://api.seniverse.com/v3/weather/now.json?key=your_api_key&location=beijing&language=zh-Hans&unit=c

esp8266休眠模式时钟 esp8266时钟教程_JSON

参数列表见上,其中API密钥在产品管理->免费版->API密钥->私钥处获取。

原作者设置语言为英语en,其他三个参数是预先定义好的:

这里填写私钥和城市的拼音。城市拼音参见:接口中的通用参数-Location

拼接好了一个字符串参数reqRes,传入函数httpRequest,这个函数的作用是发请求,在下面定义。

3.3 发送请求

可以看到,在这个函数里又定义了一个字符串变量httpRequest,这是模拟HTTP请求报文。具体原理涉及《计算机网络》,不在这里赘述了。

拼接字符串中的host是目标主机(也即接口地址的主机域名部分),在程序开始已经定义了:

接下来发送请求(大括号未闭合):

先试图连接主机,如果连接成功,client.connect(host, 80)应当为true,这个函数或者说表达式能够检验连接是否建立。

接下来,通过client.print(httpRequest)发送请求。

发送请求成功后,服务器会给我们响应,具体以响应报文的形式实现(这也是《计算机网络》中的内容)。

简单来说,响应报文由响应行、响应头和响应体组成。响应行是响应报文的第一行,而readStringUntil(' ')表示读取到第一个换行符(即' '),可见这个status_response就是响应行。响应行包括协议、状态码和描述,可以在串口监视器中看看它长什么样。

然后,使用find跳过HTTP响应头,这里不再细讲了。

之后判断stat是0还是1,这个参数为0时解析实时信息,为1时解析未来信息。

可以看到,在用于获取实时天气的函数 TandW中,为httpRequest传的stat参数就是0,作者还特意在这个函数那里标记了0。

3.4 信息解析

信息解析需要使用ArduinoJson这个库(返回的响应是json格式的),在库管理器中安装它,就像前一篇中一样。

原作者的代码如下:

解析的主要原理在于

  • 定义了一个对象,其容量根据JSON结构的需求计算而来。这是为了确保有足够的空间存储解析后的JSON数据。
  • 使用函数从读取JSON数据,并将其解析到中。
  • 从中提取天气信息,包括当前天气状况、天气代码、温度和最后更新时间。

特别需要指出的是,capacity就是创建doc时指定的容量,它是根据响应而定的。

接下来介绍一下设置方法:

借助ApiPost(或者其他的接口测试工具),对接口进行HTTP测试,得到响应为

esp8266休眠模式时钟 esp8266时钟教程_嵌入式硬件_02

观察响应的结构,可以发现:

  1. 顶层对象:仅包含一个键。
  2. 数组:包含一个对象。
  3. 中的对象:包含三个键(, , )。
  4. 对象:包含六个键(, , , , , )。
  5. 对象:包含三个键(, , )。

由此可知容量是上面五个的和:

和原作者的比对一下,会发现还差了230,这是哪里来的呢?

其实,因为这个json里面有大量的字符串,所以需要额外的空间来保证字符串值都被存储。

字符串值的内存开销通常比简单的数字或布尔值要大,因为它们需要存储每个字符。此外,还需要为每个字符串分配结束字符'0'(这是《C++程序设计》中的,可以去阅读相关书籍,这里不再赘述)。

但是这个值到底该怎么取呢?

实际上,这个值通常是一个估计值,因为除了上述开销,还应当留有一定的裕量。

但是,可以借助ArduinoJson库的Assistant来方便地确定这个值,链接:https://arduinojson.org/v6/assistant/

esp8266休眠模式时钟 esp8266时钟教程_esp8266休眠模式时钟_03

在步骤2中输入Json即可,这里就不放图了,接下来是步骤3:

esp8266休眠模式时钟 esp8266时钟教程_esp8266休眠模式时钟_04

可以看到,在Strings这一项,显示的数字是204,也就是说,对于我们这个capacity,需要加上的字符串存储空间为204,并且至少为204(建议发请求时设定language为en,就像原作者一样,因为中文占3字节,为了节省空间,还是英文更好一点)。

再考虑到裕量,所以设定为230,这是比较合理的选择。

以上就是通式通法。

特别说明:上述求和的方法目前已被弃用,推荐设为定值,即采用ArduinoJson库的Assistant的建议,也许还有其他的设置,但我还没有研究,仍采用的这种旧方法。如果有大佬有方案,可以在评论区指点一手或者贴个链接让我去膜一下。O(∩_∩)O

此外再补充两点:

  1. 如果出现错误DeserializationError::NoMemory,这意味着容量选小了,应当扩大容量。
  2. DynamicJsonDocument,内存分配在heap区,无固定大小,可以自动增长所需空间,方法调用完自动回收,建议内存大小大于1KB使用。

上面的第2条我是在简书上看到的,原文链接为玩转 ESP32 + Arduino (十五) ArduinoJSON库(V6版本),欢迎前去膜拜。

此外,这个assistant还有一个非常强大的功能,它可以根据json生成解析代码:

esp8266休眠模式时钟 esp8266时钟教程_JSON_05

原作者在这里进行了类型转换:

本来提取到的数据都是C风格的字符串,在这里将其转换成了String和int类型。

在最开始,定义了两个全局变量,用于保存断网前的最新数据:

可以看到,在类型转换后,就将获得的数据展示并储存了下来:

其中display_0函数就是用于将数据显示到屏幕上,而下面两行的作用就是将数据储存在全局变量里,这样就可以在其他函数中使用了。

值得注意的是,在这个解析函数parseInfo_now中,除了client这个需要解析的对象外,还存在一个参数i,不难看出,如果i==1,就解析数据、更新数据、显示数据,而其他情况下就直接显示原有数据,即results_0_now_temperature_int_old和results_0_now_text_str_old。

3.5 未来天气

与实时天气大同小异,这里不再赘述了。

4. 数据展示

上面用到的display_0函数如下:

这一部分使用了u8g2这个库,它是一个非常强大的LCD、OLED、elink的扩展库,需要在库管理器中安装。如果使用的显示屏属于上面三种,就可以使用这个库。

注意导入方式为:

4.1 U8g2

接下来先简单介绍一下这个库的常用函数:

这个函数的作用是清除图形缓冲区。这是准备绘制新图形之前的常见步骤,以确保从干净的状态开始,简言之——清屏。

这个函数的作用是设置字体,可以看到我们已经传入了一个参数u8g2_font_wqy16_t_gb2312,它代表着龙泉驿点阵宋体16x16 点阵字库。

GitHub上有个中文字库仓库,得到了较为广泛地使用:https://github.com/larryli/u8g2_wqy。

同样,也有英文字库。具体可以搜索相关资料,这里不再赘述。

这两行的作用是设置光标输出。需要注意的是,它的意思是将画图位置移动到x=15,y=14处,然后以这个点的右上区域进行字符串的显示,纵坐标必须留有裕量,否则输出会到屏幕外面,这样就看不到了。

因为刚才设置了中文字体,所以能够输出中文(想修改输出的内容就在此修改)。

此外,显示屏的分辨率值得注意,更高分辨率的显示屏可以显示更多的字符。例如,128x64像素的OLED屏幕在使用16x16字体时,理论上每行可以显示8个字符。所以这个情况是合适的(我的显示屏就是128x64的),而且这六个字得以基本居中,但如果长度大于8,建议滚动显示以保证效果。

这个函数用于将在内存中准备好的图形缓冲区内容发送到显示屏上。在U8g2库中,绘制操作(如设置像素、绘制线条、显示文本等)首先在内存中的一个图形缓冲区(frame buffer)进行,而不是直接在显示屏上。这种方法允许复杂的图形处理和更新,而不会直接影响到屏幕显示,从而避免了绘图过程中可能出现的闪烁现象。

此外,还有draw系列函数没有用到,具体包括画线、画框等,使用方法比较简单,大家可以自行了解。

特别注意,使用以上函数前,应当先初始化显示屏,这意味着将显示屏所需的硬件接口设置为正确的工作状态,这里就是指配置I2C(这是一种基础通信协议,具体可参看《通信原理》)。

初始化方法如下:

特别地,对于我们的项目,还需要调用下面这个方法来显示各种语言的文本(主要是中文):

它的作用是允许UTF8形式输出。

4.2 温度显示

第一行的文字部分已经在4.1中简要介绍过了,接下来讨论温度显示的实现方法。

可以观察到,上面三行代码实现了将温度显示到屏幕上。

在输出前先设置了字体为Logisoso24,它的特点是具有较大的尺寸(大约24个像素高),适合显示重要的或需要突出的信息。字体名称中的后缀表示该字体支持透明背景,即在文本周围不会有一个不透明的矩形框。

但是有一个问题,原作者只设计了数字的显示,没有单位(即摄氏度°C),这样比较影响观感,如何优化呢?

很简单,在温度后面加上一行代码即可:

但是这产生了又一个奇怪的问题,我们可以看到显示屏只显示了C,而没有°。

这是因为:在U8g2库中,不是所有的字体都包含全范围的Unicode字符,特别是对于一些专用或较大的字体来说,它们可能仅支持有限的字符集。

而我们所使用的Logisoso24恰好属于这种情况,解决方案有两种(对于其他的特殊字符也使用):

  1. 采用Unicode字符集,例如u8g2_font_unifont_t_symbols,它支持的字符更多。
  2. 手动绘制符号,对于这种情况就是说在合适的位置画一个圆。

优化后的代码如下(摄氏度的符号会居于数字的右下侧):

最后是显示气象名称:

包括Sunny、Cloudy、Overcast等等,具体可以参看心知天气的手册,不再赘述了。

不过谨记,必须发送缓冲区才能使上述生效:

5. 时间获取

5.1 NTP

时间的获取是根据NTP实现的,先简要介绍一下NTP。

NTP(Network Time Protocol,网络时间协议),

是用于同步网络中计算机的时间的协议。它可以使计算机时钟与世界标准时间(如UTC)对齐。NTP是一种分层的、自适应的同步系统,包括一组分布式的服务器和客户端。这些服务器和客户端通过网络交换时间信息,以此来调整客户端的本地时钟。

正因为分布式,所以我们使用阿里云的:

它主要为国内网络设备提供服务。

NTP基于UDP报文进行传输,使用的UDP端口号为123,如下面这个函数所示:

UDP是一种运输层协议,具体原理、应用等可参看《计算机网络》。

NTP的具体实现原理可以参看《通信原理》,这里不再细讲原理。

特别需要指出的是,尽管NTP的精度很高,但误差仍然存在,因此如果发现存在几百毫秒的误差,也是正常的。当然,我们的项目也并不要求那么精确。

5.2 代码实现

获取数据的部分已经在5.1中展示了,数据显示的部分如下:

大家可以按需修改,如果本篇文章有疏漏,参考原作者的文章即可:利用ESP8266+OLED(I2C)打造智能时钟(网络校时+实时天气+天气预报)

此外还有断网处理,与3.4中相近,这里不再赘述了。

没想到写了这么多,,下一篇放我自己的代码(也许说是补丁或者其他的更加合适...)。

至少下一篇会介绍ESP8266的中断机制,其他的emm看情况看看能写多少吧。

到此这篇esp8266oled制作天气时钟(esp8266天气时钟教程)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • 爱普生c7000(爱普生c7000打印机使用教程视频)2024-12-26 18:36:09
  • 跳转链接怎么制作视频(跳转链接怎么制作视频教程)2024-12-26 18:36:09
  • cmake教程pdf(cmake教程 多层目录)2024-12-26 18:36:09
  • keil破解(keil破解安装教程)2024-12-26 18:36:09
  • exe如何反编译为源码(exe反编译成源码详细教程)2024-12-26 18:36:09
  • 服务器部署教程图解(服务器部署步骤)2024-12-26 18:36:09
  • 启动u盘制作教程(win10启动u盘制作教程)2024-12-26 18:36:09
  • 操作系统教程电子版(操作系统教程电子版)2024-12-26 18:36:09
  • 服务器部署教程视频(服务器部署教程视频讲解)2024-12-26 18:36:09
  • 安装虚拟机蓝屏解决方法(虚拟机安装教程win7蓝屏)2024-12-26 18:36:09
  • 全屏图片