Budzikolendarz

Wpis autorstwa mojego męża:

Tytułem przydługiego wstępu

Zaczęło się w sumie (jak to zwykle w bajkach bywa) niewinnie. Otóż pewien piękny dzień, czy też właściwie noc okazał się być TYM DNIEM, w którym trzeba przestawić zegarek, bo oto nadeszła Zmiana Czasu™. Prawie wszystkie zegarki w domu przestawiają się już automatycznie, z wyjątkiem dwóch – przedpotopowego budzika, który ledwo działa (w nocy ładnie wyświetla godzinę, ale głosu już nie jest w stanie z siebie dobyć i stąd drugi budzik jakim jest…) i stara Nokia C3-00, która budzi mnie co rano (pomimo 15 lat na karku bateria trzyma jakieś trzy tygodnie – pobij to ajfonie!). O ile Nokia jeszcze jest całkiem żwawa i zmiana godziny w niej może nie jest przyjemnością, ale jest daleko mniej upierdliwa niż tym starym budziku, bo w nim przyciski cały czas się zacinają i wpadają do środka (nie wspomnę o tym, że opisy już dawno się wytarły i za każdym razem trzeba zgadywać który jest do czego). Podtrzymanie bateryjne niestety nie zdaje egzaminu, bo gdy jest w użyciu zegar zaczyna się spieszyć o jakieś 100%, więc jako, że to może wprowadzić w błąd i ogólnie nie ma sensu wyjąłem baterię i teraz po każdym spadku napięcia muszę ustawiać go od nowa. Generalnie nic co by powodowało utratę włosów z głowy, raczej drobna niedogodność, z którą nagle zapragnąłem zawalczyć, a właściwie mógłbym, ale mi się nie chciało dopóki…

Dopóki kolejny raz przypomnienie znikąd uświadomiło mi, że bez kalendarza Google nie pamiętałbym już chyba o niczym, dobrze, że głowę mam przymocowaną na stałe, to przynajmniej z tym nie ma problemu. Czasem jednak dopuszczam do sytuacji gdy powiadomień z kalendarza mam tyle, że nie ogarniam już nowych, a oczywiście i tak nie przeszkadza mi to w zapominaniu co gdzie kiedy i komu. To też w sumie nie jest aż taki znowu duży problem, wystarczy trochę się zorganizować i ogólnie jakoś ogarnąć i problemu by nie było.
Któregoś jednak dnia oba problemy przydarzyły się w niedługim odstępie czasowym. Pomyślałem więc sobie „fajnie byłoby mieć taki budzik co się sam ustawia i jeszcze wyświetla co tam w kalendarzu piszczy…”. W sumie i kalendarz i budzik są formą pomiaru czasu, więc w mojej głowie urodził się pomysł na budzikolendarz. Choć bardziej prawidłowa nazwa powinna brzmieć zegarolendarz, bo nie dodałem buzzera żeby dzwonił i nigdy nie miałem zamiaru tego robić – Nokia daje radę, a jak przestanie to wtedy pomyślę.

Założenia projektu i niezbędne zakupy

Po pierwsze zasilanie 230V, zawsze to trochę upraszcza życie. Wybrałem do tego celu zasilacz Hi-Link 5V 1A (czy może raczej jego podróbkę bo w sieci jest tego mnóstwo wersji i nie dojdziesz która jest oryginalna). Mimo, że sam mikrokontroler zadowala się stosunkowo niewielkim prądem, to trzeba pamiętać o tym, że jeszcze trzeba czymś nakarmić ekrany..

Po drugie zastosowanie mikrokontrolera z WiFi, żeby sam sobie pobierał potrzebne dane. Wybór był prosty – albo RPi Pico W, albo ESP32. Ten pierwszy miałem w domu, więc został zwycięzcą. Później zmieniłem go na Pico 2W (na szczęście też miałem w domu) ze względu na większą ilość pamięci, ale po ostatnich optymalizacjach kodu mógłbym wrócić do zwykłego Pico.  Ogólnie zdecydowanie się na RPi Pico miało też kilka wad – gdybym zaczynał ten projekt od początku poważnie rozważałbym użycie jednak RPi Zero W, ale o tym później. Ogólnie zdał egzamin, ale miał pomoc.

Po trzecie dwa ekrany. Pierwszy, do wyświetlania godziny, obowiązkowo zielony w stylu dotmatrix:

Do tego ekranu jest taka uwaga, że trudno znaleźć rzetelne informacje na temat ile to właściwie żre prądu przy pełnej jasności i zapalonych wszystkich diodach. Testowałem pojedynczy segment bezpośrednio zasilany z Pico i nic się nie zjarało. To właśnie ten ekran był głównym powodem użycia przeze mnie zasilacza 1A. Wiem, że daje radę, bo na początku coś źle podłączyłem i zapaliły się wszystkie diody z pełną jasnością i świeciły przez około minutę zanim zorientowałem się, że na zasilaczu można przyrządzać jajka sadzone i wszystko wyłączyłem.

Drugi e-ink do wyświetlania kalendarza (e-ink w sumie tylko dlatego, że wcześniej się nimi nie bawiłem, a bardzo chciałem – był to też zdaje się najdroższy komponent).

Do koszyka wpadło jeszcze kilka drobiazgów, które również okazały się przydatne:

Zestaw uniwersalnych przycisków wkręcanych w panel

i gniazdo z włącznikiem na kabel ósemkę

Później dokupiłem jeszcze takie kabelki, żeby łatwiej przeprogramowywać sterownik, bez otwierania obudowy za każdym razem, gdy jakaś zmiana przyjdzie mi do głowy.

Do tego szereg rzeczy, których nie kupowałem, ale miałem na stanie, jak płytki prototypowe, kabelki, gniazda o rastrze 2,54mm, terminale śrubowe, zaciski na kable etc.

Tak sobie patrzę po tych linkach i widzę, że Aliexpress powinno mnie sponsorować. Nie robi tego jednak ani Ali, ani nikt inny (a ja chętnie dam się zasponsorować jak coś).

Realizacja, czyli przygotowania i narzekania

Pierwsze co postanowiłem opanować to wyświetlacz LED. Z pojedynczym segmentem poszło banalnie wręcz łatwo, bo gotowa biblioteka jest częścią Micropythona, w którym to najbardziej lubię programować Pico. Największym wyzwaniem okazało się… projektowanie czcionek. Koniec końców napisałem sobie program w C# pod Windows, żeby jakoś zgrabnie to ogarnąć.

Jeśli pojawią się takie prośby udostępnię kod na GitHubie. Na tą chwilę nie bardzo chcę to robić, ponieważ program nie jest dopracowany (kategoria software: wieczna alfa), ale spełnia swoje zadanie, więc nie było potrzeby dalej go rozwijać.

Przejście do wyświetlacza wielosegmentowego okazało się znacznie trudniejsze i to z powodu, którego zupełnie się nie spodziewałem. Otóż w trakcie montażu okazało się, że piny przygotowane przez producenta do podłączenia ekranu zahaczają o obudowę i trzeba je przelutować na drugą stronę PCB. Żebym ja wiedział na co ja się piszę… Dość powiedzieć, że używali jakiejś naprawdę egzotycznej cyny, która za żadne skarby nie chciała się topić. Dopiero, gdy użyłem naprawdę wysokiej temperatury udało się wyciągnąć piny i… uszkodzić ścieżki na PCB. Już kiedyś próbowałem sobie poradzić w podobnej sytuacji i nie skończyło się to najlepiej. Jak to mówią do dwóch razy sztuka. Koniec końców piny przelutowałem na drugą stronę, a uszkodzone ścieżki zastąpiłem kawałkami drutu z kabla telefonicznego. Poniżej efekty tego druciarstwa.

Trochę (nie za dużo jednak) widać też na jednym z dalszych zdjęć z wnętrza urządzenia. W każdym razie najważniejsze, że działa.

Gdy na LEDowym wyświetlaczu jakoś to działało przyszła pora na drugi ekran… To była droga przez mękę i pierwszy powód dla którego trzeba było jednak użyć Rpi Zero W do tego zadania. Przyznaję, że nie zrobiłem tego tylko dlatego, że wymagałoby to zainwestowania ponad 100 PLN, bo potrzebny by był nowy zasilacz (co najmniej 3A, bo samo Zero potrafi w szczytowym momencie zeżreć tych amperów aż 2,5), RPI Zero W (a jeszcze lepiej Zero 2W, bo ma procesor na którym można zdalnie uruchamiać procesy pod VS Code i jest szybsze, a oba te czynniki bardzo ułatwiają pisanie kodu) i karta SD. No nie uśmiechało mi się to specjalnie.

Najbardziej irytujący był fakt, że wszystkie dema i przykłady dla urządzeń z rodziny RPi skupiały się na SBC (Single Board Computer), a nie mikrokontrolerach. W zdecydowanej większości przypadków nie jest to problem, ale tutaj jakoś był. Program napisany zgodnie z dokumentacją, oraz wykorzystujący elementy dołączonego dema nie działał na mikrokontrolerze, ale śmigał na SBC. Długo nie mogłem dojść o co chodzi i prawie się poddałem, aż w końcu odkryłem dwie rzeczy – pierwszą była napisana w C i skompilowana biblioteka, której używało oryginalne demo i dwa, że w dokumentacji jest błąd. Skompilowana biblioteka w C (próbowałem zdekompilować, ale udało się tylko do assmeblera – za chudy w uszach na to jeszcze jestem, żeby z kodu asemblerowego cokolwiek zrozumieć) najprawdopodobniej prawidłowo przesyłała informacje do ekranu EPD (Electronic Paper Display), podczas gdy ja radośnie próbowałem napisać to samo w Micropythonie, ale za to zgodnie z dokumentacją. Zajęło mi to chyba z miesiąc, najpierw przez złe podłączenie, a finalnie okazało się, że przesyłane do EPD są interpretowane w innej kolejności niż mówi instrukcja (a konkretnie odwrotnej), kolory zaś są zupełnie inaczej kodowane. Efektem ubocznym tych prac było odkrycie, że Pico nie nadaje się do programowego generowania obrazów dla EPD.

Początkowo myślałem, że ze względu na brak pamięci (stąd zmiana z Pico W na Pico 2W), ale to się udało obejść – większym problem jest konieczność napisania naprawdę wszystkiego od podstaw w Micropythonie, bo zwyczajnie nie ma odpowiednich bibliotek aby w locie tworzyć bardziej złożone obrazy. Na swoje szczęście miałem do dyspozycji laptopa, który robi u mnie za serwer wydruku, serwer Pi Hole i serwer Samby (sieciowego współdzielenia plików na Linuksie). Zaczął też wiec robić za serwer-generator obrazków do mojego budzikolendarza. Gdyby użyć Pi Zero zamiast Pi Pico tego problemu by nie było, bo nawet rachityczny procesor tego pierwszego jest z 10 razy szybszy od tego drugiego, no i ma 1000 razy więcej pamięci do dyspozycji.

Jest jeszcze trzeci powód dla którego Zero sprawdziłoby się lepiej – komunikacja z kalendarzem Google. Z powodu braków w języku Micropython, ale przede wszystkim z powodu małej ilości pamięci (jak stwierdził LLM Gemini) i konieczności przepisania gotowych bibliotek ze zwykłego Pythona na Micropythona (co jest gorsze od przepisywania z C na Arduino – wiem bo to robiłem). Usiadłem, pomyślałem jakieś 5 sekund i doszedłem do wniosku, że skoro i tak już musiałem generować obrazki na serwerze, to logiczne było, że i tam muszę pobierać dane z zewnątrz.

Ostatni element układanki to właśnie łączność z usługą od wielkiego Gie. Jest to proces z jednej strony bardzo łatwy, a z drugiej dosyć trudny i nieintuicyjny. Otóż zrobienie tak, że jakoś to działa jest bardzo proste, ale ma jeden feler – trzeba raz na tydzień wejść na stronę usług chmurowych Google za pomocą linka, który w przesyła ci kalendarz w momencie gdy wysyłasz żądanie o dane. Możecie mi wierzyć – to jest znacznie bardziej upierdliwe niż się wydaje i stwarza szereg durnych problemów zwłaszcza jeśli się ma tak rozwleczoną architekturę jak ja mam (kolejny powód by użyć Pi Zero W). Rozwiązanie było trochę głupie – otóż udało mi się zarejestrować w chmurze Google’a moją aplikację jako publiczną. Musiałem się przy tym trochę naoszukiwać, bo chmura przyjmuje że usługa jest powiązana z serwerem, który ma jakiś ładny adres w internecie, pod którym będzie można znaleźć ten serwer. Co gorsza ten adres nie może być byle jaki, tylko musi się kończyć na .com lub .org. W tym momencie myślałem już, że ktoś tu zginie, bo ja na pewno nie będę sobie teraz kupował domeny, której nie potrzebuję (w zasadzie dopiero teraz przyszło mi do głowy, że mogłem użyć domeny wynalazkowo.com). Nie mniej jednak i na to znalazła się rada. Trzeba… kłamać i oszukiwać. Wymyśliłem sobie domenę (potem okazało się, że zajętą przez japońską stronę organizacji zrzeszającej miłośników kobiecych piersi), a potem jeszcze jedną (tym razem nikt jej nie używał) i wpisałem w odpowiednie pole w konsoli chmury Google. Potem na serwerze i na komputerze z którym najczęściej łączyłem się z serwerem zmodyfikowałem plik hosts.txt tak, aby zapytania do mojej zmyślonej domeny kierował do serwera. Na koniec trzeba było jeszcze zainstalować certyfikat SSL bo przecież wielkie Gie nie zadowoli się adresem z http – musi być https… Przyznaję nie pamiętam skąd go wytrzasnąłem, ale był to jakiś certyfikat developerski i z którym też się chwilę bujałem. Jak widać okazało się, że nie tyle serwer ma być dostępny z internetu, co ma mieć do niego dostęp. Mnie pasi.

Jeśli ktoś jakimś cudem dotarł do tego momentu i nabrał przeświadczenia, że chyba palma mi odbiła, że życie sobie tak utrudniam, to oczywiście nie tak to sobie wyobrażałem. Gdyby mi ktoś powiedział, gdy zaczynałem, że będę się bujać z cholernym budzikolendarzem przez kilka miesięcy to bym go wyśmiał (w sumie tych miesięcy wyszło chyba ze trzy albo cztery, ale jeśli przeliczyć to na czas rzeczywiście spędzony nad tym projektem, to myślę, że sumarycznie wyszło to około 100h), bo to jest przecież banalny projekt. I on powinien być banalny, ale jak udało mi się na własnej skórze przekonać – szereg głupich problemów wszystko dramatycznie wydłużył (bo to nie powinno zająć więcej niż 20-30h).

Projekt 3D

Obudowa budzikolendarza to oczywiście wydruk 3D. Jako jedyna część chyba nie powstawał w bólach, choć oczywiście nie bez problemów.

Pierwsza wersja wyglądała tak:

Tutaj to był bardzo wczesny „szkic” – rozważałem, różne opcje. Niestety jakoś nigdy nie stworzyłem pełnoprawnej złożeniówki, która mógłbym tu zaprezentować, ale mogę się za to pochwalić kilkoma szkicami koncepcyjnymi rozkładu tego bajzlu.

No i na koniec zwycięska koncepcja:

A tak wyglądały poszczególne części (kompletnie nie w skali):

Ogólnie było z tym kilka niewielkich problemów – okazało się, że integrowanie obudowy z podpórkami to średni pomysł, bo wydruk się odrobinę nie udał i gdyby chcieć robić go od nowa poleciałoby strasznie dużo filamentu. Koniec końców udało się go poprawić opalarką. Modeli raczej nie udostępnię, bo można to zrobić lepiej.

Elektryka prąd nie tyka

Tym razem od strony okablowania projekt nie miał w sobie nic szczególnego, więc nie bawiłem się w szczegółowe rozrysowywanie schematów – po prostu poszedłem na żywioł. I choć zużyłem większość dostępnych pinów mikrokontrolera to pod względem połączeń był to jeden z prostszych projektów, choć na zdjęciach oczywiście tego nie widać.

Poniżej jeden z etapów podłączenia EPD do interfejsu SPI:

Ogólny widok wnętrza, z pięknymi glutami cyny na płytce prototypowej widocznej w dole, widać tutaj pomysł, z którego jestem najbardziej dumny – oryginalnie przyciski miały czerwony i czarny kabel bez zakończenia. Ponieważ i tak potrzebowałem końcówek do nałożenia na piny użyłem kabelków od płytki prototypowej w takich kolorach w jakich były przyciski. Bardzo to ułatwiło późniejsze potwierdzenie który przycisk jest gdzie podłączony:

Zbliżenie na mikrokontroler tym razem od strony gdzie podłączony jest ekran LED i przyciski (po lewej stronie widać dodatkowe piny gdzie podałem GND dla przycisków, bo na mikrokontrolerze było ich na styk i się bałem, że jak będę chciał coś jeszcze dołożyć, to będzie mi trudniej, a już nie wspomnę o tym, że ich użycie zwiększyłoby bajzel w kablach jeszcze bardziej):

Prostota polegała na tym, że w zasadzie prawie wszystko jest podłączone bezpośrednio do mikrokontrolera (z wyjątkiem zasilania panelu LED, które idzie bezpośrednio od zasilacza). Ta prostota kosztowała mnie jednak kolejny tydzień grzebania po kabelkach, sprawdzania połączeń i ogólnego kombinowania.

Otóż aby przypadkiem nie zasilić panelu LED z mikrokontrolera wsadziłem między niego a zasilacz diodę prostowniczą. I wszystko pięknie działało. Poza jednym – mikrokontroler nie działał gdy podłączony był tylko do zasilacza. Myślę sobie – prosta sprawa, pomyliłem kierunek przewodzenia na diodzie. Przytknąłem miernik i pokazał mi całkiem spory spadek napięcia na diodzie (kierunek jednak był dobry), po czym akurat ta jego część, która była odpowiedzialna za mierzenie tego spadku i ciągłości obwodu postanowiła sobie częściowo wyzionąć ducha. Ogólnie już drugi raz (na dwa podejścia) mi się zdarza, że ten układ zdycha tuż po wymianie baterii w multimetrze. Przypadek? Nie sądzę… Wracając jednak do meritum. Myślę sobie – prosta sprawa dam mniejszą diodę. Dałem. Nie działało. Nie mogłem już jak człowiek sprawdzić kierunku przewodzenia. Poddałem się na jakiś czas, bo już miałem dość problemów z tym projektem.

Podejście drugie. Zmiana kierunku diody. Nie działa. Podejście trzecie. Wywalenie diody. Nie działa. Wtedy dopiero się połapałem, że to chyba jednak nie wina diody. Tym moim niepełnosprawnym multimetrem usiłowałem sprawdzić ciągłość obwodu i co ciekawe często udawało mi się ją potwierdzić. Dopiero za którymś podejściem, gdy sprawdziłem absolutnie wszystko co było (jak mi się wydawało) do sprawdzenia postanowiłem przyjrzeć się lutom na kontrolerze. I właśnie ten przy pinie od zasilania był trochę niedorobiony. Szybki rachunek sumienia ujawnił, że za każdym razem gdy uzyskiwałem ciągłość dotykałem lutowanego pinu, a nie pola lutowniczego z którym nie było kontaktu. Poprawiłem lut. Zadziałało. Wlutowałem diodę. Nie działa. No tak, oczywiście, że w złą stronę. Wylutowałem diodę i wlutowałem ponownie. To była tak banalna sprawa, a rozpracowanie jej zajęło mi o wiele za dużo czasu. Wiem, że jestem kompletnym amatorem jeśli chodzi o elektrykę i elektronikę, no ale żeby aż tak?

Koniec końców – działa jak natura chciała, albo raczej jak ja chciałem.

Prezentacja i podsumowanie

Dla tych, którzy dotrwali do końca prezentacja działania. To nie jest niestety demon prędkości.

Kod niestety w swojej obecnej formie niespecjalnie nadaje się do publikacji (co tu dużo kryć – jest tam śmietnik), ale jeśli ktoś bardzo, bardzo będzie chciał, to wystarczy, że zostawi komentarz. Zmotywuje mnie to do ogarnięcia sprawy w kilka dni i publikacji na githubie. Gdyby ktoś się napalił na moje przeróbki biblioteki do EPD – to jest dostosowane do bardzo specyficznych warunków, gdzie obraz jest wstępnie przetworzony przez serwer i przesłany jako strumień bajtów do mikrokontrolera.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.