ARDUINO从入门到创客带师第⑤弹 自制WIFI时钟
20多块钱做个永远精准的时钟,用大佬的代码
虽然20包邮买个手机就能解决问题,但是还是折腾下比较好,了解原理
其实这方面的制作教程已经有很多了,当然咱接触的大多数都是视频,偶尔见视频教程但是仍然不是特别详细,所以咱最终还是觉得自己应该写成文章,而不是简单的做视频教程。毕竟相比视频,文章的阅读更加随意而且节奏容易把握,对于小白来说更容易理解,而且咱对自己的教程还是有自信的,毕竟好歹也是年度达人。不得不说咱在张大妈这一年收获不少。
这是阿卡林的教程:
一分钟教你做OLED时钟,ESP8266一键刷机方法与小白常见问题
只需20元DIY一个永远精准的数字时钟,快速制作教程及原理讲解
咱之前也商量过,如果自己做的话能不能做个实用的自动对时钟,就像家里的老挂钟一样不用插电用电池就能自动对时并且有效的在大面积上显示时间,结果最后得到的结论是自己做要用电子墨水屏太贵,不如买小米那个现成的温湿度计,要是机械表盘的话又不知道正时是用什么机构,所以不如买现成的。
不过今天我们仅仅站在DIY的角度上而非实用的角度来说下怎么能用这个成本不到10块钱的ESP8266模块和10多块钱的12864 OLED屏幕自己制作WIFI正时钟。写教程要面对小白,咱的目标是要做到即使是咱三年级的妹妹读完这篇教程也能自己把需要的东西组装好然后刷好程序,就像给自己的手机装软件一样。
NODEMCU或者说8266的性能相比多少年前的51单片机或者标准ARDUINO用的AVR单片机性能强了很多,而且还自带WLAN功能且成本很低,因此被广泛的应用于IOT物联网领域。
单论性能,8266甚至可以驱动屏幕放送视频内容:
ESP8266小电视 (康美之恋) NodeMCU
不过这种玩法说实在的只是把视频转成了图片之后用OLED屏幕逐帧播放的,并没有什么意义,相比之下我还是觉得之前咱玩的那套用ARDUINO播放MIDI音乐更有意思。ESP8266正经的应用场合果然还是物联网,这里的网络时钟就是最简单的应用场合,虽然实用的大屏幕很贵但是以学习为目的制作这样一套网络时钟还是很有意思的。
因为要做时钟所以首先说下时钟的原理
从沙漏、日晷、滴水计时到钟摆这部分内容咱就省了,直接开始说现代电子计时器吧
不同于物理的钟摆计时器依靠机械摆的固有周期计时,电子计时器依靠晶体来完成计时的。计算机的计时器通常是一个精密加工过的石英晶体,石英晶体在其张力限度内以一定的频率振荡,这种频率取决于晶体本身如何切割及其受到张力的大小。当然不同的计算机有不同的晶体,而不同的晶体计时的精度就完全不同,因此不同的时钟实际上计时的速度是完全不一样的,也就是说存在精度差异。劣质的时钟经常走着走着时间就跑了,因此经常需要对时。过去我们通常都是靠电台或者电视的整点报时来正时,而现在我们就不用费这个劲了,因为可以通过网络时钟自动正时。
什么是网络时钟?
ntp
网络时钟是基于网络时间协议的
高性能时钟,一般来说开启了网络时间的手机和电脑等设备的时钟都是准的,而之前我们说的小米的温度计的网络正时就是通过蓝牙和手机的时间保持同步的(虽然自身搭载的时钟也不是几块钱的那种便宜温湿度计上的每几天就跑几分钟的垃圾时钟能比的)
关于网络时间协议
网络时间协议,英文名称:Network Time Protocol(
NTP
)是用来使计算机时间同步化的一种
协议
,它可以使计算机对其服务器或时钟源(如石英钟,GPS等等)做同步化,它可以提供高精准度的时间校正,所以经常网络授时的设备的时间相对来说就总是准的
深层:发送和接受信息包括处理信息都需要时间,但是NTP协议通过自己的一套算法可以消除这部分时间带来的误差(上图这里就是总耗费时间T1和T4差,减去服务器处理时间=客户端与服务器通讯往返时间),虽然依靠网络得到准确的时间比依靠GPS或者电波授时台需要考虑的条件更多但是一样可以完成任务
其实忽略这个时差也是可以的,网络的速度其实没那么慢,也就差一两秒顶多几秒钟,可以忽略。
扩展:
收到电波的手表会根据信号里的时间、星期、年月日、夏令时间等讯息自动校正,让你有跟原子钟般的精准度。(手表会根据你设定的所在地自动计算与站台间的时差)。比如从日本买的手表,它出厂时就设置成收日本信号走日本时间,然而带到中国东南沿海城市使用,就应该把手表时间转换成东八区时间, 这样手表就会收日本信号走北京时间。黑龙江北部地区可以收到日本的时钟信号,因此也是可以正常使用的。可能会出现少量误码现象
目前世界总共有6个商用电波台分别是:1.中国(代号BPC)——河南商丘(68.5kHz)
2、日本(JJY)——福岛(40kHz)
3、美国(WWVB)——科罗拉多Fort Collins(60kHz)
4、英国(MSF)——Anthorn(60kHz)
5、德国(DCF77)——Frankfurt (77.5kHz)
6、日本(JJY)——九州(60Khz)
在本期教程中我们了解了网络时钟的原理之后就可以开始自己制作一个基于WLAN正时的时钟模型了
硬件方面
总之,要做一个可以用的WIFI正时时钟你至少需要三样东西:一台能上网的电脑
一个ESP8266模块
和一个带连接线的12864 OLED屏幕
这几样东西其实我们以前都做过开箱(
图吧垃圾佬的日常开箱
)(
100块钱的工作站 NEC VY21A
),都很便宜。8266模块一个最便宜不到10块钱,这次建议是用D1或者 NODEMCU之类的迷你版就行,可以不用上D1大板,12864 OLED屏幕现在10块钱出头能买到包邮的双色屏幕了,杜邦线这种东西价格很低基本不零售,建议各位买长一点的接头全一点的质量好一点的线,公对公母对母公对母都买齐这样很长时间以内都可以不用发愁线的事。此外还需要准备一个MICRO USB的数据线(记住是数据线,很多充电线是没有数据口的,这样的线在我们这期教程里是无法使用的,历史上也坑过很多小白导致开局就卡关GG)
这里如果各位不是小白而且对有屏幕的8266模块开发有兴趣的话或者如果图省事的话各位还可以买这种自带了OLED屏幕的NODEMCU,这样可以省去判断OLED屏幕的协议和如何插连接线的步骤。
价格嘛稍微贵了一点但是省线啊(理论上,在这期教程并没有省)
硬件方面还要和上次讲ARDUINO一样讲讲现在市场上的坑,正如很多JS把利用原版设计图生产出来的ARDUINO开发板打上所谓“正版”标识然后高价售卖获取暴利(实际上一样是产自深圳华强北)一样,ESP8266模块网上也有很多针对小白的陷阱,这里简单说一下这个东西:
WIFI DEAUTHER或者传说中的WIFI杀手这种东西其实我们以前也都研究过,项目地址:
spacehuhn/esp8266_deauther
说实在的是一种利用WIFI协议的漏洞对AP进行类似DDOS的一种方案,因为WIFI协议本身的漏洞所以当使用WIFI模块对热点进行DEAUTH攻击的时候WIFI上的所有设备会掉线(看到这里我终于明白当年为何我们一直在讲要普及WAPI了,当年说WIFI协议不安全如今看来确实是真的),作者的本意是提醒WIFI联盟WIFI协议现存的BUG可能导致的后果,然而过了不久之后就变成如上图所示这种情况了,同样的东西刷上个固件就开始收
智商税
了,那么遇到这种情况我们改怎么办呢?
买爆×
举报√
当然是举报了,因为干扰网络设备是非常严重的危害公共安全的行为。如果各位想研究,建议自己买个WIFI模块然后只对自己家的路由器使用,以便研究学习。
法律适用:破坏广播电视设施、公用电信设施罪,是指故意破坏正在使用中的广播电视设施、公用电信设施,危害公共安全的行为。是以广播电视设施、公用电信设施为特定破坏对象的危害公共安全罪。
总之看到上面这种关键词的东西举报就对了,这东西一点一个准的。以前TB大规模下架过电磁炮(原理都是假的然而在堆能量量级之后还挺有威力),这种同样是智商税的商品下架也只是时间问题,至于究竟需要多长时间那就需要看各位的行动了。拒绝智商税,从我做起。
总之在琳琅满目的商品列表中我建议各位用这几种基于8266WIFI模块的开发板
我建议各位上NODEMCU就可以,经实践检验NODEMCU各个引脚功能齐全并不缺所谓的5V供电,而且加上扩展板之后功能也不少,完全是可以担当大任的。
还有就是需要注意的就是视频教程里阿卡林只提到了装驱动的时候装CH340 CH341的驱动而没有提到NODEMCU使用的另一种USB转串口模块的驱动CP210X,说实在的以前在玩NODEMCU的时候NODEMCU有两种USB转串口芯片这对于咱来说是常识了但是这里还是说一下吧,我相信我不说的话咱的观众也会像阿卡林的观众群里面的小白一样各种卡BUG然后卡关的。
而右边这两种基于ARDUINO演进的8266开发板这里也是可以用的
这种单体的ESP8266模块不是很建议使用,因为IO接口是在是少了点,这种模块一般是作为WIFI串口使用的,就像搞单片机经常用的蓝牙串口模块一样。
关于OLED屏幕其实OLED屏幕型号还是挺多的,别看都是12864
SPI I2C两种协议以及ssd1306 1309 sh1106各种型号的驱动还是有区别的,一旦选择错误那就是用不了
这种用不了可不是电源插座用不了还可以大力出奇迹或者飞线解决的问题,而是它就是用不了。所以购买和使用的时候还是注意点好,虽然代码都是全的,但是对于小白来说无法判断自己买到手里的东西究竟是哪种型号的可能还是有的。不如一开始就决定好自己要买哪种型号,一般来说OLED都是1306的驱动比较多,对1106支持比较少不建议买这种。而I2C和SPI两种协议的选择上可以随意点,支持哪种都可以用,当然如果有得选买两种协议都支持的是最好,没有也没关系。
这家9.9包邮的就可以
左边这个是咱很久以前买了一直没用在吃灰的12864模块,可以通过改变外围元件支持两种协议,有六个引脚,现在是按4SPI配置了。右边是新买的只支持I2C(IIC)的双色OLED 12864显示屏,基于SSD1306驱动。
值得注意的是12864屏幕虽然看着有128*64像素挺不错,实际上体积很小的,和手机屏一比就能看出来大概了
实际上比一元硬币大不了太多,所以当挂钟用还是差点啊,所以玩归玩学习归学习实用层次上这玩意最多当个手表,还是离不开WIFI的那种。
然后就是咱说的杜邦线的问题了,还是和之前说的一样,不同的开发板因为引脚不同所以需要选用不同的杜邦线,12864屏幕是排针NODEMCU是排针所以线需要母对母,而D1 WIFI模块焊接排插或者标准D1 ARDUINO板型的开发板则需要用公对母杜邦线连接屏幕。
至于连线方式呢这里以D1为例,因为12864屏幕是3.3V供电的,所以电源方面VCC直接连开发板的3.3V输出就可以了(现代的电器设备基本上很少有直接用5V的了,别说3.3,低功耗IC都开始普及1.8V甚至更低的电平了,电脑上硬盘光驱用的SATA信号只有0.5V)
具体的接法咱就简单带过了,因为咱用的是NODEMCU所以接法和这个不一样但是大同小异(NODEMCU则是用了D123456和GPIO……分别在板子的上下定义丝印标注,不过使用起来都一样)注意电源别接反就行了,大部分模块接反必烧
D1和NODEMCU的原理图
简单分析NODEMCU引脚关系,发现默认I2C的SDA和SCL分别是GOIO04和GPIO05,就是上面丝印的D1和D2,所以简单改下接线定义就可以了
(其中NODEMCU的GPIO02连接到了ESP-12上的LED,GPIO00烧写需要用所以都不能被定义为I2C接口)
扩展:IIC和SPI(以及UART)
UART(Universal Asynchronous Receive Transmitter):也就是我们经常所说的串口,基本都用于调试。
SPI(Serial Peripheral Interface, 同步外设接口)是由摩托罗拉公司开发的全双工同步串行总线,该总线大量用在与EEPROM、ADC、FRAM和显示驱动器之类的慢速外设器件通信。
SPI是一种串行同步通讯协议,由一个主设备和一个或多个从设备组成,主设备启动一个与从设备的同步通讯,从而完成数据的交换。SPI 接口由SDI(串行数据输入),SDO(串行数据输出),SCK(串行移位时钟),CS(从使能信号)四种信号构成,CS 决定了唯一的与主设备通信的从设备,片选信号低电平有效。如没有CS 信号,则只能存在一个从设备,主设备通过产生移位时钟来发起通讯。通讯时,数据由SDO 输出,SDI 输入,数据在时钟的上升或下降沿由SDO 输出,在紧接着的下降或上升沿由SDI 读入,这样经过8/16 次时钟的改变,完成8/16 位数据的传输。
SPI比较混乱,主要是没有标准的协议,只有moto的事实标准。所以衍生出多个版本,但没有本质的差异。常见的SPI信号有:SS片选、SCK同步时钟、MISO、MOSI(也有叫SDI、SDO的)数据输入和输出,还的有包括DCX命令数据选择。
SPI分4线和3线,4线接口:包括SCLK、SDO、SDI、SS;3线接口:包括SCLK、SDA、SS。所以3线和4线的不同在于,4线接口可以实现的是master in和master out。但3线只有master out。不管是3线还是4线,SS是必须有的。master使用不同的SS信号可以连接多个salve
IIC(Inter Integrated Circuit):两根线:一个时钟线SCL和一个数据线SDA。只有一根数据线,所以是半双工通信。接线不难,而且两根线上也可以挂很多设备(每个设备的IIC地址不同)
速率
SPI 速率与芯片有关,有的400K,有的到几兆;
rs232速率一般最大115200
iic一般应用400K,CAN最高可到1M
所以为了接线方便原则上可以用IIC协议的屏,牺牲点速率没什么又不是搞动画MTV,就为了看时间这点速度差没什么
UART, SPI, IIC的详解及三者的区别和联系 - 一抹烟霞 - 博客园
软件方面
代码:
https://git.io/fj3p1
大佬已经提供了,还按我们上次说的
ARDUINO环境库的安装和使用GITHUB上的开源项目
的方法下载就可以,这次并不需要ARDUINO环境
关于程序的刷写,首先刷写程序之前要安装好驱动这个是常识。驱动都驱不上你刷写个屁(没有硬件支持你破解个屁)
如果你用的是CH340 CH341转接方案的开发板就用CH340的驱动,如果用的是CP210X转接方案的开发板就用CP210X的驱动,我这里提供了WIN7的驱动。我建议各位都安装一遍然后再说,毕竟多动动鼠标安装个驱动自己也不少块肉。(这里MAC用户和LINUX用户需要自己想办法了,XP用户也要麻烦一下自己去找32位的驱动)
打开驱动包,WIN7 WIN8就选WIN7_8 WIN10就选WIN10
如果你有管理员权限,直接在压缩包里面打开安装文件就可以了,64位系统选X64,32位系统选X86,XP需要另外找驱动 MAC驱动安装比较麻烦如果有双系统建议切换到WIN干这个。
阿卡林给的是更高级的工具
这里要先选择好写入工具需要写入的模块种类然后才能进同样难用的GUI图形界面选择要刷写的包和波特率 COM口等参数
其实这和ARDUINO开发板的程序上传差不太多,只是多了个选包和波特率的环节
但是这个界面对于单纯的ESP8266固件烧写太麻烦了
我建议各位做基于8266模块的WIFI钟就不要用ESP写入工具了,直接用8266 FLASHER,能省不少事呢
首先还是熟悉的界面,8266烧写器,当年咱用这个玩意可是没少烧录。
不知道串口是哪个就用设备管理器看看或者挨个试试,反正试错了也没啥大事。一般COM口1是系统自带的,往COM1刷写没用。
基本上选对了COM口之后再加载打包好的BIN固件就行了 这里是SPI就选SPI I2C就选I2C
如果烧写失败考虑一下把波特率改成9600试试,当然代价是烧写的速度基本上得等挺长时间
然后如果没事了的话点开始就可以烧写了
开始烧写
写完了之后会告诉你写入成不成功,这个对号表示的就是成功了,恭喜,如果错了也没关系,再来就是了。
一般烧写前后按操作规范需要按下模块的FLASH和RESET键,不过管他呢咱这次没按也照样正常工作了。
模块亮起来了!
因为咱现在接的是后买的I2C的屏幕所以这里是按照I2C的接线。
然后之后就简单了,就和配置普通的智能硬件差不多,打开手机或者带WLAN的电脑搜8266模块的AP热点名,然后连接完了之后就像配置路由器一样连接自家WIFI就可以。
如果热点扫不出来就多等会儿
会出来的
然后就简单了
这水平还用不着机翻吧
总之就是输SSID和密码的简单无聊物联网配置环节,这上面的SSID是可以实时扫描显示的
现在的智能手机会自动检测WIFI能不能联网,且在不能联网的时候会倾向于断线切换到其他网络,华为手机就会实现问你,当然是选择不切了活还没干完呢。
有的手机像以前我那个小米就喜欢不问你直接切,如果手动连回来还继续这样的话那实在不行就只能删掉原先的SSID了
如果忘了自家WIFI密码就上路由器管理页面去找,或者用手机拿二维码分享一下WIFI然后识别二维码文字信息。
输入WIFI密码之后就完成了配置
设定完了
可以看到模块显示的时间已经被设定好是UTC+8北京时间了。
NODEMCU刷上一样的固件也是一样能用的
GPIO4和5即使接反也不会烧模块,但是VCC和GND一定不要接错电压或者接反
但是如果用SPI的屏幕的话还按照I2C的方法接线就怎么都不行了
另外呢咱自己的自带屏幕的NODEMCU也不出意外的GG了,因为这个模块没记错的话屏幕的信号接口定义和驱动好像和常见的1306都不一样,是另一套来着。
但是我们可以仿照普通NODEMCU的屏幕接线法暂且先顶一下……
emmmmm 然后怎么办?当然是这么办
这个世界就是这样子的,什么事都自己干这种思想是不对的
咱去年这个时候还觉得自己一个人就能应付字幕组的所有事,不会可以自学,但是现在想想思想也不对,得学会依靠人。虽然一个人可以凭实力变强但是不学会组团也是不行的,要是什么事都能靠自己的话就不需要社会了
(这两天我还被动画教育了,过两天更漫评)
总之虽然我们会用ARDUINO更换库和重新定义屏幕的数字输出定义,但是由于项目在阿卡林大佬手里所以还是麻烦大佬代劳了……还有ARDUINO真的是非常好玩的东西,当年咱实验室的大佬说自己学会用单片机驱动一个又一个模块很有成就感的时候我就能想象得到这种感觉了,因为咱自己当时用高压电源驱动一个又一个演示设备的时候也非常有成就感。代码强悍的大佬实际动手操作水平和物理素养并不是特别好,所以当时咱也有帮助大佬解决困难的时候,人与人之间的关系永远都是这样的,取长补短互相帮助嘛。咱和阿卡林大佬有着同样的爱好,也同样都是有修为和自己的字幕组的UP(至少我是前UP),互相帮助共同进步也是挺不错的事呢。
总之下期我们再好好整整进阶的HID设备(自制鼠标键盘)教程吧,届时我们会通过之前的ARDUINO LEONARDO完成我们梦寐以求的项目的起点——自制指点杆(我倒是更想知道怎么驱动IBM的原装带指点杆的键盘,如果能解决信号定义的问题的话转USB估计就不是问题了)
用Arduino和DS1302时钟模块做个简易电子钟
今天更个
ARDUINO从入门到创客带师第⑤弹 自制WIFI时钟
的简单番外,以前在实验室的时候刚入门的小白经常喜欢玩的用DS1302 DS1307+ATMEL332做外部时钟同步时间的简单教程
当然,还是基于ARDUINO
首先,关于ARDUINO咱就不用多说了吧,相信各位都懂是什么东西了,比51单片机先进,编程理念前卫,有封装好的库,小白非常容易上手搞制作之类的……
DS1302 芯片介绍
一个时钟芯片,可以设置和获取当前时间。可以自动处理月份、闰年等信息。支持双电源,可以同时使用外接电源和电池同时供电。系统会自动选用电压较高的电源供电。一般模块接一个3v的纽扣电池, 联机使用接开发板上的外接电源,当外界电源断电后,就会使用纽扣电池供电。(然而模块不应该使用开发板上的5V电源,电压太高时钟会走的过快)
引脚定义
VCC1 和VCC2 ,双供电电源。X1 和X2 接32768Hz晶振
SCLK和IO和RST共同完成通讯过程。SCLK为通讯的时钟信号。当RST为高电平时,开始通讯。
写入逻辑
写入时间需要转换很多次的电平
读取也差不多少,总之是非常麻烦了
因此,ARDUINO环境带有了
DS1302库
,可以自动的来完成这种复杂重复的操作
#include
#include
DS1302 rtc(2, 3, 4); // RST, DAT, CLK
void getdatetime()
{
Serial.println(rtc.getDateStr(FORMAT_LONG, FORMAT_LITTLEENDIAN, '/'));
Serial.print(rtc.getDOWStr());
Serial.print(" ");
Serial.println(rtc.getTimeStr());
}
void setup()
{
Serial.begin(9600);
// 设置时间后, 需要注释掉设置时间的代码,并重新烧录一次. 以免掉电重新执行setup中的时间设置函数.
rtc.halt(false);
rtc.writeProtect(false);
rtc.setDOW(SATURDAY);
rtc.setTime(17, 22, 30);
rtc.setDate(31, 12, 2016);
rtc.writeProtect(true);
}
void loop()
{
getdatetime();
delay(1000);
}
接线图
1602可以无视了,在这个项目中我们可以用串口监视器来读取时钟数据,老式1602显示屏现在哪还有人用了,上期我们都用12864显示日期时间了好吗
虽然ARDUINO也有对1602显示屏的库就是了
作为一个番外我们并不需要太长的篇幅,简单介绍一下就完事
简单编译上传成功之后我们打开串口监视器
emmmmmmm,看来这个代码定义的时钟的时间停在了2016年
简单改一下
rtc.writeProtect(false);
rtc.setDOW(TUESDAY);
rtc.setTime(21, 05, 30);
rtc.setDate(28, 1, 2020);
rtc.writeProtect(true);
PS:英语的星期月份:星期一 Monday 缩写:Mon. 星期二 Tuesday 缩写:Tues. 星期三 Wednesday 缩写:Wed. 星期四 Thursday 缩写:Thur./Thurs. 星期五 Friday 缩写:Fri. 星期六 Saturday 缩写:Sat. 星期日 Sunday 缩写:Sun. (2)月份:第一栏为英语月份的缩写。一月 Jan. January 二月 Feb. February 三月 Mar. March 四月 Apr. April 五月 May. May 六月 Jun. June 七月 Jul. July 八月 Aug. August 九月 Sept. September 十月 Oct. October 十一月 Nov. November 十二月 Dec. December
总之改好之后再上传一次
这次没问题了
记得把设置时间的代码注释之后再上传一次,不然每次单片机开发板重新上电都会把时钟模块的时间设置为代码上写死的时间
那么它有什么用呢?当然有用了,现在这个1307模块就有了相对准确的时间,可以执行现在我们需要的记录时间的功能了。当我们把电脑关机,单片机开发板断电的时候,1307时钟模块的时间还是准的,而且因为内置了纽扣电池,所以它的时间虽然可能走的不精确,但是续航非常长,因此作为早期小白娱乐向项目还是有点实用意义的。
PS:上期改进后的代码(适用于D DUINO自带12864的NODEMCU模块)
/* 作者:flyAkari 会飞的阿卡林 b站 UID:751219
* 本代码适用于ESP8266 NodeMCU + 12864显示屏
* 7pin SPI引脚,正面看,从左到右依次为GND、VCC、D0、D1、RES、DC、CS
* ESP8266 --- OLED
* 3V --- VCC
* G --- GND
* D7 --- D1
* D5 --- D0
* D2orD8--- CS
* D1 --- DC
* RST --- RES
* 4pin IIC引脚,正面看,从左到右依次为GND、VCC、SCL、SDA
* ESP8266 --- OLED
* 3.3V --- VCC
* G (GND) --- GND
* D1(GPIO5)--- SCL
* D2(GPIO4)--- SDA
*/
#include
#include
#include
#include
#include
#include
//U8G2_SSD1306_128X64_NONAME_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/4, /* dc=*/5, /* reset=*/3);
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* clock=*/ 4, /* data=*/ 5);
DYWiFiConfig wificonfig;
ESP8266WebServer webserver(80);
#define DEF_WIFI_SSID "D1"
#define DEF_WIWI_PASSWORD "01234567890"
#define AP_NAME "flyAkari" //dev
void wificb(int c)
{
Serial.print("=-=-=-=-");
Serial.println(c);
}
static const char ntpServerName[] = "ntp1.aliyun.com"; //NTP服务器,阿里云
const int timeZone = 8; //时区,北京时间为+8
WiFiUDP Udp;
unsigned int localPort = 8888; // 用于侦听UDP数据包的本地端口
time_t getNtpTime();
void sendNTPpacket(IPAddress& address);
void oledClockDisplay();
void sendCommand(int command, int value);
void initdisplay();
boolean isNTPConnected = false;
const unsigned char xing[] U8X8_PROGMEM = {
0x00, 0x00, 0xF8, 0x0F, 0x08, 0x08, 0xF8, 0x0F, 0x08, 0x08, 0xF8, 0x0F, 0x80, 0x00, 0x88, 0x00,
0xF8, 0x1F, 0x84, 0x00, 0x82, 0x00, 0xF8, 0x0F, 0x80, 0x00, 0x80, 0x00, 0xFE, 0x3F, 0x00, 0x00
}; /*星*/
const unsigned char liu[] U8X8_PROGMEM = {
0x40, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00,
0x20, 0x02, 0x20, 0x04, 0x10, 0x08, 0x10, 0x10, 0x08, 0x10, 0x04, 0x20, 0x02, 0x20, 0x00, 0x00
}; /*六*/
void setup()
{
Serial.begin(115200);
while (!Serial)
continue;
Serial.println("NTP Clock oled version v1.1");
Serial.println("Designed by flyAkari");
initdisplay();
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_unifont_t_chinese2);
u8g2.setCursor(0, 14);
u8g2.print("Waiting for WiFi");
u8g2.setCursor(0, 30);
u8g2.print("connection...");
u8g2.setCursor(0, 47);
u8g2.print("flyAkari");
u8g2.setCursor(0, 64);
u8g2.print("192.168.4.1");
u8g2.sendBuffer();
Serial.println("OLED Ready");
Serial.print("Connecting WiFi...");
wificonfig.begin(&webserver, "/");
DYWIFICONFIG_STRUCT defaultConfig = wificonfig.createConfig();
strcpy(defaultConfig.SSID, DEF_WIFI_SSID);
strcpy(defaultConfig.SSID_PASSWORD, DEF_WIWI_PASSWORD);
strcpy(defaultConfig.HOSTNAME, AP_NAME);
strcpy(defaultConfig.APNAME, AP_NAME);
wificonfig.setDefaultConfig(defaultConfig);
wificonfig.enableAP();
while (WiFi.status() != WL_CONNECTED)
{
wificonfig.handle();
//Serial.println("Waiting for Connection...");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
Serial.println("Starting UDP");
Udp.begin(localPort);
Serial.print("Local port: ");
Serial.println(Udp.localPort());
Serial.println("waiting for sync");
setSyncProvider(getNtpTime);
setSyncInterval(30); //每300秒同步一次时间
isNTPConnected = true;
}
time_t prevDisplay = 0; //当时钟已经显示
void loop()
{
if (timeStatus() != timeNotSet)
{
if (now() != prevDisplay)
{ //时间改变时更新显示
prevDisplay = now();
oledClockDisplay();
}
}
wificonfig.handle();
}
void initdisplay()
{
u8g2.begin();
u8g2.enableUTF8Print();
}
void oledClockDisplay()
{
int years, months, days, hours, minutes, seconds, weekdays;
years = year();
months = month();
days = day();
hours = hour();
minutes = minute();
seconds = second();
weekdays = weekday();
Serial.printf("%d/%d/%d %d:%d:%d Weekday:%d\n", years, months, days, hours, minutes, seconds, weekdays);
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_unifont_t_chinese2);
u8g2.setCursor(0, 14);
if (isNTPConnected)
u8g2.print("当前时间 (UTC+8)");
else
u8g2.print("无网络!"); //如果上次对时失败,则会显示无网络
String currentTime = "";
if (hours < 10)
currentTime += 0;
currentTime += hours;
currentTime += ":";
if (minutes < 10)
currentTime += 0;
currentTime += minutes;
currentTime += ":";
if (seconds < 10)
currentTime += 0;
currentTime += seconds;
String currentDay = "";
currentDay += years;