用ESP8266打造NTP网络授时+天气信息的OLED屏幕时钟

发布日期:分类:智能硬件 & IOT 用ESP8266打造NTP网络授时+天气信息的OLED屏幕时钟有 14 条评论
时效性提醒:本文首次编写发布于8 年前。

使用NodeMcu ESP8266开发板(其实就是带了个USB-TTL和自动重启),驱动ssd1306 I2C OLED 12864 屏幕,通过WiFi联网获取时间及天气信息及PM2.5信息

(没错这400多的PM2.5正是我大霾都-北京)

NodeMCU的lua开发,使用了两个天气的API,代码见下文

配套的NodeMCU固件下载:https://1drv.ms/u/s!AnyMcqveiSwuhzEYIHmd7TdEg12C

包含模块:cjson file gpio http i2c net node ow rtctimesntp tmr u8g uart wifi及u8g的6x10,7x14r,9x18r几个字体。

-- Clock 2 - OLED Display clock


TIMEZONE = 8
SDA_PIN = 2 -- OLED SDA Pin
SCL_PIN = 1 -- OLED SCL Pin
WEATHER_CITY = "Beijing"


DAYS = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}
WEATHER_TEXT=""
WEATHER_TEMP=""
WEATHER_PM25=""

function getTime() -- Get Time by connecting to timeapi.org
    sntp.sync('time-a.nist.gov',
        function(sec,usec,server)
            print('sync', sec, usec, server)
        end,
        function()
            print('sntp.sync() failed!')
        end
    )
end


function getWeather()
    http.get("http://api.thinkpage.cn/v3/weather/now.json?key=3puseql9n2vxuknr&location=Beijing&language=en", nil, function(code, data)
        if (code < 0) then
            print("HTTP request failed")
        else
            print(code, "weather ok")
            weather = cjson.decode(data)
            WEATHER_TEXT = weather["results"][1]["now"]["text"]
            WEATHER_TEMP = weather["results"][1]["now"]["temperature"]
        end

        -- Then get PM2.5 data
        node.task.post(function()
            http.get("http://api.jirengu.com/weather.php", nil, function(code, data)
                if (code < 0) then
                    print("HTTP request failed")
                else
                    print(code, "PM2.5 ok")
                    weather = cjson.decode(data)
                    WEATHER_PM25 = weather["results"][1]["pm25"]
                end
            end)
        end)

    end)
end

    
function init_OLED(SDA_PIN, SCL_PIN) --Set up the u8glib lib
    sla = 0x3C
    i2c.setup(0, SDA_PIN, SCL_PIN, i2c.SLOW)
    disp = u8g.ssd1306_128x64_i2c(sla)
    -- disp:setFontRefHeightExtendedText()
    disp:setFont(u8g.font_6x10)
    disp:setFontPosTop()
    -- disp:setRot180() -- Rotate Display if needed
end

function update_OLED() -- Write Display
    disp:firstPage()
    repeat
        disp:setColorIndex(1);
        disp:drawBox(0, 0, 128, 64)
        disp:setColorIndex(0);
        disp:setFont(u8g.font_7x14r)
        disp:drawStr(5, 13, "NTP Clock v2")

        unixTime = rtctime.get()
        tm = rtctime.epoch2cal(unixTime + TIMEZONE*3600)
        -- print(string.format("%04d/%02d/%02d %02d:%02d:%02d", tm["year"], tm["mon"], tm["day"], tm["hour"], tm["min"], tm["sec"]))
        disp:setFont(u8g.font_9x18r)
        disp:drawStr(30, 35, string.format("%02d:%02d:%02d", tm["hour"], tm["min"], tm["sec"]))
        disp:setFont(u8g.font_6x10)
        disp:drawStr(40, 45, DAYS[tm["wday"]])
        disp:drawStr(60, 45, string.format("%02d-%02d", tm["mon"], tm["day"]))

        -- disp:drawStr(10, 55, WEATHER_CITY.." "..WEATHER_TEXT.." "..WEATHER_TEMP.."'C")
        disp:drawStr(16, 55,WEATHER_TEXT.." "..WEATHER_TEMP.."'C PM"..WEATHER_PM25)


        -- disp:drawStr(3, 63, "@Wu23333")
    until disp:nextPage() == false

    if(unixTime+30 % 3600 == 0)then
        getTime()
        getWeather()
    end
end



-- Main Program 
init_OLED(SDA_PIN,SCL_PIN)

getTime()
getWeather()
tmr.alarm(0, 1000, 1, function()
    update_OLED()
end)

上面是主程序,传进去后执行它,就可以看到效果了。

下面是一个用于调试用的init.lua脚本的内容,具有重新设置wifi信息,和延迟启动的功能(主程序需要命名为application.lua)

-- wifi config
STATION_ENABLED = true
SSID = "YourWiFiSSID"
PASSWORD = "YourWiFiPassword"

AP_ENABLED = true
AP_SSID = "NodeMCU"
AP_PASSWORD = "Password"


function startup()
 if file.open("stop.lua") ~= nil then
 print("stop.lua deleted, abort")
 else
 print("Running")
 file.close("init.lua")
 -- the actual application is stored in 'application.lua'
 dofile("application.lua")
 end
end

-- the script start here
node.setcpufreq(node.CPU160MHZ)

if(STATION_ENABLED and AP_ENABLED)then
 wifi.setmode(wifi.STATIONAP)
 wifi.ap.config({ssid=AP_SSID, pwd=AT_PASSWORD})
 print("SOFTAP is configured")
 wifi.sta.config(SSID, PASSWORD)
else
 if(STATION_ENABLED)then
 wifi.setmode(wifi.STATION)
 wifi.sta.config(SSID, PASSWORD)
 end
 if(AP_ENABLED)then
 wifi.setmode(wifi.SOFTAP)
 wifi.ap.config({ssid=AP_SSID, pwd=AT_PASSWORD})
 print("SOFTAP is configured")
 end
end

if(STATION_ENABLED)then
 print("Connecting to WiFi access point...")
 tmr.alarm(1, 1000, 1, function()
 if wifi.sta.getip() == nil then
 print("Waiting for IP address...")
 else
 tmr.stop(1)
 print("WiFi connection established, IP address: " .. wifi.sta.getip())
 print("Create a file named 'stop.lua' in 5 seconds to abort the start")
 print("Waiting...")
 tmr.alarm(0, 5000, 0, startup)
 end
 end)
else
 print("DEBUG: Create a file named 'stop.lua' in 5 seconds to abort the start")
 print("Waiting...")
 tmr.alarm(0, 5000, 0, startup)
end

作者:WuSiYu

学生,Web开发者,智能硬件&IOT爱好者

14条评论

  1. 很欣赏你的作品,我是一个退休人员,不会单片机。能不能提供完整的程序。让我也实践一下。希望得到你的支持,谢谢!

    1. 上面这段就是完整的程序。
      首先需要给ESP8266刷入NodeMCU固件,然后用ESPlorer这个IDE通过串口连接ESP8266,然后把上面这段代码存成lua并传输到ESP8266里,然后执行它就可以了。如果每次想让ESP8266一上电就执行的话可以把文件命名为init.lua

      1. 用工具ESP8266Flasher-x86-v0.9.2.4刷了v0.9.2.3 AT Firmware固件,用LuaStudio编译了init.lua,用LuaLoader工具刷init.lua到esp8266溢出全是乱码。1306上什么也没有。问二个问题:1.要专用固件?2.怎么连自家的WIFI?

        1. wifi.setmode(wifi.STATION)
          wifi.sta.config(SSID, PASSWORD)
          或者也可以使用我新放上去的init.lua,如果调试的话可以配合这个脚本,以便可以阻止问题的程序自动启动。

  2. 你使用了SNTP,RTCTIME,I2C,U8G等非官方固件包含的模块,干脆把你的定制NodeMCU固件也共享一下吧,省得金声叔再去折腾那个英文网站。

  3. 退休在家,想给自己增加的知识,因为从小爱好,巧遇文革,学识有限,只能求教于能人,望给予支持为盼!再次谢谢!

  4. 退休在家,想给自己增加点知识,原因是因为从小爱好,后又巧遇文革,所以,学识有限,只能求教于能人,望先生能给予支持为盼!再次谢谢!

    1. 近些天有些忙,没有看到回复,十分抱歉
      我先把ESPlorer发给您吧,NodeMCU固件的话我得找找,找不到的话我再重新编译一个。
      另外AT固件的话只能通过串口接受AT指令,需要配合其他控制器才能使用,所以这里没有使用AT固件

发表评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注