#include RotaryEncoder encoder(ENC_B, ENC_A); OneButton button(BUTT_ENC, true); LiquidCrystal_PCF8574 lcd(0x27); PCF8574 pcf(0x38); I2C_eeprom ee(0x50, 0x1000); OneWire oneWire(ONE_WIRE); DallasTemperature sensors(&oneWire); WiFiClient espClient; //PubSubClient client(espClient); pcf_butt c_qc; pcf_butt c_qh; pcf_butt c_flood; //leds ledRed(&pcf, LED_RED, 300, true); leds ledGreen(&pcf, LED_GREEN, 300, true); //leds ledBlue(&pcf, LED_BLUE, 100, true); //leds ledYellow(&pcf, LED_YELLOW, 100, true); //leds pin0(&pcf, 0, 100, true); bool led = false; uint16_t cnt = 0; void setup() { Serial.begin(115200); lcd.begin(16, 2); lcd.setBacklight(255); lcd.setCursor(0, 0); lcd.print(F("Booting")); WiFi.hostname("VT_ESP"); // WiFi.begin(WIFI_SSID, WIFI_PASSWORD); // if(WiFi.waitForConnectResult() == WL_CONNECTED){ // delay(500); // Serial.print("."); // } // Serial.println(""); // lcd.clear(); // lcd.setCursor(0, 0); // lcd.print(F("Conn.to wf-home")); // lcd.setCursor(0, 1); // //lcd.print("IP address: "); // lcd.println(WiFi.localIP()); // Serial.println(WiFi.localIP()); ArduinoOTA.onStart([]() { Serial.println(F("ArduinoOTA start")); }); ArduinoOTA.onEnd([]() { Serial.println(F("\nArduinoOTA end")); }); ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { Serial.printf("OTA Progress: %u%%\r", (progress / (total / 100))); }); ArduinoOTA.onError([](ota_error_t error) { Serial.printf("Error[%u]: ", error); if (error == OTA_AUTH_ERROR) { Serial.println(F("Auth Failed")); } else if (error == OTA_BEGIN_ERROR) { Serial.println(F("Begin Failed")); } else if (error == OTA_CONNECT_ERROR) { Serial.println(F("Connect Failed")); } else if (error == OTA_RECEIVE_ERROR) { Serial.println(F("Receive Failed")); } else if (error == OTA_END_ERROR) { Serial.println(F("End Failed")); } }); ArduinoOTA.begin(); wifiConnectHandler = WiFi.onStationModeGotIP(onWifiConnect); wifiDisconnectHandler = WiFi.onStationModeDisconnected(onWifiDisconnect); mqttClient.onConnect(onMqttConnect); mqttClient.onDisconnect(onMqttDisconnect); mqttClient.onSubscribe(onMqttSubscribe); mqttClient.onUnsubscribe(onMqttUnsubscribe); mqttClient.onMessage(onMqttMessage); mqttClient.onPublish(onMqttPublish); mqttClient.setServer(mqtt_server, 1883); mqttClient.setClientId("VT"); Serial.println("WF"); connectToWifi(); pcf.begin(); hdc1080.begin(0x40); ee.begin(); button.attachClick(buttClick); button.attachLongPressStart(buttLongClick); ee.readBlock(0, (uint8_t *)&wCounter, sizeof(wCounter)); ee.readBlock(8, (uint8_t *)&wUstavki, sizeof(wUstavki)); ee.readBlock(16, (uint8_t *)&ventUst, sizeof(ventUst)); LCDtimeout = ee.readByte(20); Serial.printf("QCold=%f, QHot=%f\n", wCounter.QC, wCounter.QH); Serial.printf("H_SP=%d, H_DB=%d\n", wUstavki.hSP, wUstavki.hDB); Serial.printf("TWork=%d, TPause=%d\n", ventUst.tWork, ventUst.tPause); Serial.println(LCDtimeout); //c_qc.update(b & 0x01); //c_qh.update((b >> 1) & 0x01); //c_flood.update((b >> 2) & 0x01); // client.setServer(MQTT_SERV, 1883); // client.setCallback(callback); sensors.begin(); sensors.requestTemperatures(); sensors.setResolution(11); cTemp = sensors.getTempCByIndex(0); hTemp = sensors.getTempCByIndex(1); sensors.setWaitForConversion(false); pinMode(VENT_TUAL, OUTPUT); pinMode(VENT_VANNA, OUTPUT); digitalWrite(VENT_TUAL, 1); digitalWrite(VENT_VANNA, 1); pcf.write(LED_RED, 1); pcf.write(LED_GREEN, 1); lcd.clear(); lcd.setCursor(0, 0); lcd.print(F("Init completed")); cRun = 0; page = 0; LCDsec = 0; vvannaSent0 = vvannaSent1 = false; modeEdit = 0; } // setup() // Read the current position of the encoder and print out when changed. void loop() { ArduinoOTA.handle(); // client.loop(); button.tick(); chkEnc(); //ledBlue.tick(); ledGreen.tick(); //ledRed.tick(); //ledYellow.tick(); if(cRun + 99 < millis()){ cRun = millis(); //ledGreen.start(); chkCount(); if(cnt % 10 == 0){ ledGreen.start(); chkLight(); adc = analogRead(A0); mws = (adc - 186) / 7.303396f; temp = hdc1080.readTemperature(); hum = hdc1080.readHumidity(); // Serial.print(F("cnt:")); // Serial.print(cnt); // Serial.print(F("\t")); // Serial.print(cRun); // Serial.print(F("\tT=")); // Serial.print(temp); // Serial.print(F("C, RH=")); // Serial.print(hum); // Serial.print("% adc: "); // Serial.println(adc); getTemps(); if(++LCDsec >= LCDtimeout){ LCDsec = LCDtimeout; lcd.setBacklight(0); modeEdit = 0; } showLCD(page, false); } if(++cnt == 600){ cnt = 0; sendData(); } } if(hum >= wUstavki.hSP + wUstavki.hDB){ digitalWrite(VENT_VANNA, 0); if (!vvannaSent1){ vvannaSent1 = true; vvannaSent0 = false; mqttClient.publish(TOPIC"vt/vvanna", 1, false, "1"); } } else if(hum <= wUstavki.hSP){ digitalWrite(VENT_VANNA, 1); if (!vvannaSent0){ vvannaSent0 = true; vvannaSent1 = false; mqttClient.publish(TOPIC"vt/vvanna", 1, false, "0"); } } } // loop () void buttClick() { Serial.println("Button Click"); LCDsec = 0; lcd.setBacklight(255); if(modeEdit == 1){ if (++itemEdit == 2) itemEdit = 0; switch(page){ case 0: if(itemEdit == 0) encoder.setPosition(wUstavki.hSP); else encoder.setPosition(wUstavki.hDB); break; case 1: if(itemEdit == 0) encoder.setPosition(ventUst.tWork); else encoder.setPosition(ventUst.tPause); break; case 2: if(itemEdit == 0) encoder.setPosition((int)(wCounter.QC*100)); else encoder.setPosition((int)(wCounter.QH*100)); break; } } } void buttLongClick() { Serial.println("Button LongClick"); LCDsec = 0; lcd.setBacklight(255); if (page == 3){ pcf.write(LED_RED, 1); mqttClient.publish(TOPIC"vt/flood", 1, false, "0"); return; } if (modeEdit == 0){ modeEdit = 1; itemEdit = 0; switch(page){ case 0: encoder.setPosition(wUstavki.hSP); break; case 1: encoder.setPosition(ventUst.tWork); break; case 2: encoder.setPosition((int)(wCounter.QC*100)); break; } } else{ modeEdit = 0; switch(page){ case 0: ee.writeBlock(8, (uint8_t *)&wUstavki, sizeof(wUstavki)); break; case 1: ee.writeBlock(16, (uint8_t *)&ventUst, sizeof(ventUst)); break; case 2: ee.writeBlock(0, (uint8_t *)&wCounter, sizeof(wCounter)); break; } encoder.setPosition(page); } curPos = encoder.getPosition(); } void chkCount() { byte b = pcf.read8(); if(c_qc.chngDown((b >> Q_C) & 0x01)){ wCounter.QC += 0.01f; ee.writeBlock(0, (uint8_t*)&wCounter, sizeof(wCounter)); sprintf(v, "%.2f", wCounter.QC); mqttClient.publish(TOPIC"vt/qcold", 1, false, v); Serial.printf("QCold=%f\n", wCounter.QC); //pcf.write(7, led); //led = !led; } if(c_qh.chngDown((b >> Q_H) & 0x01)){ wCounter.QH += 0.01f; ee.writeBlock(0, (uint8_t*)&wCounter, sizeof(wCounter)); sprintf(v, "%.2f", wCounter.QH); mqttClient.publish(TOPIC"vt/qhot", 1, false, v); Serial.printf("QHot=%f\n", wCounter.QH); //pcf.write(7, led); //led = !led; } if(c_flood.chngDown((b >> FLOOD) & 0x01)){ mqttClient.publish(TOPIC"vt/flood", 1, false, "1"); pcf.write(LED_RED, 0); //Send MQTT Flood Serial.printf("Flood\n"); //pcf.write(7, led); //led = !led; } } void showLCD(uint8_t page, bool chgd) { char c = ' '; if(chgd) c = '*'; switch (page) { case 0: lcd.setCursor(0, 0); lcd.printf("V H%4.1f%% T%4.1fC%c", hum, temp, c); lcd.setCursor(0, 1); lcd.printf("SP:%2d DB:%2d ", wUstavki.hSP, wUstavki.hDB); if (modeEdit == 1){ lcd.cursor(); lcd.blink(); if(itemEdit == 0) lcd.setCursor(4, 1); else lcd.setCursor(10, 1); } else{ lcd.noCursor(); lcd.noBlink(); } break; case 1: lcd.setCursor(0, 0); lcd.printf("TW:%2ds TP:%2ds %c", ventUst.tWork, ventUst.tPause, c); lcd.setCursor(0, 1); lcd.printf("TC:%4.1fcTH:%4.1fc", cTemp, hTemp); if (modeEdit == 1){ lcd.cursor(); lcd.blink(); if(itemEdit == 0) lcd.setCursor(4, 0); else lcd.setCursor(11, 0); } else{ lcd.noCursor(); lcd.noBlink(); } break; case 2: lcd.setCursor(0, 0); lcd.printf("QC: %7.2f m3 %c", wCounter.QC, c); lcd.setCursor(0, 1); lcd.printf("QH: %7.2f m3 ", wCounter.QH); if (modeEdit == 1){ lcd.cursor(); lcd.blink(); if(itemEdit == 0) lcd.setCursor(10, 0); else lcd.setCursor(10, 1); } else{ lcd.noCursor(); lcd.noBlink(); } break; case 3: lcd.setCursor(0, 0); lcd.printf("ADC: %4d %c", adc, c); lcd.setCursor(0, 1); lcd.printf("P: %5.2f mws ", mws); break; default: break; } //Serial.println(F("ShLCD")); } void chkEnc() { encoder.tick(); int newPos = encoder.getPosition(); if (curPos != newPos) { LCDsec = 0; lcd.setBacklight(255); // if((newPos < 0) || (newPos > 3)){ // encoder.setPosition(curPos); // return; // } // Serial.println(); curPos = newPos; //Serial.print(curPos); if(modeEdit == 1){ if (newPos < 0) encoder.setPosition(0); else switch(page){ case 0: if(itemEdit == 0){ if(curPos > MAX_HSP){ encoder.setPosition(MAX_HSP); curPos = MAX_HSP; } else wUstavki.hSP = curPos; } else{ if(curPos > MAX_HDB){ encoder.setPosition(MAX_HDB); curPos = MAX_HDB; } else wUstavki.hDB = curPos; } break; case 1: if(itemEdit == 0){ if(curPos > MAX_TWORK){ encoder.setPosition(MAX_TWORK); curPos = MAX_TWORK; } else ventUst.tWork = curPos; } else{ if(curPos > MAX_TPAUSE){ encoder.setPosition(MAX_TPAUSE); curPos = MAX_TPAUSE; } else ventUst.tPause = curPos; } break; case 2: if(itemEdit == 0){ if(curPos > 999999){ encoder.setPosition(999999); curPos = 999999; } else wCounter.QC = curPos / 100.0f; } else{ if(curPos > 999999){ encoder.setPosition(999999); curPos = 999999; } else wCounter.QH = curPos / 100.0f; } break; } } else{ page = curPos; if(page > MAX_PAGE - 1) page = curPos = 0; if(page < 0) page = curPos = MAX_PAGE - 1; } encoder.setPosition(curPos); showLCD(page, false); // Serial.print(page); // Serial.println(); } // if } void getTemps() { static uint8_t cnt = 0; switch (cnt) { case 0: sensors.requestTemperatures(); break; case 1: cTemp = sensors.getTempCByIndex(0); break; case 2: hTemp = sensors.getTempCByIndex(1); break; } if(++cnt > 2){ cnt = 0; } } void chkLight() { static int sec = 0; static unsigned long currun = millis(); static bool lOn = false; //Lamp is on if(!pcf.read(LIGHT_SENS)){ if((currun + 999 < millis()) && !lOn){ sec++; currun = millis(); #ifdef DEBUG Serial.print("Sec On: ");Serial.println(sec); Serial.print("Lamp State: ");Serial.println(lOn); #endif } if((sec >= ventUst.tPause) && !lOn){ //lamp on #ifdef DEBUG Serial.print("Lamp On: ");Serial.println(sec); #endif lOn = true; digitalWrite(VENT_TUAL, LOW); mqttClient.publish(TOPIC"vt/vtual", 1, false, "1"); //sec = 0; } if(lOn) sec = 0; } else{ if(lOn == true){ if(currun + 999 < millis()){ sec++; currun = millis(); #ifdef DEBUG Serial.print("Sec Off: ");Serial.println(sec); Serial.print("Lamp State: ");Serial.println(lOn); #endif } if(sec >= ventUst.tWork){ #ifdef DEBUG Serial.print("Lamp Off: ");Serial.println(sec); #endif lOn = false; digitalWrite(VENT_TUAL, HIGH); mqttClient.publish(TOPIC"vt/vtual", 1, false, "0"); sec = 0; } } else{ sec = 0; } } } void connectToWifi() { Serial.println(F("Connecting to Wi-Fi...")); //Serial1.flush(); WiFi.begin(WIFI_SSID, WIFI_PASSWORD); } void connectToMqtt() { Serial.println(F("Connecting to MQTT...")); //Serial1.flush(); mqttClient.connect(); } void onWifiConnect(const WiFiEventStationModeGotIP& event) { Serial.println(F("Connected to Wi-Fi.")); Serial.print(F("IP: ")); //Serial1.flush(); Serial.println(WiFi.localIP()); pcf.write(LED_YELLOW, 0); connectToMqtt(); } void onWifiDisconnect(const WiFiEventStationModeDisconnected& event) { Serial.println(F("Disconnected from Wi-Fi.")); //Serial1.flush(); mqttReconnectTimer.detach(); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi wifiReconnectTimer.once(2, connectToWifi); pcf.write(LED_YELLOW, 1); } void onMqttConnect(bool sessionPresent) { Serial.println(F("Connected to MQTT.")); Serial.print(F("Session present: ")); //Serial1.flush(); Serial.println(sessionPresent); //digitalWrite(B_LED, HIGH); //digitalWrite(R_LED, LOW); //uint16_t packetIdSub = // //Serial1.print("Subscribing Lamp1, packetId: "); // //Serial1.println(packetIdSub); //packetIdSub = sprintf(v, "%.2f", wCounter.QH); mqttClient.publish(TOPIC"vt/qhot", 1, false, v); mqttClient.publish(TOPIC"vt/qhot_set", 1, false, v); sprintf(v, "%.2f", wCounter.QC); mqttClient.publish(TOPIC"vt/qcold", 1, false, v); mqttClient.publish(TOPIC"vt/qcold_set", 1, false, v); itoa(wUstavki.hDB, v, 10); mqttClient.publish(TOPIC"vt/hdb", 1, false, v); itoa(wUstavki.hSP, v, 10); mqttClient.publish(TOPIC"vt/hsp", 1, false, v); itoa(ventUst.tWork, v, 10); mqttClient.publish(TOPIC"vt/twork", 1, false, v); itoa(ventUst.tPause, v, 10); mqttClient.publish(TOPIC"vt/tpause", 1, false, v); mqttClient.subscribe(TOPIC"vt/qhot_set", 1); mqttClient.subscribe(TOPIC"vt/qcold_set", 1); mqttClient.subscribe(TOPIC"vt/tpause_set", 1); mqttClient.subscribe(TOPIC"vt/twork_set", 1); mqttClient.subscribe(TOPIC"vt/hsp_set", 1); mqttClient.subscribe(TOPIC"vt/hdb_set", 1); mqttClient.subscribe(TOPIC"vt/flood", 1); ////Serial1.print("Subscribing Lamp2, packetId: "); ////Serial1.println(packetIdSub); ////Serial1.println("Publishing at Lamp 1"); //mqttClient.publish(TOPIC"kor/lamp2", 1, false, lStat2 ? "1" : "0"); ////Serial1.println("Publishing at Lamp 2"); pcf.write(LED_BLUE, 0); } void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) { Serial.println("Disconnected from MQTT."); //digitalWrite(B_LED, LOW); //digitalWrite(R_LED, HIGH); if (WiFi.isConnected()) { mqttReconnectTimer.once(2, connectToMqtt); } pcf.write(LED_BLUE, 0); } void onMqttSubscribe(uint16_t packetId, uint8_t qos) { // //Serial1.println("Subscribe acknowledged."); // //Serial1.print(" packetId: "); // //Serial1.println(packetId); // //Serial1.print(" qos: "); // //Serial1.println(qos); } void onMqttUnsubscribe(uint16_t packetId) { // //Serial1.println("Unsubscribe acknowledged."); // //Serial1.print(" packetId: "); // //Serial1.println(packetId); } void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) { if(strcmp(topic, TOPIC"vt/qhot_set") == 0){ wCounter.QH = atof(payload); ee.writeBlock(0, (uint8_t*)&wCounter, sizeof(wCounter)); sprintf(v, "%.2f", wCounter.QH); mqttClient.publish(TOPIC"vt/qhot", 1, false, v); } else if(strcmp(topic, TOPIC"vt/qcold_set") == 0){ wCounter.QC = atof(payload); ee.writeBlock(0, (uint8_t*)&wCounter, sizeof(wCounter)); sprintf(v, "%.2f", wCounter.QC); mqttClient.publish(TOPIC"vt/qcold", 1, false, v); } else if(strcmp(topic, TOPIC"vt/tpause_set") == 0){ ventUst.tPause = atoi(payload); ee.writeBlock(16, (uint8_t*)&ventUst, sizeof(wCounter)); itoa(ventUst.tPause, v, 10); mqttClient.publish(TOPIC"vt/tpause", 1, false, v); } else if(strcmp(topic, TOPIC"vt/twork_set") == 0){ ventUst.tWork = atoi(payload); ee.writeBlock(16, (uint8_t*)&ventUst, sizeof(wCounter)); itoa(ventUst.tWork, v, 10); mqttClient.publish(TOPIC"vt/twork", 1, false, v); } else if(strcmp(topic, TOPIC"vt/hsp_set") == 0){ wUstavki.hSP = atoi(payload); ee.writeBlock(8, (uint8_t*)&wUstavki, sizeof(wCounter)); itoa(wUstavki.hSP, v, 10); mqttClient.publish(TOPIC"vt/hsp", 1, false, v); } else if(strcmp(topic, TOPIC"vt/hdb_set") == 0){ wUstavki.hDB = atoi(payload); ee.writeBlock(8, (uint8_t*)&wUstavki, sizeof(wCounter)); itoa(wUstavki.hDB, v, 10); mqttClient.publish(TOPIC"vt/hdb", 1, false, v); } else if(strcmp(topic, TOPIC"vt/flood") == 0){ pcf.write(LED_RED, !atoi(payload)); c_flood = atoi(payload); } } void onMqttPublish(uint16_t packetId) { //Serial1.println("Publish acknowledged."); //Serial1.print(" packetId: "); //Serial1.println(packetId); //g_led.start(); } void sendData(){ sprintf(v, "%.2f", temp); mqttClient.publish(TOPIC"vt/vtemp", 1, false, v); sprintf(v, "%.2f", hum); mqttClient.publish(TOPIC"vt/vhum", 1, false, v); sprintf(v, "%.2f", cTemp); mqttClient.publish(TOPIC"vt/tcold", 1, false, v); sprintf(v, "%.2f", hTemp); mqttClient.publish(TOPIC"vt/thot", 1, false, v); sprintf(v, "%.2f", mws); mqttClient.publish(TOPIC"vt/wpress", 1, false, v); Serial.print("millis: "); Serial.print(millis()); Serial.println(" Sent data"); }