Po długim oczekiwaniu przyszedł czas abym zaprezentował na tej stronie pierwszy projekt z dziedziny elektroniki. Jest to zegar LED którego wyświetlaczem są cztery matryce 8×8 pikseli z kontrolerem MAX7219. Układ zegara RTC to bardzo dokładny DS3231 a całością steruje ESP8266 (ESP-21E). Zegar wyposażony jest w funkcje odczytu temperatury, wilgotności zrealizowane w oparciu o czujnik DHT22 oraz opcjonalnie odczyt ciśnienia poprzez BMP280. Zegar potrafi automatycznie aktualizować czas z Internetu oraz wysyłać pomiary temperatury na serwer logujący dane. Jasność wyświetlacza reguluje na podstawie odczytu nasłonecznienia z zainstalowanego w nim fotorezystora. Poszczególne jego funkcje postaram się pokazać i opisać w dalszej części artykułu.

Funkcje zegara

Temperatura, wilgotność i ciśnienie

Zegar oprócz wyświetlania godziny potrafi wyświetlać temperaturę, wilgotność i ciśnienie. Schemat wyświetlania tych parametrów wygląda mniej więcej tak:

czas - temperatura - czas - wilgotność - czas - ciśnienie

i całość się zapętla. Godzina wyświetlana jest przez 30 sekund a pozostałe elementy przez 3 sekundy. Wartości te można oczywiście dostosować w programie.

Niestety dość ciężko oddać na zdjęciach jak w rzeczywistości wygląda ekran zegara. Dodatkowo jednostka ciśnienia (hPa) nie mieści się na ekranie, zatem wyświetlana jest jedynie wartość liczbowa. Dlatego też wyświetlanie ciśnienia jest raczej opcjonalne.

Aktualizacja czasu

Zegar LED wyposażony jest w dość dokładny układ zegara czasu rzeczywistego (RTC) DS3231. Urządzenie natomiast nie posiada żadnych przycisków do ustawiania godziny. Czas pobierany jest z internetu – zegar aktualizuje czas po uruchomieniu i połączeniu się z WiFi a następnie w odstępach co kilka godzin (na wypadek np zmiany czasu z zimowego na letni przestawi się sam). Przygotowałem do tego celu specjalny skrypt w PHP, który zegar odpytuje. Skrypt zwraca w postaci JSON aktualną datę oraz godzinę, którą procesor wpisuje do RTC. JSON wygląda mniej więcej tak:

{"seconds":9,"minutes":16,"hours":10,"mday":21,"wday":4,"mon":5,"year":2020,"yday":141,"weekday":"Thursday","month":"May","0":1590048969}

Mimo to w zegarze zastosowałem bateryjne podtrzymanie działania RTC. Jest to przydatne w przypadku zaniku zasilania w całym mieszkaniu – zegar wystartuje wcześniej niż router, zatem zegar nie będzie mógł od razu pobrać czasu z internetu. Dzięki potrzymaniu czasu baterią, nawet w takiej sytuacji od razu po uruchomieniu pokaże właściwą godzinę.

Logowanie pomiarów

Stacjami meteo i zbieraniem wyników pomiarów interesują się od dawna. Dlatego też na moim serwerze działa skrypt zbierający dane z różnych czujników i zapisujący je w bazie danych. Następnie na ich podstawie można przeglądać wykresy czy obserwować ekstrema. Podobnie i ten zegar co 5 minut wysyła pomiary z wszystkich swoich czujników na serwer. Zastosowanie pamięci EEPROM ma umożliwić zachowanie pomiarów w pamięci w przypadku braku połączenia z serwerem. Na chwilę obecną jeszcze nie zrealizowałem tej funkcji.

Automatyczna regulacja jasności

Zegar posiada wbudowany fotorezystor w panelu przednim. Na podstawie odczytów z dzielnika napięcia zbudowanego w oparciu o ten element, program dobiera odpowiednią jasność ekranu. Przetwornik analogowo-cyfrowy w ESP8266 posiada rozdzielczość 1024 bitów natomiast ekran posiada 16 stopni jasności. Program mapuje odczyt z ADC na poziomy jasności wyświetlacza. Dzięki temu w dziennym świetle ekran pozostaje czytelny, natomiast nocą nie razi zbyt mocnym światłem.

Regulacja jasności
Wyświetlacz reaguje na jasność otoczenia

Animacje przejść

Przejścia z trybu wyświetlania czasu do trybu wyświetlania pomiarów posiadają proste animacje przesuwającego się tekstu. Z oczywistych względów gdy wyświetlacz jest aktualizowany co sekundę podczas wyświetlania czasu, animacje są wyłączone. Poniżej możecie zobaczyć jak to mniej więcej wygląda.

Animacja zmiany tekstu
Animacja przejścia

Schemat ideowy

Układy scalone

Na poniższym obrazku możecie zobaczyć poglądowy schemat budowy zegara. Jest on naprawdę prosty gdyż sam zegar składa się z garstki elementów. Najważniejsze są w nim oczywiście główny procesor ESP8266, który występuje tutaj w postaci modułu ESP-12E. Procesor ten komunikuje się poprzez magistralę I2C z zegarem RTC DS3231 oraz opcjonalnym czujnikiem temperatury i ciśnienia BMP280. Kolejnym układem korzystającym z I2C jest pamięć EEPROM AT24C104BW mająca przechowywać wykonywane pomiary w przypadku, gdyby ich wysłanie na serwer nie było z jakichś względów możliwe. Magistrala zawiera dwa rezystory podciągające ją do napięcia zasilania – R2 i R3. Czujnik temperatury i wilgotności DHT22 połączony jest magistralą podobną do 1-wire.

Programowanie

Układ programowania i automatycznego resetu
Układ automatycznego resetu ESP8266

Programowanie ESP8266 odbywa się poprzez port szeregowy. Aby wprowadzić ESP w tryb programowania należy na GPIO0 podać stan niski i zresetować układ. Dlatego na płytce znalazły się dwa przyciski odpowiadające właśnie za reset (S1) i tryb flash (S2). Jednak czynność tą można zautomatyzować jeśli nasz adapter USB -> UART posiada wyprowadzone sygnały DTR i RST. Układ zbudowany w oparciu o tranzystory T1 i T2 oraz rezystory R1 i R5 zapewnia automatyczny restart oraz wprowadzenie ESP8266 w tryb flash. Wszystkie potrzebne synały do programowania wyprowadzone są na listwę goldpin JP3.

Zasilanie

Zasilanie zagara LED
Stabilizator napięcia 3.3V

Zasilanie to chyba najbardziej oczywista część schematu. Zastosowałem stabilizator liniowy LF33CV, który obniża napięcie wejściowe z zasilacza sieciowego 5V do napięcia 3.3V zasilającego całe urządzenie. Stabilizatorowi napięcia towarzyszą kondensatory filtrujące napięcie, po dwa elektrolity 100uF (przewlekane) oraz dwa 100nF (SMD). Na wejściu zasilania profilaktycznie zastosowałem diodę prostowniczą 1N4007 aby nie pomylić polaryzacji. Napięcie 5V wyprowadziłem profilaktycznie również na złącze JP7, jednak nie było potrzeby z niego korzystać. Układ zegara RTC posiada gniazdo na baterię CR2032, która zapewnia podtrzymanie działania RTC w przypadku zaniku zasilania sieciowego.

Zużycie energii elektrycznej przez zegar zależne jest głównie od jasności świecenie wyświetlacza. Waha się ono od około 1,5W dla najniższej jasności, do 2,5W przy maksymalnej.

Fotorezystor

Schemat regulacji jasności
Fotorezystor do regulacji jasności

Fotoopornik podłączony do złącza JP5 wraz z rezystorem R6 tworzy dzielnik napięcia, który to z kolei podłączony jest do portu przetwornika ADC wbudowanego w ESP. Napięcie na wyjściu dzielnika zmienia się w zależności od tego jak oświetlony jest fotorezystor. Na tej podstawie program dobiera poziom jasności wyświetlacza.

Dobór fotorezystora oraz drugiego rezystora w dzielniku napięcia jest dowolny, pod warunkiem,że wynikowe napięcie z dzielnika nie będzie większe niż 1V, gdyż jest to maksymalny zakres pomiarowy ADC w ESP8266. W moim przypadku rezystor dobierałem „na oko” i R6 wynosi 4,7k, natomiast typu użytego fotorezystora nie pamiętam 🙂

Projekt płytki drukowanej

Płytkę drukowaną dla tego zegara zaprojektowałem w programie Eagle. Tym razem jednak nie wykonywałem jej metodami domowymi a zleciłem jej wykonanie w Chinach firmie JLCPCB. Było to moje pierwsze zamówienie PCB w fabryce w Chinach więc dopiero przecierałem szlak i chciałem zobaczyć jak to wyjdzie. Moim zdaniem wyszło świetnie! Majfrendy spisały się naprawdę dobrze a samo zamówienie dotarło do mnie w miesiąc i 1 dzień co uważam za znakomity wynik biorąc pod uwagę fakt, że zamówienie było realizowane w czasie pandemii.

Przed przesłaniem plików do wykonania projektu starałem się upewnić, że na pewno wszystko dobrze zaprojektowałem, gdyż była to moja pierwsza dwustronna płytka. Przydatne do tego celu okazało się narzędzie ZofzPCB, które pozwalało obejrzeć w 3D projekt płytki.

W poniższej galerii możecie zobaczyć jak finalnie wygląda płytka wyprodukowana w Chinach. Nie obeszło się bez drobnej wpadki – biblioteka gniazda baterii okazała się nieco różnić od faktycznego wyglądu gniazda. Jednak mimo wszystko udało się je prawidłowo zamontować.

Obudowa

Jako opakowanie całości posłużyła obudowa Kardex Z1A. Jak widać na poniższych zdjęciach, płytka PCB w obudowie ma bardzo dużo wolnego miejsca, można więc sądzić, że obudowa jest za duża. Jej rozmiar jednak został dobrany według wielkości panelu frontowego tak, aby wpasował się w niego wyświetlacz.

Płytka przykręciłem do obudowy na czterech 20mm mosiężnych dystansach śrubami M3. Taką samą śrubą przykręciłem również od zewnątrz obudowy osłona czujnika wilgotności DHT22. Dzięki temu pomiaru temperatury nie zakłóca nagrzewający się w trakcie pracy stabilizator napięcia.

Sam wyświetlacz zamontowany jest… może niezbyt efektownie, ale na pewno efektywnie. Docięta na wymiar panelu przedniego wraz z odpowiednim otworem na ekran tekturka, została pomalowana czarną farbą w spreju. Sam wyświetlacz zamocowałem w niej przy użyciu kleju na gorąco, podobnie również fotorezystor. Wyświetlacz od świata zewnętrznego oddziela plastikowy filtr w kolorze zielonym.

Oprogramowanie

Program napisałem w Arduino, gdyż moim zdaniem jest to najwygodniejsza i najszybsza metoda programowania ESP. Skorzystałem z biblioteki Parola MD do obsługi wyświetlacza MAX7219. Co prawda, w tak prostym zastosowaniu to trochę jak strzelanie z armaty do muchy, ale spełnia swoją rolę. Tym bardziej, że w ESP8266 nie brakuje ani mocy obliczeniowej ani pamięci FLASH i RAM. Dodałem również możliwość aktualizacji oprogramowania poprzez OTA czyli bez podłączania kabelków, bezpośrednio przez WiFi.

Program jest niechlujnie napisany co przyznaję od razu 🙂 Komentarze do kodu dodawałem już po napisaniu programu, tak by był on dla Was czytelny. Postarałem się dodać w jednym miejscu najważniejsze parametry konfiguracyjne (SSID i hasło do sieci WiFi, parametry odnośnie czasów aktualizacji, pomiarów czy wyświetlania).

Program potrafi pobierać plik JSON z serwera a następnie go rozkodować i wpisać do RTC aktualny czas. Dodatkowo przesyła on na serwer wyniki pomiarów temperatury, wilgotności itp. Na razie przesyłanie pomiarów zrealizowałem bardzo prosto – dodaję je jako parametry w GET.

Część po stronie serwera napisałem w PHP, jak na razie obsługuje ona już kilka innych zegarów i stację meteo i sprawdza się w 100%. W przyszłości planuję udostępnić publicznie część dotyczącą prezentacji danych w skład której będą wchodziły wyniki pomiarów ze stacji meteo, które rozwijam równolegle i które być może zaprezentuję niedługo w osobnym artykule.

Podsumowanie

Jest to pierwszy z moich projektów, którego stopień ukończenia i ogólny efekt końcowy pozwolił mi na jego prezentację na tej stronie. Zazwyczaj projekty miały mniejsze, bądź większe niedociągnięcia, które zniechęcały mnie do podzielenia się z nimi szerszej publiczności. Ten projekt oczywiście nie jest wolny od wad i niedoróbek, jednak uważam, że mimo wszystko jest godny uwagi. Zachęcam do komentowania i dzielenia się ze mną swoimi uwagami na jego temat.

Do pobrania

Chętnym umożliwiam odtworzenie projektu we własnym zakresie udostępniając pliki Gerbera oraz PDF do termotransferu oraz plik sketch Arduino wraz z załączonymi niezbędnymi bibliotekami.

Matrycowy zegar LED - gerber (1167 pobrań )

Matrycowy Zegar LED - PCB (903 pobrania )

Matrycowy zegar LED - program (1068 pobrań )

25 komentarzy

Rafał · 28 maja 2020 o 14:01

Fajny projekcik, zastanów się nad użyciem NTP – są przykłady użycia w przykładach biblioteki Time. Może jeszcze jakieś informacje pogodowe? openweathermap API?

    Konrad · 28 maja 2020 o 14:29

    W planach mam osobne urządzenie z wyświetlaczem LCD do prezentacji pomiarów z pomieszczenia oraz mojej stacji meteo. Openweathermap API może być tam ciekawym dodatkiem! NTP na pewno również postaram się wprowadzić, teraz jest to zrobione może trochę na około, choć działa zgodnie z założeniami.

Marcin · 27 lipca 2020 o 07:53

Plik .INO jest chyba niewłaściwy.
Marcin

    Konrad · 27 lipca 2020 o 19:48

    Czym objawia się Twój problem? 🙂

Marcin · 27 lipca 2020 o 20:53

Gdzie ssid i hasło ?

    Konrad · 28 lipca 2020 o 17:36

    Spróbuj pobrać plik programu jeszcze raz (wrzuciłem go ponownie), chyba rzeczywiście wkradł się tam jakiś bardzo stary kod.

Marcin · 3 sierpnia 2020 o 11:22

Mam problem.
Pierwszy odczyt z DHT22 zawsze jest prawidłowy.
Gdy następuje kolejny odczyt wchodzi w pętlę do-while i następuje reset zegara.
Czujnik na innym przykładowym kodzie działa prawidłowo.

    Marcin · 3 sierpnia 2020 o 12:54

    Problem rozwiązany.
    Błędna biblioteka DHT.

      Konrad · 3 sierpnia 2020 o 22:49

      Super, rozumiem, że korzystasz z zamieszczonego przeze mnie kodu? Czy wykonywałeś własne PCB do swojej wersji?

        Marcin · 5 sierpnia 2020 o 20:15

        Wemos D1 połączony kabelkami na pająka. Zmieniłem tylko odczyt czasu na NTP.

Marc · 29 sierpnia 2020 o 07:18

Błąd w spakowanym pliku zip program

    Konrad · 31 sierpnia 2020 o 20:35

    Jaki błąd?

Marc · 2 września 2020 o 08:00

Już jest ok

marc · 20 września 2020 o 11:20

jak wygląda sprawa z programowaniem jakiś program ? zamówiłem płytki i co dalej ?

    Konrad · 20 września 2020 o 18:41

    Na płytkę należałoby teraz wlutować niezbędne elementy, podłączyć do komputera poprzez przejściówkę UART-USB i zaprogramować poprzez Arduino z wykorzystaniem załączonego projektu programu (ewentualnie zmodyfikować go podając choćby własne dane do sieci WiFi).

dziku · 29 marca 2021 o 18:22

Fajny projekt, ale cos jest z programem. Nie można rozpakować, uszkodzone archiwum. Mógłbyś ponownie wrzucić? pozdrawiam

    Konrad · 29 marca 2021 o 18:49

    Sprawdź teraz, mam nadzieję, że problem został ostatecznie rozwiązany 😉

dziku · 29 marca 2021 o 21:15

jest ok, dzięki

Przemek · 9 stycznia 2022 o 00:33

Czy istnieje możliwość rozbudować ten projekcik o sekundnik?? Bardzo mi się podoba i chętnie zbudowałbym taki jeżeli dałoby się wprowadzić taką modyfikację 🙂

    Konrad · 9 stycznia 2022 o 08:23

    Czy jest taka możliwość? Na pewno 🙂 Jednak ze względu na rozmiar czcionki i szerokość wyświetlacza sekundnik się po prostu nie mieści. Trzeba by zastosować niestandardową, mniejszą czcionkę (jeśli taka istnieje gdyż nie przerabiałem tematu) lub dołożyć dodatkowe segmenty wyświetlacza by zrobić miejsce dla sekund.

      Przemek · 9 stycznia 2022 o 11:28

      Tak właśnie myślałem nad dołożeniem jednego segmentu dla sekund i było by lodzio miodzio 🙂 jak już się zabiorę za robotę to napewno dam znać czy się udało 🙂

Przemek · 22 stycznia 2022 o 14:45

Konrad możesz podać do siebie jakieś namiary żeby wesprzeć mnie w kompilacji programu?? Wywala mi błąd:
/Users/***/Downloads/Matrycowy zegar LED – program 2/zegar_matrycowy/zegar_matrycowy.ino: In function 'bool wyslijPomiary()’:
zegar_matrycowy:463:15: error: call to 'HTTPClient::begin’ declared with attribute error: obsolete API, use ::begin(WiFiClient, url)
463 | http.begin(„http://meteo.kbprogram.pl/dodaj_pomiar.php?id_czujnika=5&temp1=”);
| ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/***/Downloads/Matrycowy zegar LED – program 2/zegar_matrycowy/zegar_matrycowy.ino: In function 'bool aktualizujCzas()’:
zegar_matrycowy:347:15: error: call to 'HTTPClient::begin’ declared with attribute error: obsolete API, use ::begin(WiFiClient, url)
347 | http.begin(„http://meteo.kbprogram.pl/czas.php”);
| ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
exit status 1
call to 'HTTPClient::begin’ declared with attribute error: obsolete API, use ::begin(WiFiClient, url)

Prośba o wsparcie 🙂

    Konrad · 24 stycznia 2022 o 19:32

    Spróbuj starszej wersji definicji płytek (Narzędzie -> Płytka -> Menedżer płytek i w wyszukiwarce wpisać esp8266). Zdaje się, że na wersji 2.x.x en kod działał a później w 3.x.x wprowadzili zmiany, które wymusiły dostosowanie programu.
    Swoją drogą zapewne w tym roku na stronie pojawi się wpis z aktualizacją oprogramowania gdyż dostosowałem je do nowszego esp core oraz dodałem nowe funkcje. Niemniej, nowy kod nie jest jeszcze gotowy do publikacji.

Przemek · 28 stycznia 2022 o 07:14

Udało mi sie uruchomić zegarek jednak występuje błąd na stronie skryptu. Zegarek po uruchomieniu zgłasza problem i pobiera czas 00:00.

Dodaj komentarz

Avatar placeholder

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *


The reCAPTCHA verification period has expired. Please reload the page.