W artykule zaprezentujemy bezprzewodowy kontroler poziomu wody, bazujący na mikrokontrolerach ESP32 oraz ESP8266. Układ został wyposażony w zabezpieczenie napięciowe i prądowe, aby chronić silnik pompy i wyeliminować ryzyko awarii. Do przesyłu danych zastosowano protokół ESP-NOW. Kluczowe cechy systemu – założenia projektowe autora, to:
- komunikacja bezprzewodowa,
- ochrona przed przepięciami i zapadami napięcia,
- ochrona przed przeciążeniem i pracą pompy na sucho,
- wbudowane przyciski do konfiguracji systemu,
- możliwość zapisu ustawień w pamięci flash,
- wyświetlacz TFT o przekątnej 1,8 cala,
- pomiar i prezentacja danych takich jak napięcie, prąd, moc i współczynnik mocy silnika pompy,
- przełącznik wyboru trybu pracy,
- przycisk do dopełniania zbiornika.
Dlaczego regulator poziomu wody?
Dla autora głównym celem budowy tego sterownika jest sterowanie napełnianiem zbiornika wody, gdy jego stan spada do 50% pojemności. Prezentowane tutaj urządzenie jest drugą wersją kontrolera. Wcześniejszy system zawierał wodoodporny czujnik ultradźwiękowy do pomiaru poziomu wody. Kontroler używany był przez rok. Głównym problemem tamtego urządzenia było tworzenie się kropel wody na powierzchni przetwornika ultradźwiękowego, co powodowało fałszywe odczyty. Zwykle działo się tak w czasie deszczu. Jako że zbiornik na wodę stał w trudno dostępnym miejscu, wspinanie się i czyszczenie czujnika ultradźwiękowego w deszczową pogodę było naprawdę problematyczne. Potrzebne było niezawodne i trwałe rozwiązanie.
Autor rozważał początkowo jakiś inny, bardziej zaawansowany czujnik poziomu wody, np. sensor ciśnienia, jednak z uwagi na brak dostępności tego rodzaju sensorów w miejscu zamieszkania zdecydował się finalnie na klasyczny pływak, aktywujący się, gdy poziom wody osiągnie 50%. Kluczową zmianą, względem poprzedniej generacji urządzenia, było przejście na komunikację bezprzewodową. W poprzedniej wersji zastosowano kabel CAT 6 do podłączenia czujnika ultradźwiękowego do sterownika, ale przy długości 50 metrów podłączenie było dosyć trudne z uwagi na problemy elektryczne (duża długość przewodu) i praktyczne (doprowadzenie 50 metrów przewodu od sterownika do zbiornika wody nie jest trywialne).
W nowym kontrolerze autor zastosował protokół ESP-NOW do przesyłania danych. Używa on układu ESP32U w module odbiornika i ESP07S w module nadajnika. W teście uzyskano zasięg prawie 450 metrów (w linii wzroku), umieszczając nadajnik na szczycie budynku, co jest naprawdę dobrym osiągnięciem, biorąc pod uwagę fakt, że nie są używane żadne zewnętrzne moduły bezprzewodowe. Inną nową cechą sterownika jest ochrona przed wysokim i niskim napięciem, przeciążeniem i suchobiegiem. Zabezpieczenie przed przeciążeniem i suchobiegiem działa poprzez pomiar poboru prądu silnika. Gdy silnik pracuje na sucho, pobór prądu znacznie się zmniejsza. Z użyciem biblioteki Emonlib do pomiaru napięcia i prądu monitorowana jest praca i status pompy.
Potrzebne elementy
Nadajnik
Do budowy nadajnika potrzebne będą następujące elementy:
- moduł z mikrokontrolerem ESP 07S,
- antena dla modułu z ESP,
- stabilizator LDO LM2950G-3.3,
- przyciski (microswitche) SMD – 2 sztuki,
- kondensator elektrolityczny 2200 μF,
- oporniki 10 kΩ/SMD0805 (3 sztuki),
- opornik 100 kΩ/SMD0805,
- opornik 330 kΩ/SMD0805,
- opornik 22 kΩ/SMD0805,
- złącze śrubowe na PCB,
- złącze RMC,
- ogniwo 18650,
- moduł ładowarki TP4056,
- czujnik pływakowy,
- przełącznik pływakowy P43 (do funkcji dopełniania zbiornika),
- wodoodporna obudowa,
- ogniwo słoneczne 5 V,
- płytka drukowana.
Odbiornik
Do zestawienia odbiornika potrzebne nam będą:
- moduł z mikrokontrolerem ESP32U,
- antena dla modułu z ESP,
- stabilizator AMS1117-3.3,
- tranzystor MOSFET AO3400,
- przycisk (microswitch) SMD – 2 sztuki,
- wyświetlacz TFT o przekątnej 1,7 cala ze sterownikiem ST7735,
- trójpozycyjny przełącznik kołyskowy,
- dwupozycjny przełącznik kołyskowy,
- przycisk dwupozycyjny z diodą LED,
- przekaźnik 5 V ze stykami do 40 A,
- sensor do pomiaru prądu (do 25 A),
- transformator pomiarowy ZMPT101B do pomiaru napięcia,
- złącza RMC,
- złącze śrubowe do PCB,
- dioda 1N4007,
- kondensator elektrolityczny 10 μF (3 sztuki),
- kondensator 100 nF w obudowie SMD0805,
- kondensator 4,7 μF w obudowie SMD1206 (2 sztuki),
- opornik 82 kΩ o mocy 1 W,
- rezystor 10 kΩ w obudowie SMD0805 (9 sztuk),
- rezystor 1 kΩ w obudowie SMD0805,
- rezystor 470 kΩ w obudowie SMD0805,
- rezystor 220 kΩ w obudowie SMD0805,
- wodoodporna obudowa,
- śruby M3,
- płytka drukowana.
Natomiast do zestawienia dodatkowej płytki z przyciskami, którą podłącza się do sterownika, potrzebne są:
- przyciski (microswitche) SMD – 3 sztuki,
- rezystor 10 kΩ w obudowie SMD0805,
- rezystor 4,7 kΩ w obudowie SMD0805,
- rezystor 20 kΩ w obudowie SMD0805,
- płytka drukowana.
Budowa układu
Autor zaprojektował dla układu 3 płytki drukowane: nadajnik, odbiornik i płytka z przyciskami. Ich schematy pokazane są odpowiednio na rysunku 1, rysunku 2 oraz rysunku 3.
Płytki zostały wykonane w oprogramowaniu EasyEDA. Dostęp do tego pakietu (w chmurze) jest bezpłatny dla hobbystów, więc każdy może otworzyć i edytować te projekty. Jest to szczególnie istotne, jeśli chcemy zamawiać je w zakładzie produkcyjnym, gdyż pozwala to na zmodyfikowanie projektu pod kątem specyficznych wymagań danego, konkretnego zakładu.
Ponadto, z poziomu EasyEDA można wygenerować wszystkie niezbędne pliki produkcyjne – pliki Gerber, odwiert (pliki dla drukarki numerycznej), a także pliki dla frezarek, dokumentacja do produkcji masek do nakładania pasty lutowniczej itd. Można wygenerować też zestaw plików dla maszyn pick & place, aby możliwy był montaż automatyczny płytek. Linki do projektów płytek znajdują się w artykule źródłowym (patrz linki na końcu artykułu). Po wykonaniu płytek PCB należy przylutować w pierwszej kolejności wszystkie elementy SMD, a następnie elementy przewlekane.
Oprogramowanie
Oprogramowanie korzysta z protokołu ESP-NOW do transmisji danych pomiędzy sensorem a odbiornikiem. ESP-NOW to protokół opracowany przez firmę Espressif do komunikacji pomiędzy jej urządzeniami z wykorzystaniem sieci bezprzewodowej, ale bez konieczności instalacji routera w sieci Wi-Fi. Istotnie upraszcza to implementację systemu, a także samo oprogramowanie – wystarczy skorzystać z odpowiednich bibliotek.
C#include <ESP8266WiFi.h>
#include <espnow.h>
#define NUM_SAMPLES 10
int float_switch1_pin = 13;
int float_switch2_pin = 12;
int float_switch1;
int float_switch2;
// Adres MAC odbiornika
uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
int sum = 0;
unsigned char sample_count = 0;
// Przykładowa struktura do przesyłu danych
typedef struct struct_message {
int Float_switch1;
int Float_switch2;
int a;
float BatV;
} struct_message;
// Wiadomość o zdefiniowanej strukturze
struct_message myData;
// Odwołanie po wysłaniu danych
void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
Serial.print(“Last Packet Send Status: “);
if (sendStatus == 0) {
Serial.println(“Delivery success”);
} else {
Serial.println(“Delivery fail”);
}
}
void setup() {
Serial.begin(115200);
pinMode(float_switch1_pin, INPUT);
pinMode(float_switch2_pin, INPUT);
WiFi.mode(WIFI_STA);
// Inicjalizacja ESP-NOW
if (esp_now_init() != 0) {
Serial.println(“Error initializing ESP-NOW”);
return;
}
// Definicja roli urządzenia
esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);
// Rejestracja call-backu
esp_now_register_send_cb(OnDataSent);
// Rejestracja nadajnika w sieci ESP-NOW
esp_now_add_peer(broadcastAddress, ESP_NOW_ROLE_SLAVE, 1, NULL, 0);
}
void loop() {
// Odczyt stanu pływaków
float_switch1 = digitalRead(float_switch1_pin);
float_switch2 = digitalRead(float_switch2_pin);
// Przesłanie stanu do struktury danych
myData.Float_switch1 = float_switch1;
myData.Float_switch2 = float_switch2;
myData.a = 1;
while (sample_count < NUM_SAMPLES) {
// Odczyt napięcia baterii
sum += analogRead(A0);
sample_count++;
delay(10);
}
// Średnie napięcie baterii
myData.BatV = ((float)sum / (float)NUM_SAMPLES * 1) / 1024.0;
sample_count = 0;
sum = 0;
// Wysłanie danych przez ESP-NOW
esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
ESP.deepSleep(20000000, WAKE_NO_RFCAL);
delay(100);
}
Fragment kodu programu nadajnika pokazuje listing 1, a dla odbiornika listing 2. Pełne oprogramowanie dostępne jest na stronie z projektem.
TFT_eSPI tft = TFT_eSPI();
Preferences preferences;
// Przykładowa struktura do przesyłu danych
typedef struct struct_message {
int Float_switch1;
int Float_switch2;
int a;
float BatV;
} struct_message;
// Wiadomość o zdefiniowanej strukturze
struct_message myData;
// Odwołanie po odebraniu danych
void OnDataRecv(const uint8_t * mac,
const uint8_t *incomingData,
int len) {
memcpy(&myData, incomingData, sizeof(myData));
Serial.print(“Bytes received: “);
Serial.println(len);
Serial.print(“Int: “);
Serial.println(myData.a);
Serial.print(“Battery voltage: “);
Serial.println(myData.BatV * Batv_Calib);
Serial.print(“float1: “);
Serial.println(float_switch1);
Serial.print(“float2: “);
Serial.println(float_switch2);
}
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
// Konfiguracja ustawień
preferences.begin(“settings”, false);
Vmax = preferences.getInt(“value”, 250);
Vmin = preferences.getInt(“value1”, 180);
Imax = preferences.getFloat(“value2”, 5.2);
Imin = preferences.getFloat(“value3”, 3.8);
Delay = preferences.getInt(“value4”, 5);
V_Cutoff = preferences.getInt(“value5”, 0);
I_Cutoff = preferences.getInt(“value6”, 0);
RST_Delay = preferences.getInt(“value7”, 1);
// Inicjalizacja ESP-NOW
if (esp_now_init() != ESP_OK) {
Serial.println(“Error initializing ESP-NOW”);
return;
}
// Rejestracja call-backu
esp_now_register_recv_cb(OnDataRecv);
// Inicjalizacja ekranu
tft.init();
tft.fillScreen(TFT_BLACK);
pinMode(relaypin, OUTPUT);
pinMode(topup_pin, INPUT_PULLUP);
myData.Float_switch2 = 0;
// Napięcie: kalibracja, przesunięcier fazowe
emon1.voltage(voltagepin, 346, 1.7);
// Prąd: kalibracja
emon1.current(currentpin, 11.261);
}
void loop() {
unsigned long currentTime = millis();
float_switch1 = myData.Float_switch1;
float_switch2 = myData.Float_switch2;
modepinvalue = analogRead(modepin);
topup_value = digitalRead(topup_pin);
readbutton(); // Odczyt przycisków
options(); // Ustawianie opcji
// Oblicza liczbę [przejść napięcia przez zero
emon1.calcVI(20, 2000);
voltage = emon1.Vrms;
// (...) – pełna zaimplementowana automatyka ograniczeń,
// uzalezniona od konkretnej instalacji
// Przykładowy kod automatyki, z oryginalnego systemu,
// dostępny jest na stronie z projektem
pointer1 = constrain(pointer1, 20, 132);
pointer2 = constrain(pointer2, 0, 0);
Vmax = constrain(Vmax, 0, 325);
Vmin = constrain(Vmin, 0, 325);
Imax = constrain(Imax, 0, 13);
Imin = constrain(Imin, 0, 13);
Delay = constrain(Delay, 0, 60);
RST_Delay = constrain(RST_Delay, 0, 60);
// Wyświetlenie odpowiedniego ekranu
switch (screen) {
case 0:
screen_0();
break;
case 1:
screen_1();
break;
case 2:
screen_2();
break;
case 3:
screen_3();
break;
}
// Zapis danych do pamięci
preferences.putInt(“value”, Vmax);
preferences.putInt(“value1”, Vmin);
preferences.putFloat(“value2”, Imax);
preferences.putFloat(“value3”, Imin);
preferences.putInt(“value4”, Delay);
preferences.putInt(“value5”, V_Cutoff);
preferences.putInt(“value6”, I_Cutoff);
preferences.putInt(“value7”, RST_Delay);
}
Zanim kod ten zostanie wprowadzony do Arduino IDE, skompilowany i wgrany do odpowiednich modułów, konieczne jest zainstalowanie wsparcia dla tych układów (ESP8266 oraz ESP32) i wymaganych bibliotek:
- TFT_eSPI: https://github.com/Bodmer/TFT_eSPI,
- Preferences: https://www.arduino.cc/reference/en/libraries/preferences/,
- EmonLib-esp32: https://github.com/Savjee/EmonLib-esp32.
Następnie należy skonfigurować bibliotekę TFT_eSPI do współpracy z układem ESP32. W pliku User_Setup.h, będącym częścią biblioteki, należy zmienić wybrane sterowniki oraz zdefiniować piny, do których podłączony jest sterownik wyświetlacza TFT. W źródłowym artykule znajduje się link do tutoriala dokładnie objaśniający, jak należy korzystać z tej biblioteki. Przed przesłaniem kodu do ESP07S (nadajnika – listing 1) należy wprowadzić adres MAC odbiornika. Adres MAC odbiornika można poznać, wgrywając do modułu ekstremalnie prosty szkic, który zwróci przez port szeregowy adres MAC, pokazany na listingu 3.
#include <WiFi.h>
void setup(){
Serial.begin(115200);
Serial.println();
Serial.print("ESP Board MAC Address: ");
Serial.println(WiFi.macAddress());
}
Budowa
Autor do zamknięcia odbiornika wykorzystał komercyjną obudowę z PCV z pokrywką, wykonaną w technice druku 3D. W pokrywce umieszczony jest wyświetlacz i przyciski (fotografia 1).
W obudowie umieszczono wszystkie komponenty wraz z zasilaczem 5 V, podłączonym do sieci 230 V. Przewód fazowy i neutralny podłączone są do zacisku śrubowego płytki drukowanej, a jeden przewód silnika przechodzi do normalnie rozwartego styku przekaźnika, drugi jest natomiast podłączony do przewodu neutralnego (fotografia 2).
Obudowa głównego modułu sensora pokazana jest na fotografii 3. W otworach przewodów nadajnika zastosowano silikon RTV, aby zapobiec przedostawaniu się wody do środka.
Działanie układu
W systemie zastosowano dwa wyłączniki pływakowe. Gdy pierwszy (czerwony) wyłącznik pływakowy jest w niskiej pozycji, silnik włącza się automatycznie, a gdy jest w wysokiej pozycji, silnik wyłącza się automatycznie. Więc po co drugi (biały) pływak? Służy do realizacji funkcji uzupełniania. Biały wyłącznik pływakowy znajduje się tuż pod rurą przelewową. Jeśli chcemy napełnić zbiornik, ale czerwony pływak jest nadal w pozycji wysokiej, można nacisnąć przycisk doładowania, a silnik wyłączy się automatycznie, gdy woda dotknie białego przełącznika pływakowego. Ten kontroler ma 3 tryby: AUTO, OFF, MANUAL. Tryb ręczny jest jak normalny przełącznik, który włącza silnik. W tym trybie silnik nie ma żadnych zabezpieczeń.
Do menu ustawień można wejść tylko po przełączeniu w tryb OFF. W ustawieniach można zdefiniować maksymalne bezpieczne poziomy napięcia i prądu silnika, a także zdefiniować opóźnienia w systemie, sterować stanem zabezpieczenia napięciowego i prądowego oraz opóźnieniem przy resecie systemu. Menu informacyjne pokazuje na wyświetlaczu układu aktualne napięcie, prąd, moc, współczynnik mocy i napięcie akumulatora nadajnika.
Nikodem Czechowski, EP
Źródła:
http://bit.ly/3UhKqif
https://oshwlab.com/electronics220903/wlc-v2
https://oshwlab.com/electronics220903/wlc-transmitter
https://oshwlab.com/electronics220903/button_breakout_board