引子
前段时间用5个HPDL-1414做了一个20字符的显示模块HPDL1414x5,理论上可以作为许多应用的外设,于是决定使用基于ESP8266的NODEMCU平台驱动HPDL1414x5做一个自动网络校时的时钟。
NODEMCU
NODEMCU是一个很久远的项目了,最开始是适配ESP8266的,但是ESP8266似乎都要退市了。项目主要就是一个最小开发板和lua的固件,硬件开源在这里,固件开源在这里,和它类似的还有microPython的固件,使用的是类似于python的语法。
NODEMCU的固件是支持ESP32的,但是需要注意ESP8266和ESP32的固件、提供的函数、文档都不完全相同,ESP32的文档在这里,ESP8266的文档在这里。
我的开发板是在网上买的LiLon NodeMCU V3,和原版的MODEMCU有一些区别。
NODEMCU固件编译
NODEMCU可以选择编译不同的模块,并且由于全部模块都编译可能运行不起来,所以没有提供包含所有模块的固件,需要手动选择需要编译的模块,最简单的方法是使用云编译服务。选择需要使用的模块并填写邮箱,使用ESP8266时Select branch to build from选择release,若要使用ESP32需要选择dev-esp32-idf3-final(此版本idf较低),对于本项目至少需要使用spi、sntp、RTC time、bit模块(ESP8266)或spi、time模块(ESP32)。处理时间大约5分钟,随后会将固件下载链接发送至邮箱。
spi模块用于驱动HPDL1414x5模块,bit模块用于位运算,sntp用于网络校时,RTC time用于提供基础的时间类函数,ESP32的time模块同时包含了stnp和RTC time。
烧录固件
最简单的方法是使用NodeMCU PyFlasher来烧录固件,具体参考文档。
编写驱动(HPDL1414x5.lua
)
对于ESP8266只有一个额外SPI可用,即HSPI(ID 1),并且引脚也是固定的,对于原版NODEMCU使用的是D5、6、7、8:
需要注意spi.send()
函数的参数虽然可以发送多个数据,但是每个数据之间的cs会被拉起,也就是说每个数据有相当于是重新发送,因此配置为16位一次性发送地址和数据:
local HPDL1414x5
local function init()
spi.setup(1, spi.MASTER, spi.CPOL_HIGH, spi.CPHA_HIGH, 16, 1)
end
local function putc(address, char)
spi.send(1, bit.bor(bit.lshift(address, 8), string.byte(char, 1)), bit.bor(0xFC00, string.byte(char, 1)))
end
local function clear()
for i = 0, 19 do
putc(i, ' ')
end
end
local function puts(str)
for i = 1, math.min(#str, 20) do
putc(20 - i, string.sub(str, i, i))
end
end
HPDL1414x5 = {
init = init,
putc = putc,
clear = clear,
puts = puts
}
return HPDL1414x5
对于ESP32,拥有两个可用spi:HSPI、VSPI,并且可以自由绑定在大部分引脚上:
local HPDL1414x5
local bus = nil;
local device = nil;
local function init()
bus = spi.master(spi.HSPI, {sclk = 19, mosi = 23})
device = bus:device({cs = 22, mode = 3 ,freq = 1000000})
end
local function putc(address, char)
device:transfer(string.char(address)..char)
device:transfer(string.char(0xFC)..char)
end
local function clear()
for i = 0, 19 do
putc(i, ' ')
end
end
local function puts(str)
for i = 1, math.min(#str, 20) do
putc(20 - i, string.sub(str, i, i))
end
end
HPDL1414x5 = {
init = init,
putc = putc,
clear = clear,
puts = puts
}
return HPDL1414x5
编写主程序(init.lua
)
在固件启动后会调用init.lua
,因此将主程序写在这里:
local HPDL1414x5 = require("HPDL1414x5")
HPDL1414x5.init()
function adjust_rtc(sec, usec, server, info)
rtctime.set(sec, usec)
end
local status = false
function prtint_time()
local sec, usec = rtctime.get()
localTime = rtctime.epoch2cal(sec + 8 * 3600)
if sec <= 1704038400 then
if status then
HPDL1414x5.puts(" SYNC WITH NTP ")
else
HPDL1414x5.puts("POWERED BY HADONGZHU")
end
status = not status
else
HPDL1414x5.puts(string.format(" %02d-%02d-%02d %02d:%02d:%02d ", localTime["year"] % 100, localTime["mon"], localTime["day"], localTime["hour"], localTime["min"], localTime["sec"]))
end
print(string.format("%02d-%02d-%02d %02d:%02d:%02d", localTime["year"] % 100, localTime["mon"], localTime["day"], localTime["hour"], localTime["min"], localTime["sec"]))
print(sec)
end
wifi.setmode(wifi.STATION)
wifi.sta.config({ssid="ssid", pwd="password"})
sntp.sync(nil, adjust_rtc, nil, 1)
mytimer = tmr.create()
mytimer:register(1000, tmr.ALARM_AUTO, prtint_time)
mytimer:start()
HPDL1414x5.puts("POWERED BY HADONGZHU")
对于ESP32的使用方式略有不同:
local HPDL1414x5 = require("HPDL1414x5")
HPDL1414x5.init()
function ntpsync()
time.initntp("cn.ntp.org.cn")
end
local status = false
function prtint_time()
sec, usec = time.get()
localTime = time.getlocal()
HPDL1414x5.puts(string.format("%04d-%02d-%02d %02d:%02d:%02d", localTime["year"], localTime["mon"], localTime["day"], localTime["hour"], localTime["min"], localTime["sec"]))
print(string.format("%02d-%02d-%02d %02d:%02d:%02d", localTime["year"] % 100, localTime["mon"], localTime["day"], localTime["hour"], localTime["min"], localTime["sec"]))
print(sec)
end
time.settimezone("CST-8")
wifi.mode(wifi.STATION)
wifi.start()
wifi.sta.on("connected", ntpsync)
wifi.sta.config({ssid="ssid", pwd="password"})
wifi.sta.connect()
mytimer = tmr.create()
mytimer:register(1000, tmr.ALARM_AUTO, prtint_time)
mytimer:start()
HPDL1414x5.puts("-----HADONGZHU------")
上传脚本
使用ESPlorer将HPDL1414x5.lua
和init.lua
上传到nodemcu中,当ntp未获取到时将交错显示『POWERED BY HADONGZHU』和『SYNC WITH NTP』,获取到时间后将显示当前的时间:
其他的一点小问题
HPDL1414x5的5V接在VIN显示会很暗淡,查看了一下原理图,NODEMCU的VIN和真的输入之间还隔了一个二极管,会引起比较大的压降,不过我使用的LiLon NodeMCU V3将NODEMCU保留的引脚改为了5V直接输出(VV),接在VV上就可以了。