thermostat.ino 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  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. sendStatus("DHT reading Temp OK");
  17. i=DHTreadRetries;
  18. }
  19. //else {
  20. // sendStatus("DHT reading Temp failed - retrying..");
  21. //}
  22. }
  23. for(int i=0; i < DHTreadRetries; i++) {
  24. readDHTsensorHum();
  25. if(!isnan(tmpHum)) {
  26. sendStatus("DHT reading Hum OK");
  27. i=DHTreadRetries;
  28. }
  29. //else {
  30. // sendStatus("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. sendStatus("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. sendStatus(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. sendStatus(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. sendStatus(buf);
  122. //Serial.println("heating off");
  123. //mqttclient.publish(tmp_topic_out, "off");
  124. publishCurrentThermostatValues();
  125. sendToDomoticz_Heating();
  126. }
  127. else if ( !turnHeatingOn && heatingMode > 0 && ( currTemp < (currSetTemp - setTempDecreaseVal - hysteresis) ) && ( heatingOffTime > heatingMinOffTime ) ) {
  128. turnHeatingOn = true;
  129. heatingLastOnMillis = millis();
  130. digitalWrite(PIN_RELAIS, RELAISONSTATE);
  131. updateDisplay();
  132. char buf[101];
  133. sprintf(buf, "switch heating ON, off since %d s", heatingOffTime);
  134. sendStatus(buf);
  135. //Serial.println("heating on");
  136. //mqttclient.publish(tmp_topic_out, "on");
  137. publishCurrentThermostatValues();
  138. sendToDomoticz_Heating();
  139. }
  140. }
  141. else {
  142. if (turnHeatingOn) {
  143. digitalWrite(PIN_RELAIS, !RELAISONSTATE);
  144. turnHeatingOn = false;
  145. heatingLastOffMillis = millis();
  146. }
  147. if ( lastTempUpdate != 0 ) sendStatus("switch heating OFF, temp reading not yet available");
  148. else if ( (millis() - lastTempUpdate) > maxMeasurementAge ) sendStatus("switch heating OFF, last temp reading too old");
  149. //mqttclient.publish(tmp_topic_out, "off");
  150. publishCurrentThermostatValues();
  151. sendToDomoticz_Heating();
  152. }
  153. }
  154. void toggleOnOff() {
  155. if (heatingMode > 0) {
  156. heatingMode = 0;
  157. lastValueChange = millis();
  158. heatingModeAlreadySaved = false;
  159. }
  160. else {
  161. heatingMode = 1;
  162. lastValueChange = millis();
  163. heatingModeAlreadySaved = false;
  164. }
  165. updateCurrentHeatingModeName();
  166. updateDisplay();
  167. }
  168. void togglePreset() {
  169. Serial.print("switch preset to ");
  170. if (pendingPreset < 0 || pendingPreset > 2) pendingPreset = preset;
  171. // if (pendingPresetToggle && preset == 0 && pendingPreset == 0) pendingPreset = 1;
  172. // else if (pendingPresetToggle && preset == 1 && pendingPreset == 1) pendingPreset = 0;
  173. // else if (pendingPreset == 1 && pendingPresetToggle) pendingPreset = 2;
  174. // else if (pendingPreset == 2 && !pendingPresetToggle) pendingPreset = 0;
  175. // else if (pendingPreset == 2 && pendingPresetToggle) pendingPreset = 1;
  176. if (pendingPreset == 0) pendingPreset = 1;
  177. else if (pendingPreset == 1) pendingPreset = 2;
  178. else if (pendingPreset == 2) pendingPreset = 0;
  179. // if (preset == 0 && pendingPreset == 0) pendingPreset = 1;
  180. // else if (preset == 0 && pendingPreset == 1) pendingPreset = 2;
  181. // else if (preset == 1 && pendingPreset == 0) pendingPreset = 2;
  182. // else if (preset == 1 && pendingPreset == 1) pendingPreset = 0;
  183. // else if (preset == 1 && pendingPreset == 2) pendingPreset = 1;
  184. // else if (preset == 1 && pendingPreset == 0) pendingPreset = 1;
  185. // else if (preset == 2 && pendingPreset == 0) pendingPreset = 1;
  186. // else if (preset == 2 && pendingPreset == 1) pendingPreset = 0;
  187. // else if (preset == 2 && pendingPreset == 2) pendingPreset = 0;
  188. lastValueChange = millis();
  189. presetAlreadySaved = false;
  190. updatePendingPresetName();
  191. //updateDisplay();
  192. //pendingPresetToggle = true;
  193. displayShowLine2OverlayMessage(pendingPresetName);
  194. Serial.print(pendingPreset);
  195. Serial.print(" - \"");
  196. Serial.print(currentPresetName);
  197. Serial.println("\"");
  198. }
  199. void updateCurrentHeatingModeName() {
  200. if (heatingMode == 0) strlcpy(currentModeName, modename0, 14);
  201. else if (heatingMode == 1) strlcpy(currentModeName, modename1, 14);
  202. }
  203. void updateCurrentPresetName() {
  204. if (preset == 0) strlcpy(currentPresetName, psetname0, 14);
  205. else if (preset == 1) strlcpy(currentPresetName, psetname1, 14);
  206. else if (preset == 2) strlcpy(currentPresetName, psetname2, 14);
  207. }
  208. void updatePendingPresetName() {
  209. if (pendingPreset == 0) strlcpy(pendingPresetName, psetname0, 14);
  210. else if (pendingPreset == 1) strlcpy(pendingPresetName, psetname1, 14);
  211. else if (pendingPreset == 2) strlcpy(pendingPresetName, psetname2, 14);
  212. }
  213. void setTempStepUp() {
  214. if (heatingMode == 1) {
  215. Serial.println("setTemp +0.5");
  216. if ( setTemp <= (setTempMax - 0.5)) {
  217. setTemp += 0.5;
  218. lastValueChange = millis();
  219. setTempAlreadySaved = false;
  220. }
  221. updateDisplay();
  222. }
  223. }
  224. void setTempStepDown() {
  225. if (heatingMode == 1) {
  226. Serial.println("setTemp -0.5");
  227. if ( setTemp >= (setTempMin + 0.5)) {
  228. setTemp -= 0.5;
  229. lastValueChange = millis();
  230. setTempAlreadySaved = false;
  231. }
  232. updateDisplay();
  233. }
  234. }
  235. void setTempTo(float setTo) {
  236. boolean changes = false;
  237. if (setTo >= setTempMin && setTo <= setTempMax) {
  238. setTemp = setTo;
  239. changes = true;
  240. }
  241. else if (setTo > setTempMax) {
  242. setTemp = setTempMax;
  243. changes = true;
  244. }
  245. else if (setTo < setTempMin) {
  246. setTemp = setTempMin;
  247. changes = true;
  248. }
  249. if (changes) {
  250. lastValueChange = millis();
  251. setTempAlreadySaved = false;
  252. updateDisplay();
  253. publishCurrentThermostatValues();
  254. }
  255. }
  256. void setTempLowTo(float setTo) {
  257. boolean changes = false;
  258. if (setTo >= setTempLowMin && setTo <= setTempLowMax) {
  259. setTempLow = setTo;
  260. changes = true;
  261. }
  262. else if (setTo > setTempLowMax) {
  263. setTempLow = setTempLowMax;
  264. changes = true;
  265. }
  266. else if (setTo < setTempLowMin) {
  267. setTempLow = setTempLowMin;
  268. changes = true;
  269. }
  270. if (changes) {
  271. updateDisplay();
  272. publishCurrentThermostatValues();
  273. }
  274. }
  275. void setTempLow2To(float setTo) {
  276. boolean changes = false;
  277. if (setTo >= setTempLowMin && setTo <= setTempLowMax) {
  278. setTempLow2 = setTo;
  279. changes = true;
  280. }
  281. else if (setTo > setTempLowMax) {
  282. setTempLow2 = setTempLowMax;
  283. changes = true;
  284. }
  285. else if (setTo < setTempLowMin) {
  286. setTempLow2 = setTempLowMin;
  287. changes = true;
  288. }
  289. if (changes) {
  290. updateDisplay();
  291. publishCurrentThermostatValues();
  292. }
  293. }
  294. void setHeatingmodeTo(byte setTo) {
  295. boolean changes = false;
  296. switch (setTo) {
  297. case 0:
  298. heatingMode = 0;
  299. changes = true;
  300. break;
  301. case 1:
  302. heatingMode = 1;
  303. changes = true;
  304. break;
  305. }
  306. if (changes) {
  307. updateCurrSetTemp();
  308. lastValueChange = millis();
  309. heatingModeAlreadySaved = false;
  310. updateCurrentHeatingModeName();
  311. updateDisplay();
  312. publishCurrentThermostatValues();
  313. }
  314. }
  315. void setPresetTo(byte setTo) {
  316. boolean changes = false;
  317. switch (setTo) {
  318. case 0:
  319. preset = 0;
  320. pendingPreset = 0;
  321. changes = true;
  322. break;
  323. case 1:
  324. preset = 1;
  325. pendingPreset = 1;
  326. changes = true;
  327. break;
  328. case 2:
  329. preset = 2;
  330. pendingPreset = 2;
  331. changes = true;
  332. break;
  333. }
  334. if (changes) {
  335. updateCurrSetTemp();
  336. lastValueChange = millis();
  337. presetAlreadySaved = false;
  338. updateCurrentPresetName();
  339. updateDisplay();
  340. publishCurrentThermostatValues();
  341. }
  342. }
  343. void checkValuesChanged() { // called every second by everySecond() / misc.ino
  344. if ( !setTempAlreadySaved || !heatingModeAlreadySaved || !presetAlreadySaved) {
  345. if ( (millis() - lastValueChange) > saveValuesTimeout ) { // value was changed 5s ago. now save if auto-save enabled
  346. if (!setTempAlreadySaved) {
  347. lastUpdate_setTemp = millis();
  348. sendToDomoticz_thermostat();
  349. if (autoSaveSetTemp && setTemp != setTempSaved) {
  350. saveSetTemp();
  351. sendStatus("setTemp autosave done");
  352. }
  353. setTempAlreadySaved = true;
  354. }
  355. if (!heatingModeAlreadySaved) {
  356. lastUpdate_heatingMode = millis();
  357. sendToDomoticz_heatingMode();
  358. if (autoSaveHeatingMode && heatingMode != heatingModeSaved) {
  359. saveHeatingMode();
  360. sendStatus("heatingMode autosave done");
  361. }
  362. heatingModeAlreadySaved = true;
  363. }
  364. if (!presetAlreadySaved) {
  365. lastUpdate_preset = millis();
  366. //sendToDomoticz_heatingMode();
  367. preset = pendingPreset;
  368. if (autoSaveHeatingMode && preset != presetSaved) {
  369. savePreset();
  370. sendStatus("preset autosave done");
  371. }
  372. presetAlreadySaved = true;
  373. }
  374. publishCurrentThermostatValues();
  375. }
  376. }
  377. }