thermostat.ino 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. float tmpHum, tmpTemp;
  2. int DHTreadRetries = 2;
  3. //int DHTreadDelay = 20;
  4. void readDHTsensorTemp() {
  5. //delay(DHTreadDelay);
  6. tmpTemp = dht.readTemperature(); // Read temperature as Celsius (the default)
  7. }
  8. void readDHTsensorHum() {
  9. //delay(DHTreadDelay);
  10. tmpHum = dht.readHumidity();
  11. }
  12. void measureTempHum() {
  13. for (int i = 0; i < DHTreadRetries; i++) {
  14. readDHTsensorTemp();
  15. if (!isnan(tmpTemp)) {
  16. mqttSendLog("DHT reading Temp OK");
  17. i = DHTreadRetries;
  18. }
  19. //else {
  20. // mqttSendLog("DHT reading Temp failed - retrying..");
  21. //}
  22. }
  23. for (int i = 0; i < DHTreadRetries; i++) {
  24. readDHTsensorHum();
  25. if (!isnan(tmpHum)) {
  26. mqttSendLog("DHT reading Hum OK");
  27. i = DHTreadRetries;
  28. }
  29. //else {
  30. // mqttSendLog("DHT reading Hum failed - retrying..");
  31. //}
  32. }
  33. // Check if any reads failed
  34. if (isnan(tmpHum) || isnan(tmpTemp)) {
  35. //Serial.println("Failed to read from DHT sensor!");
  36. mqttSendLog("Error: Failed to read from DHT sensor!");
  37. }
  38. else {
  39. tmpTemp = tmpTemp + tempCorrVal;
  40. tmpHum = round(tmpHum) + humCorrVal;
  41. int tmpHumInt = tmpHum;
  42. if (tmpTemp < 50.0 && tmpTemp > -20.0) {
  43. // measurement is in range
  44. currTemp_raw = tmpTemp;
  45. currHum_raw = tmpHumInt;
  46. if ( lastTempUpdate > 0 && tmpTemp <= ( currTemp + 2.0 ) && tmpTemp >= ( currTemp - 2.0 ) ) {
  47. // temp has already been measured - only accept new measurement if it does not differ much from the last value
  48. //Temp = (Temp * (FilterFaktor -1) + AktuellerMesswert) / FilterFaktor;
  49. //temperature = tmpTemp;
  50. currTemp = (currTemp * 9 + tmpTemp) / 10; // filter
  51. currHum = (currHum * 9 + tmpHumInt) / 10; // filter
  52. lastTempUpdate = millis();
  53. }
  54. else if ( lastTempUpdate == 0 || (millis() - lastTempUpdate) > maxMeasurementAge ) {
  55. // this is the first measurement or the last one is older than 5m - then accept this measurement
  56. currTemp = tmpTemp + tempCorrVal;
  57. currHum = tmpHumInt + humCorrVal;
  58. lastTempUpdate = millis();
  59. }
  60. // skip in all other cases
  61. //#ifdef DEBUG_VERBOSE
  62. // Serial.print("lastTempUpdate: ");
  63. // long lastTempUpdateDelta = millis() - lastTempUpdate;
  64. // Serial.print(lastTempUpdateDelta / 1000);
  65. // Serial.println("s ago");
  66. //#endif
  67. }
  68. }
  69. }
  70. void updateCurrSetTemp() {
  71. // set target temp for heating mode
  72. if (heatingMode > 0) { // heating on
  73. if (preset == 0) { // normal/day preset
  74. currSetTemp = setTemp;
  75. }
  76. else if (preset == 1) { // night/reduction preset
  77. currSetTemp = setTempLow;
  78. }
  79. else if (preset == 2) { // night/reduction 2 preset
  80. currSetTemp = setTempLow2;
  81. }
  82. }
  83. else { // if heatingMode == 0
  84. currSetTemp = DEFAULT_SETTEMP_HEATOFF;
  85. }
  86. }
  87. void thermostat() {
  88. updateCurrSetTemp();
  89. char tmp_topic_out[50];
  90. if (heatingMode > 0 && turnHeatingOn) {
  91. heatingOnTime = (millis() - heatingLastOnMillis) / 1000;
  92. char buf[101];
  93. sprintf(buf, "heating on since %d s", heatingOnTime);
  94. mqttSendLog(buf);
  95. }
  96. else if (heatingMode > 0 && !turnHeatingOn) {
  97. heatingOffTime = (millis() - heatingLastOffMillis) / 1000;
  98. char buf[101];
  99. sprintf(buf, "heating off since %d s", heatingOffTime);
  100. mqttSendLog(buf);
  101. }
  102. //char tmp_topic_out[50];
  103. //sprintf(tmp_topic_out, "%s/%s", mqtt_topic_out, "heating");
  104. if ( lastTempUpdate != 0 && (millis() - lastTempUpdate) <= maxMeasurementAge ) {
  105. // thermostat - only active if measured temperature is < 2 min old
  106. #ifdef DEBUG_VERBOSE
  107. Serial.print("thermostat, lastTempUpdate=");
  108. Serial.print(lastTempUpdate);
  109. Serial.print(", lastTempUpdate_delta=");
  110. long lastTempUpdateDelta = millis() - lastTempUpdate;
  111. Serial.println(lastTempUpdateDelta);
  112. #endif
  113. // thermostat with hysteresis
  114. if ( turnHeatingOn && currTemp >= (currSetTemp - setTempDecreaseVal) ) {
  115. turnHeatingOn = false;
  116. heatingLastOffMillis = millis();
  117. digitalWrite(PIN_RELAIS, !RELAISONSTATE);
  118. updateDisplay();
  119. char buf[101];
  120. sprintf(buf, "switch heating OFF, on since %d s", heatingOnTime);
  121. mqttSendLog(buf);
  122. //Serial.println("heating off");
  123. //mqttclient.publish(tmp_topic_out, "off");
  124. publishCurrentThermostatValues();
  125. }
  126. else if ( !turnHeatingOn && heatingMode > 0 && ( currTemp < (currSetTemp - setTempDecreaseVal - hysteresis) ) && ( heatingOffTime > heatingMinOffTime ) ) {
  127. turnHeatingOn = true;
  128. heatingLastOnMillis = millis();
  129. digitalWrite(PIN_RELAIS, RELAISONSTATE);
  130. updateDisplay();
  131. char buf[101];
  132. sprintf(buf, "switch heating ON, off since %d s", heatingOffTime);
  133. mqttSendLog(buf);
  134. //Serial.println("heating on");
  135. //mqttclient.publish(tmp_topic_out, "on");
  136. publishCurrentThermostatValues();
  137. }
  138. }
  139. else {
  140. if (turnHeatingOn) {
  141. digitalWrite(PIN_RELAIS, !RELAISONSTATE);
  142. turnHeatingOn = false;
  143. heatingLastOffMillis = millis();
  144. }
  145. if ( lastTempUpdate != 0 ) mqttSendLog("switch heating OFF, temp reading not yet available");
  146. else if ( (millis() - lastTempUpdate) > maxMeasurementAge ) mqttSendLog("switch heating OFF, last temp reading too old");
  147. //mqttclient.publish(tmp_topic_out, "off");
  148. publishCurrentThermostatValues();
  149. }
  150. }
  151. void toggleOnOff() {
  152. if (heatingMode > 0) {
  153. heatingMode = 0;
  154. lastValueChange = millis();
  155. heatingModeAlreadySaved = false;
  156. }
  157. else {
  158. heatingMode = 1;
  159. lastValueChange = millis();
  160. heatingModeAlreadySaved = false;
  161. }
  162. updateCurrentHeatingModeName();
  163. updateDisplay();
  164. }
  165. void togglePreset() {
  166. Serial.print("switch preset to ");
  167. if (pendingPreset < 0 || pendingPreset > 2) pendingPreset = preset;
  168. // if (pendingPresetToggle && preset == 0 && pendingPreset == 0) pendingPreset = 1;
  169. // else if (pendingPresetToggle && preset == 1 && pendingPreset == 1) pendingPreset = 0;
  170. // else if (pendingPreset == 1 && pendingPresetToggle) pendingPreset = 2;
  171. // else if (pendingPreset == 2 && !pendingPresetToggle) pendingPreset = 0;
  172. // else if (pendingPreset == 2 && pendingPresetToggle) pendingPreset = 1;
  173. if (pendingPreset == 0) pendingPreset = 1;
  174. else if (pendingPreset == 1) pendingPreset = 2;
  175. else if (pendingPreset == 2) pendingPreset = 0;
  176. // if (preset == 0 && pendingPreset == 0) pendingPreset = 1;
  177. // else if (preset == 0 && pendingPreset == 1) pendingPreset = 2;
  178. // else if (preset == 1 && pendingPreset == 0) pendingPreset = 2;
  179. // else if (preset == 1 && pendingPreset == 1) pendingPreset = 0;
  180. // else if (preset == 1 && pendingPreset == 2) pendingPreset = 1;
  181. // else if (preset == 1 && pendingPreset == 0) pendingPreset = 1;
  182. // else if (preset == 2 && pendingPreset == 0) pendingPreset = 1;
  183. // else if (preset == 2 && pendingPreset == 1) pendingPreset = 0;
  184. // else if (preset == 2 && pendingPreset == 2) pendingPreset = 0;
  185. lastValueChange = millis();
  186. presetAlreadySaved = false;
  187. updatePendingPresetName();
  188. //updateDisplay();
  189. //pendingPresetToggle = true;
  190. displayShowLine2OverlayMessage(pendingPresetName);
  191. Serial.print(pendingPreset);
  192. Serial.print(" - \"");
  193. Serial.print(currentPresetName);
  194. Serial.println("\"");
  195. }
  196. void updateCurrentHeatingModeName() {
  197. if (heatingMode == 0) strlcpy(currentModeName, modename0, 14);
  198. else if (heatingMode == 1) strlcpy(currentModeName, modename1, 14);
  199. }
  200. void updateCurrentPresetName() {
  201. if (preset == 0) strlcpy(currentPresetName, psetname0, 14);
  202. else if (preset == 1) strlcpy(currentPresetName, psetname1, 14);
  203. else if (preset == 2) strlcpy(currentPresetName, psetname2, 14);
  204. }
  205. void updatePendingPresetName() {
  206. if (pendingPreset == 0) strlcpy(pendingPresetName, psetname0, 14);
  207. else if (pendingPreset == 1) strlcpy(pendingPresetName, psetname1, 14);
  208. else if (pendingPreset == 2) strlcpy(pendingPresetName, psetname2, 14);
  209. }
  210. void setTempStepUp() {
  211. if (heatingMode == 1) {
  212. Serial.println("setTemp +0.5");
  213. if ( setTemp <= (setTempMax - 0.5)) {
  214. setTemp += 0.5;
  215. lastValueChange = millis();
  216. setTempAlreadySaved = false;
  217. }
  218. updateDisplay();
  219. }
  220. }
  221. void setTempStepDown() {
  222. if (heatingMode == 1) {
  223. Serial.println("setTemp -0.5");
  224. if ( setTemp >= (setTempMin + 0.5)) {
  225. setTemp -= 0.5;
  226. lastValueChange = millis();
  227. setTempAlreadySaved = false;
  228. }
  229. updateDisplay();
  230. }
  231. }
  232. void setTempTo(float setTo) {
  233. boolean changes = false;
  234. if (setTo >= setTempMin && setTo <= setTempMax) {
  235. setTemp = setTo;
  236. changes = true;
  237. }
  238. else if (setTo > setTempMax) {
  239. setTemp = setTempMax;
  240. changes = true;
  241. }
  242. else if (setTo < setTempMin) {
  243. setTemp = setTempMin;
  244. changes = true;
  245. }
  246. if (changes) {
  247. lastValueChange = millis();
  248. setTempAlreadySaved = false;
  249. updateDisplay();
  250. publishCurrentThermostatValues();
  251. }
  252. }
  253. void setTempLowStepUp() {
  254. Serial.println("setTempLow +0.5");
  255. if ( setTempLow <= (setTempLowMax - 0.5)) {
  256. setTempLow += 0.5;
  257. lastValueChange = millis();
  258. setTempLowAlreadySaved = false;
  259. }
  260. updateDisplay();
  261. }
  262. void setTempLowStepDown() {
  263. Serial.println("setTempLow -0.5");
  264. if ( setTempLow >= (setTempLowMin + 0.5)) {
  265. setTempLow -= 0.5;
  266. lastValueChange = millis();
  267. setTempLowAlreadySaved = false;
  268. }
  269. updateDisplay();
  270. }
  271. void setTempLowTo(float setTo) {
  272. boolean changes = false;
  273. if (setTo >= setTempLowMin && setTo <= setTempLowMax) {
  274. setTempLow = setTo;
  275. changes = true;
  276. }
  277. else if (setTo > setTempLowMax) {
  278. setTempLow = setTempLowMax;
  279. changes = true;
  280. }
  281. else if (setTo < setTempLowMin) {
  282. setTempLow = setTempLowMin;
  283. changes = true;
  284. }
  285. if (changes) {
  286. lastValueChange = millis();
  287. setTempLowAlreadySaved = false;
  288. updateDisplay();
  289. publishCurrentThermostatValues();
  290. }
  291. }
  292. void setTempLow2StepUp() {
  293. Serial.println("setTempLow2 +0.5");
  294. if ( setTempLow2 <= (setTempLowMax - 0.5)) {
  295. setTempLow2 += 0.5;
  296. lastValueChange = millis();
  297. setTempLow2AlreadySaved = false;
  298. }
  299. updateDisplay();
  300. }
  301. void setTempLow2StepDown() {
  302. Serial.println("setTempLow2 -0.5");
  303. if ( setTempLow2 >= (setTempLowMin + 0.5)) {
  304. setTempLow2 -= 0.5;
  305. lastValueChange = millis();
  306. setTempLow2AlreadySaved = false;
  307. }
  308. updateDisplay();
  309. }
  310. void setTempLow2To(float setTo) {
  311. boolean changes = false;
  312. if (setTo >= setTempLowMin && setTo <= setTempLowMax) {
  313. setTempLow2 = setTo;
  314. changes = true;
  315. }
  316. else if (setTo > setTempLowMax) {
  317. setTempLow2 = setTempLowMax;
  318. changes = true;
  319. }
  320. else if (setTo < setTempLowMin) {
  321. setTempLow2 = setTempLowMin;
  322. changes = true;
  323. }
  324. if (changes) {
  325. lastValueChange = millis();
  326. setTempLow2AlreadySaved = false;
  327. updateDisplay();
  328. publishCurrentThermostatValues();
  329. }
  330. }
  331. void setHeatingmodeTo(byte setTo) {
  332. boolean changes = false;
  333. switch (setTo) {
  334. case 0:
  335. heatingMode = 0;
  336. changes = true;
  337. break;
  338. case 1:
  339. heatingMode = 1;
  340. changes = true;
  341. break;
  342. }
  343. if (changes) {
  344. updateCurrSetTemp();
  345. lastValueChange = millis();
  346. heatingModeAlreadySaved = false;
  347. updateCurrentHeatingModeName();
  348. updateDisplay();
  349. publishCurrentThermostatValues();
  350. }
  351. }
  352. void setPresetTo(byte setTo) {
  353. boolean changes = false;
  354. switch (setTo) {
  355. case 0:
  356. preset = 0;
  357. pendingPreset = 0;
  358. changes = true;
  359. break;
  360. case 1:
  361. preset = 1;
  362. pendingPreset = 1;
  363. changes = true;
  364. break;
  365. case 2:
  366. preset = 2;
  367. pendingPreset = 2;
  368. changes = true;
  369. break;
  370. }
  371. if (changes) {
  372. updateCurrSetTemp();
  373. lastValueChange = millis();
  374. presetAlreadySaved = false;
  375. updateCurrentPresetName();
  376. updateDisplay();
  377. publishCurrentThermostatValues();
  378. }
  379. }
  380. void checkValuesChanged() { // called every second by everySecond() / scheduler.ino
  381. if ( !setTempAlreadySaved || !heatingModeAlreadySaved || !presetAlreadySaved || !setTempLowAlreadySaved || !setTempLow2AlreadySaved ) {
  382. if ( (millis() - lastValueChange) > saveValuesTimeout ) { // value was changed 5s ago. now save if auto-save enabled
  383. if (!setTempAlreadySaved) {
  384. lastUpdate_setTemp = millis();
  385. if (autoSaveSetTemp && setTemp != setTempSaved) {
  386. saveSetTemp();
  387. mqttSendLog("setTemp autosave done");
  388. }
  389. setTempAlreadySaved = true;
  390. }
  391. if (!setTempLowAlreadySaved) {
  392. lastUpdate_setTempLow = millis();
  393. if (autoSaveSetTemp && setTempLow != setTempLowSaved) {
  394. saveSetTempLow();
  395. mqttSendLog("setTempLow autosave done");
  396. }
  397. setTempLowAlreadySaved = true;
  398. }
  399. if (!setTempLow2AlreadySaved) {
  400. lastUpdate_setTempLow2 = millis();
  401. if (autoSaveSetTemp && setTempLow2 != setTempLow2Saved) {
  402. saveSetTempLow2();
  403. mqttSendLog("setTempLow2 autosave done");
  404. }
  405. setTempLow2AlreadySaved = true;
  406. }
  407. if (!heatingModeAlreadySaved) {
  408. lastUpdate_heatingMode = millis();
  409. if (autoSaveHeatingMode && heatingMode != heatingModeSaved) {
  410. saveHeatingMode();
  411. mqttSendLog("heatingMode autosave done");
  412. }
  413. heatingModeAlreadySaved = true;
  414. }
  415. if (!presetAlreadySaved) {
  416. lastUpdate_preset = millis();
  417. preset = pendingPreset;
  418. if (autoSaveHeatingMode && preset != presetSaved) {
  419. savePreset();
  420. mqttSendLog("preset autosave done");
  421. }
  422. presetAlreadySaved = true;
  423. }
  424. publishCurrentThermostatValues();
  425. }
  426. }
  427. }