From fd6781c683e50ec40f940a27091e6f607676e750 Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Sat, 26 Aug 2017 02:30:51 -0400 Subject: [PATCH] Add support for WS2812 status indicator LED --- README.rst | 20 +++++++++++++++++++- init3.lua | 12 ++++++++++++ led.lua | 45 +++++++++++++++++++++++++++++++++++++++++++++ thermostat.lua | 17 +++++++++++------ 4 files changed, 87 insertions(+), 7 deletions(-) create mode 100644 led.lua diff --git a/README.rst b/README.rst index c134a33..113b3da 100644 --- a/README.rst +++ b/README.rst @@ -114,7 +114,25 @@ lines are used as follows: -------------- We have a DS1820 temperature probe attached to the 1Wire bus. This device -calls itself 1013878a02080098 in my case. +calls itself ``1013878a02080098``, in my case. + +WS2812 Peripherals +------------------ + +We have one LED attached (of course, could string more on) through a level +shifter (sigh). We assign the following colors meaning: + ++-----------+------------------------------------------------+ +| Red | Heating | ++-----------+------------------------------------------------+ +| Blue | Cooling | ++-----------+------------------------------------------------+ +| Orange | Fan lingering | ++-----------+------------------------------------------------+ +| Green | System idle | ++-----------+------------------------------------------------+ +| Purple | Fan forced on, nothing else running | ++-----------+------------------------------------------------+ Internals ========= diff --git a/init3.lua b/init3.lua index 40f00c7..3a8329f 100644 --- a/init3.lua +++ b/init3.lua @@ -18,6 +18,15 @@ if rtcfifo.ready() == 0 then rtcfifo.prepare() end ow.setup(owpin) i2c.setup(0,2,3,i2c.SLOW) +-- setup LED +blinkT = tmr.create() +ws2812.init() + +wsfb = ws2812.newBuffer(1,3) +wsfb:fill(0,0,0) +function led(...) dofile("led.lc")(blinkT,wsfb,...) end +led(1) + -- hook registry, MQTT connection management local mqtt_reconn_timer local function mqtt_reconn(_t) @@ -35,6 +44,7 @@ nwfnet.onnet["init"] = function(e,c) if e == "mqttdscn" and c == mqc then if mqtt_beat_cron then mqtt_beat_cron:unschedule(); mqtt_beat_cron = nil end if not mqtt_reconn_timer then mqtt_conn() end + led(4) elseif e == "mqttconn" and c == mqc then if mqtt_reconn_timer then mqtt_reconn_timer:unregister() @@ -46,8 +56,10 @@ nwfnet.onnet["init"] = function(e,c) mqc:subscribe(mqttTargTopic,1) mqc:subscribe(mqttModeTopic,1) mqc:subscribe(mqttFanTopic ,1) + led(0) elseif e == "wstagoip" then if not mqtt_reconn_timer then mqtt_conn() end + led(4) end end diff --git a/led.lua b/led.lua new file mode 100644 index 0000000..1f5160f --- /dev/null +++ b/led.lua @@ -0,0 +1,45 @@ +-- This file generates a function which manages the WS2812 LED we have +-- attached to us. It mutates a global function named "setLed" which +-- can be used as if it were a ws2812 buffer's :set function but which +-- additionally interacts with whatever blinking is going on. + +-- turn off the blue led by deinitializing the ws2812 bus driver +local function bloff() gpio.mode(4,gpio.INPUT,gpio.PULLUP) end + +local function writeLedBOff(x) ws2812.init() ws2812.write(x) bloff() end + +local function mkBlinker(bona,boffa,inita) + return function(blinkT,ton,toff) + local function boff() boffa() blinkT:alarm(toff, tmr.ALARM_SINGLE, bon ) end + function bon() bona() blinkT:alarm(ton , tmr.ALARM_SINGLE, boff) end + if inita then inita() end; bon() + end +end + +return function (tmr,fb,ty,ton,toff) + local bfb = fb:sub(1) -- blank + bfb:fill(0,0,0) + + local function setLed_Just(...) fb:set(...) ws2812.write(fb) end + local function setLed_BOff(...) fb:set(...) writeLedBOff(fb) end + + local tyt = { [0] = function() writeLedBOff(fb) setLed = setLed_BOff end -- blue off, no blinking + , [1] = function() ws2812.init() ws2812.write(fb) setLed = setLed_Just end -- blue on, no blinking + , [2] = mkBlinker( function() writeLedBOff(fb) end -- blink ws2812, blue off as much as possible + , function() writeLedBOff(bfb) end + , function() setLed = setLed_Boff end + ) + , [3] = mkBlinker( function() ws2812.write(fb) end -- blink ws2812, blue on steady + , function() ws2812.write(bfb) end + , function() ws2812.init() ; setLed = setLed_Just end + ) + , [4] = mkBlinker( function() ws2812.init() ws2812.write(fb) ; setLed = setLed_Just end -- steady ws2812, blink blue + , function() bloff() ; setLed = setLed_BOff end + ) + , [5] = mkBlinker( function() ws2812.init() ws2812.write(fb) ; setLed = setLed_Just end -- blink both + , function() writeLedBOff(bfb) ; setLed = setLed_BOff end + ) + } + tmr:unregister() + tyt[ty](tmr,ton or 500,toff or 500) +end diff --git a/thermostat.lua b/thermostat.lua index a669ee3..ede1804 100644 --- a/thermostat.lua +++ b/thermostat.lua @@ -26,23 +26,28 @@ end local function mkRelays(mode, drive, forcefan) local v = 0xF -- "off" + local c = string.char(0,8,0) if drive then - if mode == "cool" then v = 0xC - elseif mode == "heat" then v = 0xA - elseif mode == "emht" then v = 0x6 + if mode == "cool" then v = 0xC ; c = string.char(0,0,8) + elseif mode == "heat" then v = 0xA ; c = string.char(8,0,0) + elseif mode == "emht" then v = 0x6 ; c = string.char(8,0,0) end end - if forcefan then v = bit.band(v, 0xE) end + if forcefan then + if v == 0xf then if fanOffDelayTMR then c = string.char(8,8,0) else c = string.char(8,0,8) end end + v = bit.band(v, 0xE) + end - return v + return v, c end local i2cu = require "i2cu" function doRelays() - local v = mkRelays(tcmode, driving, tcfan) + local v, c = mkRelays(tcmode, driving, tcfan) i2cu.writen(pcfaddr, string.char(bit.bor(pcfhigh, v))) + setLed(1,c) return v -- XXX debug end -- 2.50.1