Zastanawialiśmy się, jak wprowadzić niestandardową kamerę, która byłaby przystępna cenowo i łatwa do zintegrowania z ponad 400 000 drukarek Original Prusa, które już wysłaliśmy na cały świat. Pewnego dnia natknęliśmy się na świetne rozwiązanie open-source, które zostało stworzone specjalnie dla Prusa Connect przez członka naszej społeczności, Miroslava Pivovarský’ego – moduł ESP32-CAM z niestandardowym firmware.

ESP32CAM

Ten niedrogi moduł ma zintegrowaną diodę doświetlającą LED i WiFi, a można go kupić praktycznie wszędzie, sflashować firmware Miroslava i od razu zacząć go używać. Nie jest to szczególnie rewolucyjne rozwiązanie, ale zapewnia łatwe, tanie i, co najważniejsze, funkcjonalne rozwiązanie do zdalnego monitorowania drukarki za pomocą kamery.

Po wgraniu firmware, cała konfiguracja to kwestia kilku kliknięć. Następnie wystarczy zarejestrować kamerę w Prusa Connect, skopiować jej token dostępu, a po kilku sekundach w interfejsie pojawi się pierwszy zrzut. Nie oczekuj jednak strumienia wideo 4K60 – przy obecnej implementacji kamera wysyła obraz co kilka sekund, ale nawet to jest więcej niż wystarczające do zdalnego monitorowania wydruku. Lub nawet do wysłania obrazu do sieci neuronowej w celu automatycznego wykrywania błędów, jak zapowiadaliśmy w odcinku Prusa Podcast o sztucznej inteligencji w druku 3D. A ponieważ firmware oferuje aktualizacje OTA, funkcjonalność może zostać ulepszona w przyszłości.

Szczegółowe instrukcje dotyczące całej konfiguracji możesz znaleźć w tym PDFie. Możesz również wydrukować poręczny uchwyt kamery, który następnie przymocujesz do ramy drukarki 3D. Jest giętki, ale wytrzymały i pozwala na łatwe ustawienie pozycji kamery. Został on stworzony przez świetnego projektanta, Michała Fantę i możesz go pobrać >za darmo z Printables, wraz z >obudową modułu kamery.

A jeśli zastanawiasz się, co jest potrzebne do opracowania takiego rozwiązania, w tym interfejsu aplikacji internetowej, aktualizacji firmware OTA i wielu innych interesujących rzeczy, pozwól, że przedstawimy Ci szczegółową historię jego rozwoju! 🙂

Początek historii

Miroslav wyjaśnia, jak rozpoczęła się praca nad jego rozwiązaniem: „Mieliśmy w pracy kilka drukarek 3D MK3S+, które były podłączone do sieci przez Raspberry Pi z PrusaLink”. PrusaLink pozwala uzyskać zaawansowane funkcje sieciowe nawet na starszych 8-bitowych maszynach i umożliwia podłączenie ich do Prusa Connect. „Używałem starszego smartfona jako kamery (jest to funkcja wbudowana w Prusa Connect), ale szukałem czegoś bardziej kompaktowego. Idealna byłaby mała kamera, która byłaby funkcjonalna bez zbędnych rzeczy” – dodał.

W międzyczasie zaczął więc analizować wewnętrzne działanie systemu – w szczególności sposób, w jaki telefon wysyła obraz do Connect. Zmodyfikowanie skryptu NodeJS, który zarządza przesyłaniem obrazu, tak aby mógł uzyskać przechwycone zdjęcia z małej kamery Raspberry Pi za pośrednictwem magistrali CSI, nie zajęło dużo czasu.

Następnie Miroslav przesłał skrypt do innego Raspberry Pi, podłączył do niego kamerę i wykonał skrypt, aby pobrać obraz z kamery i wysłać go do Connect. Wciąż jednak był pewien minus: wymagało to dwóch RPi – jednej do zarządzania kamerą, drugiej do uruchamiania PrusaLink. To działało, ale jak powiedział Miroslav, było dalekie od ideału.

Camera attached to Original Prusa MK4

Kamera przymocowana do Original Prusa MK4

Jak to często bywa, przełom nastąpił przez zupełny przypadek. „Pewnego dnia sprzątałem biurko i szuflady, ponieważ mam mnóstwo różnych modułów Arduino oraz dodatków – i tam go znalazłem! Mały moduł ESP32-CAM,” wspomina Miroslav. Ten tani MCU (Micro Controller Unit) ma własny procesor ARM, dużą pamięć Flash, wystarczającą ilość pamięci RAM, a także moduł Wi-Fi. To było idealne! 🙂

Oczywiście droga do działającego rozwiązania nie była usłana różami. Choć mogłoby się wydawać, że podstawowe IDE Arduino (środowisko programistyczne) wystarczy, nie było to do końca prawdą. Ostatecznie Miroslav stworzył własny serwer HTTP do odbierania i zapisywania przychodzących obrazów, podobnie jak Prusa Connect. Za pomocą tego serwera przetestował pierwsze wersje swoich skryptów – te, które działały już na Raspberry Pi.

Działa na moim Raspberry Pi!

Kolejny krok był dość oczywisty – sprawić, by moduł ESP32-CAM wykonywał tę samą pracę, co Raspberry Pi. Konieczne było zrozumienie, jak działa moduł kamery i jak wysyłać zdjęcia nie tylko przez HTTP, ale także przez HTTPS, którego używa Prusa Connect, a z którym praca jest bardziej skomplikowana. Jednak po chwili poszukiwania, uzyskaniu i poprawnym skonfigurowaniu niezbędnego certyfikatu, Miroslav z powodzeniem wysłał prawidłowe dane z ESP32-CAM do serwera, a nawet do Prusa Connect! Wszystko wydawało się działać dobrze, ale od razu pojawiły się pierwsze problemy.

Jednym z największych problemów był rozmiar i rozdzielczość przesyłanego obrazu. Maksymalna rozdzielczość, którą udało się bezproblemowo przesłać wynosiła 320×240 pikseli, co nie jest szczególnie dużą wartością. Ograniczenie to było spowodowane przez sam moduł ESP32-CAM, w którym problem pojawiał się, gdy rozmiar pliku wysyłanego przez HTTPS był większy niż 9kB. Po przeprowadzeniu pewnych badań i kilku prób, Miroslav odkrył, że jeśli podzieli plik na fragmenty o rozmiarze 5kB i wyśle je sekwencyjnie, wszystko działa poprawnie. Chociaż spowodowałoby to nieco wolniejsze przesyłanie, było to idealne rozwiązanie, przynajmniej na razie.

Wystarczyło to nawet do stworzenia strumienia wideo dla sieci lokalnej. Pierwotnie obawiał się, że maksymalna liczba klatek na sekundę wyniesie około 1, ale po rozwiązaniu kilku problemów, w których strumieniowanie powodowało różne kolorowe artefakty i słabą synchronizację poziomą, wyniki pokazały 5-7 FPS w rozdzielczości 1024×768, co było świetnym wynikiem 🙂 . A MCU powinno mieć potencjał, aby uzyskać jeszcze więcej FPS i lepszą rozdzielczość, więc Miroslav wciąż nad tym pracuje.

Miroslav miał już proste, ale funkcjonalne oprogramowanie, którym natychmiast podzielił się na GitHubie i forum Prusy, ponieważ chciał być po prostu pierwszą osobą, która wpadła na taki pomysł.

Prusa Connect dashboard

Możesz wyświetlić najnowszy obraz z kamery w Prusa Connect

Wciąż było wiele rzeczy do rozwiązania, na przykład zintegrowanie konfiguracji MCU z kodem źródłowym – token, odcisk palca, SSID WiFi, konfiguracja kamery i inne. Cały ten pakiet jest kompilowany i wgrywany do pamięci MCU, bez możliwości wprowadzania dodatkowych zmian. Miroslav zaczął więc szukać rozwiązania w dziedzinie, w której miał niewielkie doświadczenie – interfejsu sieciowego.

Chociaż tworzenie interfejsów sieciowych nie było głównym obszarem zainteresowań Miroslava, podszedł on do swojego pomysłu z entuzjazmem i po kilku wieczorach programowania opracował funkcjonalną aplikację internetową do konfiguracji strumienia, która działała bezpośrednio na module kamery. „Wyglądała jakby pochodziła prosto z lat 90-tych, ale działała, więc nie miałem nic przeciwko,” mówi Miroslav, śmiejąc się.

The first version of the camera web interface

Jedna z pierwszych wersji interfejsu internetowego kamery

Na drodze rozwoju

Zauważyliśmy jego rozwiązanie i bardzo nam się spodobało, więc skontaktowaliśmy się z nim mailowo, aby zaoferować mu współpracę przy rozwoju. „Byłem bardzo mile zaskoczony ofertą i natychmiast się na nią zgodziłem. Między innymi dlatego, że chciałbym wnieść większy wkład w społeczność open source” – powiedział Miroslav.

Po kilku dyskusjach i przeglądzie kodu przedstawiliśmy kilka pomysłów na ulepszenie oprogramowania i interfejsu sieciowego, na przykład wdrożenie bardziej nowocześnie wyglądającego UI, itp. Miroslav przyjął wszystkie te punkty z entuzjazmem i natychmiast zaczął nad nimi pracować. „Najtrudniejszą częścią całego projektu był dla mnie rozwój samej aplikacji sieciowej”, powiedział Miroslav. Strona musiała wyglądać dobrze i nowocześnie, idealnie w stylistyce Prusa, jednocześnie mieszcząc się w ograniczonej pamięci Flash MCU. Z drugiej strony, po przeanalizowaniu i przeczytaniu kilku artykułów, ocenił, że jego obecne rozwiązanie, obejmujące połączenie HTML i JavaScript z jQuery, jest właściwą drogą.

Miroslav skorzystał również z możliwości oferowanych przez AI, która pomogła mu w tworzeniu strony. Na przykład szukał porad i wyjaśnień dla poszczególnych komponentów, jak się nazywają, jak z nich korzystać itp. „To było zabawne. Próbowałem wyjaśnić sztucznej inteligencji, czego chcę, ale nawet sam dokładnie tego nie wiedziałem. Miałem tylko wizję ostatecznego wyglądu,” wspomina Miroslav. Przyznał również, że mimo iż interfejs sieciowy mógłby być bardziej optymalny i ładniejszy, świetnie się bawił podczas jego tworzenia i nauczył się wielu nowych rzeczy.

Potrzeba konfiguracji

Teraz, gdy projekt interfejsu sieciowego był prawie ukończony, zaczął myśleć o innych funkcjach. Na przykład aktualizacja firmware powinna być możliwa za pośrednictwem interfejsu internetowego – kamera mogłaby sprawdzić najnowszą wersję firmware i pobrać ją w razie potrzeby, a wszystko powinno być tak przyjazne dla użytkownika, jak to tylko możliwe.

Current camera web interface

Aktualny wygląd interfejsu internetowego kamery

Teraz nadszedł czas, aby zająć się jedną z bardzo ważnych rzeczy, czyli pierwszym uruchomieniem i konfiguracją MCU. Miroslav wymyślił dwa różne rozwiązania, które mogą działać wspólnie, a każdy może wybrać preferowany sposób reejstracji kamery.

Pierwszym rozwiązaniem jest tryb AP, w którym po włączeniu MCU tworzony jest punkt dostępowy o określonym identyfikatorze SSID. Klient może połączyć się z punktem dostępowym przez WiFi i tutaj może ustawić dane logowania do swojej sieci bezprzewodowej, aby dalej skonfigurować kamerę. Aby zapobiec niepotrzebnemu zakłócaniu pasma WiFi 2,4 GHz przez nieużywane punkty dostępowe (wyobraź sobie, że masz ich włączonych dziesiątki), jeśli żadne urządzenie nie połączy się w ciągu pięciu minut od włączenia kamery, tryb AP jest automatycznie wyłączany.

Po skonfigurowaniu kamery można zlokalizować jej panel administora w sieci za pomocą adresu IP, ale nie jest to zbyt wygodne, zwłaszcza jeśli nie znasz adresu IP i nie masz uprawnień admina do routera. Aby ominąć tę niedogodność, Miroslav dodał również funkcję mDNS do oprogramowania kamery, co oznacza, że możesz uzyskać dostęp do urządzenia w sieci lokalnej za pośrednictwem rekordu DNS (można to porównać do pseudonimu), więc nie musisz znać ani pamiętać jego adresu IP. Rekord mDNS jest konfigurowalny – na przykład teraz jest to http://prusa-esp32cam.local.

Tryb AP wiązał się jednak z pewnym problemem, ponieważ interfejs sieciowy musiał działać w trybie offline, podczas gdy użytkownik łączył się z kamerą w trybie AP. Z tego powodu konieczne było zapisanie biblioteki jQuery bezpośrednio w kodzie źródłowym MCU. Na szczęście istnieją już małe i zoptymalizowane biblioteki jQuery do tego celu, chociaż nadal zajmują około 86 kB pamięci Flash MCU, a to całkiem sporo.

SSID kamery składa się z przedrostka ESP32_camera + ID, które są pierwszymi trzema liczbami z UID MCU. Dlatego jeśli ktoś używa kilku modułów, na przykład do monitorowania farmy, za pomocą tej etykiety może łatwo rozpoznać, który jest który.

Innym sposobem konfiguracji kamery był szeregowy interfejs komunikacyjny, którego użytkownicy mogą używać zamiast trybu AP, jeśli nie mogą lub nie chcą z niego korzystać. Tutaj użytkownik może ustawić poświadczenia WiFi i token autoryzacji dla aplikacji backendowej, wyświetlić adres IP kamery w sieci lub użyć innych poleceń za pośrednictwem konsoli.

Czym więcej, tym…

W tym momencie projekt dość mocno się rozrósł. Miroslav przepisywał stronę około 3-4 razy, ponieważ zawsze znajdował coś, co można było zrobić lepiej. Pierwsza wersja kodu była napisana w C, więc teraz próbował przepisać wszystko w C++, co wciąż nie jest do końca zrobione, ale kod jest edytowany i ulepszany część po części. Chociaż projekt rozrósł się dość znacznie, rozpoczął się i trwa jako projekt Arduino, więc społeczność może łatwo edytować kod źródłowy bez konieczności korzystania z innego dedykowanego IDE z kompilatorem.

Teraz nadszedł czas, aby dowiedzieć się, jak zaimplementować aktualizację firmware OTA (over-the-air). Obecna wersja MCU ma 4 MB pamięci Flash, co oznacza, że tylko 1,9 MB pamięci Flash może być wykorzystane na całą aplikację. Jeśli zastanawiasz się dlaczego, to dlatego, że do aktualizacji firmware wykorzystywany jest tak zwany „double banking”, co oznacza, że pamięć dzielona jest na dwa sektory (w rzeczywistości jest ich więcej, ale dla uproszczenia powiedzmy, że dwa). W jednym sektorze działa aktualna, zwalidowana aplikacja (nazwiemy go sektorem A). W drugim sektorze znajduje się nieprawidłowa, nieaktualna wersja aplikacji (tak jest, to sektor B).

Camera system information with OTA

Informacje o systemie kamery, w tym opcje aktualizacji firmware OTA.

Po pobraniu nowego firmware, sektor B (nieprawidłowa aplikacja) jest nadpisywany. Następnie sprawdzana jest integralność zainstalowanego firmware i jeśli wszystko jest w porządku, aplikacja w sektorze B jest ustawiana jako aktywna. Dzięki temu systemowi aktualizacja OTA nigdy nie nadpisuje aktualnie uruchomionej aplikacji.

Ograniczenia sprzętowe

Oprócz różnych problemów z oprogramowaniem, było też kilka problemów z samym sprzętem. Niektóre wersje testowe przestały wysyłać zdjęcia, rozłączały się z WiFi, restartowały się itp. „To było wiele różnych problemów, ale ich rozwiązywanie dawało mi frajdę. Zobaczenie jak występują, a następnie wymyślenie rozwiązań, by je wyeliminować, było bardzo interesujące” – skomentował Miroslav.

Największym problemem był projekt płytki ESP32-CAM. Na przykład, ponieważ procesor ma niewiele pinów i stosunkowo dużą liczbę peryferiów, projektant wykorzystał pin do zapalania diody LED również jako jeden z pinów do komunikacji z kartą microSD. Spowodowało to problem z komunikacją między MCU a kartą microSD, gdy dioda LED była włączona. Problem ten został rozwiązany poprzez wykorzystanie „trybu jednoprzewodowego” karty microSD, w którym dane są odczytywane i zapisywane tylko przez jedno cyfrowe wejście/wyjście.

Znacznie większym problemem jest dioda LED flash na płycie – projektant podłączył ją bezpośrednio do napięcia 3,3V bez rezystora ograniczającego prąd, co powoduje, że prąd płynący przez diodę LED jest zbyt wysoki i dioda pada po pewnym czasie. Na jednej płytce dioda LED zgasła po miesiącu migania co 30 sekund. Miroslav wymyślił kilka rozwiązań tego problemu, w tym wlutowanie rezystora pomiędzy kolektor tranzystora a płytkę PCB lub użycie zewnętrznego źródła światła, włączanego przez przekaźnik, MOSFET lub coś podobnego. Niektóre elementy płytki również dość mocno się nagrzewają, ale zależy to od aktualnej partii. Nad tą kwestią wciąż pracujemy, ponieważ przeprowadziliśmy kilka prób, takich jak zmniejszenie częstotliwości taktowania procesora, ale nie przyniosły one większej poprawy.

Possible solutions to the LED problem

Kilka możliwych rozwiązań problemu LED zaproponowanych przez Miroslava

Jak widać, jest jeszcze wiele rzeczy do rozwiązania i poprawienia w tym projekcie. Jednak Miroslav nadal się nim cieszy i lubi nad nim pracować. Najbardziej lubi odkrywać, co można zrobić z małym, tanim modułem kamery. Chciałby jeszcze popracować nad wielozadaniowością, ponieważ wszystko działa jednocześnie tylko na jednym rdzeniu procesora, chociaż procesor ma dwa (dual core). I na pewno będzie kilka innych poprawek/ulepszeń, które chciałby dodać.

Nie wahaj się więc wypróbować tego interesującego rozwiązania, a także podziel się z nami i autorem wszelkimi komentarzami lub pytaniami.

Udanego drukowania!