Sterownik Akwarium
Powstał jako pierwszy ? Umożliwia załączenie i wyłączenie filtrów i oświetlenia w akwarium. Sterowanie ręczne jak i automatyczne o wyznaczonych godzinach.
Urządzenie to składa się z zasilacza 5V, podwójnego przełącznika SSR, czujnika temperatury BS18B20 oraz ESP8266. Całość zmieściła się w obudowie od potrójnego gniazda natynkowego, dwa pozostały aktywne a w trzecim jest elektronika.
[dodać tu foto]
Kod napisałem na podstawie modyfikacji kilku innych rozwiązań i scaliłem to na własne potrzeby. Kod zwiera automatyczny reset po utracie połączenia WiFI lub brokera MQTT.
#include <EEPROM.h> #include <ESP8266WiFi.h> #include <PubSubClient.h> #include <OneWire.h> #include <DallasTemperature.h> #define ONE_WIRE_BUS 1 #define RELAY1 0 #define RELAY2 2 #define LED 3 #define MQTT_CLIENT "Akwarium" #define MQTT_SERVER "192.168.15.235" #define MQTT_PORT 1883 #define MQTT_TOPIC "/akwa/relay" #define MQTT_USER "mqtt_u" #define MQTT_PASS "mqtt_p" #define WIFI_SSID "WiFi_SSID" #define WIFI_PASS "WiFi_PASS" #define VERSION "------------------------ Akwarium v1.01p ------------------------" bool rememberRelayState = true; // Czy pamietac ustawienia w eeprom bool sendStatusR1 = false; bool sendStatusR2 = false; bool requestRestart = false; float tmp_p, tmp_s, tmp_o; int licz = 1; char bufor[10]; int kUpdFreq = 1; // Co ile minut sprawdzac polaczenie int kRetries = 10; // Licznik wznawiania polaczenia wifi int lastRELAY1State; int lastRELAY2State; unsigned long TTasks; unsigned long TTasks1; unsigned long count = 0; long czas_temp = 10000; //co ile ma być odczyt z czujników w milisekundach int licznik = 60; //co ile odczytów wysyłamy MQTT bool serial = false; String message=""; WiFiClient wifiClient; PubSubClient mqttClient(wifiClient); OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); void callback(char* topic, byte* payload, unsigned int length) { if(serial){Serial.print("COLLECT ->\tTopic:\t["); Serial.print(topic); Serial.print("]\tMsg: [");} for (int i=0;i<length;i++) { message += (char)payload[i]; } if(serial){Serial.print(message);} if(message == "F-off"){digitalWrite(RELAY1, HIGH);sendStatusR1 = true;} if(message == "F-on"){digitalWrite(RELAY1,LOW);sendStatusR1 = true;} if(message == "S-off"){digitalWrite(RELAY2, HIGH);sendStatusR2 = true;} if(message == "S-on"){digitalWrite(RELAY2,LOW);sendStatusR2 = true;} if(serial){Serial.print("]\tLength="); Serial.println(length);} message=""; } void setup() { pinMode(LED, OUTPUT); pinMode(RELAY1, OUTPUT); pinMode(RELAY2, OUTPUT); digitalWrite(LED, LOW); digitalWrite(RELAY1, HIGH); digitalWrite(RELAY2, HIGH); if(serial){Serial.begin(115200);} EEPROM.begin(8); lastRELAY1State = EEPROM.read(0); lastRELAY2State = EEPROM.read(1); if (rememberRelayState && lastRELAY1State == 1) { digitalWrite(RELAY1, LOW); } if (rememberRelayState && lastRELAY2State == 1) { digitalWrite(RELAY2, LOW); } sendStatusR1 = true; sendStatusR2 = true; sensors.begin(); sensors.setWaitForConversion(false); // makes it async sensors.requestTemperatures(); mqttClient.setCallback(callback); mqttClient.setServer(MQTT_SERVER, MQTT_PORT); WiFi.mode(WIFI_STA); WiFi.begin(WIFI_SSID, WIFI_PASS); if(serial){Serial.println(VERSION); Serial.print("\nUnit ID: "); Serial.print("esp8266-"); Serial.print(ESP.getChipId(), HEX); Serial.print("Send temperature every: "); Serial.print((czas_temp*licznik)/60000); Serial.print(" minutes"); Serial.print("\nConnecting to "); Serial.print(WIFI_SSID); Serial.print(" Wifi"); } while ((WiFi.status() != WL_CONNECTED) && kRetries --) { delay(500); if(serial){Serial.print(" .");} } if (WiFi.status() == WL_CONNECTED) { if(serial){Serial.println(" DONE"); Serial.print("IP Address is: "); Serial.println(WiFi.localIP()); Serial.print("Connecting to ");Serial.print(MQTT_SERVER);Serial.print(" Broker . .");} delay(500); while (!mqttClient.connect(MQTT_CLIENT, MQTT_USER, MQTT_PASS)) { if(serial){Serial.print(" .");} delay(1000); } if(mqttClient.connected()) { if(serial){Serial.println(" DONE"); Serial.println("\n---------------------------- Logs ----------------------------"); Serial.println();} mqttClient.subscribe(MQTT_TOPIC); blinkLED(LED, 300, 4); } else { if(serial){Serial.println(" FAILED!"); Serial.println("\n----------------------------------------------------------------"); Serial.println();} } } else { if(serial){Serial.println(" WiFi FAILED!"); Serial.println("\n----------------------------------------------------------------"); Serial.println();} } } void loop() { mqttClient.loop(); timedTasks(); checkStatus(); } void blinkLED(int pin, int duration, int n) { for(int i=0; i<n; i++) { digitalWrite(pin, HIGH); delay(duration); digitalWrite(pin, LOW); delay(duration); } } void checkConnection() { if (WiFi.status() == WL_CONNECTED) { if (mqttClient.connected()) { if(serial){Serial.println("mqtt broker connection . . . . . . . . . . OK");} } else { if(serial){Serial.println("mqtt broker connection . . . . . . . . . . LOST");} requestRestart = true; } } else { if(serial){Serial.println("WiFi connection . . . . . . . . . . LOST");} requestRestart = true; } } void checkStatus() { if (sendStatusR1) { if(digitalRead(RELAY1) == LOW) { if (rememberRelayState) { EEPROM.write(0, 1); } mqttClient.publish(MQTT_TOPIC"/F/stat", "F-on", false); if(serial){Serial.println("SEND ->\t\tTopic:\t["MQTT_TOPIC"/F/stat]\tMsg: [F-on]\tRelay F: ON");} } else { if (rememberRelayState) { EEPROM.write(0, 0); } mqttClient.publish(MQTT_TOPIC"/F/stat", "F-off", false); if(serial){Serial.println("SEND ->\t\tTopic:\t["MQTT_TOPIC"/F/stat]\tMsg: [F-off]\tRelay F: OFF");} } if (rememberRelayState) { EEPROM.commit(); } blinkLED(LED, 50, 2); sendStatusR1 = false; } if (sendStatusR2) { if(digitalRead(RELAY2) == LOW) { if (rememberRelayState) { EEPROM.write(1, 1); } mqttClient.publish(MQTT_TOPIC"/S/stat", "S-on", false); if(serial){Serial.println("SEND ->\t\tTopic:\t["MQTT_TOPIC"/S/stat]\tMsg: [S-on]\tRelay S: ON");} } else { if (rememberRelayState) { EEPROM.write(1, 0); } mqttClient.publish(MQTT_TOPIC"/S/stat", "S-off", false); if(serial){Serial.println("SEND ->\t\tTopic:\t["MQTT_TOPIC"/S/stat]\tMsg: [S-off]\tRelay F: OFF");} } if (rememberRelayState) { EEPROM.commit(); } blinkLED(LED, 50, 2); sendStatusR2 = false; } if (requestRestart) { blinkLED(LED, 30, 15); ESP.restart(); } } void checktemp() { tmp_p = sensors.getTempCByIndex(0); //tmp_p = 23.88; tmp_s = (tmp_s + tmp_p); // Serial.println("Licznik:\t"licz"/"licznik"Temperature:\t"tmp_p); licz++; if(licz > licznik){ tmp_s = tmp_s / (licz-1); if(serial){Serial.print("READING ->\tAverage temperature:\t"); Serial.println(tmp_s);} if(tmp_s != tmp_o){ tmp_o = tmp_s; dtostrf(tmp_o , 0, 1, bufor); if(serial){Serial.print("SEND ->\t\tTopic:\t["MQTT_TOPIC"/temp]\tMsg: ["); Serial.print(bufor); Serial.println("]"); } mqttClient.publish(MQTT_TOPIC"/temp", bufor, false); blinkLED(LED, 50, 2); } tmp_s = 0; licz = 1; } sensors.requestTemperatures(); } void timedTasks() { if ((millis() > TTasks + (kUpdFreq*60000)) || (millis() < TTasks)) { TTasks = millis(); checkConnection(); blinkLED(LED, 100, 1); } if ((millis() > TTasks1 + czas_temp) || (millis() < TTasks1)) { TTasks1 = millis(); checktemp(); blinkLED(LED, 10, 1); } }
Tak wygląda sterowanie ręczne po stronie HA
