microPython + esp8266 +tm1650= 网络时钟
[复制链接]
本帖最后由 是最帅的啊 于 2021-11-6 13:32 编辑
大家好呀好久没有露面啦,问其原因肯定不是打游戏和陪女朋友啦。
这次我给大家带来的是网络时钟,原理是这样的8266联网之后可以获取网络时间,ws2812可以测量环境温度,光敏电阻可以获取当前的光照强度,把他们组合在一起就可以做一个网络时钟啦。
先不说了上视频
原理其实很简单,多一点的是PCB布局和外壳制作,我想要的是一面全部都是数码管,因为数码管面积的限制和需要和外壳连接所以布局可用面积很小了。
下面是我的原理图和PCB,需要的话也可以查看附件进行下载。
具体的实物效果图就如下所示
在正面有4个并排的数码管,我把第三个倒置过来了,用来模仿时间中的 : 符号,所以我对tm1650的原版进行了一定的修改。后面在代码段我会具体和大家讲解的。
在这一面中我画了4个定位孔,目的是让板子和外壳能连接起来,便于固定。孔径是M3的,支撑的螺柱是12mm的,板与板之间相互固定的螺丝是m2的,相关的资料请查看附件。
这是部分图纸
接下来是代码部分:下面是改的tm1650代码
'''
此函数只适用于李先生所画的错版TM1650,ET V1.0版本的灯,请勿对号入座
'''
from machine import I2C
from micropython import const
COMMAND_I2C_ADDRESS = const(0x24)
DISPLAY_I2C_ADDRESS = const(0x34)
buf = (0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71)
buf2 = (0x3f,0x30,0x5b,0x79,0x74,0x6d,0x6f,0x38,0x7f,0x7d)
class TM1650():
def __init__(self,i2c):
self.i2c = i2c
self._intensity = 3
self.dbuf = [0, 0, 0, 0]
self.tbuf = bytearray(1)
self.on()
#调节亮度,亮度范围为0-8,
def intensity(self, dat = -1):
if dat < 0 or dat > 8:
return self._intensity
if dat == 0:
self.off()
else:
self._intensity = dat
self.cmd((dat<<4)|0x01)
#此行为写命令函数,地址位为0x24
def cmd(self, c):
self.tbuf[0] = c
self.i2c.writeto(COMMAND_I2C_ADDRESS, self.tbuf)
#此行打开数码管
def on(self):
self.cmd((self._intensity<<4)|0x01)
#关闭数码管
def off(self):
self._intensity = 0
self.cmd(0)
#此行为写数据函数,地址位为0x34
def dat(self, d, bit):
self.tbuf[0] = d
self.i2c.writeto(DISPLAY_I2C_ADDRESS + bit%4, self.tbuf)
#清除数码管的值
def clear(self):
self.dat(0, 0)
self.dat(1, 0)
self.dat(2, 0)
self.dat(3, 0)
self.dbuf = [0, 0, 0, 0]
#显示单个字的函数
def showbit(self, num, bit = 0):
if bit == 1:
self.dbuf[1] = buf2[num]
self.dat(buf2[num%10],bit)
else:
self.dbuf[bit] = buf[num%16]
self.dat(buf[num%16],bit)
#显示数字的函数
def shownum(self,num):
if num < 0 :
self.dat(0x40,3)
num = -num
else :
self.showbit(num//1000,3)
self.showbit((num//100)%10,2)
self.showbit((num//10)%10,1)
self.showbit(num%10,0)
#打开点
def showdp(self,show = True,bit=1):
if show:
self.dat(self.dbuf[bit] | 0x80,bit)
else:
self.dat(self.dbuf[bit] & 0x7F,bit)
#显示时间的函数
def rtc_time(self,hour=0,minute=0):
self.dat(buf[hour//10],3)
self.dat(buf[hour%10]|0x80,2)
self.dat(buf2[minute//10]|0x80,1)
self.dat(buf[minute%10],0)
#显示温度的函数
def temperature(self,num=10.1):
if num >= 10 :
num = num * 10
self.dat(buf[int(num/100)],3)
self.dat(buf[int(num/10%10)]|0x80,2)
self.dat(buf2[int(num%10)],1)
self.dat(buf[12],0)
if 0 <= num < 10 :
num = num * 100
self.dat(buf[int(num/100)]|0x80,3)
self.dat(buf[int(num/10%10)],2)
self.dat(buf2[int(num%10)],1)
self.dat(buf[12],0)
if -10 < num < 0 :
num = - num * 10
self.dat(0x40,3)
self.dat(buf[int(num/10)]|0x80,2)
self.dat(buf2[int(num%10)],1)
self.dat(buf[12],0)
if num < -10 :
num = - num
self.dat(0x40,3)
self.dat(buf[int(num/10)],2)
self.dat(buf2[int(num%10)],1)
self.dat(buf[12],0)
接下来就是主程序了,在这里我选择使用的是网络时钟,但是经常刷新时间会报系统错误,暂时我也不知道是啥原因,所以我在这里恳请大家能给我解惑,谢谢啦。
from machine import I2C,Pin,RTC
import time,ntptime1
import tm1650
i2c = I2C(scl=Pin(4),sda=Pin(5),freq=100000)
tm = tm1650.TM1650(i2c)
#联网
def do_connect():
import network
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
if not wlan.isconnected():
print('没有连上网络')
wlan.connect('你家的WiFi账号','你家的WiFi密码')
while not wlan.isconnected():
tm.dat(0x40,3)
tm.dat(0x40,2)
tm.dat(0x40,1)
tm.dat(0x40,0)
#时间顺序排序
def wtime(h=0,m=0):
tm.showbit(h//10,3)
tm.showbit(h%10,2)
tm.showbit(m//10,1)
tm.showbit(m%10,0)
tm.showdp(1,1)
tm.showdp(1,2)
def main():
i = 0
do_connect()
rtc=RTC()
ntptime1.settime() # set the rtc datetime from the remote server
while 1:
if i > 5*60 : #每隔5分钟获取一次网络时间
i = 0
ntptime1.settime()
etime=rtc.datetime()
tm.rtc_time(etime[4]+8,etime[5])
time.sleep(1)
i = i + 1
main()
最开始的时候,我以为是这个授时的服务器被我经常访问崩掉了,所以我把ntptime.py里面的网址改成国内的阿里云
try:
import usocket as socket
except:
import socket
try:
import ustruct as struct
except:
import struct
# (date(2000, 1, 1) - date(1900, 1, 1)).days * 24*60*60
NTP_DELTA = 3155673600
# The NTP host can be configured at runtime by doing: ntptime.host = 'myhost.org'
host = "ntp1.aliyun.com" #修改为国内的阿里云
def time():
NTP_QUERY = bytearray(48)
NTP_QUERY[0] = 0x1B
addr = socket.getaddrinfo(host, 123)[0][-1]
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
s.settimeout(1)
res = s.sendto(NTP_QUERY, addr)
msg = s.recv(48)
finally:
s.close()
val = struct.unpack("!I", msg[40:44])[0]
return val - NTP_DELTA
# There's currently no timezone support in MicroPython, so
# utime.localtime() will return UTC time (as if it was .gmtime())
def settime():
t = time()
import machine
import utime
tm = utime.localtime(t)
machine.RTC().datetime((tm[0], tm[1], tm[2], tm[6] + 1, tm[3], tm[4], tm[5], 0))
把更新的时间放缓了一点点,但是时间长了还是会有更新错误出现
对应的为ntptime1.py 中 msg = s.recv(48)这段代码,请求大家帮我看一下具体的原因,谢谢。
def time():
NTP_QUERY = bytearray(48)
NTP_QUERY[0] = 0x1B
addr = socket.getaddrinfo(host, 123)[0][-1]
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
s.settimeout(1)
res = s.sendto(NTP_QUERY, addr)
msg = s.recv(48) #错误的点
finally:
s.close()
val = struct.unpack("!I", msg[40:44])[0]
return val - NTP_DELTA
|