CORE-ESP32C3|eink|墨水屏日历+时间日期+温度显示|I2C软件模拟| LuatOS-SOC接口|官方demo|学习(14):墨水屏动态日历+oled日期显示+ AHT10测温模组

该项目基于ESP32C3开发板,实现了墨水屏日历、时间日期和温度的动态显示。主要修改包括删除watchdog、更新eink初始化流程、使用软硬件I2C接口等。使用AHT10模块进行温度采集,并通过SPI接口与1.54寸墨水屏连接。软件版本为LuatOS@ESP32C3base22.12bspV100332bit,同时涉及OLED显示屏的I2C接口操作。项目提供了详细的接线说明和示例代码。
摘要由CSDN通过智能技术生成

目录

参考博文

源于网友oled+eink+aht10项目

源代码修改及复现说明

主要修改

显示效果

​编辑硬件准备

软件版本

日志及soc下载工具

软件使用

接线说明

天气显示屏

硬件接线

温度采集

日期温度显示屏

正常初始化LOG

示例代码


参考博文:

CORE-ESP32C3|eink|墨水屏日历|天气API|LuatOS公共接口|气象要素数据V1|collectgarbage垃圾回收|LuatOS-SOC接口|官方demo|学习:墨水屏动态日历

CORE-ESP32C3|eink|日期格式化|IO11解锁|墨水屏操作库|SNTP自动同步|局部刷新|全局刷新|LuatOS-SOC接口|官方demo|学习(12):简单日期显示

合宙Air105|摄像头|capture|SPI|Serial 串口|TFTLCD|Micro SD卡|GC032A|USB转TTL|官方demo|学习(2-1):摄像头camera-capture_合宙air105的摄像头_打酱油的工程师的博客-CSDN博客

合宙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()之后后面不要加任何语句!!!!!

首先,需要使用ESP-IDF开发环境,包括ESP32C3的SDK和相关工具链。 接下来,按照以下步骤进行操作: 1. 配置WiFi连接:在ESP-IDF中,使用WiFi连接需要配置一个WiFi连接管理器。在代码中添加以下代码: ```c #include "esp_wifi.h" #include "esp_event.h" #include "esp_log.h" #define WIFI_SSID "your_wifi_ssid" #define WIFI_PASS "your_wifi_password" static void wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { if (event_id == WIFI_EVENT_STA_START) { esp_wifi_connect(); } else if (event_id == WIFI_EVENT_STA_DISCONNECTED) { esp_wifi_connect(); } } void wifi_init_sta(void) { tcpip_adapter_init(); ESP_ERROR_CHECK(esp_event_loop_create_default()); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&cfg)); ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL)); wifi_config_t wifi_config = { .sta = { .ssid = WIFI_SSID, .password = WIFI_PASS, }, }; ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); ESP_ERROR_CHECK(esp_wifi_start()); } ``` 2. 获取网络时间:在ESP32C3上获取网络时间需要使用NTP协议。在代码中添加以下代码: ```c #include "esp_sntp.h" void obtain_time(void) { ESP_LOGI(TAG, "Obtaining time from NTP server..."); sntp_setoperatingmode(SNTP_OPMODE_POLL); sntp_setservername(0, "pool.ntp.org"); sntp_init(); // wait for time to be set time_t now = 0; struct tm timeinfo = {0}; while (timeinfo.tm_year < (2021 - 1900)) { ESP_LOGI(TAG, "Waiting for system time to be set..."); vTaskDelay(1000 / portTICK_PERIOD_MS); time(&now); localtime_r(&now, &timeinfo); } } ``` 3. 显示时间:接下来,将获取的时间显示OLED屏幕上。在代码中添加以下代码: ```c #include "driver/i2c.h" #include "ssd1306.h" #define I2C_SDA_GPIO 21 #define I2C_SCL_GPIO 22 ssd1306_t dev; void oled_init(void) { i2c_config_t i2c_config = { .mode = I2C_MODE_MASTER, .sda_io_num = I2C_SDA_GPIO, .scl_io_num = I2C_SCL_GPIO, .sda_pullup_en = GPIO_PULLUP_ENABLE, .scl_pullup_en = GPIO_PULLUP_ENABLE, .master.clk_speed = 1000000, }; ESP_ERROR_CHECK(i2c_param_config(I2C_NUM_0, &i2c_config)); ESP_ERROR_CHECK(i2c_driver_install(I2C_NUM_0, I2C_MODE_MASTER, 0, 0, 0)); ssd1306_init(&dev, 128, 64, ssd1306_i2c_addr); ssd1306_set_whole_display_lighting(&dev, false); ssd1306_clear_screen(&dev, false); } void show_time(struct tm* timeinfo) { char strftime_buf[64]; strftime(strftime_buf, sizeof(strftime_buf), "%c", timeinfo); ssd1306_clear_screen(&dev, false); ssd1306_draw_string(&dev, 0, 0, strftime_buf, 1, true); ssd1306_refresh(&dev, true); } ``` 4. 将上述步骤集成到主函数中: ```c void app_main() { wifi_init_sta(); obtain_time(); oled_init(); struct tm timeinfo = {0}; time_t now = 0; while (1) { time(&now); localtime_r(&now, &timeinfo); show_time(&timeinfo); vTaskDelay(1000 / portTICK_PERIOD_MS); } } ``` 这样,ESP32C3就可以连接WiFi,获取网络时间,并将时间显示OLED屏幕上了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

打酱油的工程师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值