Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Thermostat Controller #8212

Merged
merged 76 commits into from
May 7, 2020
Merged

Thermostat Controller #8212

merged 76 commits into from
May 7, 2020

Conversation

arijav
Copy link
Contributor

@arijav arijav commented Apr 17, 2020

Description:

New driver created for thermostat control. I have created initially this as a LUA script running in Domoticz on a Raspberry Pi to control floor heating valves using Qubino Z-wave relays. I have ported this to a Tasmota driver embedding the functionality in the relays. This driver has been successfully tested with a Shelly 1PM, a Shelly 2.5 and a Sonoff 4CH PRO R2. Summary of the features:

  • Implementation of multi independent controllers in the same device (number selected by define to save memory, in-depth testing started with Sonoff 4CH PRO R2, optimizations pending).
  • The controller offers three operation modes, Off, Automatic (controller active) and Manual (controller following the input from a serial connected wall thermostat). The transition to manual happens once the input switch is active, allowing seamless integration with existing wall thermostats.
  • The controller offers 2 climate modes, heating as well as cooling (for cooling the testing is pending as well as further optimizations).
  • The controller offers 3 controlling strategies (Hybrid, predictive rampup control and PI).
  • The temperature can be received via MQTT or a local temperature sensor (name set by define, default DS18B20).
  • The default input format for the temperature is degrees Celsius but it can be switched to Fahrenheit via MQTT command.
  • The controller offers a diagnostic functionality based on inconsistent states between output, command and input (Diagnostic for maximum power at output already covered by the energy driver).

Future features (TODO´s):

  • Configuration over the Web Timer's GUI (Selector for Thermostat and box for Setpoint).
  • Rework of global_temperature concept in Tasmota for using several temp. sensors
  • Humidity control (to be defined).

Related issue (if applicable): fixes #

Checklist:

  • The pull request is done against the latest dev branch
  • Only relevant files were touched
  • Only one feature/fix was added per PR.
  • The code change is tested and works on core Tasmota_core_stage
  • The code change pass travis tests. Your PR cannot be merged unless tests pass
  • I accept the CLA.

arijav and others added 25 commits April 17, 2020 10:31
…as a Domoticz (running on a raspberry pi) script and controlling Qubino relays for floor heating. Ported to tasmota to get the logic within the relay itself and be less dependent on Domoticz.

The controller supports several working modes. From off (no action) to manual (following input), automatic (hybrid, rampup or pi controller) and timeplan (automatic following predefined schedule with 3 temperatures for each weekday). It is fully configured via commands, it will include in the future diagnostics and will be extended to more outputs (will be tested on sonoff 4CH Pro).

The controller has been tested successfully with a Shelly 1PM device and works as the original LUA domoticz script.
- Add config version tag
- Bump version 8.2.0.4
This reverts commit 56788a3.
Fix error for ESP32. Scripts checks if exists and generates only in target folder if there
to build special Tasmota versions with Compiler switches defined in [env:tasmota-xyz] in `platformio_tasmota_cenv.ini` to control
user_config_override.h
Example:
"[env:tasmota-zigbee]
build_flags = ${common.build_flags} -DHANS_CONFIG_ZIGBEE=true"
which referrs to in user_config_override.h
```#ifdef HANS_CONFIG_ZIGBEE  // ******************************************************************

#undef CODE_IMAGE_STR
#define CODE_IMAGE_STR "ZIGBEE"

#define USE_WEBSERVER                            // Enable web server and Wifi Manager (+66k code, +8k mem)
  #define USE_JAVASCRIPT_ES6                     // Enable ECMAScript6 syntax using less JavaScript code bytes (fails on IE11)
//  #define USE_WEBSEND_RESPONSE                   // Enable command WebSend response message (+1k code)

//#define USE_RULES                                // Add support for rules (+4k4 code)
//  #define USE_EXPRESSION                         // Add support for expression evaluation in rules (+3k2 code, +64 bytes mem)
//    #define SUPPORT_IF_STATEMENT                 // Add support for IF statement in rules (+4k2 code, -332 bytes mem)
//  #define SUPPORT_MQTT_EVENT                     // Support trigger event with MQTT subscriptions (+3k5 code)

//#define USE_SCRIPT                               // Add support for script
//  #define USE_SCRIPT_FATFS 4                     // Add support for script storage on SD card (+12k code, +4k mem)
//  #define USE_SCRIPT_WEB_DISPLAY


#define USE_ADC_VCC                              // Display Vcc in Power status. Disable for use as Analog input on selected devices


// -- Zigbee interface ----------------------------
#define USE_ZIGBEE                               // Enable serial communication with Zigbee CC2530 flashed with ZNP (+35k code, +3.2k mem)
  #define USE_ZIGBEE_PANID  0x1A63                // arbitrary PAN ID for Zigbee network, must be unique in the home
  #define USE_ZIGBEE_EXTPANID 0xCCCCCCCCCCCCCCCCL // arbitrary extended PAN ID
  #define USE_ZIGBEE_CHANNEL  11                  // Zigbee Channel (11-26)
  #define USE_ZIGBEE_PRECFGKEY_L 0x0F0D0B0907050301L  // note: changing requires to re-pair all devices
  #define USE_ZIGBEE_PRECFGKEY_H 0x0D0C0A0806040200L  // note: changing requires to re-pair all devices
  #define USE_ZIGBEE_PERMIT_JOIN false           // don't allow joining by default
  #define USE_ZIGBEE_COALESCE_ATTR_TIMER 350     // timer to coalesce attribute values (in ms)


#endif ```
Add ESP32 brownout disable for weak onboard LDO's - eventually you'll need to change the LDO to a better one.
… as a LUA script running in Domoticz on a Raspberry Pi to control floor heating valves using Qubino relays. I have ported this to a Tasmota driver embedding the functionality in the relays. This driver has been successfully tested with a shelly 1PM. The controller offers 3 controlling strategies (Hybrid, Rampup and PI) as well as time planning (3 diff. temp. each weekday).
@device111
Copy link
Contributor

issue, address not correct:
uint8_t free_f36[70];
check:
tasmota/tasmota.h

do you think, you can integrate like tasmota timers? i don't now if this works, but will be easier for set heating plan.
at the moment you are loose all settings from heating plan?

@s-hadinger
Copy link
Collaborator

From what I can see you are not using Flash Settings anymore, but only compile time options. Right?

@arijav arijav closed this Apr 18, 2020
@arijav arijav reopened this Apr 18, 2020
@arijav
Copy link
Contributor Author

arijav commented Apr 18, 2020

Thanks for the comments:

  1. I will correct Tasmota.h and recommit the change. Regarding the timers I can investigate, which ones do you mean that are existing in Tasmota?

  2. Yes, I do no longer use the flash settings. The only small drawback is that for specific configurations not fitting the default values, after a reset the device should be reconfigured via MQTT (which is possible for each of the parameters).

@arendst
Copy link
Owner

arendst commented Apr 30, 2020

There is no need to scan JSON messages to find a locally connected temperature sensor. Tasmota provides an internal variable called global_temperature which contains the temperature read by a locally attached temperature sensor. Could be any type of hardware.

So I suggest you rewrite your latest addition using the knowledge from xdrv_03_energy.ino lines 442-446 demonstrating the use of this local variable.

I suggest too to search for global_temperature to find more examples in the code.

And pls remember, keep the code as small as possible. I see a lot of logging which luckily can be disabled by a define which looks good.

@arijav
Copy link
Contributor Author

arijav commented Apr 30, 2020

There is no need to scan JSON messages to find a locally connected temperature sensor. Tasmota provides an internal variable called global_temperature which contains the temperature read by a locally attached temperature sensor. Could be any type of hardware.

So I suggest you rewrite your latest addition using the knowledge from xdrv_03_energy.ino lines 442-446 demonstrating the use of this local variable.

I suggest too to search for global_temperature to find more examples in the code.

And pls remember, keep the code as small as possible. I see a lot of logging which luckily can be disabled by a define which looks good.

Thanks for the tip, I have modified the code to use global_temperature but I have issues. In the shelly PM I have attached a DS18B20 and adapted the template according to your modifications (old issue from February I think) to read both temperatures the internal one of the module and the DS18B20. The issue is that the variable global_temperature is being update with both of them sequentially:

Example of my reads:
13:21:10 MQT: stat/tasmota_BA0DC9/RESULT = {"GlobalTemp":21.9}
13:21:13 MQT: stat/tasmota_BA0DC9/RESULT = {"GlobalTemp":33.5}
13:21:16 MQT: stat/tasmota_BA0DC9/RESULT = {"GlobalTemp":33.5}
13:21:17 MQT: stat/tasmota_BA0DC9/RESULT = {"GlobalTemp":33.5}
13:21:18 MQT: stat/tasmota_BA0DC9/RESULT = {"GlobalTemp":21.9}
Infos of the main Tasmota webpage of my Shelly:
Temperature: 33.5°
DS18B20 Temperature: 21.9°

I can have a look to solve the issue, but currently I foresee that all modules with an internal temperature sensor and an attached external one would face this problem. Maybe it would make sense to separate the global_temperature into two variables, one for internal and one for external, since you need to keep the overtemperature protection feature of the modules in xdrv_03_energy.ino.

Regarding Debug, yes, I will leave everything into the define and disable it by default, furthermore it is my intention to reduce it drastically soon, since I see that the controller reacts exactly as the one I have in Domoticz based on LUA.

@arendst
Copy link
Owner

arendst commented Apr 30, 2020

You're right. I had hoped only one sensor was connected but if more are used it becomes "messy".

Adding and "external" global_temperature is indeed a fix as long as there is only one external sensor connected. It will need a kind of large rework task.

For now, let's leave your solution in place and only think about a possible global solution.

@ascillato2 ascillato2 changed the title New driver for thermostat controller (xdrv_39). 2nd Pull-request with size optimizations Thermostat Controller Apr 30, 2020
@kretu
Copy link

kretu commented May 3, 2020

Would it be hard to implement control by humidity rather than temperature?

@arijav
Copy link
Contributor Author

arijav commented May 3, 2020

Would it be hard to implement control by humidity rather than temperature?

It means some rework but it is feasible. I can make it active via define to save some memory and will need to think about a better name for the driver. If you describe the system a little bit I can add it to the lists of TODO´s and evaluate

@yury-sannikov
Copy link
Contributor

hi @arijav, awesome PR! Do you think it makes sense to add telemetry output enabling tasmota Rules tapping into the output value and do other things rather than MQTT and Relay control?

@arijav
Copy link
Contributor Author

arijav commented May 6, 2020

hi @arijav, awesome PR! Do you think it makes sense to add telemetry output enabling tasmota Rules tapping into the output value and do other things rather than MQTT and Relay control?

Thanks, what it is foreseen is to be able to configure the timers to arm the thermostat to reach a given set point and disarm them and therefore rules could be used. Do you mean this or something else (maybe an example can help)?

@3ricj
Copy link

3ricj commented May 6, 2020

First of all, I am really excited about this capability. I don't like the idea of thermostats running off external devices, so having it integrated on the controller is perfect. Thank you.

Some general feedback:

  • there are lots of application specific control methods.

For example, compressor based heat pumps (AC/cooling/heating) need a minimum cycle time because you don't want to restart a compressor quickly; this can lead to stalling. Inversely, a sousvide cooker would want a fast cycle time. I feel this is pretty important.

There are also TECs that may need proportional control (not just on or off but on percentages) using PIDs. Its unlikely many will use this. Some really complicated systems use variable speed heat pumps. You see these marketed as "inverters".

It would be great if this code could also manage error states. For example, if the heater is "ON" but it's not getting warmer, it's an error. Same for AC on but not cooling. In some cases it should error on overrun: if it's set to cool down to 1c, but we are below that (say -3c) that could be worthy of an error flag. If this was used to control a fridge you don't want to go below freezing.

A related, but harder to compute is a flag for "stable temp". Eg: it's not oscillating, overrun, underrun, etc.

  • it would likely be important to have a concept of deadband. Cold tolerance and hot tolerance.

Anyway, none of this needs to be implemented, this is not a feature request, but just some food for thought.

@yury-sannikov
Copy link
Contributor

Thanks, what it is foreseen is to be able to configure the timers to arm the thermostat to reach a given set point and disarm them and therefore rules could be used. Do you mean this or something else (maybe an example can help)?

My point is pretty much the same as @3ricj

There are also TECs that may need proportional control (not just on or off but on percentages) using PIDs. Its unlikely many will use this. Some really complicated systems use variable speed heat pumps. You see these marketed as "inverters".

I can see 2 types of the telemetry output:

  • Power, in a range of 0-100%
  • The desired temperature in celsius.

For example, to control the duty cycle of some inverter one can use:

Rule
  on tele-pid#output#duty_cycle do event pwm=(%value%*1024) endon
  on event#pwm do  WebSend [...] Pwm %value% endon

For example, to control the boiler with PID:

Rule
  on tele-pid#output#temperature do ot_tboiler %value% endon

In those examples telemetry JSON might look like:

{...., "pid":{"output": {"duty_cycle": 0.85, "temperature": 78}}, ....}

@arendst arendst merged commit 2c40be9 into arendst:development May 7, 2020
@arijav
Copy link
Contributor Author

arijav commented May 7, 2020

Thanks, what it is foreseen is to be able to configure the timers to arm the thermostat to reach a given set point and disarm them and therefore rules could be used. Do you mean this or something else (maybe an example can help)?

My point is pretty much the same as @3ricj

There are also TECs that may need proportional control (not just on or off but on percentages) using PIDs. Its unlikely many will use this. Some really complicated systems use variable speed heat pumps. You see these marketed as "inverters".

I can see 2 types of the telemetry output:

  • Power, in a range of 0-100%
  • The desired temperature in celsius.

For example, to control the duty cycle of some inverter one can use:

Rule
  on tele-pid#output#duty_cycle do event pwm=(%value%*1024) endon
  on event#pwm do  WebSend [...] Pwm %value% endon

For example, to control the boiler with PID:

Rule
  on tele-pid#output#temperature do ot_tboiler %value% endon

In those examples telemetry JSON might look like:

{...., "pid":{"output": {"duty_cycle": 0.85, "temperature": 78}}, ....}

Understood, will evaluate for sure. Thanks for the input

@arijav arijav deleted the new_branch branch May 7, 2020 19:56
@ascillato ascillato mentioned this pull request May 10, 2020
@Bibinsa
Copy link

Bibinsa commented Nov 26, 2020

Hi ! I'm using Thermostat feature since a fex days now.

I wonder if there is any option to activate telemetry with cycle reset, max time, ... any reasons that trigger Power ON/OFF ?
If not, could it be possible to implement that ?

Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.