瀏覽代碼

init

master
Robin Thoni 1 年之前
當前提交
8476f63443
簽署人: Robin THONI <robin@rthoni.com> GPG 金鑰 ID: 4E09DEF46B99E61E
共有 1 個檔案被更改,包括 453 行新增0 行删除
  1. 453
    0
      zuno-test.ino

+ 453
- 0
zuno-test.ino 查看文件

@@ -0,0 +1,453 @@
1
+#include "EEPROM.h"
2
+
3
+#include <ZUNO_OneWire.h>
4
+#include <ZUNO_DS18B20.h>
5
+
6
+#define PIN_RELAY_BURNER 12
7
+#define PIN_RELAY_WATER_LOAD 11
8
+#define PIN_RELAY_WATER_RECYCLING 10
9
+#define PIN_RELAY_HEAT_PUMP_1 9
10
+
11
+#define PIN_INPUT_BURNER_RUNNING 16
12
+#define PIN_INPUT_BURNER_ALARM 17
13
+#define PIN_INPUT_BOILER_ALARM 18
14
+
15
+#define PIN_ONEWIRE 15
16
+
17
+#define EEPROM_MAGIC_VALUE 0x4242
18
+#define EEPROM_MAGIC_ADDR 0
19
+#define EEPROM_REQUESTED_TEMP_ADDR_BASE (EEPROM_MAGIC_ADDR + 2)
20
+#define EEPROM_THERMOSTAT_MODE_BASE (EEPROM_REQUESTED_TEMP_ADDR_BASE + 4) // req temp is 2 bytes per thermostat
21
+
22
+#define ZW_PARAM_BASE 64
23
+#define ZW_PARAM_UPDATE_UNSOLICITED_TIME_BASE (ZW_PARAM_BASE) // 64, 65
24
+#define ZW_PARAM_UPDATE_THRESHOLD_TEMP_BASE (ZW_PARAM_UPDATE_UNSOLICITED_TIME_BASE + 2) // 66, 67
25
+#define ZW_PARAM_MIN_CYCLE_DURATION_BASE (ZW_PARAM_UPDATE_THRESHOLD_TEMP_BASE + 2) // 68, 69
26
+#define ZW_PARAM_TOLERANCE_TEMP_BASE (ZW_PARAM_MIN_CYCLE_DURATION_BASE + 2) // 70, 71
27
+
28
+#define LOG_INIT() Serial.begin(9600)
29
+#define LOG_WRITE(x) Serial.print(x)
30
+#define LOG_WRITELN(x) Serial.println(x)
31
+
32
+//#define LOG_INIT()
33
+//#define LOG_WRITE(x)
34
+//#define LOG_WRITELN(x)
35
+
36
+#define DALLAS_ADDR_SIZE 8
37
+
38
+struct thermostat_t {
39
+  byte dallasAddress[DALLAS_ADDR_SIZE];
40
+  word currentTemp;
41
+  
42
+  byte requestedMode;
43
+  word requestedTemp;
44
+  
45
+  unsigned long lastZwaveReadTime;
46
+  word lastZwaveReadTemp;
47
+  
48
+  word updateUnsolicitedTime;
49
+  word updateThresholdTemp;
50
+  
51
+  word minCycleDuration;
52
+  word toleranceTemp;
53
+
54
+  bool requestHeat;
55
+};
56
+
57
+struct output_t {
58
+  int pin;
59
+  bool currentValue;
60
+  unsigned long lastChangedTime;
61
+};
62
+
63
+OneWire oneWire(PIN_ONEWIRE);
64
+DS18B20Sensor dallas(&oneWire);
65
+
66
+
67
+#define THERMOSTATS_COUNT 2
68
+#define THERMOSTAT_HEAT_IDX 0
69
+#define THERMOSTAT_WATER_IDX 1
70
+thermostat_t thermostats[THERMOSTATS_COUNT];
71
+
72
+#define OUTPUTS_COUNT 4
73
+#define OUTPUT_BURNER_IDX 0
74
+#define OUTPUT_WATER_LOAD_IDX 1
75
+#define OUTPUT_WATER_RECYCLING_IDX 2
76
+#define OUTPUT_HEAT_PUMP_1_IDX 3
77
+output_t outputs[OUTPUTS_COUNT];
78
+
79
+ZUNO_SETUP_CHANNELS(
80
+  ZUNO_THERMOSTAT(THERMOSTAT_FLAGS_OFF | THERMOSTAT_FLAGS_HEAT, THERMOSTAT_UNITS_CELSIUS, THERMOSTAT_RANGE_POS, 10, getHeaterMode, setHeaterMode, getHeaterTemp, setHeaterTemp), // Heater
81
+  ZUNO_SENSOR_MULTILEVEL(ZUNO_SENSOR_MULTILEVEL_TYPE_WATER_TEMPERATURE, SENSOR_MULTILEVEL_SCALE_CELSIUS, METER_SIZE_TWO_BYTES, SENSOR_MULTILEVEL_PRECISION_TWO_DECIMALS, getHeaterCurrentTemp), // Heater temp
82
+  ZUNO_THERMOSTAT(THERMOSTAT_FLAGS_OFF | THERMOSTAT_FLAGS_HEAT, THERMOSTAT_UNITS_CELSIUS, THERMOSTAT_RANGE_POS, 10, getWaterMode, setWaterMode, getWaterTemp, setWaterTemp), // Water
83
+  ZUNO_SENSOR_MULTILEVEL(ZUNO_SENSOR_MULTILEVEL_TYPE_WATER_TEMPERATURE, SENSOR_MULTILEVEL_SCALE_CELSIUS, METER_SIZE_TWO_BYTES, SENSOR_MULTILEVEL_PRECISION_TWO_DECIMALS, getWaterCurrentTemp), // Water temp
84
+  ZUNO_SWITCH_BINARY(getRelayBurner, setRelayBurner), // Burner
85
+  ZUNO_SWITCH_BINARY(getRelayWaterLoad, setRelayWaterLoad), // Water load pump
86
+  ZUNO_SWITCH_BINARY(getRelayWaterRecycling, setRelayWaterRecycling), // Water recycling pump
87
+  ZUNO_SWITCH_BINARY(getRelayHeatPump1, setRelayHeatPump1), // Heater pump Floor 1
88
+  ZUNO_SENSOR_BINARY(ZUNO_SENSOR_BINARY_TYPE_GENERAL_PURPOSE, getInputBurnerRunning), // Burner running
89
+  ZUNO_SENSOR_BINARY(ZUNO_SENSOR_BINARY_TYPE_GENERAL_PURPOSE, getInputBurnerAlarm), // Burner alarm
90
+  ZUNO_SENSOR_BINARY(ZUNO_SENSOR_BINARY_TYPE_GENERAL_PURPOSE, getInputBoilerAlarm)  // Boiler alarm
91
+);
92
+ZUNO_SETUP_CFGPARAMETER_HANDLER(config_parameter_changed);
93
+
94
+byte EEPROM_put(dword address, void * value, word val_size) {
95
+  byte res = EEPROM.put(address, value, val_size);
96
+  if (!res) {
97
+    LOG_WRITELN("EEPROM put: FAIL");
98
+  }
99
+  return res;
100
+}
101
+
102
+byte EEPROM_get(dword address, void * value, word val_size) {
103
+  byte res = EEPROM.get(address, value, val_size);
104
+  if (!res) {
105
+    LOG_WRITELN("EEPROM put: FAIL");
106
+  }
107
+  return res;
108
+}
109
+
110
+word abs_diff(word v1, word v2) {
111
+  if (v1 > v2) {
112
+    return v1 - v2;
113
+  }
114
+  return v2 - v1;
115
+}
116
+
117
+void setup() {
118
+  delay(2000);
119
+  LOG_INIT();
120
+  LOG_WRITELN("setup BEGIN");
121
+  
122
+  pinMode(PIN_INPUT_BURNER_RUNNING, INPUT);
123
+  pinMode(PIN_INPUT_BURNER_ALARM, INPUT);
124
+  pinMode(PIN_INPUT_BOILER_ALARM, INPUT);
125
+
126
+  word magic_value[1] = {0};
127
+  EEPROM_get(EEPROM_MAGIC_ADDR, magic_value, sizeof(magic_value));
128
+  if (magic_value[0] != EEPROM_MAGIC_VALUE) {
129
+    LOG_WRITE("First init: ");
130
+    LOG_WRITELN((int)magic_value[0]);
131
+
132
+    zunoSaveCFGParam(ZW_PARAM_UPDATE_UNSOLICITED_TIME_BASE + 0, 600); // 10 min
133
+    zunoSaveCFGParam(ZW_PARAM_UPDATE_UNSOLICITED_TIME_BASE + 1, 600); // 10 min
134
+
135
+    zunoSaveCFGParam(ZW_PARAM_UPDATE_THRESHOLD_TEMP_BASE + 0, 50); // 0.5 °C
136
+    zunoSaveCFGParam(ZW_PARAM_UPDATE_THRESHOLD_TEMP_BASE + 1, 50); // 0.5 °C
137
+
138
+    zunoSaveCFGParam(ZW_PARAM_MIN_CYCLE_DURATION_BASE + 0, 60); // 1 min
139
+    zunoSaveCFGParam(ZW_PARAM_MIN_CYCLE_DURATION_BASE + 1, 60); // 1 min
140
+
141
+    zunoSaveCFGParam(ZW_PARAM_TOLERANCE_TEMP_BASE + 0, 2000); // 20 °C
142
+    zunoSaveCFGParam(ZW_PARAM_TOLERANCE_TEMP_BASE + 1, 1000); // 10 °C
143
+
144
+    word requestedTemps[2] = {8000, 3000}; // 80 °C; 30 °C
145
+    EEPROM_put(EEPROM_REQUESTED_TEMP_ADDR_BASE, requestedTemps, sizeof(requestedTemps));
146
+
147
+    byte modes[2] = {THERMOSTAT_MODE_OFF, THERMOSTAT_MODE_OFF};
148
+    EEPROM_put(EEPROM_THERMOSTAT_MODE_BASE, modes, sizeof(modes));
149
+
150
+    magic_value[0] = EEPROM_MAGIC_VALUE;
151
+    EEPROM_put(EEPROM_MAGIC_ADDR, magic_value, sizeof(magic_value));
152
+  }
153
+
154
+  byte dallasAddresses[DALLAS_ADDR_SIZE * 2];
155
+  byte dallasAddressesCount = dallas.findAllSensors(dallasAddresses); // TODO retry if not 2
156
+  LOG_WRITE("Found ");
157
+  LOG_WRITE(dallasAddressesCount);
158
+  LOG_WRITELN(" sensors");
159
+
160
+  word requestedTemps[2] = {8000, 3000};
161
+  EEPROM_get(EEPROM_REQUESTED_TEMP_ADDR_BASE, requestedTemps, sizeof(requestedTemps));
162
+  byte modes[2] = {THERMOSTAT_MODE_OFF, THERMOSTAT_MODE_OFF};
163
+  EEPROM_get(EEPROM_THERMOSTAT_MODE_BASE, modes, sizeof(modes));
164
+
165
+  for (int ti = 0; ti < THERMOSTATS_COUNT; ++ti) {
166
+    memcpy(thermostats[ti].dallasAddress, &dallasAddresses[ti * DALLAS_ADDR_SIZE], DALLAS_ADDR_SIZE);
167
+    thermostats[ti].currentTemp = BAD_TEMP;
168
+    
169
+    thermostats[ti].requestedMode = modes[ti];
170
+    thermostats[ti].requestedTemp = requestedTemps[ti];
171
+    
172
+    thermostats[ti].lastZwaveReadTime = 0;
173
+    thermostats[ti].lastZwaveReadTemp = BAD_TEMP;
174
+    
175
+    thermostats[ti].updateUnsolicitedTime = zunoLoadCFGParam(ZW_PARAM_UPDATE_UNSOLICITED_TIME_BASE + ti);
176
+    thermostats[ti].updateThresholdTemp = zunoLoadCFGParam(ZW_PARAM_UPDATE_THRESHOLD_TEMP_BASE + ti);
177
+    
178
+    thermostats[ti].minCycleDuration = zunoLoadCFGParam(ZW_PARAM_MIN_CYCLE_DURATION_BASE + ti);
179
+    thermostats[ti].toleranceTemp = zunoLoadCFGParam(ZW_PARAM_TOLERANCE_TEMP_BASE + ti);
180
+
181
+    thermostats[ti].requestHeat = false;
182
+  }
183
+
184
+  outputs[OUTPUT_BURNER_IDX].pin = PIN_RELAY_BURNER;
185
+  outputs[OUTPUT_WATER_LOAD_IDX].pin = PIN_RELAY_WATER_LOAD;
186
+  outputs[OUTPUT_WATER_RECYCLING_IDX].pin = PIN_RELAY_WATER_RECYCLING;
187
+  outputs[OUTPUT_HEAT_PUMP_1_IDX].pin = PIN_RELAY_HEAT_PUMP_1;
188
+  for (int oi = 0; oi < OUTPUTS_COUNT; ++oi) {
189
+    outputs[oi].currentValue = 0;
190
+    outputs[oi].lastChangedTime = 0;
191
+    pinMode(outputs[oi].pin, OUTPUT);
192
+    digitalWrite(outputs[oi].pin, 0);
193
+  }
194
+  LOG_WRITELN("setup END");
195
+}
196
+
197
+void updateValues() {
198
+  // Temp sensors
199
+  for (int ti = 0; ti < THERMOSTATS_COUNT; ++ti) {
200
+    word newValue = BAD_TEMP;
201
+    for (int j = 0; j < 3 && (newValue == BAD_TEMP || newValue == 0); ++j) {
202
+      newValue = dallas.getTemperature(thermostats[ti].dallasAddress) * 100;
203
+    }
204
+    thermostats[ti].currentTemp = newValue;
205
+
206
+    if (thermostats[ti].requestedMode == THERMOSTAT_MODE_HEAT) {
207
+      if (thermostats[ti].currentTemp <= thermostats[ti].requestedTemp - thermostats[ti].toleranceTemp && !thermostats[ti].requestHeat) { // TODO Check overflow
208
+        LOG_WRITE("Thermostat ");
209
+        LOG_WRITE(ti);
210
+        LOG_WRITE(" is too low: ");
211
+        LOG_WRITE((int)thermostats[ti].currentTemp);
212
+        LOG_WRITE(" << ");
213
+        LOG_WRITELN((int)thermostats[ti].requestedTemp);
214
+        thermostats[ti].requestHeat = true;
215
+      }
216
+      else if (thermostats[ti].currentTemp >= thermostats[ti].requestedTemp && thermostats[ti].requestHeat) {
217
+        LOG_WRITE("Thermostat ");
218
+        LOG_WRITE(ti);
219
+        LOG_WRITE(" is acceptable: ");
220
+        LOG_WRITE((int)thermostats[ti].currentTemp);
221
+        LOG_WRITE(" >= ");
222
+        LOG_WRITELN((int)thermostats[ti].requestedTemp);
223
+        thermostats[ti].requestHeat = false;
224
+      }
225
+    }
226
+    else {
227
+      if (thermostats[ti].requestHeat) {
228
+        LOG_WRITE("Thermostat ");
229
+        LOG_WRITE(ti);
230
+        LOG_WRITELN(" has been turned OFF");
231
+        thermostats[ti].requestHeat = false;
232
+        setRelayManual(OUTPUT_BURNER_IDX, 0);
233
+        setRelayManual(OUTPUT_WATER_LOAD_IDX, 0);
234
+      }
235
+    }
236
+  }
237
+}
238
+
239
+void updateZwave() {
240
+  for (int ti = 0; ti < THERMOSTATS_COUNT; ++ti) {
241
+    const word oldValue = thermostats[ti].lastZwaveReadTemp;
242
+    const word newValue = thermostats[ti].currentTemp;
243
+    if (abs_diff(newValue, oldValue) > thermostats[ti].updateThresholdTemp) {
244
+      LOG_WRITE("Sensor ");
245
+      LOG_WRITE(ti);
246
+      LOG_WRITE(" value changed from ");
247
+      LOG_WRITE((int)oldValue);
248
+      LOG_WRITE(" to ");
249
+      LOG_WRITELN((int)newValue);
250
+      zunoSendReport(2 + (ti * 2)); // 2 or 4
251
+    }
252
+    else if (millis() - thermostats[ti].lastZwaveReadTime > (unsigned long)thermostats[ti].updateUnsolicitedTime * 1000) {
253
+      LOG_WRITE("Sensor ");
254
+      LOG_WRITE(ti);
255
+      LOG_WRITE(" unsolicited update to ");
256
+      LOG_WRITELN((int)newValue);
257
+      zunoSendReport(2 + (ti * 2)); // 2 or 4
258
+    }
259
+  }
260
+}
261
+
262
+void updateOutputs() {
263
+
264
+  // TODO Handle min cycle
265
+  bool burnerRequested = thermostats[THERMOSTAT_HEAT_IDX].requestHeat || (thermostats[THERMOSTAT_WATER_IDX].requestHeat && thermostats[THERMOSTAT_HEAT_IDX].currentTemp < thermostats[THERMOSTAT_WATER_IDX].requestedTemp);
266
+  bool waterLoadRequested = thermostats[THERMOSTAT_WATER_IDX].requestHeat && thermostats[THERMOSTAT_HEAT_IDX].currentTemp > thermostats[THERMOSTAT_WATER_IDX].currentTemp;
267
+
268
+  if (thermostats[THERMOSTAT_HEAT_IDX].requestedMode == THERMOSTAT_MODE_HEAT || thermostats[THERMOSTAT_WATER_IDX].requestedMode == THERMOSTAT_MODE_HEAT) {
269
+    setRelay(OUTPUT_BURNER_IDX, burnerRequested);
270
+  }
271
+  if (thermostats[THERMOSTAT_WATER_IDX].requestedMode == THERMOSTAT_MODE_HEAT) {
272
+    setRelay(OUTPUT_WATER_LOAD_IDX, waterLoadRequested);
273
+  }
274
+}
275
+
276
+void loop() {
277
+  updateValues();
278
+  updateZwave();
279
+  updateOutputs();
280
+  delay(100);
281
+}
282
+
283
+// ZWave callbacks
284
+void config_parameter_changed(byte param, word value) {
285
+    LOG_WRITE("Zwave param ");
286
+    LOG_WRITE((int)param);
287
+    LOG_WRITE(": ");
288
+    LOG_WRITELN((int)value);
289
+
290
+    if (param >= ZW_PARAM_UPDATE_UNSOLICITED_TIME_BASE && param < ZW_PARAM_UPDATE_UNSOLICITED_TIME_BASE + THERMOSTATS_COUNT) {
291
+      thermostats[param - ZW_PARAM_UPDATE_UNSOLICITED_TIME_BASE].updateUnsolicitedTime = value;
292
+    }
293
+    else if (param >= ZW_PARAM_UPDATE_THRESHOLD_TEMP_BASE && param < ZW_PARAM_UPDATE_THRESHOLD_TEMP_BASE + THERMOSTATS_COUNT) {
294
+      thermostats[param - ZW_PARAM_UPDATE_THRESHOLD_TEMP_BASE].updateThresholdTemp = value;
295
+    }
296
+    else if (param >= ZW_PARAM_MIN_CYCLE_DURATION_BASE && param < ZW_PARAM_MIN_CYCLE_DURATION_BASE + THERMOSTATS_COUNT) {
297
+      thermostats[param - ZW_PARAM_MIN_CYCLE_DURATION_BASE].minCycleDuration = value;
298
+    }
299
+    else if (param >= ZW_PARAM_TOLERANCE_TEMP_BASE && param < ZW_PARAM_TOLERANCE_TEMP_BASE + THERMOSTATS_COUNT) {
300
+      thermostats[param - ZW_PARAM_TOLERANCE_TEMP_BASE].toleranceTemp = value;
301
+    }
302
+}
303
+
304
+// Thermostats
305
+void setMode(int ti, byte mode) {
306
+  LOG_WRITE("Thermostat ");
307
+  LOG_WRITE(ti);
308
+  LOG_WRITE(" update: mode: ");
309
+  LOG_WRITELN((int)mode);
310
+  thermostats[ti].requestedMode = mode;
311
+  EEPROM_put(EEPROM_THERMOSTAT_MODE_BASE + (sizeof(thermostats[ti].requestedMode) * ti), &thermostats[ti].requestedMode, sizeof(thermostats[ti].requestedMode));
312
+}
313
+byte getMode(int ti) {
314
+  return thermostats[ti].requestedMode;
315
+}
316
+void setTemp(int ti, byte mode, word temp) {
317
+  LOG_WRITE("Thermostat ");
318
+  LOG_WRITE(ti);
319
+  LOG_WRITE(" update: mode: ");
320
+  LOG_WRITE((int)mode);
321
+  LOG_WRITE(" temp: ");
322
+  LOG_WRITELN((int)temp);
323
+  thermostats[ti].requestedMode = mode;
324
+  EEPROM_put(EEPROM_THERMOSTAT_MODE_BASE + (sizeof(thermostats[ti].requestedMode) * ti), &thermostats[ti].requestedMode, sizeof(thermostats[ti].requestedMode));
325
+  if (mode == THERMOSTAT_MODE_HEAT) {
326
+    thermostats[ti].requestedTemp = temp * 10;// Z-Wave thermostat precision is 0.1
327
+    EEPROM_put(EEPROM_REQUESTED_TEMP_ADDR_BASE + (sizeof(thermostats[ti].requestedTemp) * ti), &thermostats[ti].requestedTemp, sizeof(thermostats[ti].requestedTemp));
328
+  }
329
+}
330
+word getTemp(int ti, byte mode) {
331
+  if (mode == THERMOSTAT_MODE_HEAT) {
332
+    return thermostats[ti].requestedTemp / 10;// Z-Wave thermostat precision is 0.1
333
+  }
334
+  return 0;
335
+}
336
+word getCurrentTemp(int ti) {
337
+  LOG_WRITE("Sensor ");
338
+  LOG_WRITE(ti);
339
+  LOG_WRITELN(" Zwave update");
340
+  thermostats[ti].lastZwaveReadTime = millis();
341
+  thermostats[ti].lastZwaveReadTemp = thermostats[ti].currentTemp;
342
+  return thermostats[ti].lastZwaveReadTemp;
343
+}
344
+
345
+
346
+
347
+// Heater
348
+void setHeaterMode(byte mode) {
349
+  setMode(THERMOSTAT_HEAT_IDX, mode);
350
+}
351
+byte getHeaterMode(){
352
+  return getMode(THERMOSTAT_HEAT_IDX);
353
+}
354
+void setHeaterTemp(byte mode, word temp) {
355
+  setTemp(THERMOSTAT_HEAT_IDX, mode, temp);
356
+}
357
+word getHeaterTemp(byte mode) {
358
+  return getTemp(THERMOSTAT_HEAT_IDX, mode);
359
+}
360
+word getHeaterCurrentTemp() {
361
+  return getCurrentTemp(THERMOSTAT_HEAT_IDX);
362
+}
363
+
364
+// Water
365
+void setWaterMode(byte mode) {
366
+  setMode(THERMOSTAT_WATER_IDX, mode);
367
+}
368
+byte getWaterMode(){
369
+  return getMode(THERMOSTAT_WATER_IDX);
370
+}
371
+void setWaterTemp(byte mode, word temp) {
372
+  setTemp(THERMOSTAT_WATER_IDX, mode, temp);
373
+}
374
+word getWaterTemp(byte mode) {
375
+  return getTemp(THERMOSTAT_WATER_IDX, mode);
376
+}
377
+word getWaterCurrentTemp() {
378
+  return getCurrentTemp(THERMOSTAT_WATER_IDX);
379
+}
380
+
381
+// Raw outputs
382
+
383
+void setRelay(int oi, bool value) {
384
+  if (value != outputs[oi].currentValue) {
385
+    LOG_WRITE("Output ");
386
+    LOG_WRITE(oi);
387
+    LOG_WRITE(" update: value: ");
388
+    LOG_WRITELN((int)value);
389
+    outputs[oi].currentValue = value;
390
+    outputs[oi].lastChangedTime = millis();
391
+    digitalWrite(outputs[oi].pin, value);
392
+    zunoSendReport(5 + oi); // 5 to 8
393
+  }
394
+}
395
+byte getRelay(int oi) {
396
+  return outputs[oi].currentValue;
397
+}
398
+
399
+void setRelayManual(int oi, byte value) {
400
+  if (oi == OUTPUT_BURNER_IDX && (thermostats[THERMOSTAT_HEAT_IDX].requestedMode == THERMOSTAT_MODE_HEAT || thermostats[THERMOSTAT_WATER_IDX].requestedMode == THERMOSTAT_MODE_HEAT)) {
401
+    return;
402
+  }
403
+  if (oi == OUTPUT_WATER_LOAD_IDX && thermostats[THERMOSTAT_WATER_IDX].requestedMode == THERMOSTAT_MODE_HEAT) {
404
+    return;
405
+  }
406
+
407
+  setRelay(oi, value ? 1 : 0);
408
+}
409
+byte getRelayZwave(int oi) {
410
+  return getRelay(oi) ? 255 : 0;
411
+}
412
+
413
+void setRelayBurner(byte value) {
414
+  setRelayManual(OUTPUT_BURNER_IDX, value);
415
+}
416
+byte getRelayBurner() {
417
+  return getRelayZwave(OUTPUT_BURNER_IDX);
418
+}
419
+
420
+void setRelayWaterLoad(byte value) {
421
+  setRelayManual(OUTPUT_WATER_LOAD_IDX, value);
422
+}
423
+byte getRelayWaterLoad() {
424
+  return getRelayZwave(OUTPUT_WATER_LOAD_IDX);
425
+}
426
+
427
+void setRelayWaterRecycling(byte value) {
428
+  setRelayManual(OUTPUT_WATER_RECYCLING_IDX, value);
429
+}
430
+byte getRelayWaterRecycling() {
431
+  return getRelayZwave(OUTPUT_WATER_RECYCLING_IDX);
432
+}
433
+
434
+void setRelayHeatPump1(byte value) {
435
+  setRelayManual(OUTPUT_HEAT_PUMP_1_IDX, value);
436
+}
437
+byte getRelayHeatPump1() {
438
+  return getRelayZwave(OUTPUT_HEAT_PUMP_1_IDX);
439
+}
440
+
441
+// Raw inputs
442
+
443
+byte getInputBurnerRunning() {
444
+  return !digitalRead(PIN_INPUT_BURNER_RUNNING);
445
+}
446
+
447
+byte getInputBurnerAlarm() {
448
+  return !digitalRead(PIN_INPUT_BURNER_ALARM);
449
+}
450
+
451
+byte getInputBoilerAlarm() {
452
+  return !digitalRead(PIN_INPUT_BOILER_ALARM);
453
+}

Loading…
取消
儲存