Popularny post MSof Napisano Marzec 4, 2025 Popularny post Udostępnij Napisano Marzec 4, 2025 (edytowany) Witajcie Chciałbym przedstawić Wam mój pierwszy projekt na ESP32. Buduję smart home i potrzebowałem pomiaru temperatury i wilgotności w pokojach z możliwością ustawiania częstotliwości wysyłania tych danych np. co minutę lub 5 minut, oraz aby te dane nie przechodziły przez chmurę tak jak np. tuya, sonoff, aqara. Są dostępne gotowe urządzenia ale nie spełniały tych założeń , dlatego zrobiłem swoje a przy okazji zacząłem przygodę z esp32 i drukiem 3D. Tak wygląda już gotowe urządzenie Założenia: maksymalnie prosty układ z gotowych części, aby cenowo był tańszy niż już gotowe urządzenia (bo takich urządzeń będę potrzebował x5) komunikacja przez WiFi wysyłka danych co 5min do serwera Home Assistant wyświetlanie danych na ekranie urządzenia gdy by padł serwer z Home Assistant zasilanie z usb C, ponieważ nie chce zmieniać baterii Wykorzystane części: esp32 wroom czujnik temperatury i wilgotności - dht22 oled 128x32 np. ten SPI/I2C - czarno-biały Zaczynam od połączenia wszystkiego na płytce i przetestowaniu programu. Założenia programu są takie żeby na początku na ekranie wyświetlił adres IP pod którym można się zalogować , ponieważ esp32 działa w trybie AP, na ekranie możemy ustawić dane sieci WiFi, częstotliwość wysyłki danych temperatura i wilgotność do HA (w sekundach), logi i hasło do klienta MQTT, oraz adresy wysyłki temperatury i wilgotności do HA. Dodatkowo tryb AP działa przez pierwsze 90s, gdy nie podłączymy się pod WiFi to na ekranie wyświetli się temperatura i wilgotność. Gdy będziemy chcieli zmienić siec to wystarczy wcisnąć wbudowany przycisk resetu, który czeka przez pierwsze 3s od momentu włączenia zasilania , wtedy zresetowana zostaje pamięć i można wprowadzić dane ponownie. Obudowę przygotowałem w programie FreeCAD i jesto to moja pierwsza w życiu obudowa i projekt 3D, ale wciągneło mnie do tego stopnia że już pracuję nad kolejnymi projektami, które wykorzystam w Home Assistant. Przygotowuję kod według założeń, korzystam z programu Arduino IDE. #include <WiFiManager.h> #include <PubSubClient.h> #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #include <Adafruit_Sensor.h> #include <DHT.h> #include <Preferences.h> // Definicje pinów i rozdzielczości OLED #define BOOT_BUTTON_PIN 0 // Przycisk BOOT (GPIO0) #define DHTPIN 4 // Pin danych czujnika DHT22 #define DHTTYPE DHT22 // Typ czujnika #define SCREEN_WIDTH 126 // Szerokość OLED #define SCREEN_HEIGHT 32 // Wysokość OLED #define OLED_RESET -1 // Brak dedykowanego pinu reset Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); DHT dht(DHTPIN, DHTTYPE); unsigned long lastMQTTAttempt = 0; bool wifiFailed = false; Preferences preferences; WiFiManager wm; WiFiClient espClient; PubSubClient client(espClient); // Domyślne ustawienia MQTT i interwału (w sekundach) char mqtt_server[40] = "192.168.1.104"; int mqtt_port = 1883; int send_interval = 30; char mqtt_user[40] = "mqtt_user"; char mqtt_password[40] = "mqtt_password"; char temp_topic[100] = "homeassistant/sensor/esp32/temperature"; char hum_topic[100] = "homeassistant/sensor/esp32/humidity"; // Czas ostatniej publikacji MQTT unsigned long lastSendTime = 0; void displayWiFiInfo() { WiFi.softAP("ESP32_Config"); IPAddress apIP = WiFi.softAPIP(); display.clearDisplay(); display.setTextSize(1); display.setTextColor(SSD1306_WHITE); display.setCursor(0, 0); display.println("Konfiguracja WiFi"); display.print("S: "); display.println("ESP32_Config"); display.print("IP: "); display.println(apIP); display.display(); Serial.println("Tryb AP: ESP32_Config"); Serial.print("Adres konfiguracyjny: "); Serial.println(apIP); } void updateDisplay() { float temperature = dht.readTemperature(); float humidity = dht.readHumidity(); display.clearDisplay(); display.setTextSize(1); display.setTextColor(SSD1306_WHITE); if (isnan(temperature) || isnan(humidity)) { Serial.println("Błąd odczytu DHT!"); display.setCursor(0, 10); display.println("DHT ERROR"); } else { String tempStr = "Temp: " + String(temperature,1) + " C"; String humStr = "Wilg: " + String(humidity,1) + " %"; // Wyśrodkowanie tekstu - obliczamy szerokość tekstu int16_t x1, y1; uint16_t w, h; display.getTextBounds(tempStr.c_str(), 0, 0, &x1, &y1, &w, &h); int xTemp = (SCREEN_WIDTH - w) / 2; int yTemp = (SCREEN_HEIGHT / 2) - h; display.setCursor(xTemp, yTemp); display.println(tempStr); display.getTextBounds(humStr.c_str(), 0, 0, &x1, &y1, &w, &h); int xHum = (SCREEN_WIDTH - w) / 2; int yHum = (SCREEN_HEIGHT / 2) + 2; display.setCursor(xHum, yHum); display.println(humStr); } display.display(); } void publishSensorData() { float temperature = dht.readTemperature(); float humidity = dht.readHumidity(); if (isnan(temperature) || isnan(humidity)) { Serial.println("Błąd odczytu DHT!"); return; } client.publish(temp_topic, String(temperature).c_str()); client.publish(hum_topic, String(humidity).c_str()); Serial.print("Publikacja: T: "); Serial.print(temperature); Serial.print("C, H: "); Serial.print(humidity); Serial.println("%"); } void reconnectMQTT() { if (!client.connected() && (millis() - lastMQTTAttempt >= 15000UL)) { lastMQTTAttempt = millis(); Serial.print("Łączenie z MQTT..."); if (client.connect("ESP32Client", mqtt_user, mqtt_password)) { Serial.println("Połączono z MQTT!"); } else { Serial.print("Błąd, rc="); Serial.print(client.state()); Serial.println(" Nie udało się połączyć."); } } } void setup() { Serial.begin(115200); pinMode(BOOT_BUTTON_PIN, INPUT_PULLUP); delay(100); bool resetSettings = false; unsigned long startTime = millis(); while (millis() - startTime < 3000) { if (digitalRead(BOOT_BUTTON_PIN) == LOW) { resetSettings = true; break; } } if (resetSettings) { Serial.println("Przycisk BOOT wciśnięty - resetowanie ustawień..."); preferences.begin("config", false); preferences.clear(); preferences.end(); wm.resetSettings(); if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { Serial.println("Błąd OLED!"); while (true); } display.clearDisplay(); display.setTextSize(1); display.setTextColor(SSD1306_WHITE); display.setCursor(0, 10); display.print("Reset ustawien!"); display.display(); delay(5000); } if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { Serial.println("Błąd OLED!"); while (true); } display.clearDisplay(); display.setTextSize(1); display.setTextColor(SSD1306_WHITE); display.setCursor(0, 10); display.print("Uruchamianie ..."); display.display(); preferences.begin("config", false); String storedServer = preferences.getString("mqtt_server", "192.168.1.100"); storedServer.toCharArray(mqtt_server, sizeof(mqtt_server)); mqtt_port = preferences.getInt("mqtt_port", 1883); send_interval = preferences.getInt("interval", 300); String storedUser = preferences.getString("mqtt_user", "mqtt_user"); storedUser.toCharArray(mqtt_user, sizeof(mqtt_user)); String storedPass = preferences.getString("mqtt_password", "mqtt_password"); storedPass.toCharArray(mqtt_password, sizeof(mqtt_password)); String storedTempTopic = preferences.getString("temp_topic", "homeassistant/sensor/esp32/temperature"); storedTempTopic.toCharArray(temp_topic, sizeof(temp_topic)); String storedHumTopic = preferences.getString("hum_topic", "homeassistant/sensor/esp32/humidity"); storedHumTopic.toCharArray(hum_topic, sizeof(hum_topic)); preferences.end(); WiFiManagerParameter paramInterval("interval", "Co ile sekund wysyłać dane do HA?", String(send_interval).c_str(), 6); WiFiManagerParameter paramMQTTServer("mqtt_server", "MQTT serwer IP", mqtt_server, 40); WiFiManagerParameter paramMQTTPort("mqtt_port", "MQTT port", String(mqtt_port).c_str(), 6); WiFiManagerParameter paramMQTTUser("mqtt_user", "MQTT użytkownik", mqtt_user, 40); WiFiManagerParameter paramMQTTPassword("mqtt_password", "MQTT hasło", mqtt_password, 40); WiFiManagerParameter paramTempTopic("temp_topic", "MQTT Temat Temperatury", temp_topic, 100); WiFiManagerParameter paramHumTopic("hum_topic", "MQTT Temat Wilgotności", hum_topic, 100); wm.addParameter(¶mInterval); wm.addParameter(¶mMQTTServer); wm.addParameter(¶mMQTTPort); wm.addParameter(¶mMQTTUser); wm.addParameter(¶mMQTTPassword); wm.addParameter(¶mTempTopic); wm.addParameter(¶mHumTopic); displayWiFiInfo(); // Ustaw timeout, aby portal AP był aktywny przez 90 sekund (1 min i 30sec) wm.setTimeout(90); if (!wm.autoConnect("ESP32_Config")) { Serial.println("Brak połączenia z WiFi! Tryb AP."); WiFi.mode(WIFI_OFF); wifiFailed = true; } Serial.println("Połączono z WiFi!"); send_interval = String(paramInterval.getValue()).toInt(); strncpy(mqtt_server, paramMQTTServer.getValue(), sizeof(mqtt_server)); mqtt_port = String(paramMQTTPort.getValue()).toInt(); strncpy(mqtt_user, paramMQTTUser.getValue(), sizeof(mqtt_user)); strncpy(mqtt_password, paramMQTTPassword.getValue(), sizeof(mqtt_password)); strncpy(temp_topic, paramTempTopic.getValue(), sizeof(temp_topic)); strncpy(hum_topic, paramHumTopic.getValue(), sizeof(hum_topic)); preferences.begin("config", false); preferences.putString("mqtt_server", mqtt_server); preferences.putInt("mqtt_port", mqtt_port); preferences.putInt("interval", send_interval); preferences.putString("mqtt_user", mqtt_user); preferences.putString("mqtt_password", mqtt_password); preferences.putString("temp_topic", temp_topic); preferences.putString("hum_topic", hum_topic); preferences.end(); dht.begin(); client.setServer(mqtt_server, mqtt_port); } void loop() { if (!client.connected()) { reconnectMQTT(); } client.loop(); updateDisplay(); if (millis() - lastSendTime >= (send_interval * 1000UL)) { publishSensorData(); lastSendTime = millis(); } delay(1000); } Gdy wszystko pasowało zmontowałem w jedną całość i rozpocząłem kondigurację z Home Assistant aby odbierać dane temperatura i wilgotność. Całość gotowa i działa. Dane są odbierane w Home Assistant z dwóch encji. Dzięki temu mogę wykorzystać to do uruchamiania klimatyzacji, nawilżacza powietrza lub ogrzewania. Całość działą lokalnie dzięki temu wyeliminowałem chmure i chińskie serwery i całkowicie odszedłem od LocalTuya i Sonoff. Obecnie takich termometrów mam 5, testuje różne kolory wydruku 3D i wszystkie działają w Home Assistant. Projekt pewnie dla wielu z Was jest prosty ale bardzo mi pomógł w działamiu smart home i zrodził kolejne pomysły na następne urządzenia które są już w trakcie budowy. Dziękuję za uwagę. Edytowano Marzec 4, 2025 przez MSof dodanie linków 4
ethanak Marzec 5, 2025 Udostępnij Marzec 5, 2025 Hm... WiFi, czyli jesteś zależny od przynajmniej działania routera. Ja w podobnym projekcie wykorzystalem esp-now. Co prawda wymagało to podłaczenia dodatkowego esp do centralki, ale całość będzie działać nawet jeśli router wyleci w powietrze A dodatkowy esp przy okazji obsługuje wyśwuetlacz, klawiaturę i parę innych rzeczy
MSof Marzec 5, 2025 Autor tematu Udostępnij Marzec 5, 2025 Racja wtedy padnie ale w sumie padną mi też wtedy inne urządzenia Wifi mam z dwóch powodów: Bo mam już router i nie chciałem kupować kolejnej bramki np. zigbee miałem esp32 pod ręką a chciałem żeby było w miare tanio i jak najszybciej kompatybilne przez MQTT z Home Asistant'em Ale zaczynam myśleć nad wersją zigbee bo mam pomysł na inne urządzenia które potrzebuję
MSof Marzec 5, 2025 Autor tematu Udostępnij Marzec 5, 2025 To jest to? https://www.espressif.com/en/solutions/low-power-solutions/esp-now Bo faktycznie ciekawe muszę poczytać
lukaszd82 Kwiecień 19, 2025 Udostępnij Kwiecień 19, 2025 (edytowany) Jak ma być tanio to ESP8266 wychodzi sporo taniej niż ESP32 a w tak prostej aplikacji to i tak przerost mocy Edytowano Kwiecień 19, 2025 przez lukaszd82
ethanak Kwiecień 19, 2025 Udostępnij Kwiecień 19, 2025 1 godzinę temu, lukaszd82 napisał: ESP8266 wychodzi sporo taniej niż ESP32 Hm... na aledrogo Wemos D1 Mini 13 PLN, ESP32 C3 Super Mini 19 PLN. Potężna różnica 6 zeta... W Botlandzie XIAO C3 kosztuje już drożej, ale masz zintegrowaną ładowarkę do LiPo i gniazdko do jakiejś lepszej anteny niż dołączona do zestawu okaże się niewystarczająca. Układ idealny akurat do zdalnego termometru (tak, zrobiłem taki). Przy czym oba C3 to płyteczki wielkości paznokcia... a to też dużo znaczy. Tak że z tym "sporo" to ja bym się nie upierał
lukaszd82 Kwiecień 19, 2025 Udostępnij Kwiecień 19, 2025 (edytowany) Ja ESP8266 kupowałem po 4zł na ali... Wszystko zależy od ilości jaką się kupuje i ilości wykonywanych układów. Te 6zł stanowi prawie 50% różnicę. W takim kontekście patrząc, to spora różnica. Edytowano Kwiecień 19, 2025 przez lukaszd82
MSof Kwiecień 19, 2025 Autor tematu Udostępnij Kwiecień 19, 2025 mi esp32 wychodziło po 6zl jak połączyłem kilka promocji na ali w tamtym roku, kupowałem chyba z 20 szt.
adam_m Kwiecień 20, 2025 Udostępnij Kwiecień 20, 2025 bardzo ciekawy projekt ....dlaczego ? ..bo pokazuje jak niestandardowo programować czujniki w Home Assistant. Ja takie czujniki programuje w edytorze yaml HA - to chyba jest domyślny sposób komunikacji z HA ? Znam Arduino ( i uwielbiam ) ale używam do innych projektów. Wydaje mi się że korzystanie z edytora yaml w HA daje większe możliwości kontroli esp32 jak choćby OTA updates kodu. Domyślnie czujniki komunikują się z HA nie poprzez MQTT - broker MQTT ma też swoje ograniczenia dlatego projekt HA wybrał inny domyślny sposób komunikacji urządzeń. Ale ciekawy projekt pokazujący jak inaczej/niestandardowo budować czujniki
Harnas Kwiecień 22, 2025 Udostępnij Kwiecień 22, 2025 Dnia 20.04.2025 o 08:07, adam_m napisał: Ja takie czujniki programuje w edytorze yaml HA - to chyba jest domyślny sposób komunikacji z HA ? Pod spodem z tych YAML jest generowany normalny kod w C++ który ląduje w ukrytym folderze obok YAMLi. Wygląda troszkę jak to co generuje CUBE MX. Te pliki można załadować w Platformio i następnie debugować i zmieniać jak zwykły projekt. A samo ESPHome można uruchomić po prostu na swoim komputerze. Ja tak robię, wygodniej się edytuje YAMLe, łatwiej tym wszystkim zarządzać i sama kompilacja trwa szybciej. 1
Pomocna odpowiedź
Bądź aktywny - zaloguj się lub utwórz konto!
Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony
Utwórz konto w ~20 sekund!
Zarejestruj nowe konto, to proste!
Zarejestruj się »Zaloguj się
Posiadasz własne konto? Użyj go!
Zaloguj się »