--------------
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
=========
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)
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()
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
--- /dev/null
+-- 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
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