大家一开始接触到 Arduino 的时候一定是从 Arduino UNO 开始的,但是 UNO 的体积较大。所以我也一直在寻找替代品,后来就一直在使用 Arduino NANO,价格适中但是容易在不当操作之后损坏。不过其也基本上让我把它代替了 UNO 板,毕竟一样使用且体积小了很多。而后又发现了几块性价比比较高的控制板,它们都能使用 Arduino IDE 进行编程,分别是 ATTINY85 和 MH-ET Tiny88 和本文的主角 D1 mini。
本文讲介绍 D1 mini 的基本使用方法,并介绍一个使用 D1 mini 并结合 Arduino IDE 开发的小案例,案例中 D1 mini 将通过 Wifi 连接 NTP 授时服务器,实时读取现在的时间,并将日期和时间信息显示在一块 12864 OLED 屏幕上。
开始
- 在使用 D1 mini 开发板之前,可能需要下载它的驱动,驱动的下载地址如下:https://docs.wemos.cc/en/latest/ch340_driver.html
- 然后需要配置 Arduino IDE,在 IDE 中添加 esp8266 的描述文件(进入
文件
->首选项
,在附加板管理器网址
中添加该网址。):
http://arduino.esp8266.com/stable/package_esp8266com_index.json
- 点击
工具 --> 开发板 --> 开发板管理器
,搜索D1
(搜索别的关键词亦可,如 esp8266 等相关的关键词),默认安装最新版本,然后点击安装
。
4. 此时,打开 工具 -> 开发版
,选择 ESP8266 Boards
,即可找到 LOLIN(WEMOS) D1 mini (Clone)
,选择之后在选择端口即可使用。我们可以尝试一个 Blink 的示例程序来检查板子的配置是否正确。
使用场景和案例
本节将介绍一个使用 D1 mini 并结合 Arduino IDE 开发的小案例,案例中 D1 mini 将通过 Wifi 连接 NTP 授时服务器进行校时,实时读取现在的准确时间,并将日期和时间信息显示在一块 12864 OLED 屏幕上。效果如下图所示(实际上有两排,第一排是日期、第二排是时间。不过因为刷新的原因,时间在相机拍摄过程中没显示):
网络时间协议 NTP
网络时间协议(英语:Network Time Protocol,缩写:NTP)是在数据网络潜伏时间可变的计算机系统之间通过分组交换进行时钟同步的一个网络协议,位于OSI模型的应用层。自1985年以来,NTP是目前仍在使用的最古老的互联网协议之一。NTP由特拉华大学的David L. Mills设计。
NTP意图将所有参与计算机的协调世界时(UTC)时间同步到几毫秒的误差内。它使用Marzullo算法的修改版来选择准确的时间服务器,其设计旨在减轻可变网络延迟造成的影响。NTP通常可以在公共互联网保持几十毫秒的误差,并且在理想的局域网环境中可以实现超过1毫秒的精度。
上方的简介来自于维基百科。
安装NTPClient Library
NTPClient 库提供与 NTP 服务器主机的连线,并回传日期时间,可以用 getFormattedTime()
函数取得字符串,字符串格式为 2021-09-14T18:04:14Z。使用 getEpochTime()
可以获得自 1970/01/01 起算的秒数。
NTPClient 在 Github 上有好几个,星星最多的 Library 没有 getFormattedTime()
这个函数,只提供 UNIX 时间戳,需要自己计算,过于麻烦。所以为方便起见,换成上述 taranais 的 NTPClient 库即可。
- 到 Github 下载
taranais/NTPClient
,按右边绿色选项Clone or download
,再选Download ZIP
。
- 将下载的压缩包解压,放在 Arduino IDE 下的 libraries 目录内或者点击 项目->加载库->添加.ZIP库,选中刚才下载的压缩包,即可将压缩包导入到 Arduino IDE 的库文件中。
- 值得注意的是由于使用的控制是 ESP8266 的控制板,所以无法使用 Adafruit 的 SSD1306 库,我们需要下载另一个 SSD1306 的库
ESP8266 and ESP32 OLED driver for SSD1306 displays
,没错就是这么长,具体网址在此。操作和上方的第1、第2步类似,而后引入其中的 SSD1306Wire 库文件即可使用。
需要使用到的材料
- D1 mini (克隆板) x 1
- 12864 OLED I2C 显示屏
- 连接线 x 4
- 面包板 x 1
接线图
D1 Mini | SSD1306 12864 OLED 显示屏 |
---|---|
VIN | VCC |
GND | GND |
GPIO 4(D2) | SDA |
GPIO 5(D1) | SCL |
参考代码
//https://atceiling.blogspot.com/2019/07/arduino47-ntp.html
#include <NTPClient.h>
#include <ESP8266WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <Wire.h> // Only needed for Arduino 1.6.5 and earlier
#include "SSD1306Wire.h" // legacy: #include "SSD1306.h"
// Initialize the OLED display using Arduino Wire:
SSD1306Wire display(0x3c, SDA, SCL); // ADDRESS, SDA, SCL - SDA and SCL usually populate automatically based on your board's pins_arduino.h e.g. https://github.com/esp8266/Arduino/blob/master/variants/nodemcu/pins_arduino.h
// 存储日期和时间
String formattedDate;
String dayStamp;
String timeStamp;
#define DEMO_DURATION 5000
typedef void (*Demo)(void);
// 设定Wifi账号和密码
const char* ssid = "xdshcn";
const char* password = "xdshcn1234567890";
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);
void setup() {
Serial.begin(115200);
// Initialising the UI will init the display too.
display.init();
display.flipScreenVertically();
display.setFont(ArialMT_Plain_10);
// Wifi 连接
WiFi.begin(ssid, password);
Serial.print("\n\r \n\rWorking to connect");
// 等待连接,串口监视器显示 IP
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
timeClient.begin();
// 设定时区 * 60分 * 60秒,例如:
// GMT +1 = 3600
// GMT +8 = 28800 北京时间
// GMT 0 = 0
timeClient.setTimeOffset(28800);
}
void loop() {
// clear the display
display.clear();
while (!timeClient.update()) {
timeClient.forceUpdate();
}
// formattedDate函数取得的日期格式为: 2018-05-28T16:00:13Z
formattedDate = timeClient.getFormattedDate();
Serial.println(formattedDate);
// 取得日期
int splitT = formattedDate.indexOf("T");
dayStamp = formattedDate.substring(0, splitT);
Serial.print("DATE: ");
Serial.println(dayStamp);
// 取得时间
timeStamp = formattedDate.substring(splitT + 1, formattedDate.length() - 1);
Serial.print("TIME:");
Serial.println(timeStamp);
drawFontFaceDemo(dayStamp, timeStamp);
display.display();
delay(1000);
}
void drawFontFaceDemo(String dayStamp, String timeStamp) {
// Font Demo1
// create more fonts at http://oleddisplay.squix.ch/
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_10);
display.drawString(0, 0, "Hello world");
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.setFont(ArialMT_Plain_16);
display.drawString(64, 10, dayStamp);
display.setFont(ArialMT_Plain_24);
display.drawString(64, 26, timeStamp);
}