]> hydra-www.ietfng.org Git - acmetensortoys-esp-lua_thermostat/commitdiff
Add support for WS2812 status indicator LED
authorNathaniel Wesley Filardo <nwf@cs.jhu.edu>
Sat, 26 Aug 2017 06:30:51 +0000 (02:30 -0400)
committerNathaniel Wesley Filardo <nwf@cs.jhu.edu>
Sat, 26 Aug 2017 06:35:20 +0000 (02:35 -0400)
README.rst
init3.lua
led.lua [new file with mode: 0644]
thermostat.lua

index c134a3335d3bc43cd58c4b340f284fd65e43b149..113b3da1538e3791a966244559a8bc1c3c124ca7 100644 (file)
@@ -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
 =========
index 40f00c7846c3a9dd7cb170f286b1500a36f94fa4..3a8329fdb6ab15e4dd27e52d028e07efd3ef7bda 100644 (file)
--- 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 (file)
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
index a669ee3b42fda99a38271025286457b9c7a41a73..ede1804574ed31ee1fdcc94c7719b54c0aa9b8e7 100644 (file)
@@ -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