zorruno wikki: showcode "A Tasmota based fan controller for Equipment Cabinet"

Wiki source for CabinetFanController

Show raw source

======A Tasmota based fan controller for Equipment Cabinet======

More an exercise in playing with Tasmota & Documenting how Tasmota Rules work, this overly complex fan setup is for my equipment cupboard.

-- Uses a pair of fans (out of an old tower server) to provide some redundancy if one fails.
-- Measures RPM of both fans to ensure they are running.
-- The fans run in parallel, either on 5V normally, or the relay switches them to 12V to boost cooling
-- Uses a ++DHT11++ DHT22 (SI7021) to do temp measurements, ie standalone thermostat function (no additional head end control needed).
-- Thermostat hysteresis values are set with MQTT (as well as thermostat on/off setting)

-- ESP8266 based [[https://www.aliexpress.com/item/32967365594.html control single relay board (Yunshan HW-622)]] (~$6-$10)
-- [[https://www.aliexpress.com/item/10000000656280.html Buck regulator]] for 5V control of the fan (~$5)
-- 2x old 120mm Server Fans (Reclaimed)
-- 2x Vacuum filter squares (Reclaimed)
-- 1x Equipment box (from the parts cupboard)
-- Mounting screws, plywood, hookup wire etc
-- Power supply (reclaimed 12V plugpack, but will be powered from another cupboard supply later)

=====Board Notes=====
-- My Tasmota board flashing notes: https://zorruno.com/w/YunhanRelayESP8366
-- A bunch of diagrams show the board having relay NC in the top corner - it isn't on mine, this is NO
-- If the fans were smaller, you could do this without a buck converter, as the board has a 5V regulator, but I wasn't comfortable with the continual 5V load.
-- The ++DHT11++ DHT22 signal needs to feed 3.3V to the micro, so I took 3.3 supply directly off the LM117 regulator (up by the Relay)
-- Full load comes in at under 200mA continuous operation and up to 700mA with the fans on 12V (about 2W and 9W)
-- 5V is about as low as I'd want to go with the fans so they don't stall, but with the adjustable buck I can ramp them up higher if need be (or if more continual airflow is needed).

=====Tasmota notes (for those who haven't used the project much)=====
Tasmota is very versatile but is a fast moving project. Currently a bunch of items aren't documented well, and well documented examples of rules etc are not common.

Also, as the project has evolved from controlling a single relay sonoff to multiple device types, some items are not as intuitive as the could be due to backwards compatibility. Googling for help sometimes brings up old documentation, or documentation inside the github forks.

Finally note that for Rules and commands, case is not important and some items that were single commands have involved over time to multiple, so documentation doesn't always reflect this. eg, "Rule1 1", "Switchmode1", "SwitchMode 1" can be confusing when reading old documents.

=====Schematic sketch=====
{{image class="center" alt="HW-622" width="400" title="HW-622 Yunhan Relay Board" url="https://lh3.googleusercontent.com/yyAO4obF_lKbPnxVRU8vcPP_41FH_ltuqSxKLAJVCwyQnmkovFPtk6T2KLIuw11E1gi2YH28UyorMd2jDUF7wqPnsJT8KMKPEGhRBCbnXItdcRM-XuDKkVMIZ66xiD5EWKVLHhmfuVXCkpCsbvUNNxTL5Ucd0oDIKtvYt9HslEauCPHw-uJv9G64u0O4XMcRzjOlMfgxzjgaoga6RnN0gxW58XnG3UEfr6Ep1v4W8nR8g5d0v0MdiPi0FlMR5dF8VpsAL-RgaoeppBmgm06AGBgjQNFCdkosCeIYtfE4yR4lFlDyzKmOBmbJmzu0Ka7GivZ0suNw2CspMMxdLgJCBFcTwqqkvCQxHJEP7N5LkdgMfRwOR0O4n5c5ADscIKOLGiqNR1cEz0Ht1JuEnO-mlA2TEKNqtVfYuj3DOgdZL1eoPEvppdfDddI49L-ko58EK-1cZsggjzf_e2zhZdJMBIcGe2iDnTBCcW4X4mGjFyJAX2ZXtvevq7CK3xpg1f0yAY1ovAy9c1HM6DaiOTJZjxZB3fmPnVHM4LCX4uHgnVvQ649tE7HZYEoHLu9mwOyNlByn4arW8gR9JDYeFGG-DkzWPmCATpxCJmHg4K5CcW7_2dOzTFyTiYF6exx8I8nEdhxXP4qsVXclAdHE-49MRxJ24apu1rjJOhcCSqFYqiPBciGb5ozK_ioeatOM7OxCl17FANdUeSscxjsnQM1wWJZsRWbQVCEiU7AURTW3uKO7RpB6LfSoxZc=w908-h673-no" link="https://lh3.googleusercontent.com/yyAO4obF_lKbPnxVRU8vcPP_41FH_ltuqSxKLAJVCwyQnmkovFPtk6T2KLIuw11E1gi2YH28UyorMd2jDUF7wqPnsJT8KMKPEGhRBCbnXItdcRM-XuDKkVMIZ66xiD5EWKVLHhmfuVXCkpCsbvUNNxTL5Ucd0oDIKtvYt9HslEauCPHw-uJv9G64u0O4XMcRzjOlMfgxzjgaoga6RnN0gxW58XnG3UEfr6Ep1v4W8nR8g5d0v0MdiPi0FlMR5dF8VpsAL-RgaoeppBmgm06AGBgjQNFCdkosCeIYtfE4yR4lFlDyzKmOBmbJmzu0Ka7GivZ0suNw2CspMMxdLgJCBFcTwqqkvCQxHJEP7N5LkdgMfRwOR0O4n5c5ADscIKOLGiqNR1cEz0Ht1JuEnO-mlA2TEKNqtVfYuj3DOgdZL1eoPEvppdfDddI49L-ko58EK-1cZsggjzf_e2zhZdJMBIcGe2iDnTBCcW4X4mGjFyJAX2ZXtvevq7CK3xpg1f0yAY1ovAy9c1HM6DaiOTJZjxZB3fmPnVHM4LCX4uHgnVvQ649tE7HZYEoHLu9mwOyNlByn4arW8gR9JDYeFGG-DkzWPmCATpxCJmHg4K5CcW7_2dOzTFyTiYF6exx8I8nEdhxXP4qsVXclAdHE-49MRxJ24apu1rjJOhcCSqFYqiPBciGb5ozK_ioeatOM7OxCl17FANdUeSscxjsnQM1wWJZsRWbQVCEiU7AURTW3uKO7RpB6LfSoxZc=w908-h673-no"}}

=====Board Schematic=====
{{image class="center" alt="HW-622" width="400" title="HW-622 Yunhan Relay Board" url="https://lh3.googleusercontent.com/APtz3RUz0akZKUlm6TbAgY2KcoewJFeEoRbfgdAMxvZ9n9QhLBVqJbTqMZkNdVgMQWU5LoVCo3uuXA7Tv7_wCa2Eopxwho1gp0CJYSr8iBWqC8lOZdMmfaLRBLpWKKGlak4_WGcdUnMf_er2G8x3ykS8QKLHSr3dpi0nx-U6dTnl5_Lc0zB1rgNGCSWAjNmVcJ0cbNZQWWn2h2nW_VJ2j_OIeRXq-VQ6XIHOTibstRQPP0w6VRVB1eR_MUT6dkb7HcvKmFqm_jmHmQkvsy6IY9CMamtkCF4GaUdYqTr_L4EvrAeXWjzU9hhmJmJqKkOks1VNEJ3V1C42d_FjLNPxaxSubhCND-BFbd__3JhpnPEaTX-kME1ASNaQl_f_DJvCe6CAOF7FX9gI2_byF5TVKz8VB5q8tW0NA8wONnI3jTk2znWDm-m3X1Cwkv_eqRoKhE4Xqao_yKcEghFWHhuughU6RcTTRAMq1M-LoRQRvlvxFFhJPedK-Ja5nIVHh8pjp00i87IJ-zlv3jDR_Yug33cMk78Lz8TcVeW1nnI7lOdh_U_e3Et8Nb3pAYQrqnnSxvqApjk7oUDBMiCmkRSfhfqwPjzdfAXcd2JyRjU6BGDij-OfiHU4F8wgzNODp6vqu7AqWpffd-bk4d6Zx3KCVcDaM3zDj2o-DHSCw_IznlKzEalP6I773TuTQokbIazXNZUBBz2ZQswV_-uM9TPoFTqqs51Q5dwjP6PZeIRVV74nX7NHQtqr6IY=w967-h641-no" link="https://lh3.googleusercontent.com/APtz3RUz0akZKUlm6TbAgY2KcoewJFeEoRbfgdAMxvZ9n9QhLBVqJbTqMZkNdVgMQWU5LoVCo3uuXA7Tv7_wCa2Eopxwho1gp0CJYSr8iBWqC8lOZdMmfaLRBLpWKKGlak4_WGcdUnMf_er2G8x3ykS8QKLHSr3dpi0nx-U6dTnl5_Lc0zB1rgNGCSWAjNmVcJ0cbNZQWWn2h2nW_VJ2j_OIeRXq-VQ6XIHOTibstRQPP0w6VRVB1eR_MUT6dkb7HcvKmFqm_jmHmQkvsy6IY9CMamtkCF4GaUdYqTr_L4EvrAeXWjzU9hhmJmJqKkOks1VNEJ3V1C42d_FjLNPxaxSubhCND-BFbd__3JhpnPEaTX-kME1ASNaQl_f_DJvCe6CAOF7FX9gI2_byF5TVKz8VB5q8tW0NA8wONnI3jTk2znWDm-m3X1Cwkv_eqRoKhE4Xqao_yKcEghFWHhuughU6RcTTRAMq1M-LoRQRvlvxFFhJPedK-Ja5nIVHh8pjp00i87IJ-zlv3jDR_Yug33cMk78Lz8TcVeW1nnI7lOdh_U_e3Et8Nb3pAYQrqnnSxvqApjk7oUDBMiCmkRSfhfqwPjzdfAXcd2JyRjU6BGDij-OfiHU4F8wgzNODp6vqu7AqWpffd-bk4d6Zx3KCVcDaM3zDj2o-DHSCw_IznlKzEalP6I773TuTQokbIazXNZUBBz2ZQswV_-uM9TPoFTqqs51Q5dwjP6PZeIRVV74nX7NHQtqr6IY=w967-h641-no"}}

=====Tasmota Module Configuration=====
{{image class="center" alt="HW-622" width="400" title="HW-622 Tasmota Config" url="https://lh3.googleusercontent.com/7uxyCSkp4DTC7Hm38mhmqGdGqTBT9ycwiis2FilFtagOee5lE1rrPQy8LaGouflksk-ed7wOPwT9FD0CdhK8wv2kHCjWtnn1L9flMUsJlYFk_NaMRr9yl09bWMcO1QBbQUD9kiC0xwaRPZM-j4MSn4JKnTKjCyDmqJQ49rhoRC5V7x03b5IWmI08LJGXRCrECe47JfzxzItGgXw5lWdFR5-p0AyGKvC4L4vDGARUChSsr4rdQa4n9h6XzmZO3TZ-NO02DoUWY1mu3IYwZRO-iZYAZ78w9bE8dscqM6JPr2ps0cIqo6YENNGa7UaNYeKnctJOlgsrjvvsJ5HR5rMEhCLDNBToZDB-hsCTYMbh5shc4810DVMNPtj4cllJAnmFtHd-9o5YConPK0YsspwmgXE_LHP0oe335IU6LK9XGMiZ3X2AWlEpB9ij0J535v4eCrxkJpCvsjDC7dsiLpTklHmcfAFd5bn3k9ybk7uDKDyCDsrDjdfc32oASOqMSXIZ1PYR6m26XC-qE6n_qedXsvL123718umJUpjBYIMwqJhsz7CwqQtJUmQK2j84rtFsT6Kf0qbvFSROxDViZp_dR6ZG68QvMLTg48D_ntlU_TiHuwaMRJV0UVBFbsydKikXktF1HfyP0327ZtjKNybglT24dlhAHsGb9JqaCxnVDwc660eaLkac0wnBF_MKZg=w430-h769-no" link="https://lh3.googleusercontent.com/7uxyCSkp4DTC7Hm38mhmqGdGqTBT9ycwiis2FilFtagOee5lE1rrPQy8LaGouflksk-ed7wOPwT9FD0CdhK8wv2kHCjWtnn1L9flMUsJlYFk_NaMRr9yl09bWMcO1QBbQUD9kiC0xwaRPZM-j4MSn4JKnTKjCyDmqJQ49rhoRC5V7x03b5IWmI08LJGXRCrECe47JfzxzItGgXw5lWdFR5-p0AyGKvC4L4vDGARUChSsr4rdQa4n9h6XzmZO3TZ-NO02DoUWY1mu3IYwZRO-iZYAZ78w9bE8dscqM6JPr2ps0cIqo6YENNGa7UaNYeKnctJOlgsrjvvsJ5HR5rMEhCLDNBToZDB-hsCTYMbh5shc4810DVMNPtj4cllJAnmFtHd-9o5YConPK0YsspwmgXE_LHP0oe335IU6LK9XGMiZ3X2AWlEpB9ij0J535v4eCrxkJpCvsjDC7dsiLpTklHmcfAFd5bn3k9ybk7uDKDyCDsrDjdfc32oASOqMSXIZ1PYR6m26XC-qE6n_qedXsvL123718umJUpjBYIMwqJhsz7CwqQtJUmQK2j84rtFsT6Kf0qbvFSROxDViZp_dR6ZG68QvMLTg48D_ntlU_TiHuwaMRJV0UVBFbsydKikXktF1HfyP0327ZtjKNybglT24dlhAHsGb9JqaCxnVDwc660eaLkac0wnBF_MKZg=w430-h769-no"}}

=====Fan RPM Count Rules=====
===First Setup===
TelePeriod is a standard value of time when certain things happen, mainly when a number of "Tele" messages are pushed to MQTT with many of the tasmota state values included. By default this is 300, or every 5 minutes, but we will set to 60. (We don't need to do this obviously if already set for another ruleset)

So we use the console to set the teleperiod.
%%TelePeriod 60%%

===Fan Count Rules===
At the end of each Tele time, publish the vars to a MQTT topic as JSON and reset the counters.

Using this method, you get a reasonably accurate count of revolutions per minute published for the two fans.

We will do this all with one ruleset (Tasmota has 4 available as standard build), but be mindful of the current 512 character limit for a rule. Laying it out as multiple rules might look nicer, but this project has multiple needs for rules.

Note that with a counter input, counter#c1 will trigger any time the counter changes (with the current counter value of counter1), but tele-counter#c1 is the value triggered at TelePeriod (which is what we want here... trigger once per minute).

These are the rules, spaced out for visibility.
on tele-counter#c1>0 do backlog
publish stat/%topic%/Fan1Count {"Fan1":%value%} ;
counter1 0 endon
on tele-counter#c2>0 do backlog
publish stat/%topic%/Fan2Count {"Fan2":%value%};
counter2 0 endon%%

This is the ruleset on one line for easier copy/paste
%%rule1 on tele-counter#c1>0 do backlog publish stat/%topic%/Fan1Count {"Fan1":%value%} ; counter1 0 endon on tele-counter#c2>0 do backlog publish stat/%topic%/Fan2Count {"Fan2":%value%} ; counter2 0 endon%%

===Fan Count Rules Explanation===

**on tele-counter#c1>0 do **
When the value of TelePeriod hits (we previously set it to 60 secs), and the tasmota counter number 1 is greater than zero implement the rule. The value %value% will be the current C1 count.

Just allows multiple commands in one line. Use semi-colons to separate them

**publish stat/%topic%/Fan1Count {"Fan1":%value%}**
Publish the fan rotation count value (ie a one minute shapshot with TelePeriod set to 60) to MQTT as a pair of JSON values. With MQTT, we don't have to pre-declare any MQTT topics or other variables, we just publish the MQTT topic name that we choose to (in this case I've called them Fan1Count and Fan2Count as the topic and Fan1, Fan2 as the count name)

**counter1 0 ;**
Zero the counters

//Now do the same with counter 2//

=====Thermostat Control=====
===Variable Use===
We need to pick some varibles to use. Mem variables are saved in flash even after a power outage. The Var variables aren't.

**Mem1 1**: <- thermostat status: 0-off 1-enabled - View or set by MQTT cmnd/mqttTopic/mem1
**Mem2 26**: <- setpoint Temp lower limit - View or set by MQTT cmnd/mqttTopic/mem2
**Mem3 28**: <- setpoint Temp upper limit - View or set by MQTT cmnd/mqttTopic/mem3
**Var3 0**: <- thermostat true status: 1-OK 0-NOT READY - View by MQTT cmnd/mqttTopic/var3

===Setup Console Commands===
%%backlog SwitchMode1 2; Rule2 1; Rule2 4; TelePeriod 60; SetOption26 1; SetOption0 0; poweronstate 0; mem1 1; mem2 26; mem3 28; var3 0%%

===Console Commands Explanation===
**SwitchMode1 2**: Set the first input switch to send an MQTT message of 'ON' or 'OFF'. eg it will send "stat/mqttTopic/STATUS10 message of Switch1=ON when our door is closed". Once a rule is added to control the relay, pressing the button won't control the relay directly anymore. Using SwitchMode1 2 rather than SwitchMode1 1 is inverted mode as we are using it with a doorswitch that is normally closed (we want the thermostat on when the door is closed), and it this case being closed pulls the input high the way I have wired it.

**Rule2 1**: Turn on Rule 2 (which obviously is blank to start with won't do anything until you add a rule.

**Rule2 4**: Set the rule (2nd rule, but any one of the 3 rules will do) so that it will always fire if the condition is met - ie ensure one-shot mode is not enabled

**TelePeriod 60**: We will check temp every 'TelePeriod', so let's make it once per minute. We want this for the fan rev speed above anyway (and you can't have 2 TelePeriods)

**SetOption26 1**: Tasmota used to use 'POWER' on MQTT messages when it was built for just one relay. Now it can have multiple outputs, you can use POWER or POWER1 on the first output. This option sets it to use POWER1

**PowerOnState 0**: Startup with relay off.

**Mem1 1**: Set Mem1 to 1, or thermostat enabled

**Mem2 26**: Set lower limit for temp (ie when relay turns off/fans go low speed)

**Mem3 28**: Set upper limit for temp (ie when relay turns on/fans go high speed)

**Var3 0**: Initialise the thermostat status setting it to 0

===Rules for thermostat control===
These are the rules, spaced out for visibility. We'll use rule 3 (as we used the others previously) but a rule can have many commands in one set:
%%Rule2 on system#boot do RuleTimer1 70 endon
on switch1#state do backlog
mem1 %value% ;
publish stat/%topic%/DoorSwitch {"DoorState":"%mem1%"} endon
on Rules#Timer=1 do backlog var3 0; RuleTimer1 70; power1 0 endon
on tele-SI7021#temperature do backlog
var3 1 ;
RuleTimer1 70 ;
event ctrl_ready=1 ;
event temp_demand=%value% ;
publish stat/%topic%/ThermostatSP {"SetpointLow":%mem2%,"SetpointHigh":%mem3%}
on event#ctrl_ready>%mem1% do var3 0 endon
on event#temp_demand<%mem2% do power1 0 endon
on event#temp_demand>%mem3% do power1 %var3% endon%%

This is the same rule3 set, with no linebreaks for a cut/paste:
%%Rule2 on system#boot do RuleTimer1 70 endon on switch1#state do backlog mem1 %value% ; publish stat/%topic%/DoorSwitch {"DoorState":%value%} endon on Rules#Timer=1 do backlog var3 0 ; RuleTimer1 70 ; power1 0 endon on tele-SI7021#temperature do backlog var3 1 ; RuleTimer1 70 ; event ctrl_ready=1 ; event temp_demand=%value% ; publish stat/%topic%/ThermostatSP {"SetpointLow":%mem2%,"SetpointHigh":%mem3%} endon on event#ctrl_ready>%mem1% do var3 0 endon on event#temp_demand<%mem2% do power1 0 endon on event#temp_demand>%mem3% do power1 %var3% endon%%

=====Potential Improvements=====
-- Rule to publish warnings to MQTT such as fan stall
-- Pressure sense for filter change warning?
-- button on GPIO5? ++Fan boost maybe++ (used as cupboard door open sense AND thermostat on off)
-- Fix issue with temp sense on GPIO0 meaning occasionally micro doesn't boot. Current fix is to no turn it off.... or remove the DHT22 temporarily on a reboot.
-++- Switch to a DHT22 for prettier graphs (more resolution!)++

{{lastedit show="3"}}