目录
参考博文:
CORE-ESP32C3|eink|墨水屏日历|天气API|LuatOS公共接口|气象要素数据V1|collectgarbage垃圾回收|LuatOS-SOC接口|官方demo|学习:墨水屏动态日历
CORE-ESP32C3|eink|日期格式化|IO11解锁|墨水屏操作库|SNTP自动同步|局部刷新|全局刷新|LuatOS-SOC接口|官方demo|学习(12):简单日期显示
合宙ESP32系列|自定义固件|在线云编译|本地编译|Windows|luat_conf_bsp.h|(2)、CORE-ESP32S3编译_打酱油的工程师的博客-CSDN博客
Lua基础|CORE-ESP32C3|eink|日期格式化|os.date|weekarray|tonumber|SOC固件编译|汉字星期|墨水屏:今天星期几?
源于网友oled+eink+aht10项目:
项目地址:墨水屏天气
源代码修改及复现说明:
该网友的GIT项目实现代码为蓝本,实现墨水屏日历+时间日期+温度动态显示功能。
墨水屏日历的初始功能实现及说明详见:
CORE-ESP32C3|eink|墨水屏日历|天气API|LuatOS公共接口|气象要素数据V1|collectgarbage垃圾回收|LuatOS-SOC接口|官方demo|学习:墨水屏动态日历
基于当前的适配的LuatOS@ESP32C3 base 22.12 bsp V1003 32bit (IDF5)版本,对原主程序中相关代码进行了修正和更新,以实现目标功能。
主要修改:
1、删除硬狗(IDF5暂未适配);
2、eink初始化流程;
3、2个I2C设备分别采用软、硬件I2C接口;
4、http.request接口调整,
5、http连接后自动更新ntp,删除手动更新代码;
6、程序中用到的字符有:
font_opposansm8
font_opposansm8_chinese
font_opposansm12_chinese
底包编译时注意取消相关字体编译注释。
显示效果:
硬件准备
ESP32C3-CORE开发板(经典款)1块,面包板1块,EINK1.54墨水屏,0.91寸oled(SSD1306),AHT10测温模组。
ESP32C3-CORE开发板pinout
EINK1.54墨水屏
0.91寸OLED(SSD1306)
AHT10温湿度模块
软件版本
CORE-ESP32C3:LuatOS@ESP32C3 base 22.12 bsp V1003 32bit
日志及soc下载工具
luatools 版本:2.1.88
Luatools软件安装目录下存放有各型号的SOC,也可用于刷机。
软件使用
接口文档可参考: eink - 墨水屏操作库
接线说明
天气显示屏
为合宙 1.54寸v2,200x200,快刷屏,SPI标准屏
硬件接线:
显示屏SPI --> CORE-ESP32
GND GND
VCC 3.3V
SCL (IO02)
SDA (IO03)
RES (IO10)
DC (IO06)
CS (IO07)
BUSY (IO11)-IO11默认配置为SPI-FLASH的VDD,需解锁配置为GPIO使用。如不考虑解锁,可选择右侧IO,但后期存在复用冲突风险。
温度采集
使用AHT10模组,I2C接口,
使用板载硬件I2C.FAST端口,
硬件接线:
AHT10(I2C) --> CORE-ESP32
GND GND
VCC 3.3V
SCL (IO05)
SDA (IO04)
日期温度显示屏
为0.91寸OLED屏,SSD1306芯片,I2C接口屏,
硬件接线:
OLED显示屏(I2C) --> CORE-ESP32
GND GND
VCC 3.3V
SCL (IO00)
SDA (IO01)
Esp2 c3开发板引出一组硬件I2C接口(接入测温模组),故另一组I2C屏幕使用软件模拟I2C。
正常初始化LOG:
示例代码:
PROJECT = "wifidemo"
VERSION = "1.0.0"
--测试支持硬件:ESP32C3
--测试固件版本:LuatOS-SoC_V0003_ESP32C3[_USB].soc
local sys = require "sys"
require("sysplus")
--定义是否使用I2C 的ATH10好 OLED,默认零打开,其余任何字符都是关闭,这里只要Oled_on 不为0 ,就关闭了后面的所有OLED的显示
local on = 0
local off = 1
local ath10_on = on --加上ATH10 运存可能会不够,不需要就自己关了
local oled_on = on --I2C OLED屏幕,买的是ssd1306,不需要就自己关了
local eink_weather = on --水墨屏部分,不需要就自己关了,这里是按照合宙提供的方法解锁了IO11,没解锁的可以把水墨屏对应的针脚飞线插到别的地方,并且修改对应初始化代码即可
-- 兼容V1001固件的
if http == nil and http2 then
http = http2
end
local rtos_bsp = rtos.bsp()
-- spi_id,pin_reset,pin_dc,pin_cs,pin_busy,mode
function eink_pin()
if rtos_bsp == "AIR101" then
return 0,pin.PB03,pin.PB01,pin.PB04,pin.PB00
elseif rtos_bsp == "AIR103" then
return 0,pin.PB03,pin.PB01,pin.PB04,pin.PB00
elseif rtos_bsp == "AIR105" then
return 5,pin.PC12,pin.PE08,pin.PC14,pin.PE09
elseif rtos_bsp == "ESP32C3" then
--(spi_id, pin_busy, pin_reset, pin_dc, pin_cs)
return 2,11,10,6,7
elseif rtos_bsp == "ESP32S3" then
return 2,16,15,14,13
elseif rtos_bsp == "EC618" then
return 0,1,10,8,18
else
log.info("main", "bsp not support")
return
end
end
--需要自行填写的东西
--wifi信息
local wifiName,wifiPassword = "MERCURY_*****", "*******你的wifi密码****"
--地区id,请前往https://api.luatos.org/luatos-calendar/v1/check-city/ 查询自己所在位置的id
local location = "101000000"
--天气接口信息,需要自己申请,具体参数请参考https://api.luatos.org/ 页面上的描述
--采用天气API:https://tianqiapi.com/
local appid,appsecret = "2754****","3wdK*****"
local function connectWifi()
log.info("wlan", "wlan_init:", wlan.init())
wlan.setMode(wlan.STATION)
wlan.connect(wifiName,wifiPassword,1)
-- 等待连上路由,此时还没获取到ip
result, _ = sys.waitUntil("WLAN_STA_CONNECTED")
log.info("wlan", "WLAN_STA_CONNECTED", result)
-- 等到成功获取ip就代表连上局域网了
result, data = sys.waitUntil("IP_READY")
log.info("wlan", "IP_READY", result, data)
end
local function requestHttp()
local code, headers, body = http.request("GET","http://apicn.luatos.org:23328/luatos-calendar/v1?mac=111&battery=10&location="..location.."&appid="..appid.."&appsecret="..appsecret).wait()
if code == 200 then
return body
else
log.info("http get failed",code, headers, body)
sys.wait(500)
return ""
end
end
function refresh()
log.info("refresh","start!")
local data
for i=1,5 do--重试最多五次
collectgarbage("collect")
data = requestHttp()
collectgarbage("collect")
if #data > 100 then
break
end
log.info("load fail","retry!")
end
if #data < 100 then
log.info("load fail","exit!")
return
end
collectgarbage("collect")
local spi_id, pin_busy, pin_reset, pin_dc, pin_cs = eink_pin()
local mode =0
if spi_id then
eink.model(eink.MODEL_1in54)
spi.setup(spi_id,nil,0,0,8,20*1000*1000)
eink.setup(mode, spi_id,pin_busy,pin_reset,pin_dc,pin_cs)
eink.setWin(200, 200,2)
--稍微等一会,免得墨水屏没初始化完成
sys.wait(100)
eink.clear(1)
log.info("eink", "end setup")
eink.drawXbm(0, 0, 200, 200, data)
-- 刷屏幕
eink.show()
eink.sleep()
log.info("refresh","done")
end
end
--这里用于后面I2C读值四舍五入,例如
--num1=(aht10_data.RH*100) --基于小米蓝牙温湿度计比对调的湿度原始数据+/-差异值或者直接修改传感器读取代码,确保串口和屏幕信息一致
--num2=(aht10_data.T) --基于小米蓝牙温湿度计比对调的温度原始数据+/-差异值或者直接修改传感器读取代码,确保串口和屏幕信息一致
--hum=keepDecimalTest(num1, 2)
--temp=keepDecimalTest(num2, 2)
local function keepDecimalTest(num, n)
if type(num) ~= "number" then
return num
end
-- n = n or 2
return string.format("%." .. n .. "f", num)
end
if oled_on == 0 then
local TAG = "main"
-- 初始化显示屏
log.info(TAG, "init ssd1306")
-- 初始化硬件i2c的ssd1306
--u8g2.begin({ic = "ssd1306",direction = 0,mode="i2c_hw",i2c_id=0,i2c_speed = i2c.FAST}) -- direction 可选0 90 180 270
--初始化软件i2c的ssd1306
u8g2.begin({ic = "ssd1306",direction =180,mode="i2c_sw", i2c_scl=0, i2c_sda=1}) -- 通过PA1 SCL / PA4 SDA模拟
u8g2.SetFontMode(1)
u8g2.ClearBuffer()
u8g2.SetFont(u8g2.font_opposansm8)
u8g2.DrawUTF8("U8g2+LuatOS", 32, 10)
u8g2.SetFont(u8g2.font_opposansm12_chinese)
u8g2.DrawUTF8("中文测试", 40, 38)
-- u8g2.SetFont(u8g2.font_opposansm8_chinese)
-- u8g2.DrawUTF8("有内鬼终止止交易", 5, 32)
u8g2.SendBuffer()
end
--local aht10 = require "aht10"
if ath10_on == 0 then
aht10 = require "aht10"
i2cid = 0
i2c_speed = i2c.FAST
end
sys.taskInit(function()
--手动设置rtc
rtc.set({year=2023,mon=2,day=7,hour=21,min=15,sec=43})
--先连wifi
connectWifi()
if eink_weather == 0 then
refresh()
end
local str_month1
local str_day
local str_month
local str_year
local str_time
local str_datetime2
local str_date
local str_week
local str_week1 = ""
local str_week2
local str_voidhour
local str_min
local num3 = 2
if ath10_on == 0 then
i2c.setup(i2cid,i2c_speed)
aht10.init(i2cid)
end -- sys.wait(2000)
while 1 do
sys.wait(50)
local str_datetime = os.date()
str_week = string.sub(str_datetime,1,3)
str_month = string.sub(str_datetime,5,7)
str_day = string.sub(str_datetime,9,10)
if str_week == "Sun" then
str_week1 = "天"
str_week2 = 7
elseif str_week == "Mon" then
str_week1 = "一"
str_week2 = 1
elseif str_week == "Tue" then
str_week1 = "二"
str_week2 = 2
elseif str_week == "Wed" then
str_week1 = "三"
str_week2 = 3
elseif str_week == "Thu" then
str_week1 = "四"
str_week2 = 4
elseif str_week == "Fri" then
str_week1 = "五"
str_week2 = 5
elseif str_week == "Sat" then
str_week1 = "六"
str_week2 = 6
end
if(str_month=="Jan") then
str_month1 = "01"
elseif str_month == "Feb" then
str_month1 = "02"
elseif str_month == "Mar" then
str_month1 = "03"
elseif str_month == "Apr" then
str_month1 = "04"
elseif str_month == "May" then
str_month1 = "05"
elseif str_month == "Jun" then
str_month1 = "06"
elseif str_month == "Jul" then
str_month1 = "07"
elseif str_month == "Aug" then
str_month1 = "08"
elseif str_month == "Aep" then
str_month1 = "09"
elseif str_month == "Oct" then
str_month1 = "10"
elseif str_month == "Nov" then
str_month1 = "11"
elseif str_month == "Dec" then
str_month1 = "12"
end
str_year = string.sub(str_datetime,21,24)
str_time = string.sub(str_datetime,12,20)
-- log.info("输出:"..str_time)
str_voidhour = string.sub(str_datetime,15,19) --这里是截取时间数据里面的分和秒
str_min = string.sub(str_datetime,18,19) --截取秒
if ath10_on == 0 then
local aht10_data = aht10.get_data()
num1=(aht10_data.RH*100) --基于小米蓝牙温湿度计比对调的湿度原始数据+/-差异值或者直接修改传感器读取代码,确保串口和屏幕信息一致
num2=(aht10_data.T) --基于小米蓝牙温湿度计比对调的温度原始数据+/-差异值或者直接修改传感器读取代码,确保串口和屏幕信息一致
hum=keepDecimalTest(num1, 2)
temp=keepDecimalTest(num2, 2)
--u8g2.ClearBuffer() -- 清屏
--u8g2.SetFont(u8g2.font_opposansm12_chinese)
-- u8g2.SendBuffer()
end
-- 定义OLED刷新
if oled_on == 0 then
u8g2.ClearBuffer()
if ath10_on == 0 then
u8g2.SetFont(u8g2.font_opposansm8_chinese)
u8g2.DrawUTF8("温:"..temp.."C'", 0, 60)
u8g2.DrawUTF8("湿:"..hum.."%", 65,60)
else
u8g2.SetFont(u8g2.font_opposansm8)
u8g2.DrawUTF8("U8g2+LuatOS", 30, 60)
end
sys.wait(50)
-- u8g2.SetFont(u8g2.font_opposansm8_chinese)
u8g2.DrawUTF8(str_year.."-"..str_month1.."-"..str_day,50, 10)
u8g2.DrawUTF8("星期"..str_week1,5, 10)
-- sys.wait(50)
u8g2.SetFont(u8g2.font_opposansm12_chinese)
u8g2.DrawUTF8(str_time,30, 40)
u8g2.SendBuffer()
end
--u8g2.SetFont(u8g2.font_opposansm12_chinese)
--u8g2.DrawUTF8("中文测试", 40, 38)
-- u8g2.SendBuffer()
-- 定义 水墨屏刷新的时间节点
if eink_weather == 0 then
-- if str_min == "59" then --可以每分钟刷新一次
if str_voidhour == "00:00" or str_voidhour == "30:00" then --每整点或者30分刷新一次
log.info("1小时准点刷新水墨屏天气")
log.info(str_year.." "..str_month1.." "..str_day..str_time..str_week1)
-- 后面的代码是为了限制水墨屏在一秒内刷新次数太多,造成RAM拥堵
num3 = num3 + 1
print("num3 = "..num3)
bbb = num3%3
if bbb == 0 then
num3 = 1
if oled_on == 0 then
u8g2.ClearBuffer()
u8g2.SetFont(u8g2.font_opposansm8_chinese)
u8g2.DrawUTF8(str_year.."-"..str_month1.."-"..str_day,50, 10)
sys.wait(50)
u8g2.DrawUTF8("天气更新中....",35, 40)
u8g2.DrawUTF8("星期"..str_week1,5, 10)
u8g2.SendBuffer()
end
collectgarbage("collect")
refresh()
end
end
end
-- lvgl.label_set_text(label_time,"#00CED1 "..str_year.."-"..str_month1.."-"..str_day.." ##00ff00 " ..str_time.."##90EE90 星期"..str_week1.."#")
sys.wait(50)
end
end)
-- 用户代码已结束---------------------------------------------
-- 结尾总是这一句
sys.run()
-- sys.run()之后后面不要加任何语句!!!!!