thermostat.ino 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. #ifdef FIRMWARE_VARIANT_THERMOSTAT
  2. void thermostat_setup() {
  3. pinMode(PIN_THERMOSTAT_OUTPUT, OUTPUT);
  4. digitalWrite(PIN_THERMOSTAT_OUTPUT, !THERMOSTAT_OUTPUT_ONSTATE);
  5. }
  6. void thermostat_updateCurrSetTemp() {
  7. // set target temp for heating mode
  8. if (thermostat_heatingMode > 0) { // heating on
  9. if (thermostat_preset == 0) { // normal/day preset
  10. thermostat_currSetTemp = thermostat_setTemp;
  11. thermostat_currActualSetTemp = thermostat_setTemp - confTherm.setTempDecreaseVal;
  12. }
  13. else if (thermostat_preset == 1) { // night/reduction preset
  14. thermostat_currSetTemp = thermostat_setTempLow;
  15. thermostat_currActualSetTemp = thermostat_setTempLow - confTherm.setTempDecreaseVal;
  16. }
  17. else if (thermostat_preset == 2) { // night/reduction 2 preset
  18. thermostat_currSetTemp = thermostat_setTempLow2;
  19. thermostat_currActualSetTemp = thermostat_setTempLow2 - confTherm.setTempDecreaseVal;
  20. }
  21. }
  22. else { // if heatingMode == 0
  23. thermostat_currSetTemp = DEFAULT_SETTEMP_HEATOFF;
  24. thermostat_currActualSetTemp = thermostat_currSetTemp;
  25. }
  26. }
  27. void thermostat_mainFunction() {
  28. thermostat_updateCurrSetTemp();
  29. //char tmp_topic_out[50];
  30. if (thermostat_heatingMode > 0 && thermostat_turnHeatingOn) {
  31. thermostat_heatingOnTime = (millis() - thermostat_heatingLastOnMillis) / 1000;
  32. //char buf[101];
  33. //sprintf(buf, "heating on for %lus", heatingOnTime);
  34. //sendLog(buf, LOGLEVEL_INFO);
  35. }
  36. else if (thermostat_heatingMode > 0 && !thermostat_turnHeatingOn) {
  37. if(thermostat_heatingLastOnMillis > 0) {
  38. // prevent locking the heating after a reboot
  39. thermostat_heatingOffTime = (millis() - thermostat_heatingLastOffMillis) / 1000;
  40. }
  41. //char buf[101];
  42. //sprintf(buf, "heating off for %lus", heatingOffTime);
  43. //sendLog(buf, LOGLEVEL_INFO);
  44. }
  45. //char tmp_topic_out[50];
  46. //sprintf(tmp_topic_out, "%s/%s", mqtt_topic_out, "heating");
  47. if ( sensor_DHT_lastUpdate != 0 && (millis() - sensor_DHT_lastUpdate) <= sensors_maxMeasurementAge ) {
  48. // thermostat - only active if measured temperature is < 2 min old
  49. #ifdef DEBUG_VERBOSE
  50. Serial.print("thermostat, lastTempUpdate=");
  51. Serial.print(sensor_DHT_lastUpdate);
  52. Serial.print(", lastTempUpdate_delta=");
  53. long _lastTempUpdateDelta = millis() - sensor_DHT_lastUpdate;
  54. Serial.println(_lastTempUpdateDelta);
  55. #endif
  56. // thermostat with hysteresis
  57. if ( thermostat_turnHeatingOn && sensor_DHT_currTemp >= thermostat_currActualSetTemp ) {
  58. thermostat_turnHeatingOn = false;
  59. thermostat_heatingLastOffMillis = millis();
  60. thermostat_heatingLockTime = confTherm.heatingMinOffTime;
  61. digitalWrite(PIN_THERMOSTAT_OUTPUT, !THERMOSTAT_OUTPUT_ONSTATE);
  62. display_update();
  63. sprintf_P(logBuf, "TSTAT: %s OFF, on for %lus", PGMStr_switchHeating, thermostat_heatingOnTime);
  64. sendLog(logBuf, LOGLEVEL_INFO);
  65. //Serial.println("heating off");
  66. //mqttclient.publish(tmp_topic_out, "off");
  67. thermostat_publishCurrentValues();
  68. }
  69. else if ( !thermostat_turnHeatingOn && thermostat_heatingMode > 0 && thermostat_heatingLockTime == 0 && thermostat_heatingPause == 0 && ( sensor_DHT_currTemp < (thermostat_currActualSetTemp - confTherm.hysteresis) ) ) {
  70. //if ( heatingOffTime > confThermAdv.heatingMinOffTime || heatingLastOnMillis == 0) {
  71. thermostat_turnHeatingOn = true;
  72. //heatingLockTimeActive = false;
  73. //heatingLockTime = 0;
  74. thermostat_heatingLastOnMillis = millis();
  75. digitalWrite(PIN_THERMOSTAT_OUTPUT, THERMOSTAT_OUTPUT_ONSTATE);
  76. display_update();
  77. snprintf(logBuf, LOG_BUFFER_SIZE, "TSTAT: switch heating ON, off for %lus", thermostat_heatingOffTime);
  78. sendLog(logBuf, LOGLEVEL_INFO);
  79. //Serial.println("heating on");
  80. //mqttclient.publish(tmp_topic_out, "on");
  81. thermostat_publishCurrentValues();
  82. //}
  83. //else {
  84. // // heating should run BUT lock time is active
  85. // heatingLockTimeActive = true;
  86. // heatingLockTime = confThermAdv.heatingMinOffTime - heatingOffTime;
  87. // display_update();
  88. //}
  89. }
  90. else if (thermostat_heatingPause > 0) {
  91. thermostat_turnHeatingOn = false;
  92. thermostat_heatingLastOffMillis = millis();
  93. digitalWrite(PIN_THERMOSTAT_OUTPUT, !THERMOSTAT_OUTPUT_ONSTATE);
  94. display_update();
  95. }
  96. }
  97. else {
  98. // turn off as no temp reading is available
  99. if (thermostat_turnHeatingOn) {
  100. digitalWrite(PIN_THERMOSTAT_OUTPUT, !THERMOSTAT_OUTPUT_ONSTATE);
  101. thermostat_turnHeatingOn = false;
  102. thermostat_heatingLastOffMillis = millis();
  103. }
  104. if ( sensor_DHT_lastUpdate != 0 ) sendLog(F("TSTAT: heating OFF, temp reading not yet available"), LOGLEVEL_INFO);
  105. else if ( (millis() - sensor_DHT_lastUpdate) > sensors_maxMeasurementAge ) sendLog(F("TSTAT: heating OFF, last temp reading too old"), LOGLEVEL_WARN);
  106. //mqttclient.publish(tmp_topic_out, "off");
  107. thermostat_publishCurrentValues();
  108. }
  109. }
  110. void thermostat_toggleOnOff() {
  111. if (thermostat_heatingMode > 0) {
  112. thermostat_heatingMode = 0;
  113. thermostat_heatingPause = 0;
  114. thermostat_heatingLockTime = 0;
  115. thermostat_lastValueChange = millis();
  116. thermostat_heatingModeAlreadySaved = false;
  117. }
  118. else {
  119. thermostat_heatingMode = 1;
  120. thermostat_heatingPause = 0;
  121. thermostat_heatingLockTime = 0;
  122. thermostat_lastValueChange = millis();
  123. thermostat_heatingModeAlreadySaved = false;
  124. }
  125. thermostat_updateCurrentHeatingModeName();
  126. display_update();
  127. }
  128. void thermostat_togglePreset() {
  129. //sendLog(F("switch preset to "));
  130. if (thermostat_pendingPreset < 0 || thermostat_pendingPreset > 2) thermostat_pendingPreset = thermostat_preset;
  131. // if (pendingPresetToggle && preset == 0 && pendingPreset == 0) pendingPreset = 1;
  132. // else if (pendingPresetToggle && preset == 1 && pendingPreset == 1) pendingPreset = 0;
  133. // else if (pendingPreset == 1 && pendingPresetToggle) pendingPreset = 2;
  134. // else if (pendingPreset == 2 && !pendingPresetToggle) pendingPreset = 0;
  135. // else if (pendingPreset == 2 && pendingPresetToggle) pendingPreset = 1;
  136. // pendingPreset 0 => Normal
  137. // pendingPreset 1 => Reduction 1
  138. // pendingPreset 2 => Reduction 2
  139. if(thermostat_preset == 0) { // Normal > Reduction 1 > Reduction 2
  140. if (thermostat_pendingPreset == 0) thermostat_pendingPreset = 1;
  141. else if (thermostat_pendingPreset == 1) thermostat_pendingPreset = 2;
  142. else if (thermostat_pendingPreset == 2) thermostat_pendingPreset = 0;
  143. }
  144. else if(thermostat_preset == 1) { // Reduction 1 > Normal > Reduction 2
  145. if (thermostat_pendingPreset == 1) thermostat_pendingPreset = 0;
  146. else if (thermostat_pendingPreset == 0) thermostat_pendingPreset = 2;
  147. else if (thermostat_pendingPreset == 2) thermostat_pendingPreset = 1;
  148. }
  149. else if(thermostat_preset == 2) { // Reduction 2 > Normal > Reduction 1
  150. if (thermostat_pendingPreset == 2) thermostat_pendingPreset = 0;
  151. else if (thermostat_pendingPreset == 0) thermostat_pendingPreset = 1;
  152. else if (thermostat_pendingPreset == 1) thermostat_pendingPreset = 2;
  153. }
  154. // if (preset == 0 && pendingPreset == 0) pendingPreset = 1;
  155. // else if (preset == 0 && pendingPreset == 1) pendingPreset = 2;
  156. // else if (preset == 1 && pendingPreset == 0) pendingPreset = 2;
  157. // else if (preset == 1 && pendingPreset == 1) pendingPreset = 0;
  158. // else if (preset == 1 && pendingPreset == 2) pendingPreset = 1;
  159. // else if (preset == 1 && pendingPreset == 0) pendingPreset = 1;
  160. // else if (preset == 2 && pendingPreset == 0) pendingPreset = 1;
  161. // else if (preset == 2 && pendingPreset == 1) pendingPreset = 0;
  162. // else if (preset == 2 && pendingPreset == 2) pendingPreset = 0;
  163. thermostat_lastValueChange = millis();
  164. thermostat_presetAlreadySaved = false;
  165. thermostat_updatePendingPresetName();
  166. //display_update();
  167. //pendingPresetToggle = true;
  168. display_showRow2OverlayMessage(thermostat_pendingPresetName);
  169. //Serial.print(pendingPreset);
  170. //Serial.print(" - \"");
  171. //Serial.print(currentPresetName);
  172. //Serial.println("\"");
  173. }
  174. void thermostat_updateCurrentHeatingModeName() {
  175. if (thermostat_heatingMode == 0) strlcpy(thermostat_currentModeName, confTherm.modeName0, 14);
  176. else if (thermostat_heatingMode == 1) strlcpy(thermostat_currentModeName, confTherm.modeName1, 14);
  177. }
  178. void thermostat_updateCurrentPresetName() {
  179. if (thermostat_preset == 0) strlcpy(thermostat_currentPresetName, confTherm.psetName0, 14);
  180. else if (thermostat_preset == 1) strlcpy(thermostat_currentPresetName, confTherm.psetName1, 14);
  181. else if (thermostat_preset == 2) strlcpy(thermostat_currentPresetName, confTherm.psetName2, 14);
  182. }
  183. void thermostat_updatePendingPresetName() {
  184. if (thermostat_pendingPreset == 0) strlcpy(thermostat_pendingPresetName, confTherm.psetName0, 14);
  185. else if (thermostat_pendingPreset == 1) strlcpy(thermostat_pendingPresetName, confTherm.psetName1, 14);
  186. else if (thermostat_pendingPreset == 2) strlcpy(thermostat_pendingPresetName, confTherm.psetName2, 14);
  187. }
  188. void thermostat_setTempStepUp() {
  189. if (thermostat_heatingMode == 1) {
  190. sendLog(F("TSTAT: setTemp +0.5"));
  191. if ( thermostat_setTemp <= (confTherm.setTempMax - 0.5)) {
  192. thermostat_setTemp += 0.5;
  193. thermostat_lastValueChange = millis();
  194. thermostat_setTempAlreadySaved = false;
  195. }
  196. thermostat_mainFunction();
  197. display_update();
  198. }
  199. }
  200. void thermostat_setTempStepDown() {
  201. if (thermostat_heatingMode == 1) {
  202. sendLog(F("TSTAT: setTemp -0.5"));
  203. if ( thermostat_setTemp >= (confTherm.setTempMin + 0.5)) {
  204. thermostat_setTemp -= 0.5;
  205. thermostat_lastValueChange = millis();
  206. thermostat_setTempAlreadySaved = false;
  207. }
  208. thermostat_mainFunction();
  209. display_update();
  210. }
  211. }
  212. void thermostat_setTempTo(float _setTo) {
  213. bool _changed = false;
  214. if(_setTo != thermostat_setTemp) {
  215. if (_setTo >= confTherm.setTempMin && _setTo <= confTherm.setTempMax) {
  216. _changed = true;
  217. }
  218. else if (_setTo > confTherm.setTempMax) {
  219. _setTo = confTherm.setTempMax;
  220. _changed = true;
  221. }
  222. else if (_setTo < confTherm.setTempMin) {
  223. _setTo = confTherm.setTempMin;
  224. _changed = true;
  225. }
  226. if (_changed) {
  227. thermostat_setTemp = _setTo;
  228. thermostat_lastValueChange = millis();
  229. thermostat_setTempAlreadySaved = false;
  230. thermostat_mainFunction();
  231. display_update();
  232. thermostat_publishCurrentValues();
  233. sprintf_P(logBuf, "%s: %s %s %2.1f", PGMStr_thermostat, PGMStr_setTemp, PGMStr_changedTo, thermostat_setTemp);
  234. sendLog(logBuf);
  235. }
  236. }
  237. }
  238. void thermostat_setTempLowStepUp() {
  239. sendLog(F("TSTAT: setTempLow +0.5"));
  240. if ( thermostat_setTempLow <= (thermostat_setTempLowMax - 0.5)) {
  241. thermostat_setTempLow += 0.5;
  242. thermostat_lastValueChange = millis();
  243. thermostat_setTempLowAlreadySaved = false;
  244. }
  245. display_update();
  246. }
  247. void thermostat_setTempLowStepDown() {
  248. sendLog(F("TSTAT: setTempLow -0.5"));
  249. if ( thermostat_setTempLow >= (thermostat_setTempLowMin + 0.5)) {
  250. thermostat_setTempLow -= 0.5;
  251. thermostat_lastValueChange = millis();
  252. thermostat_setTempLowAlreadySaved = false;
  253. }
  254. display_update();
  255. }
  256. void thermostat_setTempLowTo(float _setTo) {
  257. bool _changed = false;
  258. if(_setTo != thermostat_setTempLow) {
  259. if (_setTo >= thermostat_setTempLowMin && _setTo <= thermostat_setTempLowMax) {
  260. _changed = true;
  261. }
  262. else if (_setTo > thermostat_setTempLowMax) {
  263. _setTo = thermostat_setTempLowMax;
  264. _changed = true;
  265. }
  266. else if (_setTo < thermostat_setTempLowMin) {
  267. _setTo = thermostat_setTempLowMin;
  268. _changed = true;
  269. }
  270. if (_changed) {
  271. thermostat_setTempLow = _setTo;
  272. thermostat_lastValueChange = millis();
  273. thermostat_setTempLowAlreadySaved = false;
  274. display_update();
  275. thermostat_publishCurrentValues();
  276. sprintf_P(logBuf, "%s: %s %s %2.1f", PGMStr_thermostat, PGMStr_setTempLow, PGMStr_changedTo, thermostat_setTempLow);
  277. sendLog(logBuf);
  278. }
  279. }
  280. }
  281. void thermostat_setTempLow2StepUp() {
  282. sendLog(F("TSTAT: setTempLow2 +0.5"));
  283. if ( thermostat_setTempLow2 <= (thermostat_setTempLowMax - 0.5)) {
  284. thermostat_setTempLow2 += 0.5;
  285. thermostat_lastValueChange = millis();
  286. thermostat_setTempLow2AlreadySaved = false;
  287. }
  288. display_update();
  289. }
  290. void thermostat_setTempLow2StepDown() {
  291. sendLog(F("TSTAT: setTempLow2 -0.5"));
  292. if ( thermostat_setTempLow2 >= (thermostat_setTempLowMin + 0.5)) {
  293. thermostat_setTempLow2 -= 0.5;
  294. thermostat_lastValueChange = millis();
  295. thermostat_setTempLow2AlreadySaved = false;
  296. }
  297. display_update();
  298. }
  299. void thermostat_setTempLow2To(float _setTo) {
  300. bool _changed = false;
  301. if(_setTo != thermostat_setTempLow2) {
  302. if (_setTo >= thermostat_setTempLowMin && _setTo <= thermostat_setTempLowMax) {
  303. _changed = true;
  304. }
  305. else if (_setTo > thermostat_setTempLowMax) {
  306. _setTo = thermostat_setTempLowMax;
  307. _changed = true;
  308. }
  309. else if (_setTo < thermostat_setTempLowMin) {
  310. _setTo = thermostat_setTempLowMin;
  311. _changed = true;
  312. }
  313. if (_changed) {
  314. thermostat_setTempLow2 = _setTo;
  315. thermostat_lastValueChange = millis();
  316. thermostat_setTempLow2AlreadySaved = false;
  317. display_update();
  318. thermostat_publishCurrentValues();
  319. sprintf_P(logBuf, "%s: %s %s %2.1f", PGMStr_thermostat, PGMStr_setTempLow2, PGMStr_changedTo, thermostat_setTempLow2);
  320. sendLog(logBuf);
  321. }
  322. }
  323. }
  324. void thermostat_setHeatingmodeTo(unsigned char _setTo) {
  325. if(_setTo != thermostat_heatingMode) {
  326. thermostat_heatingMode = _setTo;
  327. thermostat_heatingPause = 0;
  328. thermostat_heatingLockTime = 0;
  329. thermostat_updateCurrSetTemp();
  330. thermostat_lastValueChange = millis();
  331. thermostat_heatingModeAlreadySaved = false;
  332. thermostat_updateCurrentHeatingModeName();
  333. thermostat_mainFunction();
  334. display_update();
  335. thermostat_publishCurrentValues();
  336. sprintf_P(logBuf, "%s: %s %s %u", PGMStr_thermostat, PGMStr_heatingMode, PGMStr_changedTo, thermostat_heatingMode);
  337. sendLog(logBuf);
  338. }
  339. }
  340. void thermostat_setHeatingPause(uint8_t _setTo) {
  341. bool _changed = false;
  342. if(_setTo == 0) {
  343. thermostat_heatingPause = 0;
  344. _changed = true;
  345. sprintf_P(logBuf, "%s: %s %s", PGMStr_thermostat, PGMStr_heatingPause, PGMStr_disabled);
  346. }
  347. else if (_setTo == 1 && thermostat_heatingPause == 0) {
  348. thermostat_heatingPause = confTherm.pauseTout;
  349. _changed = true;
  350. sprintf_P(logBuf, "%s: %s %s", PGMStr_thermostat, PGMStr_heatingPause, PGMStr_enabled);
  351. }
  352. if(_changed) {
  353. thermostat_lastValueChange = millis();
  354. thermostat_mainFunction();
  355. display_update();
  356. thermostat_publishCurrentValues();
  357. sendLog(logBuf);
  358. }
  359. }
  360. void thermostat_setPresetTo(unsigned char _setTo) {
  361. if(_setTo != thermostat_preset) {
  362. if(_setTo >= 0 && _setTo <=2) {
  363. thermostat_preset = _setTo;
  364. thermostat_pendingPreset = _setTo;
  365. thermostat_updateCurrSetTemp();
  366. thermostat_lastValueChange = millis();
  367. thermostat_presetAlreadySaved = false;
  368. thermostat_updateCurrentPresetName();
  369. thermostat_mainFunction();
  370. display_update();
  371. thermostat_publishCurrentValues();
  372. sprintf_P(logBuf, "%s: %s %s %u", PGMStr_thermostat, PGMStr_preset, PGMStr_changedTo, thermostat_preset);
  373. sendLog(logBuf);
  374. }
  375. }
  376. }
  377. void thermostat_checkValuesChanged() { // called every second by everySecond() / scheduler.ino
  378. if ( !thermostat_setTempAlreadySaved || !thermostat_heatingModeAlreadySaved || !thermostat_presetAlreadySaved || !thermostat_setTempLowAlreadySaved || !thermostat_setTempLow2AlreadySaved ) {
  379. if ( (millis() - thermostat_lastValueChange) > thermostat_saveValuesTimeout ) { // value was changed 5s ago. now save if auto-save enabled
  380. if (!thermostat_setTempAlreadySaved) {
  381. thermostat_lastUpdate_setTemp = millis();
  382. if (confTherm.autoSaveSetTemp && thermostat_setTemp != thermostat_setTempSaved) {
  383. thermostat_saveSetTemp();
  384. sendLog(F("TSTAT: setTemp autosave done"));
  385. }
  386. thermostat_setTempAlreadySaved = true;
  387. }
  388. if (!thermostat_setTempLowAlreadySaved) {
  389. thermostat_lastUpdate_setTempLow = millis();
  390. if (confTherm.autoSaveSetTemp && thermostat_setTempLow != thermostat_setTempLowSaved) {
  391. thermostat_saveSetTempLow();
  392. sendLog(F("TSTAT: setTempLow autosave done"));
  393. }
  394. thermostat_setTempLowAlreadySaved = true;
  395. }
  396. if (!thermostat_setTempLow2AlreadySaved) {
  397. thermostat_lastUpdate_setTempLow2 = millis();
  398. if (confTherm.autoSaveSetTemp && thermostat_setTempLow2 != thermostat_setTempLow2Saved) {
  399. thermostat_saveSetTempLow2();
  400. sendLog(F("TSTAT: setTempLow2 autosave done"));
  401. }
  402. thermostat_setTempLow2AlreadySaved = true;
  403. }
  404. if (!thermostat_heatingModeAlreadySaved) {
  405. thermostat_lastUpdate_heatingMode = millis();
  406. if (confTherm.autoSaveHeatingMode && thermostat_heatingMode != thermostat_heatingModeSaved) {
  407. thermostat_saveHeatingMode();
  408. sendLog(F("TSTAT: heatingMode autosave done"));
  409. }
  410. thermostat_heatingModeAlreadySaved = true;
  411. }
  412. if (!thermostat_presetAlreadySaved) {
  413. thermostat_lastUpdate_preset = millis();
  414. thermostat_preset = thermostat_pendingPreset;
  415. if (confTherm.autoSaveHeatingMode && thermostat_preset != thermostat_presetSaved) {
  416. thermostat_savePreset();
  417. sendLog(F("TSTAT: preset autosave done"));
  418. }
  419. thermostat_presetAlreadySaved = true;
  420. }
  421. thermostat_publishCurrentValues();
  422. }
  423. }
  424. }
  425. #endif