# Climate regulator
Zonal climate regulator - can be used as a thermostat for a specific zone heating or cooling. Output should be provided to a climate regulator hub.
# Inputs
| ID | Abbrev | Name | Type | Default | Description |
|---|---|---|---|---|---|
air_temp | AT | Air temperature | NUMBER | 0 | Current air temperature |
outside_temp | OT | Outside temperature | NUMBER | -1000 | Current outside temperature |
presence | PRE | Presence | BOOLEAN | false | Extends the comfort temperature period when high. Switches from eco to comfort after a specified configuration parameter. |
dwc | DWC | Door window contact | BOOLEAN | false | If active longer than configured duration: 1) switches off heating for open door or window if outside temperature is lower than target, 2) switches off cooling if outside temperature is higher than target |
comfort | COM | Comfort mode | BOOLEAN | false | Activates the comfort temperature mode until the next schedule period change. |
protection | PRO | Protection mode | BOOLEAN | false | Activates the protection temperature mode to protect the building from frost or overheat. |
# Outputs
| ID | Abbrev | Name | Type | Default | Description |
|---|---|---|---|---|---|
target_temp | TT | Target temperature | NUMBER | 0 | The output target temperature |
temp_deviation | TD | Temperature deviation | NUMBER | 0 | Output expressing the heating or cooling requirement expressed as a difference between a current and a target temperature. Positive for heating. Negative for cooling. |
# Configuration
| ID | Name | Type | Default | Unit | Description |
|---|---|---|---|---|---|
thermal_mode | Thermal mode | ENUM | 0 | Defines the thermal mode: Heating and cooling, Heating only, Cooling only Details: Values: Heating and cooling, Heating only, Cooling only | |
operation_mode | Operation mode | ENUM | 0 | Defines the operation mode: Schedule, Manual Details: Values: Schedule, Manual | |
schedule | Schedule | SCHEDULE | 0 | Schedule to use for schedule based operation mode Details: Subtype: CLIMATE Visible when operation_mode = Schedule | |
comfort_heating_temp | Comfort heating temperature | NUMBER | 21 | °C | Comfort heating temperature Details: Visible when thermal_mode = Heating and cooling, Heating only≤ comfort_cooling_temp |
comfort_cooling_temp | Comfort cooling temperature | NUMBER | 25 | °C | Comfort cooling temperature Details: Visible when thermal_mode = Heating and cooling, Cooling only≥ comfort_heating_temp |
eco_heating_temp_diff | Eco heating temperature diff | NUMBER | 2 | °C | Eco heating temperature diff. below the comfort temp. Details: Visible when thermal_mode = Heating and cooling, Heating only≥ 0 |
eco_cooling_temp_diff | Eco cooling temperature diff | NUMBER | 3 | °C | Eco cooling temperature diff. above the comfort temp. Details: Visible when thermal_mode = Heating and cooling, Cooling only≥ 0 |
frost_protection_temp | Frost protection temperature | NUMBER | 10 | °C | Frost protection temperature. If the temperature is below this temperature, the heating is activated to protect the building. Details: Visible when thermal_mode = Heating and cooling, Heating only≥ 5 < comfort_heating_temp |
overheat_protection_temp | Overheat protection temperature | NUMBER | 40 | °C | Overheat protection temperature. If the temperature is above this temperature, the cooling is activated to protect the building. Details: Visible when thermal_mode = Heating and cooling, Cooling only≥ comfort_cooling_temp |
dwc_delay | DWC delay in seconds | NUMBER | 30 | s | Door, window contact delay in seconds. Prevents short door, window opening to interrupt the climate control. Details: > 0 |
presence_extension_duration | Presence extension duration | NUMBER | 1800 | s | Comfort temperature extension duration (in seconds) on presence detection. Details: Visible when operation_mode = Schedule≥ 0 |
# State
| ID | Name | Type | Default | Unit | Description |
|---|---|---|---|---|---|
dwc_state_change_ts | Last DWC state change timestamp | NUMBER | 0 | ||
dwc_state | Current DWC state | BOOLEAN | false | Used to prevent DWC duration extension on re-sending the same input | |
dwc_lock | DWC lock state | BOOLEAN | false | DWC lock state | |
last_activation_ts | Last execution timestamp | NUMBER | 0 | s | Last execution timestamp in seconds from epoch |
next_activation_ts | Next execution timestamp | NUMBER | 0 | s | Next execution timestamp in seconds from epoch |
# Source Code
View Volang source
extern fn std::next_activation_at() {
operation_mode = config::get("operation_mode")
if (operation_mode == 0) { // schedule
schedule_id = config::get("schedule")
return schedule::get_next_activation_ts(schedule_id)
}
return 0
}
extern fn process() {
channel = input::channel()
value = input::value()
now = time::uptime()
// inputs
air_temp = input::get("air_temp")
floor_temp = input::get("floor_temp")
outside_temp = input::get("outside_temp")
presence = input::get("presence")
dwc = input::get("dwc")
comfort_forced = input::get("comfort")
protection_forced = input::get("protection")
// configs
thermal_mode = config::get("thermal_mode") // 0=heating and cooling, 1=heating only, 2=cooling only
operation_mode = config::get("operation_mode") // 0=schedule, 1=manual
comfort_heating_temp = config::get("comfort_heating_temp")
comfort_cooling_temp = config::get("comfort_cooling_temp")
eco_heating_temp_diff = config::get("eco_heating_temp_diff")
eco_cooling_temp_diff = config::get("eco_cooling_temp_diff")
frost_protection_temp = config::get("frost_protection_temp")
overheat_protection_temp = config::get("overheat_protection_temp")
dwc_delay_sec = config::get("dwc_delay")
presence_extension_duration = config::get("presence_extension_duration")
last_dwc_state = state::get("dwc_state")
if (channel == "dwc") {
// on DWC switch
if ((value and !last_dwc_state) or (!value and last_dwc_state)) {
callback::clear()
callback::set(dwc_delay_sec * 1000 + 5, "process")
state::set("dwc_state_change_ts", now)
state::set("dwc_state", value)
}
}
last_dwc_ts = state::get("dwc_state_change_ts")
dwc_duration_sec = (now - last_dwc_ts) / 1000.0
fn round2decimal(temp_deviation) {
return math::round(100.0 * temp_deviation) / 100.0
}
// define:
// - comfort mode: 0=eco, 1=comfort, 2=protection
// - target temperatures for heating and cooling
comfort_mode = 0
target_heating_temp = 0
target_cooling_temp = 0
if (operation_mode == 0) { // schedule
schedule_id = config::get("schedule")
comfort_mode = schedule::get_entry_type(schedule_id)
}
if (comfort_mode == 1 or comfort_forced) { // comfort
target_heating_temp = comfort_heating_temp
target_cooling_temp = comfort_cooling_temp
} else if (comfort_mode == 2 or protection_forced) { // protection
target_heating_temp = frost_protection_temp
target_cooling_temp = overheat_protection_temp
} else { // no entry - default: eco
target_heating_temp = comfort_heating_temp - eco_heating_temp_diff
target_cooling_temp = comfort_cooling_temp + eco_cooling_temp_diff
}
// define:
// - chosen thermal mode: 0=idle, 1=heating, 2=cooling
// - temperature deviation
chosen_thermal_mode = 0 // idle
target_temp = air_temp
temp_deviation = 0.0
outside_temp_helps = false
outside_temp_sensor = outside_temp != -1000
if (air_temp < target_heating_temp and (thermal_mode == 0 or thermal_mode == 1)) {
chosen_thermal_mode = 1 // heating
target_temp = target_heating_temp
temp_deviation = target_temp - air_temp // positive
outside_temp_helps = outside_temp_sensor and (outside_temp > target_heating_temp)
}
if (air_temp > target_cooling_temp and (thermal_mode == 0 or thermal_mode == 2)) {
chosen_thermal_mode = 2 // cooling
target_temp = target_cooling_temp
temp_deviation = target_temp - air_temp // negative
outside_temp_helps = outside_temp_sensor and (outside_temp < target_cooling_temp)
}
if (!outside_temp_helps and (dwc and dwc_duration_sec > dwc_delay_sec)) {
state::set("dwc_lock", true)
}
if (state::get("dwc_lock") and !dwc and dwc_duration_sec > dwc_delay_sec) {
state::set("dwc_lock", false)
}
dwc_lock_active = state::get("dwc_lock")
protective_action_required = air_temp < frost_protection_temp or air_temp > overheat_protection_temp
if (dwc_lock_active and !protective_action_required) {
output::set("temp_deviation", round2decimal(0.0))
output::set("target_temp", round2decimal(target_temp))
return
}
output::set("temp_deviation", round2decimal(temp_deviation))
output::set("target_temp", round2decimal(target_temp))
}
process()
# Climate Schedules
The Climate Regulator uses a Climate-type schedule to define temperature setpoints across a 24-hour daily cycle. Each schedule entry carries a numeric target temperature; the regulator compares it against measured values to drive heating or cooling outputs.
Different temperature profiles for weekdays, weekends, or custom situations (away, party, etc.) are achieved by combining the schedule with Operation Modes rather than hard-coding days of the week.
For details on configuring Climate schedules in the visual editor see Voldeno Studio – Schedules.
