1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
| number:
- platform: template
id: stooklijn_min_oat
name: "Stooklijn Minimum Buitentemperatuur"
min_value: -15
max_value: 4
step: 1
restore_value: yes
initial_value: -5
unit_of_measurement: "°C"
optimistic: true
icon: mdi:thermometer-minus
on_value:
then:
- lambda: |-
static unsigned long last_publish_time = 0;
// static unsigned long defrosting_last_off_time = 0;
// static unsigned long compressor_last_off_time = 0;
static bool compressorHzLessThanEqualOneInLastMinute = false;
static bool OvershootLogic = false;
if(id(bedrijfsmodus).state != 2 ) return;
if(isnan(id(buiten_temp).state)) return;
if(!id(stooklijn_on_off).state) return;
if (millis() - last_publish_time < 10000) {
return;
}
last_publish_time = millis();
static float prev_oat = 0; // hold previous script run ota value to check if it changed since last run
static float prev_tr = id(water_temp_retour).state;
float temp_new_target = id(watertemp_target).state; //new anti-pendel target
static bool target_reached = false; //system logic (to switch off after target is reached)
static int state = 0; // State variable to track the current step
static unsigned long last_offset_publish_time = 0;
float oat = round(id(buiten_temp).state);
const float Z = ((float)id(stooklijn_min_wtemp).state-(float)id(stooklijn_max_wtemp).state) / ((float)id(stooklijn_max_oat).state - (float)id(stooklijn_min_oat).state);
ESP_LOGD("stooklijn", "verwarmen volgens stooklijn, met buitentemp: %.1f, Z: %.1f",oat, Z);
// Check compressor_hz in the past minute
// ESP_LOGD("debug", "Initial Compressor Hz value: %.0f", id(compressor_hz).state);
unsigned long currentTime = millis();
// bool compressorHzLessThanEqualOneInLastMinute = false;
ESP_LOGD("debug", "Controlleer status compressor");
for (unsigned long time = currentTime - 100 * 1000; time <= currentTime; time += 1000) {
// Check if compressor_hz was less than or equal to 1 at any moment in the past minute
if (id(compressor_hz).raw_state <= 0.00) {
compressorHzLessThanEqualOneInLastMinute = true;
ESP_LOGD("debug", "Compressor Hz is 0.00, (her)start");
break; // No need to continue checking
}
}
// --------warmtepomp is actief ----------------------
if (id(compressor_running).state) {
ESP_LOGD("debug", "Compressor is running - checking overshoot control");
ESP_LOGD("debug", "overshootcontrol_on_off.state: %s", id(overshootcontrol_on_off).state ? "true" : "false");
ESP_LOGD("debug", "OvershootLogic: %s", OvershootLogic ? "true" : "false");
if ((id(overshootcontrol_on_off).state && compressorHzLessThanEqualOneInLastMinute) || (id(overshootcontrol_on_off).state && OvershootLogic)) {
float temp_target_incremented = 0.0;
switch (state) {
case 0:
// als defrost stille modus uit
if (id(defrosting).state) {
id(silent_mode_switch).turn_off();
ESP_LOGD("debug", "Silent Mode switch set to OFF");
}
ESP_LOGD("debug", "gaat naar case 0");
id(overshoot_stooklijn_offset).publish_state(-4); // stooklijn verlaging in aantal graden Ta
OvershootLogic = true;
ESP_LOGD("debug", "OvershootLogic: %s", OvershootLogic ? "true" : "false");
last_offset_publish_time = millis();
state++;
id(stooklijn_target) = (int)round(Z * (oat - id(stooklijn_min_oat).state) + id(stooklijn_max_wtemp).state) +
(id(wp_stooklijn_offset).state) + (id(overshoot_stooklijn_offset).state);
ESP_LOGD("stooklijn", "gecorrigeerd target stap 1 overshoot: %.1f", id(stooklijn_target));
id(watertemp_target).publish_state(id(stooklijn_target));
break;
case 1:
ESP_LOGD("debug", "gaat naar case 1");
ESP_LOGD("debug", "Millis difference: %lu", millis() - last_offset_publish_time);
ESP_LOGD("debug", "OvershootLogic: %s", OvershootLogic ? "true" : "false");
if (millis() - last_offset_publish_time >= 3 * 60 * 1000) { // duur van 1e verlaging in minuten
ESP_LOGD("debug", "bezig met timer case 1");
ESP_LOGD("debug", "Millis difference: %lu", millis() - last_offset_publish_time);
ESP_LOGD("debug", "Seconds difference: %.2f", (millis() - last_offset_publish_time) / 1000.0);
id(overshoot_stooklijn_offset).publish_state(-3); // stooklijn verlaging in aantal graden Ta, 1 hoger dan vorige stap
ESP_LOGD("debug", "Published -3, millis: %lu", millis());
last_offset_publish_time = millis();
state++;
id(stooklijn_target) = (int)round(Z * (oat - id(stooklijn_min_oat).state) + id(stooklijn_max_wtemp).state) +
(id(wp_stooklijn_offset).state) + (id(overshoot_stooklijn_offset).state);
ESP_LOGD("stooklijn", "gecorrigeerd target stap 2 overshoot: %.1f", id(stooklijn_target));
id(watertemp_target).publish_state(id(stooklijn_target));
}
break;
case 2:
ESP_LOGD("debug", "gaat naar case 2");
ESP_LOGD("debug", "OvershootLogic: %s", OvershootLogic ? "true" : "false");
if (millis() - last_offset_publish_time >= 4 * 60 * 1000) { // duur van 2e verlaging in minuten
ESP_LOGD("debug", "bezig met timer case 2");
ESP_LOGD("debug", "Millis difference: %lu", millis() - last_offset_publish_time);
ESP_LOGD("debug", "Seconds difference: %.2f", (millis() - last_offset_publish_time) / 1000.0);
id(overshoot_stooklijn_offset).publish_state(-2); // stooklijn verlaging in aantal graden Ta, 1 hoger dan vorige stap
ESP_LOGD("debug", "Published -2, millis: %lu", millis());
last_offset_publish_time = millis();
state++;
id(stooklijn_target) = (int)round(Z * (oat - id(stooklijn_min_oat).state) + id(stooklijn_max_wtemp).state) +
(id(wp_stooklijn_offset).state) + (id(overshoot_stooklijn_offset).state);
ESP_LOGD("stooklijn", "gecorrigeerd target stap 3 overshoot: %.1f", id(stooklijn_target));
id(watertemp_target).publish_state(id(stooklijn_target));
}
break;
case 3:
ESP_LOGD("debug", "gaat naar case 3");
ESP_LOGD("debug", "OvershootLogic: %s", OvershootLogic ? "true" : "false");
if (millis() - last_offset_publish_time >= 4 * 60 * 1000) {
ESP_LOGD("debug", "bezig met timer case 3");
ESP_LOGD("debug", "Millis difference: %lu", millis() - last_offset_publish_time);
ESP_LOGD("debug", "Seconds difference: %.2f", (millis() - last_offset_publish_time) / 1000.0);
id(overshoot_stooklijn_offset).publish_state(-1);
ESP_LOGD("debug", "Published -1, millis: %lu", millis());
last_offset_publish_time = millis();
state++;
id(stooklijn_target) = (int)round(Z * (oat - id(stooklijn_min_oat).state) + id(stooklijn_max_wtemp).state) +
(id(wp_stooklijn_offset).state) + (id(overshoot_stooklijn_offset).state);
ESP_LOGD("stooklijn", "gecorrigeerd target stap 4 overshoot: %.1f", id(stooklijn_target));
id(watertemp_target).publish_state(id(stooklijn_target));
}
break;
case 4:
ESP_LOGD("debug", "gaat naar case 4");
ESP_LOGD("debug", "OvershootLogic: %s", OvershootLogic ? "true" : "false");
if (millis() - last_offset_publish_time >= 4 * 60 * 1000) {
ESP_LOGD("debug", "bezig met timer case 4");
ESP_LOGD("debug", "Millis difference: %lu", millis() - last_offset_publish_time);
ESP_LOGD("debug", "Seconds difference: %.2f", (millis() - last_offset_publish_time) / 1000.0);
id(overshoot_stooklijn_offset).publish_state(-0);
ESP_LOGD("debug", "Published -0, millis: %lu", millis());
OvershootLogic = false;
ESP_LOGD("debug", "KLAAR");
id(stooklijn_target) = (int)round(Z * (oat - id(stooklijn_min_oat).state) + id(stooklijn_max_wtemp).state) +
(id(wp_stooklijn_offset).state) + (id(overshoot_stooklijn_offset).state);
ESP_LOGD("stooklijn", "origineel target: %.1f", id(stooklijn_target));
id(watertemp_target).publish_state(id(stooklijn_target));
last_offset_publish_time = millis(); // Update the last offset publish time
}
break;
}
}
temp_new_target = std::min(temp_new_target, id(stooklijn_target));
ESP_LOGD("target", "RETURN_TEMP: %.1f OUTLET_TEMP: %.1f TARGET: %.1f NEW_TARGET: %.1f ",
id(water_temp_retour).state, id(water_temp_aanvoer).state, id(stooklijn_target), temp_new_target);
id(pendel_watertemp_target).publish_state(temp_new_target);
id(water_temp_target_output).set_level(temp_new_target * 0.01);
} else if (!id(compressor_running).state) {
id(water_temp_target_output).set_level(id(stooklijn_target) * 0.01);
target_reached = false;
}
// ----------------calculate stooklijn target---------------------------------
if(prev_oat != oat || id(force_update_stooklijn)){ // if no oat change, no update needed, unless forced or first run
prev_oat = oat;
id(force_update_stooklijn) = false; //reset force boolean
const float Z = ((float)id(stooklijn_min_wtemp).state-(float)id(stooklijn_max_wtemp).state) / ((float)id(stooklijn_max_oat).state - (float)id(stooklijn_min_oat).state);
ESP_LOGD("stooklijn", "verwarmen volgens stooklijn, met buitentemp: %.1f, Z: %.1f",oat, Z);
if(oat < id(stooklijn_min_oat).state) { //if oat below minimum oat, clamp to minimum value
oat = id(stooklijn_min_oat).state;
} else if(oat > id(stooklijn_max_oat).state) { //if oat above max value, clamp to maximum value
oat = id(stooklijn_max_oat).state;
}
id(stooklijn_target) = (int)round(Z * (oat - id(stooklijn_min_oat).state) + id(stooklijn_max_wtemp).state) + (id(wp_stooklijn_offset).state) + (id(overshoot_stooklijn_offset).state);
ESP_LOGD("stooklijn", "New stooklijn target value (after correction): %.1f", id(stooklijn_target));
id(watertemp_target).publish_state(id(stooklijn_target)); //publish new stooklijn value to watertemp value sensor
} |