二、ESP32基于Arduino IDE OLED 联网显示时间
上一篇学习笔记讲了如何在Arduino上配置ESP32开发环境,这次分享一下如何让ESP32联网获取时间再通过OLED来显示。此系列文章都是学习笔记,希望能有所帮助。
ps:代码中调用的库如需要可在在文末查找下载
目录
1、OLED显示时间( SSD1306 IIC)
2、OLED显示时间(U8G2 SPI DS1302时钟芯片维持走时)
3、 夹带私货的一期产品——智锺(简陋)
4、调用的库
1、OLED显示时间( SSD1306 IIC)
这里使用的是SSD1306驱动的IIC的OLED屏幕,通过RTC时钟维持联网同步时间后的继续走时,这种走时不准,后面有说加一个时钟芯片维持走时的。并且从这里开始,笔者发现实际同步后的时间还是会比网络时间酌情慢一些(1至2s),应该是由通信延迟导致的,包括ESP32联网获取时间的延迟和ESP32向OLED屏幕传输时间的延迟。
下面的代码注释很详细,可以直接CV烧录,需要自己更改的只有wifi名字和密码(后面会更新不在代码中设置名称和密码的版本,开机后手动输入名称和密码,适合不同环境)。另外需要注意SDA,SCL的接线引脚。
附(ESP32 WROOM引脚图):
#include <WiFi.h>
#include <HTTPClient.h>
#include <Wire.h>// 引入驱动OLED所需的库
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>#define SCREEN_WIDTH 128 // 设置OLED宽度,单位:像素
#define SCREEN_HEIGHT 64 // 设置OLED高度,单位:像素// 自定义重置引脚,虽然教程未使用,但却是Adafruit_SSD1306库文件所必需的
#define OLED_RESET 4
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);const char *ssid = "821"; //你的网络名称
const char *password = "54085408"; //你的网络密码
// "pool.ntp.org";
const char *ntpServer = "ntp.neu.edu.cn";
const long gmtOffset_sec = 8 * 3600;
const int daylightOffset_sec = 0;void printLocalTime()
{struct tm timeinfo;if (!getLocalTime(&timeinfo)){display.println("Failed to obtain time");return;}display.println(&timeinfo, "%F"); // 格式化输出display.println(&timeinfo, "%T"); // 格式化输出display.println(&timeinfo, "%A"); // 格式化输出
}void setup()
{// put your setup code here, to run once://设置I2C的两个引脚SDA和SCL,这里用到的是17作为SDA,作为SCLWire.setPins(/*SDA*/33,/*SCL*/32);//初始化OLED并设置其IIC地址为 0x3Cdisplay.begin(SSD1306_SWITCHCAPVCC, 0x3C);//清除屏幕display.clearDisplay();//设置字体颜色,白色可见display.setTextColor(WHITE);//设置字体大小display.setTextSize(1);//设置光标位置display.setCursor(0, 0);WiFi.begin(ssid, password);while (WiFi.status() != WL_CONNECTED){delay(500);display.print(".");}display.println("WiFi connected!");// 从网络时间服务器上获取并设置时间// 获取成功后芯片会使用RTC时钟保持时间的更新configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);printLocalTime();WiFi.disconnect(true);WiFi.mode(WIFI_OFF);display.println("WiFi disconnected!");display.display();
}void loop()
{// put your main code here, to run repeatedly:、delay(1000);//清除屏幕display.clearDisplay();//设置光标位置display.setCursor(0, 0);printLocalTime();display.display();}
2、OLED显示时间(U8G2 SPI DS1302时钟芯片维持走时)
后面笔者和组员就使用了4线SPI的OLED屏继续开发,并且加入了时钟芯片使联网同步时间后的走时更加准确(依然有延迟,暂时不知道怎么优化,有时候就刚好玄学对的上)。
联网获取时间得到的数据用于初始化DS1302时钟芯片,后续是ESP32从时钟芯片获取时间再传到OLED进行显示。
同样的,支持两键CV烧录,只需要更改wifi名称和密码;同样的,也需要注意接线,DS1302时钟芯片和OLED SPI的接线,代码中有设置好的引脚,也可自行依据上面的引脚图自行定义。 注意!笔者的OLED是SH1106驱动的,购买OLED前,询问商家查明驱动芯片,如与我不同只需要更改此处的芯片型号即可。
#include <stdio.h>
#include <Arduino.h>
#include <WiFi.h>
#include <SPI.h>
#include <U8g2lib.h>
#include <DS1302.h>/*-------------------------------WIFI--------------------------------------------------*/
const char* ssid = "123"; //wifi 名字
const char* password = "12345678"; // wifi 密码//-----------网络时间获取-----------//
const char* ntpServer = "pool.ntp.org"; //网络时间服务器
//时区设置函数,东八区(UTC/GMT+8:00)写成8*3600
const long gmtOffset_sec = 8 * 3600;
const int daylightOffset_sec = 0; //夏令时填写3600,否则填0
/*-------------------------------WIFI--------------------------------------------------*//*-------------------------------DS1302-------------------------------------------------*/
//设置适当的数字 I/O 引脚连接
//这些是Arduino以及DS1302芯片的引脚分配。
//参见DS1302数据表:
//http://datasheets.maximintegrated.com/en/ds/DS1302.pdf
const int kCePin = 13; // RST
const int kIoPin = 23; // DAT
const int kSclkPin = 19; // CLKDS1302 rtc(kCePin, kIoPin, kSclkPin); //创建 DS1302 对象
/*-------------------------------DS1302-------------------------------------------------*//*----------------------------OLED--------------------------------*/
U8G2_SH1106_128X64_NONAME_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 18, /* data=*/ 15, /* cs=*/ 5, /* dc=*/ 22, /* reset=*/ 21);
/*----------------------------OLED--------------------------------*/struct tm timeinfo;String dayAsString() {switch (timeinfo.tm_wday) {case 1: return "Monday";case 2: return "Tuesday";case 3: return "Wednesday";case 4: return "Thursday";case 5: return "Friday";case 6: return "Saturday";case 7: return "Sunday";}return "(unknown day)";
}void printTime() //打印时间数据
{// 从芯片获取时间Time t = rtc.time();// 定义星期几const String day = dayAsString();// 设置时间和日期的格式并插入到临时缓冲区中char buf[50];snprintf(buf, sizeof(buf), "%04d-%02d-%02d %02d:%02d:%02d",t.yr, t.mon, t.date,t.hr, t.min, t.sec);u8g2.clearBuffer(); // 清除内部存储器u8g2.setFont(u8g2_font_ncenB08_tr); // 选择合适的字体u8g2.setCursor(0, 32);u8g2.print(day);u8g2.drawStr(2, 10, buf); // 写入内部存储器u8g2.sendBuffer(); // 将内部存储器传输到显示器Serial.println(day);Serial.println(buf);
}void setu8g2() {Serial.begin(115200);u8g2.begin();
}void getTime(void) //联网获取时间
{WiFi.begin(ssid, password);while (WiFi.status() != WL_CONNECTED) {delay(500);Serial.print(".");}Serial.println("WiFi connected!");// 从网络时间服务器上获取并设置时间// 获取成功后芯片会使用RTC时钟保持时间的更新configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);if (!getLocalTime(&timeinfo)) {Serial.println("Failed to obtain time");return;}Serial.println(&timeinfo, "%F %T %A"); // 格式化输出uint16_t year = (uint16_t)timeinfo.tm_year;uint8_t mon = (uint8_t)(timeinfo.tm_mon) + 1;uint8_t day = (uint8_t)timeinfo.tm_mday;uint8_t hour = (uint8_t)timeinfo.tm_hour;uint8_t min = (uint8_t)timeinfo.tm_min;uint8_t sec = (uint8_t)timeinfo.tm_sec;rtc.writeProtect(false); //关闭写保护rtc.halt(false); //清除时钟停止标志Time t((uint16_t)year + 1900, (uint8_t)mon, (uint8_t)day, (uint8_t)hour, (uint8_t)min, sec, Time::kSaturday); //新建时间对象 最后参数位星期数据,周日为1,周一为2以此类推rtc.halt(false);rtc.time(t); //向DS1302设置时间数据rtc.writeProtect(true);WiFi.disconnect(true);WiFi.mode(WIFI_OFF);Serial.println("WiFi disconnected!");
}void setup() {setu8g2();getTime();
}void loop() {printTime();delay(1000);
}
3、 夹带私货的一期产品——智锺(简陋)
#include <stdio.h>
#include <DS1302.h>#include <Arduino.h>
#include <U8g2lib.h>#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif#define BUS_CLOCK 400000 // 最大400000
#define DURATION 1000 // 加载条持续时长(ms)#include <WiFi.h>/*-------------------------------WIFI--------------------------------------------------*/
const char* ssid = "821"; //wifi 名字
const char* password = "54085408"; // wifi 密码//-----------网络时间获取-----------//
const char* ntpServer = "pool.ntp.org"; //网络时间服务器
//时区设置函数,东八区(UTC/GMT+8:00)写成8*3600
const long gmtOffset_sec = 8 * 3600;
const int daylightOffset_sec = 0; //夏令时填写3600,否则填0
/*-------------------------------WIFI--------------------------------------------------*//*-------------------------------DS1302-------------------------------------------------*/
//设置适当的数字 I/O 引脚连接
//这些是Arduino以及DS1302芯片的引脚分配。
//参见DS1302数据表:
//http://datasheets.maximintegrated.com/en/ds/DS1302.pdf
const int kCePin = 4; // RST
const int kIoPin = 23; // DAT
const int kSclkPin = 19; // CLKDS1302 rtc(kCePin, kIoPin, kSclkPin); //创建 DS1302 对象
/*-------------------------------DS1302-------------------------------------------------*//*----------------------------OLED--------------------------------*/
U8G2_SH1106_128X64_NONAME_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 18, /* data=*/ 15, /* cs=*/ 5, /* dc=*/ 22, /* reset=*/ 21);
/*----------------------------OLED--------------------------------*/struct tm timeinfo;static const unsigned char logo[] U8X8_PROGMEM = {//logo0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x1F,0x00,0x00,0xFC,0x1F,0x00,0x00,0xFC,0x0F,0x00,0xC0,0x03,0xF4,0x00,0xE0,0x01,0xE2,0x01,0xF0,0x01,0xE2,0x03,0xF0,0x00,0xC1,0x03,0x78,0x80,0x80,0x07,0x78,0x80,0x80,0x07,0x3C,0x00,0x00,0x0F,0x3C,0xE0,0x07,0x0F,0x1E,0xF0,0x07,0x1E,0xFE,0xFB,0xF7,0x1F,0x1E,0xF8,0x03,0x1E,0x3C,0xF8,0x01,0x0F,0x3C,0x00,0x00,0x0F,0x78,0x40,0x80,0x07,0x78,0x40,0x80,0x07,0xF0,0x20,0xC0,0x03,0xF0,0x11,0xE0,0x03,0xE0,0x11,0xE0,0x01,0xC0,0x0B,0xF0,0x00,0x00,0xFC,0x0F,0x00,0x00,0xFE,0x0F,0x00,0x00,0xFE,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};String dayAsString() {switch (timeinfo.tm_wday) {case 1: return "Monday";case 2: return "Tuesday";case 3: return "Wednesday";case 4: return "Thursday";case 5: return "Friday";case 6: return "Saturday";case 7: return "Sunday";}return "(unknown day)";
}void printTime() //打印时间数据
{// 从芯片获取时间Time t = rtc.time();// 定义星期几const String day = dayAsString();// 设置时间和日期的格式并插入到临时缓冲区中char buf[50];snprintf(buf, sizeof(buf), "%04d-%02d-%02d %02d:%02d:%02d",t.yr, t.mon, t.date,t.hr, t.min, t.sec);u8g2.clearBuffer(); // 清除内部存储器u8g2.setFont(u8g2_font_ncenB08_tr); // 选择合适的字体u8g2.setCursor(0, 32);u8g2.print(day);u8g2.drawStr(2, 10, buf); // 写入内部存储器u8g2.sendBuffer(); // 将内部存储器传输到显示器Serial.println(day);Serial.println(buf);
}void setu8g2() {Serial.begin(115200);u8g2.setBusClock(BUS_CLOCK);u8g2.begin();u8g2.enableUTF8Print();u8g2.setFont(u8g2_font_wqy12_t_gb2312);u8g2.setPowerSave(0);
}void load_bar(int W) {u8g2.clearBuffer();unsigned long time;time = millis();// for (; W <= 128;) // W:宽度// {for (int mode = 0; mode < 4; mode++) {u8g2.clearBuffer();for (int H = 48; H < 64; H++) // H:高度{switch (mode) {case 0:for (int j = 0; j < W; j += 4) {u8g2.drawPixel(j, H);u8g2.drawPixel(j + 1, H);}mode = 1;break;case 1:for (int j = 0; j < W; j += 4) {u8g2.drawPixel(j + 1, H);u8g2.drawPixel(j + 2, H);}mode = 2;break;case 2:for (int j = 0; j < W; j += 4) {u8g2.drawPixel(j + 2, H);u8g2.drawPixel(j + 3, H);}mode = 3;break;case 3:for (int j = 0; j < W; j += 4) {u8g2.drawPixel(j, H);u8g2.drawPixel(j + 3, H);}mode = 0;break;}}// u8g2.drawStr(0, 36, "智汇嵌入式"); // 在指定位置显示字符串u8g2.drawXBM(0, 8, 30, 30, logo);u8g2.setCursor(30, 22);u8g2.print("智汇嵌入式");u8g2.setCursor(32, 34);u8g2.print("ZHIHUIEMBEDDED"); // 在指定位置显示字符串u8g2.sendBuffer();delay(10);}// if ((millis() - time) > (DURATION / 4))// {// time = millis();// W += 32;// }// }
}void getTime(void) //联网获取时间
{WiFi.begin(ssid, password);while (WiFi.status() != WL_CONNECTED) {int W = 0;unsigned long time;time = millis();for (; W < 129;) {if ((millis() - time) > (DURATION / 4)) {time = millis();W += 32;}load_bar(W);}}Serial.println("WiFi connected!");// 从网络时间服务器上获取并设置时间// 获取成功后芯片会使用RTC时钟保持时间的更新configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);if (!getLocalTime(&timeinfo)) {Serial.println("Failed to obtain time");return;}Serial.println(&timeinfo, "%F %T %A"); // 格式化输出uint16_t year = (uint16_t)timeinfo.tm_year;uint8_t mon = (uint8_t)(timeinfo.tm_mon) + 1;uint8_t day = (uint8_t)timeinfo.tm_mday;uint8_t hour = (uint8_t)timeinfo.tm_hour;uint8_t min = (uint8_t)timeinfo.tm_min;uint8_t sec = (uint8_t)timeinfo.tm_sec;rtc.writeProtect(false); //关闭写保护rtc.halt(false); //清除时钟停止标志Time t((uint16_t)year + 1900, (uint8_t)mon, (uint8_t)day, (uint8_t)hour, (uint8_t)min, sec, Time::kSaturday); //新建时间对象 最后参数位星期数据,周日为1,周一为2以此类推rtc.halt(false);rtc.time(t); //向DS1302设置时间数据rtc.writeProtect(true);u8g2.clear();WiFi.disconnect(true);WiFi.mode(WIFI_OFF);Serial.println("WiFi disconnected!");
}void setup() {setu8g2();getTime();
}void loop() {printTime();delay(1000);
}
4、调用的库
百度网盘
链接:https://pan.baidu.com/s/1m_N8mJov1IVzlUwhobzSzg?pwd=5408
提取码:5408
二、ESP32基于Arduino IDE OLED 联网显示时间相关推荐
- ESP32基于Arduino框架下U8g2驱动I2C OLED 时间显示
ESP32基于Arduino框架下U8g2驱动I2C OLED时间显示
- 【嵌入式】STM32基于SPI通信协议OLED屏显示
STM32基于SPI通信协议OLED屏显示 一.SPI协议和OLED介绍 1.SPI协议介绍 物理层 协议层 2.OLED显示屏介绍 二.显示个人学号姓名实验 1.题目要求 2.代码部分 1.完整代码 ...
- 基于Arduino IDE开发的ESP8266(ESP-12F)项目4 ——中断及高级输入输出
本次写这篇文章是自己做一下学习记录,如有错误,还请大家斧正!!! 日后及时修正!感谢支持! 欢迎大家的关注 点赞 收藏 留言 目录 前言 一.新建工程 二. ...
- 基于Arduino IDE开发的ESP8266(ESP-12F)项目2 ——按键操作
本次写这篇文章是自己做一下学习记录,如有错误,还请大家斧正!!! 日后及时修正!感谢支持! 欢迎大家的关注 点赞 收藏 留言 目录 前言 一.新建工程 二. ...
- 基于STM32实现OLED滚动显示
基于STM32实现OLED滚动显示 滚动方式 水平滚动 水平加垂直滚动 一.文字取模 二.代码修改 三.硬件连接加结果 总结 参考文献 滚动方式 水平滚动 OLED_WR_Byte(0x2E,OLED ...
- 实验 STM32 基于SPI的OLED屏显示
STM32 基于SPI的OLED屏显示 一.任务要求 二.显示自己的学号和姓名 1.例子程序的改写 (1)下载资料 (2)解压后找到文件,并用KEIL打开. (3)改写程序 2.连接硬件 3.运行结果 ...
- 合宙ESP32C3基于Arduino IDE框架下配置分区表
合宙ESP32C3基于Arduino IDE框架下配置分区表 关于VSCode PIO配置分区表可以参考示例文章<合宙ESP32C3基于VSCode PIO开发初探教程> 有关Arduin ...
- esp32使用MicroPython驱动oled屏显示中文和英文
文章目录 esp32使用MicroPython驱动oled屏显示中文和英文 介绍 安装 特点 开源 硬件连接 API 示例 显示英文字符 显示汉字 参考链接 esp32使用MicroPython驱动o ...
- ESP32基于Arduino框架,SD卡+MAX98357模块+MP3播放器
ESP32基于Arduino框架,SD卡+MAX98357模块+MP3播放器
最新文章
- dram和nand哪个难生产_DRAM与NAND差别这么大,存储之争都争啥
- 【计算机网络】网络层 : 网络层简介 ( 功能 | 拥塞控制 )
- MySQL 高级 - 存储过程 - 语法 - 游标
- python生成1到100的列表_python列表生成式与列表生成器的使用
- 网站登录JWT的实现
- Spring 类管理机制
- 李宏毅《机器学习》完整版笔记发布
- java 祖父类_JAVA的XX.put中的put方法,是在哪个父类或祖父类中,详述父类链。
- Inception V3 的 tensorflow 实现
- 数字信号处理实验(六)—— 心电信号处理 IIR FIR滤波综合题(下篇)
- 官方配置要求_《魔兽争霸3》重制版极客装机配置和官方要求配置
- 模拟电子技术基础笔记(1)
- 邮箱怎么打开smtp服务器端口号,什么是SMTP协议?SMTP端口号是多少?什么是SMTP服务器?免费smtp服务器?...
- 黑页网站html源码,仿360网站卫士拦截页面黑页源码
- 李嘉诚:没有人愿意贫穷,但出路在哪(转自意林)
- 光猫下连接路由器的详细步骤
- u3d:200个插件免费分享
- 使用tsx开发vue项目入门
- isfinite函数_isfinite()函数以及C ++中的示例
- 百度浏览器的隐私安全问题分析