NodeMCU项目(一)天气时钟

weather-clock

概述

首先使NodeMCU模块连接WiFi,接入互联网;然后连接阿里的NTP服务器,获取网络授时,向心知天气服务器发送HTTP请求,对返回的天气信息进行解析,获得今天、明天、后天的天气信息;最后通过OLED屏幕显示获得的信息。

硬件

  • NodeMCU(CH340)
  • 0.96英寸I2C接口OLED显示屏(SSD1306)

在这里插入图片描述

软件

  • Arduino IDE
  • PCtoLCD2002 取模软件

设计

连接WiFi

NodeMCU连接WiFi方式有很多种:

  1. 使用ESP8266WiFi库,在程序中写入一个WiFi信息,并连接到该WiFi。

  2. 使用ESP8266WiFiMulti库,在程序中写入多个WiFi信息,并自动连接到信号最强的WiFi(本项目使用该方式)。

  3. 使用WiFiManager库,不需要在程序中写入WiFi信息。使用WiFiManager库,当NodeMCU上电时,会在闪存中读取曾经连接并被保存的WiFi信息,然后连接到WiFi。如果连接失败,NodeMCU会创建一个热点,用手机或电脑连接该热点,然后扫描附近的WiFi,选择WiFi后输入密码进行连接(类似于路由器的配置)。

实时时间获取
NTP服务

NTP(Network Time Protocol),网络时间协议,是用来使计算机时间同步化的一种协议。

NTPClient库

An NTPClient to connect to a time sever Get time from a NTP sever and keep it in sync.

使用NTPClient库连接NTP服务器获取网络时间并保持时间同步。

实例化NTPClient对象,选择服务器(阿里)、偏移量(时区)及更新间隔(单位为毫秒)

NTPClient timeClient(ntpUDP, "ntp.aliyun.com", 60 * 60 * 8, 30 * 60 * 1000);

获取时间

timeClient.update();
nowTime = timeClient.getFormattedTime();
天气信息获取
心知天气API

心知天气通过标准的RestfulAPI接口,提供标准化的数据访问。拥有许多丰富的功能,本项目仅使用了天气类中逐日天气预报和昨日天气这一个子类,由于是普通用户,该接口只能只返回 3 天天气预报。

请求地址示例

北京今天和未来 4 天的预报 https://api.seniverse.com/v3/weather/daily.json?key=your_api_key&location=beijing&language=zh-Hans&unit=c&start=0&days=5

北京的昨日天气、今天和未来 3 天的预报(昨日天气独立于逐日天气预报,需要单独购买) https://api.seniverse.com/v3/weather/daily.json?key=your_api_key&location=beijing&language=zh-Hans&unit=c&start=-1&days=5

请求天气数据

按照心知天气官网介绍的API使用方式,建立HTTP请求信息。

//WiFiClient对象
WiFiClient client;
//建立心知天气API天气请求资源地址
String reqRes = "/v3/weather/daily.json?key=" + privateKey +
                + "&location=" + requireCity + "&language=en&unit=" +
                temperatureUnit + "&start=0&days=3";
//建立http请求信息
String httpRequest = String("GET ") + reqRes + " HTTP/1.1\r\n" +
                     "Host: " + host + "\r\n" +
                     "Connection: close\r\n\r\n";

连接服务器,发送HTTP请求。

if (client.connect(host, 80)) {
    client.print(httpRequest);
    ......
  }
Json数据解析
ArduinoJson库

A simple and efficient JSON library for embedded C++. ArduinoJson supports seriaization, deserialization, MessagePack, fixed allcation, zero-copy, streams, fitering, and more.

ArduinoJson库是解析JSON格式信息的第三方库,可以很简单地解析json数据(反序列化)和构造序列化json(序列化)。在ArduinoJson官网里还提供了在线生成程序的工具ArduinoJson Assistant,十分便捷。

天气信息解析

利用ArduinoJson官网的在线工具ArduinoJson Assistant,首先选择处理器、模式和输入类型,接着输入心知天气服务器返回的json数据,然后选择DynamicJsonDocument对象所占的空间(按照推荐即可),最后点击生成程序。

在这里插入图片描述

生成的程序修改参数后选择需要的信息,可以直接使用(不同的ArduinoJson版本生成的程序会有些许不同)。

多任务实现
Ticker库

The Arduino Ticker Library allows you to create easily Ticker callbacks, which can call a function in a predetermined interval. You can change the number of repeats of the callbacks, if repeats is 0 the ticker runs in endless mode. Works like a “thread”, where a secondary function will run when necessary. The library use no interupts of the hardware timers and works with the micros() / millis() function. You are not (really) limited in the number of Tickers.

正常情况esp8266执行任务时是自上而下的,最终在 loop() 函数中无限循环。为了实现向服务器发送请求、显示时间、显示天气等任务并行进行,可以借助Ticker库,让esp8266间隔固定时间调用任务函数,这里的定时调用不同于delay延时,它不受程序运行的的影响也不对程序的运行造成影响,达到了类似多线程(thread)的效果。

attach函数

attach函数有两个参数,第一个参数是调用函数的时间间隔,单位是秒,第二个参数是被调用的函数,需要注意的是被调用的函数必须执行地很快。

//向服务器请求定时器(实例化Ticker对象)
Ticker requestTicker;
//向服务器请求时间间隔
int requestInterval = 0;
//开启服务器请求定时
requestTicker.attach(1, tickerRequestInterval);

这里对变量 requestInterval 进行加1操作,在 loop() 函数里对变量 requestInterval 进行判断,当其达到预定值后就去执行任务函数,这里是执行 getWeather() 函数。

void tickerRequestInterval() {
  requestInterval++;
}

最后将变量 requestInterval 重新置为0,程序继续循环。

//每隔60s向服务器发起一次请求
if (requestInterval >= 60) {
  //获取天气数据
  getWeather();
  //重新计时
  requestInterval = 0;
}
显示
U8g2库

U8g2 is a monochrome graphics library for embedded devices. U8g2 supports monochrome OLEDs and LCDs, which include the following controllers: SSD1305, SSD1306, SSD1309, SSD1322, SSD1325, SSD1327, SSD1329, SSD1606, SSD1607, SH1106, SH1107, SH1108, SH1122, T6963, RA8835, LC7981, PCD8544, PCF8812, HX1230, UC1601, UC1604, UC1608, UC1610, UC1611, UC1701, ST7565, ST7567, ST7588, ST75256, NT7534, IST3020, ST7920, LD7032, KS0108, SED1520, SBN1661, IL3820, MAX7219 (see here for a full list).

U8g2是一个用于嵌入式设备的单色图形库,支持许多单色OLED和LCD显示控制器,如SSD1306。U8g2库集成了大多数显示屏的底层驱动,拥有许多字库,而且支持中文,API众多,功能十分强大。

函数的使用

关于U8g2库相关函数的使用,网上有很多详细的资料,U8g2库也提供了丰富的示例程序(运行时需要取消构造函数的注释),可供研究使用。本项目里绘制所使用的比较重要的函数有:

  1. u8g2.drawStr()

绘制字符串。该函数有三个参数,前两个参数是待绘制的字符串首字符的坐标,第三个参数是待绘制的字符串。

u8g2.drawStr(0, 0, "Connecting to WiFi");
  1. u8g2.print()

在入指定光标位置打印内容,支持变量。该函数只有一个参数,就是需要打印的内容。

//设置光标位置  
u8g2.setCursor(65, 32);
//打印最低温度到最高温度
u8g2.print("T: " + dayWeather.low + "~" + dayWeather.high + "°C");
  1. u8g2.drawXBMP()

绘制FLASH中位图图像。该函数有五个变量,前两个参数是待绘制的位图图像的坐标,第三、四个参数是位图的宽高,最后一个参数是位图资源。

//晴天图标
u8g2.drawXBMP(0, 0, 64, 64, Sunny);
图片取模

借助PS和画图等软件,制作好图标的单色位图(bmp格式)图片,将图片导入到PCtoLCD2002中,在字模选项中调整设置,然后生成字模,生成的字模可以直接复制到程序中使用。

在这里插入图片描述

展示

启动界面

在这里插入图片描述

启动界面的汉字是图片取模制作成的,不是直接使用函数打印的。

连接WiFi界面

在这里插入图片描述

WiFi连接过程中 “.” 会逐个增加,以提示连接的过程,连接成功后会打印 “Successfully!” 提示连接成功。然后到下一个界面显示连接到的WiFi名称以及分配的IP地址。

时间日期界面

在这里插入图片描述

这里周几的计算用到了蔡勒公式。从心知天气解析的Json数据里可以得到当天的日期,将这个日期的年、月、日取出,应用蔡勒公式即可解出当天为周几。时间日期界面显示10s后变为天气界面。

天气界面

在这里插入图片描述

今天、明天、后天的天气信息轮流显示3s,显示信息包括天气图标,日期,天气文字、温度和湿度。

源代码

GitHub链接

  • 15
    点赞
  • 90
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值