Free provisioning in Avalonia 11

Introduction

If you want to create mobile applications for iPhones (iOS operating system) then you have many ways to do that: Flutter, React Native, Cordova… But if you can write code in C# there are also a few frameworks: Xamarin, MAUI and Avalonia.

Currently I’m working with Avalonia UI so I wanted to deploy my apps for testing to my iPhone. The easiest way is to use Apple Developer account from Apple Developer Program and use TestFlight service. Although TestFlight is free, a paid developer control is required to use it (100$ per year). For me it was too much to pay for possibility to only test my apps.

But there is some free alternative: Free provisioning. To use it you need to have computers with MacOS (with installed Xcode) and Windows (with installed Microsoft Visual Studio), free Apple ID account and iPhone of course 😉

So today I would like to show you how you can use Free Provisioning with Avalonia UI framework.

How to use?

Options window used to set up an Apple ID account.

At the beginning set up Apple ID account in Visual Studio (Tools -> Options -> Xamarin -> Apple Accounts).

Connecting with Mac in Microsoft Visual Studio.

Next you have to turn on Remote Login in your Mac (in Mac: System settings… -> General -> Sharing -> Remote Login). After that pair and connect with your Mac from Visual Studio in Windows (Tools -> iOS -> Pair to Mac).

Then open Visual Studio solution that you want to deploy to iPhone (it’s „FreeProvisioning” in my case). You can try to run your app in iOS simulator to check if connection is working fine and if code is building without errors.

Now it’s time to config Free Provisioning.

Creating new iOS project in Xcode.

On Mac create in Xcode default iOS app project (File -> New -> Project). This project is needed to create keys used for our Avalonia app deploy (just create project, you don’t need to write any code in Xcode).

Setting up project properties.

In next page of wizard fill text inputs (remember to use your Apple ID account in „Team” field) and before clicking „Next” remember text showed in „Bundle Identifier” property (we will use it in future).

„Signing & Capabilities” tab in Xcode project properties.

After that step you should see opened project in Xcode. Click using left mouse key on your project name in Navigator (by default it’s top position in tree on the left). In new project properties go to „Signing & Capabilities” tab. Remember value from „Signing Certificate” field.

Adding new properties in csproj file.

Now go back to computer with Windows and open in notepad *.iOS.csproj file (in my case „FreeProvisioning.iOS.csproj”) in your iOS project directory. Add „CodesignProvision” (with your „Bundle Identifier”) and „CodesignKey” (with your „Signing Certificate”) properties with values from Xcode (you can see example in screenshot above).

Changing value „Bundle Identifier” in Visual Studio.

You have to also set up in „Info.plist” file property „Bundle Identifier” with value that you saw in Xcode.

Now set up your iPhone to be used in developer mode. Connect iPhone to Mac (accept and agree all pop-up’s on Mac and iPhone) and in iPhone go to Settings -> Privacy & Security, scroll down to the Developer Mode and turn it on. Probably after first deploy try you will have to give needed permits in „VPN & Device Management” page (Settings -> General -> VPN & Device Management).

After successful set up you should see your iPhone on device list in Visual Studio. Select your device and run app with debug from Visual Studio.

If iPhone is showing „App cannot be installed because its integrity could not be verified” errors then you can try to run your app in Release mode than in Debug. You can also try to completely remove app from iPhone and try to deploy it again.

Conclusion

If there are any problems during described process then you should also check Free Provisioning manual in MSFT docs.

I also had many problems with the configuration of the whole process, which I described above. I believe the problem is that Free Provisioning is too complex. But after many attempts and restarts of used devices and software finally it started to work.

With Free Provisioning you can test your apps with some limitations (check MSFT docs to read more), but in my case I could even test Bluetooth connection without any problems.

Solution presented in this post should also work with Xamarin and MAUI so if you have any problems in that frameworks then try to use my instructions 🙂

Spacecraft

Idea

When I was looking for project to print on my new 3D printer I found very interesting model on Thingiverse:

Project for 3D printer that I found on Thingiverse

Since I’m a big fan of all astro things, I thought that I had to print this. In after-printing pictures I also saw that I can add light to the base of Space Shuttle to simulate the operation of real engines. But static lamp is not what could do the job – it had to smoothly blink 😉 And why not to try automate this light to turn on after sunset?

But that was problems for the future – now was printing time.

Printing and soldering

I was prepared for quick printing, because I had calibrated printer. After 26 hours I’ve got effect that you can see below:

I only need to remove all unnecessary supports and I could start playing with my soldering station.

After support removal

To create effect of glowing exhausting gases I figured out that I can use cheap Chinese LED candle (example on picture below).

LED candle, Source: https://www.jiomart.com/p/groceries/ein-sof-10-pcs-flameless-led-tealights-smokeless-acrylic-decorative-candles-yellow-light-3×3-cms-pack-of-10/596256307

Originally candle was not prepared to be controlled in any way so I needed to add transistor that was managing candle power source. To achieve that effect I chose 2N2222 transistor (because I had whole bag of them) with 1kΩ resistor connected to the base.

During candle modifications

As a controller I wanted to use Raspberry Pi Zero W 2, because I’m using it in one of my previous projects (HubScreen).

Originally candle was powered by CR2032 battery (3V), so I decided to use 3.3V pin as a power source.

Programming

Hardware was prepared and tested – now was time to write some code.

Because I am using Home Assistant with zigbee2mqtt at my home so I wanted to control my Spacecraft via MQTT protocol. For this I created special library mqtt2exec that is checking broker topic and performs set actions after receiving command.

Source code of mqtt2exec library on GitHub

Library checks if received command was added to C++ dictionary (map object) and then execute function assigned to this command. Adding and removing commands is possible during work of library object – to avoid data races it use mutex object from Standard Template Library. To reach the best performance MQTT broker should has special topic (in my case mqtt2exec) for sending commands and commands length should’t be too big. Code used for the Spacecraft project can be found in example directory on GitHub – it’s receiving TurnOnSpacecraft and TurnOffSpacecraft commands and changes state of GPIO 20 pin.

To setup GPIO 20 pin (e.g. I need to set pin direction) and create background service (e.g. with automatic restart of application if any fail occured) I used systemctl service manager in Debian Linux.

Now was time to add new action after sunset in Home Assistant automations…

Configured action in Home Assistant

…and last debug checks in MQTT Explorer.

Command received by MQTT broker

Finally everything was ready to work on it’s own.

Conclusion

The end result can be seen in the video below:

New smart home gadget 😉

That was really fun and quick project. It’s really good add-on to my smart home IoT network. Now I also have library that I can use in future to control in very easy way different devices in my future projects via different networks (WiFi, Ethernet, etc.).

ARStreetLamp – opis projektu

Skąd pomysł na projekt?

Będąc studentem w wielkim mieście musiałem wkręcić się w nową grę Pokemon GO (ale oczywiście dopiero jak przeszedł największy szał 😉 ). Dzięki niej spacery ze słuchawkami na uszach nabrały nowego sensu. Ale najbardziej w nowej grze zaintrygowała mnie funkcja AR (rozszerzonej rzeczywistości), bo tym razem nie ograniczała się do statycznych obiektów jak w wielu dostępnych w Internecie demach. A skoro i tak już robiłem kolejne projekty w Xamarinie to trzeba było zorientować się czy mogę coś takiego osiągnąć programując w C#. Mniej więcej w tym samym momencie pojawiła się pierwsza wersja biblioteki ARCore dla mojego Xiaomi Mi 9T. Coraz więcej znaków na niebie dawało nadzieję na fajny ciekawy. Niestety po przejrzeniu przykładów w dokumentacji biblioteki ARCore tworzonej przez Google’a stwierdziłem, że temat może być znaczniej bardziej skomplikowany niż sobie bym tego życzył. Ale tutaj z pomocą przyszedł Microsoft ze swoją dokumentacją oraz twórcy biblioteki UrhoSharp. Trzeba było jeszcze znaleźć jakieś zastosowanie dla rozszerzonej rzeczywistości… I tutaj z inspiracją przyszła moja obecna praca 🙂

O aplikacji

Plan był taki, aby opracować aplikację, która pozwoli handlowcom tworzyć szybkie wizualizacje opraw oświetleniowych (drogowych, do wnętrz, itd.) dla potencjalnych klientów. Wyszedłem z założenia, że każdy pracownik posiada smartphone’a oraz umie używać wbudowanej w niego kamery. Nic by też nie stało na przeszkodzie, aby wykorzystywać aplikację do prezentacji wszystkich produktów firmy bez dodatkowej potrzeby jeżdżenia ciężarówką wypełnioną każdym wariantem produkowanej przez zakład lampy.

Zacząłem od opracowania uproszczonego modelu 3D oprawy Siled Celebra. Na początku, z racji jakiejś znajomości ze szkoły średniej/studiów, postanowiłem wykorzystać do tego oprogramowanie Autodesk Autocad. Pomimo bardzo zadowalającego efektu podczas renderowania oprawy pod różnymi kątami (jak na swój pierwszy raz w świecie 3D) okazało się, że eksport modeli do formatów obsługiwanych przez UrhoSharp’a jest trochę bardziej skomplikowany. Po obejrzeniu wielu YouTube’owych poradników skończyłem z wirtualną maszyną Debian’a i zainstalowanym Blender’em posiadającym plug-in „Urho3D-Blender„. Po wielu podejściach do różnych konfiguracji oraz wersji Blendera i rozszerzenia udało się w końcu trafić na taką, z którą robienie kolejnych modeli było już szybsze i sprawniejsze.

Pierwszy render nowej kanciastej lampy 🙂
Podczas tworzenia nowych modeli dla rozszerzonej rzeczywistości

Po opracowaniu opraw zabrałem się za wykonanie słupa. Tutaj na szczęście mogłem posiłkować się gotowymi modelami (np. śrub z plug-in’u Bolt Factory). No i w końcu coś zaczęło się prezentować.

Modelowanie podstawy słupa

Równolegle do tworzonych modeli 3D powstawał również kod źródłowy robiony w Xamarin Android. SDK zostało wybrane ze względu na pokrycie niemal w 90% funkcji dostarczanych przez Javowe SDK od Google’a i dodatkowo po prostu bardziej jestem Team Microsoft niż Team Google czy Team Oracle.

Kodzenie zacząłem od interfejsu aplikacji (w sumie znany temat, więc chociaż od początku było widać jakiś efekt). Największy problem był z pionowym suwakiem do ustalania wysokości oprawy/długości słupa. Niestety Google nie przewidziało takiej kontrolki w swojej bibliotece. Na szczęście metodą prób i błędów udało się w końcu opracować jakiś kompromis co pozwoliło na przejście do bardziej zaawansowanych rzeczy.

Pierwsze testy aplikacji w terenie

Pierwszą z nich było wykonanie jakiegoś algorytmu pozwalającego na tworzenie całej instalacji lamp składającej się z zadanej ilości. W tym celu w świecie AR należało dodać minimum dwie oprawy, a algorytm robił resztę – obliczał odległość między najdalszymi oprawami i generował symetrycznie kolejne w tych samych odległościach. Do ekstrapolacji zostało wykorzystane proste równanie liniowe – w planach było opracowanie kolejnych wariantów algorytmu wykorzystujących bardziej wymyślne równania krzywych. Niestety świat w którym pracowałem występował w 3 wymiarach, więc estymacji potrzebnych parametrów musiałem dokonywać z pomocą równań macierzowych w funkcji StartCreatingNewInstallation() (czemu oczywiście podołałem 😉 ).

Nocne testy aplikacji. Migotanie opraw powodowane jest przez nadmierne obciążenie procesora telefonu ze względu na jednoczesne generowanie sceny w rozszerzonej rzeczywistości oraz rejestrowanie obrazu z ekranu (bez nagrywania wideo efekt ten nie występował)

Kolejną rzeczą na której mi zależało było generowanie cienia przez słup z lampą zgodnie z aktualnym położeniem słońca. Do wykonania tej funkcjonalności potrzebowałem dodać obsługę kompasu oraz GPS’u. Na bazie tych informacji (oraz aktualnej daty i godziny) mogłem obliczyć położenie słońca na niebie. Później wystarczyło dodać node’a ze źródłem światła znajdującym się w obliczonym miejscu i można było patrzeć jak wirtualny cień pokrywa się z tym rzeczywistym. W planach było jeszcze uzależnienie jasności źródła światła od wartości natężenia światła odczytywanego ze smartphone’owego czujnika, ale ostatecznie nie wcieliłem tego planu w życie.

Testy wirtualnych cieni rzucanych przez lampy vs. rzeczywiste cienie plażowiczów nad polskim Bałtykiem

Iiiiiiii… Potem czar UrhoSharp’a prysnął. Przy próbie wykonania bardziej zaawansowanych rzeczy w tym silniku graficznym zaczęły pojawiać się błędy i artefakty (np. nieprawidłowe generowanie cienia – szczegóły w zrzutach ekranu i nagraniach wideo). Na pomoc w Internecie też za bardzo nie było co liczyć – okazało się, że UrhoSharp był portem silnika graficznego Urho3D i użytkownicy Urho3D oraz UrhoSharp’a za bardzo się nie lubili (przynajmniej takie były moje odczucia, gdy prosiłem o wsparcie) 😉 . Microsoft reklamował UrhoSharp’a na stronie głównej dotyczącej Xamarin’a (na szczęście już z tego pomysłu się wycofał) i niestety dałem się zwieść. Na dodatek dzisiaj nie mam możliwości przetestowania mojej aplikacji na nowym telefonie Samsung Galaxy Note 10+, ponieważ najnowsza wersja ARCore’a generuje wyjątki zaraz po uruchomieniu opracowanej aplikacji (a UrhoSharp już od kilku lat nie jest aktualizowany) – teoretycznie jest możliwość manualnej aktualizacji potrzebnych bibliotek, ale stwierdziłem, że szkoda na to zachodu.

Głównym przekonującym argumentem za UrhoSharp’em (oprócz bardzo dużej prostoty przy tworzeniu wirtualnego świata) była licencja MIT, ale dzisiaj podchodząc jeszcze raz do tego projektu poszedłbym pewnie w stronę Unity albo bezpośrednio w ARCore’a – może kiedyś podejmę się przeportowania aplikacji, kto wie.

Ale co się nauczyłem przy tym projekcie to moje 😉

TODO

Poniżej prezentuję listę rzeczy, które chciałem uwzględnić w rozwoju tej aplikacji:

  • Poprawa działania światła dziennego i generowanego przez nie cienia,
  • Ulepszenie algorytmu do generowania całych instalacji lamp,
  • Dodanie nowych modeli opraw,
  • Opracowanie interfejsu pozwalającego na sterowanie wirtualnymi oprawami za pomocą aplikacji zarządzania inteligentnymi oprawami (CMS).

Zrzuty ekranu

Kody źródłowe

Kody źródłowe

Aplikacja

Tak jak wspominałem wcześniej aplikacja została opracowana raczej jako proof of concept i po nabytych doświadczeniach nie nadaje się raczej do rozwoju/udostępnienia 🙂 Oczywiście jak ktoś będzie naprawdę jej potrzebował to zapraszam do kontaktu/sekcji komentarzy albo zachęcam do własnoręcznej kompilacji ze źródeł dostępnych na moim GitHub’ie.

Traficar – tygodniowa wycieczka

Wstęp

Sezon wakacyjny już dawno za mną, więc mogę podsumować jeden z moich pomysłów. A chodzi o sierpniowy wyjazd, podczas którego postanowiłem skorzystać z Traficara jako środka transportu. Szczegóły poniżej 🙂

Planowanie

Miejscem wycieczki miały być Góry Sowie, czyli Dolny Śląsk. Jako bazę wypadową wybrałem miasto Dzierżoniów ze względu na zbliżoną odległość do wszystkich interesujących atrakcji w okolicy. Z Gdańska kawałek jest (dokładnie 548 km co daje prawie 6h jazdy samochodem). Żeby nie marnować całego dnia, a po przyjeździe nie być do niczego, jako alternatywę wyznaczyłem trasę pociągiem do Wrocławia (ok. 5h jazdy). Został jeszcze problem z odcinkiem Wrocław – Dzierżoniów (ok. 60 km). I tutaj z pomocą miał przyjść Traficar. Niestety w Dzierżoniowie nie ma strefy Traficara, co uniemożliwiało zakończenia wynajmu w mieście docelowym. I wtedy narodził się pomysł na zorganizowanie całej wycieczki wynajętym we Wrocławiu samochodem.

Szacowany koszt Traficara dla trasy z Gdańska do Dzierżoniowa to ok. 380 zł (+ koszty ewentualnych autostrad). Dla pociągu IC + Traficara z Wrocławia do Dzierżoniowa wyszło 162,71 zł. Dodatkowo w pociągu było można się wyspać i pooglądać seriale. Czyli druga opcja była najlepsza (no i miałem 50% zniżki w postaci wycieczki z dziewczyną 😉 ).

Polowanie

Po dojechaniu pociągiem do Wrocławia należało znaleźć jakiegoś wolnego „Traficzka”. Koło dworca głównego były akurat dwa. Na szczęście przed wyruszeniem w jego stronę zorientowałem się, że oba są modelami Renault Clio IV, a nie po to płacę tyle za wynajem, żeby teraz jeździć takim „starociem” 😉 Najbliższe Renault Clio V było spory kawałek drogi spacerem od dworca, ale nie po to są kółka w walizkach, żeby mnie to zniechęciło 😉 Nad głową słoneczna pogoda, więc nie było przeciwskazań, żeby trochę się zmęczyć po tak długim czasie w pociągu.

Skończyło się na dopłacie 1,95 zł do naszej rezerwacji. Dodatkowo po wędrówce okazało się, że do najczystszych samochód nie należał (niestety w środku), ale już nie starczyło sił, żeby po takim spacerze szukać kolejnego samochodu. Po chwili „klima” ustawiona, Android Auto skonfigurowane, Yanosik włączony – a więc w drogę. Niestety nie udało się zamocować uchwytu na telefon (deska rozdzielcza była tak zakurzona, że przyssawka co chwilę się odklejała). Na szczęście miałem obok siebie współtowarzyszkę podróży, którą mianowałem na stanowisko operatora nawigacji samochodowej. Po zatrzymaniu się na wszystkich światłach we Wrocławiu i ok. godzinie jazdy udało się dotrzeć do hotelu. Na ten dzień był to koniec samochodowych wycieczek.

Podróżowanie

Przed wyruszeniem na szlak 🙂

Samochód na górskich serpentynach sprawdzał się bez zarzutu. Android Auto też robiło robotę (szkoda, że Yanosik zrobił aktualizację w trakcie wyjazdu i nie udało się skorzystać z „samochodowej” wersji aplikacji).

Uzupełnianie prowiantu przed wycieczką 😉
„Trafi” dojedzie wszędzie 😉

Z nowych funkcji z którymi miałem do czynienia to bardzo doceniłem funkcję automatycznego otwierania i zamykania samochodu w zależności od położenia karty służącej jako kluczyk. Wadą takiego rozwiązania była możliwość pozostawienia uruchomionego silnika, bo niestety silnik w używanym modelu był bardzo cichy (trzeba było weryfikować jego działanie poprzez obrotomierz).

Uzupełnianie płynów

Z szacunków wynikało, że samochód podczas wynajmu będzie musiał przemierzyć ok. 505 km czego bak Clio raczej nie przewidywał. W związku z tym trzeba będzie zaliczyć jakieś tankowanie podczas wyjazdu.

W samochodzie, w osłonie przeciwsłonecznej, umieszczona była karta paliwowa Orlenu. Na szczęście obok hotelu znajdowała się stacja benzynowa potrzebnej firmy.

I tak przed jednym z wyjazdów na szlak zahaczyłem o Orlena (regulamin mówi, że tankować można dopiero, gdy stan w zbiorniku paliwa jest niższy niż 30%, więc najpierw trzeba było wyjeździć początkowy stan). Do baku, w przypadku Clio V, lejemy zwykłą „dziewięćdziesiątkę piątkę”.

Generowanie kodu PIN w aplikacji

Tankowanie należy opłacić z wykorzystaniem dołączonej karty paliwowej. Przy płatności potrzebna jest wiedza o:

  • kodzie PIN – generowany z poziomu aplikacji (tylko po wyłączeniu silnika 😉 ) i ważny przez 30 minut (kod najlepiej wygenerować przed rozpoczęciem tankowania),
  • aktualnym stanie przejechanego dystansu przez samochód (do odczytania z deski rozdzielczej).
Tankowanie tylko do pełna 😉

Szybko, miło i raczej bezboleśnie 😉

Podsumowanie

Podsumowanie wyjazdu

Wycieczka skończyła się na przejechaniu 473 km, które kosztowały 326,37 zł. Miłym zaskoczeniem był nowy sposób naliczania wynajmu, który dobę liczył od momentu rozpoczęcia wynajmu (wydaje mi się, że w przeszłości było to od północy do północy). Ostatecznie za 6 dni wynajmu zapłaciłem 354 zł. Całkowity koszt wyniósł 682,32 zł co przy 50-cio procentowej zniżce (uroki wycieczek z dziewczyną 😉 ) było bardzo sympatyczną kwotą za wynajem nowego samochodu (praktycznie z salonu), który można wziąć i oddać w dowolnym miejscu w strefie.

Na dodatek tuż przed zakończeniem wynajmu Traficar został przez godzinę wykorzystany jako przechowalnia bagażu, która dzięki braku opłat za parkowanie w płatnej strefie mogła znajdować się bardzo blisko dworca PKP.

Podczas wyjazdu dowiedziałem się też, że brak opłat w strefach płatnego parkowania dotyczy tylko miast, w których są strefy Traficar, więc w takim Wałbrzychu trzeba było się wykosztować ze swoich.

Ogólnie to raczej polecam taki sposób podróżowania (w głowie już jest pomysł na kolejny wyjazd) 🙂 Jeśli chodzi o wady to na pewno gdzieś z tyłu głowy bolał mnie „indywidualny” sposób podejścia do ewentualnych uszkodzeń/wypadków, bo niezależnie od intencji kierowcy może to się dla niego bardzo boleśnie skończyć (na szczęście nie musiałem tego podejścia sprawdzać).

HubScreen – nowe funkcje i optymalizacja działania

Wstęp

Z racji, że ekran z projektu HubScreen posiadał dużo potencjału, który marnował się niewykorzystany, postanowiłem znaleźć dodatkowe zastosowania. Zostały one przedstawione poniżej.

Uniwersalna bramka ZigBee

Żeby znaleźć jakieś nowe zastosowanie dla działającego przez 24h/dobę Raspberry postanowiłem zbudować sobie uniwersalną bramkę ZigBee w oparciu o układ CC2531 i oprogramowanie Zigbee2Mqtt.

Wszystko zaczęło się od potrzeby posiadania termometru na balkonie, ale jak wiemy mamy XXI wiek, więc to nie mógł być taki zwykły termometr 😉 W tym celu zakupiłem układ sniffera ZigBee CC2531 na Aliexpress za ok. 15 zł i czujnik Xiaomi Aqara WSDCGQ11LM za 67 zł.

Układ CC2531 normalnie jest wykorzystywany jako sniffer ZigBee (przetestowany na sterownikach wykorzystywanych w pracy 😉 ), ale po zmianie firmware według tej instrukcji staje się uniwersalną bramką ZigBee. Problemem podczas prób uruchomienia Zigbee2Mqtt był fakt, że usługa chciała wystartować dopiero po zainstalowaniu Node.js w wersji 11.15.0.

Do wymiany firmware chciałem wykorzystać płytkę Raspberry Pi 4B, ale niestety przy próbie odczytania wersji firmware z układu CC2531 otrzymywałem odpowiedź ID = 0000 lub ID = ffff. Niedawno czytałem, że podobno ma pomagać aktualizacja biblioteki wiringPi, ale w moim przypadku z problemem sobie poradziłem poprzez zmianę płytki na Raspberry Pi 3B (RPi 3B).

Ze względu na wcześniejsze pomiary obciążenia Raspberry Pi Zero (RPi Zero) postanowiłem wymienić je na wspomniane przed chwilą Raspberry Pi 3B, które dzięki zwiększonej wydajności miało poradzić sobie z obsługą projektu HubScreen i nowym zadaniem bycia bramką ZigBee. Na początku nie wyglądało, żeby miały występować jakieś problemy, ale po kilku dniach pracy okazało się, że nie jest tak kolorowo:

  • procesor RPi osiągał temperaturę minimum 60°C niezależnie od obciążenia (aż radiator zaczął spływać z procesora; próbowałem nawet obniżać częstotliwość, ale niczego to nie zmieniało),
  • pobór energii zwiększył się 10-krotnie w porównaniu do tego co było przy RPi Zero.

Problemy wynikały zapewne z moich studenckich czasów, gdzie RPi 3B nie miało zbyt łatwego życia. Dlatego musiałem wrócić do RPi Zero i opracować rozwiązanie dla zbyt małej mocy obliczeniowej – a o nim już poniżej.

Zdalny pulpit

Z racji uruchomienia w ostatnim czasie domowego serwera najlepszym sposobem zmniejszenia obciążenia byłoby przeniesienie zadań wymagających dużej mocy obliczeniowej na platformę bardziej do nich przystosowaną.

I taką „platformą” został domowy serwer z systemem Windows Server 2019. Różnicę w obciążeniu widać na poniższym zrzucie ekranu (trzeba pamiętać, że RPi Zero obsługuje teraz dodatkowe zadanie pod postacią bramki ZigBee).

Obciążenie Raspberry Pi Zero przy nowym podejściu

Do obsługi projektu utworzyłem nowego użytkownika, który podczas logowania otwiera przeglądarkę internetową ze stroną hostowaną na RPi Zero. Dzięki temu, gdy RPi ma awarię albo po prostu jest wyłączone, nie jest zużywany transfer danych potrzebny do ciągłego odświeżania informacji wyświetlanych na Ekranie.

Zdalny pulpit uruchamiam w systemie Linux dzięki aplikacji Remmina (dobrze mi się tego używało za czasów zabawy z Ubuntu). Skrypt uruchamiający aplikację jest uruchamiany automatycznie przy starcie RPi Zero. Dzięki temu z punktu widzenia użytkownika działanie jest dokładnie takie samo jak w przypadku wcześniejszego rozwiązania, ale za to widać znaczną różnicę w szybkości działania (chociażby po cyfrowym zegarze z sekundnikiem generowanym przez skrypt JavaScript).

Dodatkowo wykorzystałem Harmonogram zadań systemu Windows w celu wyłączania procesu przeglądarki w nocy i ponownego uruchamiania rano (kolejny sposób na oszczędność transferu).

Klasyczne problemy z Windowsem

Niestety wiele dni pracy Ekranu ze zdalnym pulpitem doprowadziło do obserwacji, że po kilku godzinach okno przeglądarki internetowej traci focus i nie mogę zmieniać kart przeglądarki za pomocą skrótu klawiaturowego Alt + Tab bez dodatkowego kliknięcia na któryś element strony internetowej. Czasami Remmina się po prostu wyłączała bez podania żadnego powodu.

Przyczyną było tracenie połączenia sesji RDP lub występowanie dużych opóźnień w połączeniu pomiędzy RPi Zero a serwerem. Problem postanowiłem rozwiązać na kilku płaszczyznach:

  • poprzez przywracanie focus’a przy logowaniu do konta użytkownika (np. gdy Remmina rozłączała się ze zdalnym pulpitem i przy ponownym łączeniu kolejny raz logowała do konta Windows’a):
Do przywrócenia focus’a wykorzystuję skrypt sendKeys, a jego uruchomienia dokonuję z wygodnego graficznego narzędzia Task Scheduler (Harmonogram zadań), które pozwala reagować na zdarzenie, którym jest zalogowanie do systemowego konta
  • poprzez automatyczne zabijanie i ponowne uruchamianie aplikacji Remmina w przypadku problemów z działaniem – w tym celu wykorzystałem program supervise (wchodzący w skład pakietu daemontools), który nadzoruje pracę uruchamianych przez niego procesów. Nie mogłem skorzystać z narzędzia systemctl w Debianie ze względu na uruchamianie zdalnego pulpitu w warstwie graficznej do której to narzędzie nie sięga.
  • poprzez usprawnienie domowej sieci komputerowej:

Ekran projektu HubScreen i router znajdują się w dwóch skrajnych miejscach mieszkania, a samo Raspberry ma antenę na płycie PCB, więc taki układ nie może sprawnie działać. W tym celu postanowiłem dokonać odpowiednich pomiarów, aby dowiedzieć się jaki ma to wpływ na opóźnienia oraz samą dostępność Raspberry w mojej sieci komputerowej. W tym celu pewnego sobotniego dnia postanowiłem zainstalować serwer Zabbix’a na moim Windows Serwerze (uroki posiadania komputera włączonego 24h/dobę oraz Docker’a, który pozwala na błyskawiczne uruchomienie dowolnego oprogramowania) i odpowiedniego agenta na RPi. Następnie przystąpiłem do pomiarów (a właściwie to Zabbix):

Opóźnienie (ping) pomiędzy serwerem a Ekranem
Dostępność Ekranu w sieci

Pomiary były dokonywane co 10 sekund, aby dało się także normalnie korzystać z domowej sieci.

Na powyższych wykresach dotyczących kilku dni pomiarów możemy odczytać następujące wartości:

  • Średnie opóźnienie (ping): 20,32 ms
  • Maksymalne opóźnienie (ping): 523,5 ms
  • Średnia dostępność Ekranu w sieci: 98,2 %

Trzeba było to w jakiś sposób usprawnić (szczególnie ten wykres dostępności). Pierwszy pomysł na jaki wpadłem to zastosowanie repeatera WiFi. Niestety klasyczny podłączany do zwykłego gniazdka w ścianie nie wchodził w grę ze względu na niekorzystne ułożenie gniazdek w mieszkaniu. Dlatego wpadłem na genialny pomysł: repeater pod sufitem jako LED’owa żarówka! W salonie akurat znajduje się kinket z idealnym widokiem na router znajdujący się na drugim końcu mieszkania. Niestety takie inteligentne żarówki wymagają zasilania 24h/dobę, więc musiałbym wymienić co najmniej dwie. I tutaj znalazłem idealny zestaw: żarówka z repeaterem WiFi i żarówka z głośnikiem bluetooth JBL’a. No idealny zestaw do mojego budowanego inteligentnego mieszkania. Na szczęście tuż przed kliknięciem przycisku „Kup” postanowiłem zasięgnąć rady ludzi z Reddita. Tam uświadomiono mnie o jeszcze jednej ważnej rzeczy: może zasięg WiFi się zwiększy, ale to wszystko kosztem opóźnień. Zasugerowano mi zbudowanie sobie sieci PLC (PowerLine Communication), która pozwala na komunikację poprzez przewody elektryczne. I to był strzał w dziesiątkę. Na Allegro za 255 zł udało mi się kupić zestaw do takiego zastosowania z routerem WiFi. Dzięki PLC opóźnienia w sieci z jednego końca mieszkania do drugiego są naprawdę minimalne, mogę sobie w końcu swobodnie korzystać z Internetu na balkonie i dodatkowo mogę grać w gry na telewizorze transmitując obraz z domowego komputera poprzez sieć (opóźnienia są naprawdę bardzo niskie).

Nowy układ sieci przedstawiłem poniżej:

A tutaj pomiary dla nowej konfiguracji:

Opóźnienie (ping) pomiędzy serwerem a Ekranem po dodaniu nowego Access Point’a
Dostępność Ekranu w sieci po dodaniu nowego Access Point’a

Na powyższych wykresach dotyczących kilku dni pomiarów po dodaniu nowego Access Point’a możemy odczytać następujące wartości:

  • Średnie opóźnienie (ping): 12,29 ms
  • Maksymalne opóźnienie (ping): 366,4 ms
  • Średnia dostępność Ekranu w sieci: 99,98 %

Teraz poziom dostępności jest na znacznie lepszym poziomie co można odczuć podczas codziennego korzystania z Ekranu 😉

Domoticz

Z racji, że w domu zaczęły pojawiać się pierwsze czujniki ZigBee to trzeba było gdzieś przechować generowane pomiary. I tak, kierując się poradami oraz doświadczeniami z pracy, poszedłem w kierunku systemu Domoticz.

Całkiem przyjemny system. Prosta konfiguracja. Szybkie działanie. Interfejs aplikacji w postaci strony WWW. Bez problemu udało się połączyć z Zigbee2MQTT. Na dodatek Domoticz posiada REST API, które pozwoliło mi na podłączenie czujnika DHT-11 czy czujnika ruchu odczytywanego przez RPi. Napisałem również aplikację, która na podstawie pingowania przez Bluetooth smartphone’ów decyduje czy w domu jest któryś z mieszkańców i modyfikuje zachowanie HubScreen’a, a historię statusów archiwizuje w bazie danych Domoticza. Dodatkowo udało się połączyć Domoticza z systemem Casambi (za pomocą autorskiej aplikacji Casambi2Domoticz napisanej w .NET Core) co pozwoliło na prezentację danych z czujnika powietrza Casambi.

Ale nie ma róży bez kolców. Jeśli chodzi o wady to Domoticz robi wrażenie przestarzałej aplikacji. Niedobór ciekawych pluginów, mało wodotrysków w interfejsie, brak prostej zmiany motywu itd. Potrzebowałem czegoś więcej.

Ostatnio ze względu na projekt prowadzony w pracy pojawiły się u mnie nowe doświadczenia z alternatywą dla Domoticza czyli Home Assistant’em, więc powoli przygotowuję się psychicznie na przeprowadzkę do nowego systemu „Inteligentnego mieszkania” 😉

Podsumowanie

Przedstawiona powyżej konfiguracja nie przetrwała próby czasu… Ale o tym w innym wpisie 😉 Najważniejsze, że to co wtedy się nauczyłem to moje 🙂

mearm-stm32f429i

Skąd pomysł na projekt?

Kolejny rok, kolejne święta – w związku z tym musiałem wziąć udział w kolejnej edycji wydarzenia Reddit Gifts, które polega na anonimowej wymianie prezentów przez użytkowników serwisu Reddit. Niestety w tym roku miałem wymianę z osobami z Wielkiej Brytanii, a połączenie tej lokalizacji z Brexitem nie wyszło mi najlepiej (problemy z dostawami przesyłek, Eurotunelem, itd. – ale nie o tym w tym wpisie). Z tej okazji otrzymałem z brytyjskiego Amazona w prezencie „manipulator z linijek”, czyli MeArm Robot Classic Maker Kits. Niestety w najbiedniejszej wersji, więc bez żadnego sterowania – goła konstrukcja z serwomechanizmami FS90MG. I tutaj trzeba było coś wymyślić 😉

O projekcie

Trochę czasu mi zajęło, żeby znaleźć sposób na oprogramowanie ramienia. Na początku musiałem to niestety złożyć, czyli dużo odklejania folii i skręcania konstrukcji. Za późno też znalazłem wideo z całym procesem składania i trochę czasu przez to zmarnowałem. Ale po jakimś czasie konstrukcja była gotowa. Teraz brakowało tylko sterowania.

Przed złożeniem…
…i po 🙂

W sprawie sterowania na początku próbowałem pójść najłatwiejszą drogą, czyli znaleźć coś gotowego. Po przeszukaniu GitHub’a i nie znalezieniu niczego co mógłbym zrobić bez dodatkowych wydatków zrozumiałem, że muszę wziąć sprawy w swoje ręce. Na początku planowałem napisać coś na Arduino czy Rapsberry, ale z jednej strony byłby problem z zakupem potrzebnych sterownikiem serw a z drugiej z wykonaniem jakiegoś przyjemnego interfejsu do sterowania.

Dlatego skończyłem z tym co już w zeszłym roku do takich zadań poznałem, czyli oprogramowaniem TouchGFX, które generuje interfejsy graficzne dla mikrokontrolerów ST – połączenie elastycznego interfejsu graficznego dla ekranu dotykowego i możliwości mikrokontrolera ARM. Do projektu postanowiłem wykorzystać posiadaną przeze mnie płytkę STM32F429I-DISC1. Jest wyposażona w mikrokontroler STM32F429ZIT6 i rezystancyjny ekran dotykowy, a więc wszystko czego potrzebowałem do projektu.

Potem było już z górki. Opracowałem interfejs w TouchGFX, wygenerowałem potrzebne kody źródłowe, dokonałem ich edycji w oprogramowaniu STM32CubeIDE (dodając kody z inicjalizacją i konfiguracją timer’ów, DMA, itd. działające w oparciu o bibliotekę HAL), skompilowałem wszystko i voilà – ramię robota ożyło 🙂 Potem tylko kalibracja serw i hardware był gotowy. Byłem zdziwiony, że do sterowania serwomechanizmami wystarczy napięcie 2.92 V, a nawet 2.80 V (nie wiem czy moja płytka nie jest przypadkiem uszkodzona).

Pierwsze testy gotowego układu
Ostateczna wersja interfejsu pozwalającego na kontrolę ramienia robota

Film z działaniem można zobaczyć poniżej:

Kody źródłowe i schematy

Kody źródłowe i schematy

Podsumowanie

Okazało się, że był to całkiem przyjemny projekt dla osoby, która nigdy wcześniej się takimi rzeczami nie zajmowała (czyli sterowaniem serwomechanizmami). W przyszłości przydałoby się zautomatyzować działanie ramienia, więc pewnie skończy się to na możliwości nagrania sekwencji kolejnych pozycji robota i jej powtarzania – ale to może jak będzie trochę więcej wolnego czasu 😉

Aktualizacja 14.04.2021 r.

Sequence recorder

Stało się to prędzej niż później – funkcja pozwalająca na nagrywanie sekwencji położeń ramienia gotowa! 🙂 Dzięki niej możliwe jest zapętlone powtarzanie zadanych pozycji. Poniżej przykład działania:

Ciężka praca robota 😉

Jak to działa?

W oprogramowaniu TouchGFX opracowałem nowy ekran pozwalający na tworzenie sekwencji (opis okna i przycisków można znaleźć na GitHub’ie):

Zasada działania polega wyznaczeniu w głównym oknie pozycji robota, którą chcemy dodać do sekwencji, a następnie na ekranie sequenceScreen przyciskiem nr 6 dodajemy pozycję do przewijanej listy (nr 4). Czynności powtarzamy do momentu opracowania całej listy. Następnie możemy odtworzyć opracowaną sekwencję przyciskiem nr 7 (uruchamiany wtedy jest asynchroniczny wątek w systemie FreeRTOS odpowiedzialny za przesuwanie ramienia do właściwych pozycji).

Niestety w przypadku zresetowania mikrokontrolera tracona jest cała utworzona lista z powodu przechowywania jej tylko w pamięci RAM. Aby usunąć ten problem postanowiłem dodać zapisywanie listy oraz prędkości odtwarzania sekwencji do nieulotnej pamięci Flash (tej samej w której przechowywany jest mój program). Po analizie rozkładu pamięci Flash w oprogramowaniu STM32CubeIDE wybrałem do tego celu ostatni sektor mikroprocesora (23; nawet w połowie go nie zapełniam). Dodatkowo zabezpieczyłem się przed nadpisywaniem sektora przez linker poprzez zmniejszenie ilości dostępnej pamięci na program o wielkość sektora (128 KB).

Największym problemem była dynamiczna lista, której długość miała być zależna od ilości dodanych pozycji. Niestety po długim czasie kręcenia się w kółko zostałem uświadomiony, że mikrokontrolery nie żyją w zgodzie z dynamiczną alokacją pamięci jak pod klasycznymi systemami operacyjnymi. Ostatecznie skończyłem ze statycznym buforem dla tekstu wszystkich pozycji w liście oraz odpowiadającym im kontenerami positionContainer (czyli bufory oraz kontenery istnieją w pamięci programu przez cały okres jego życia, a w razie potrzeby wykorzystania po prostu edytowane są ich parametry, a następne dodawane do przewijanej listy). I tak bym musiał taką sytuację rozważyć jako najbardziej krytyczny przypadek, gdybym chciał korzystać z dynamicznej alokacji pamięci, więc nie jest to taki problem.

Do komunikacji między wątkami (interfejsu graficznego i sterowania pozycją ramienia) wykorzystuję zmienne bool’owskie klasy sequenceScreenView, które przekazują do funkcji handleTickEvent() polecenia odświeżenia listy pozycji lub obszaru tekstowego dotyczącego informowania użytkownika o stanie działania algorytmu.

Film przedstawiający ostateczną wersję projektu można obejrzeć poniżej:

Podsumowanie

Teraz opracowana aplikacja w końcu wydaje się kompletna 🙂 No i jak na Automatyka i Robotyka przystało w końcu mam własne skonstruowane przeze mnie ramię robota 🙂

W przyszłości może warto byłoby dodać jakieś przesyłanie komend z pozycjami ramienia przez UART/USB, podłączyć ramię do komputera/ESP32 i sterować nim poprzez sieć… Ale to może w jakiejś dalszej w przyszłości, bo pomysłów na projekty tylko przybywa, a trochę gorzej jest z ich realizacją 😉

Domowy serwer

Wstęp

Rok jeszcze się nie skończył to nie ma co zwalniać tempa 😉 A z racji, że przed świętami udało mi się zdobyć na Allegro (za 139 zł) dysk SSD 250 GB Samsunga to postanowiłem przywrócić do życia mój stary komputer stacjonarny HP Compaq Elite 8300, o poniższych parametrach:

ProcesorIntel Core i5-3470 3,20 GHz
Ilość rdzeni procesora4
Pamięć RAM12 GB DDR3
Rodzaj dysku twardegoSSD
  
Liczba punktów uzyskana podczas testu procesora w programie PerformanceTest 96128
Liczba punktów uzyskana podczas testu pamięci w programie PerformanceTest 91859

Jak widać powyżej nie jest to demon prędkości (chociaż z symulacjami czasu rzeczywistego paneli PV i turbin wiatrowych z częstotliwością 20 kHz w Matlabie potrzebnych do wykonania pracy magisterskiej sobie poradził), ale do zastosowania w roli domowego serwera powinien być wystarczający.

Po co serwer w domu?

Pierwsze moje pomysły wykorzystania domowego serwera przedstawiam poniżej:

  • Pi-hole – W domu wykorzystuję wiele urządzeń, które są podłączone do Internetu. Niestety nie na wszystkich mam możliwość zainstalowania jakiegoś adblock’a, więc dobrze by było realizować takie zadania na poziomie całe sieci. Dodatkowo dostęp do Internetu możliwy jest dzięki sieci mobilnej Play, a jak wiadomo wszystkie oferty „no limit” są tak naprawdę z limitami transferu, więc fajnie byłoby przyoszczędzić parę megabajtów na niepobieraniu niepotrzebnych reklam. Na początku myślałem o zainstalowaniu Pi-hole’a na routerze jednak obecnie przeze mnie używany nie spełnia minimalnych wymagań, a wymiana na nowy model nie daje jakiegoś znaczącego skoku technologicznego, więc na razie wstrzymuję się z zakupem. Dlatego jeśli jedynym zadaniem dla domowego serwera nie ma być blokowanie reklam to jest to idealne miejsce na instalację Pi-hole’a.
  • Napęd DVD – Niestety dzisiaj nowe komputery czy laptopy sprzedaje się bez napędów optycznych. Ma to swoje uzasadnienie, ale problem pojawia się, gdy trzeba uzyskać dostęp do danych sprzed wielu lat przechowywanych właśnie na płytach CD/DVD. Do tej pory zawsze szukałem jakiegoś starego laptopa z napędem DVD i zawartość płyt przenosiłem za pomocą pendrive’ów. Było to zadanie czasochłonne. W związku z tym taki serwer powinien udostępniać zawartości płyt w całej domowej sieci.
  • HubScreen – Wykonany przeze mnie w tym roku projekt działa na granicy swoich możliwości. Ewentualne próby rozbudowy (np. dodanie asystenta głosowego nad którym miałbym kontrolę) wymagałoby zmiany sprzętu co mogłoby wiązać się ze znaczącymi zmianami w projekcie. Aby tego uniknąć w takiej sytuacji dobrze byłoby przenieść zadania związane z renderowaniem strony WWW na domowy serwer, a wynik tego działania prezentować na ekranie z projektu HubScreen. Do uzyskania tego efektu powinna wystarczyć nawet najprostsza aplikacja pozwalająca na uzyskiwanie „zdalnego pulpitu” na domowym serwerze.

Pierwsze podejście – Debian 10

Przy pierwszym podejściu postanowiłem podejść do tematu „po bożemu”, czyli zainstalować system operacyjny, który najczęściej występuje na serwerach. Dodatkowo Pi-hole jest oprogramowaniem, które zostało opracowane pod Raspberry Pi, czyli linux’a (a nawet Raspberry Pi OS, który jest Debianem), więc problemów z działaniem raczej nie powinno być. I tak było w rzeczywistości. Instalacja blocker’a reklam sprowadziła się do jednego polecenia wydanego w terminalu:

curl -sSL https://install.pi-hole.net | bash

Po zakończeniu procesu instalacji i konfiguracji oprogramowania, a następnie zmianie adresu serwera DNS w routerze jeden z celów został osiągnięty.

Został jeszcze napęd DVD. Do jego udostępnienia postanowiłem wykorzystać serwer protokołu iSCSI. Mogłem go uruchomić dzięki jednej z dwóch aplikacji:

  • iscsitarget – Niestety aplikacja nie była zgodna z najnowszą wersją kernela w systemie Debian 10 (była kompatybilna maksymalnie z wersją Debian 8).
  • targetcliPo skonfigurowaniu serwera wszystko działało idealnie. Na domowym komputerze z systemem Windows 10 dodanie napędu było wyjątkowo intuicyjne dzięki domyślnie zainstalowanej aplikacji „Inicjator iSCSI”. Potem mogłem posługiwać się urządzeniem tak jakby było podłączone bezpośrednio do płyty głównej w moim komputerze. Było to to czego szukałem. Niestety nie ma róży bez kolców i po wymianie płyty na inną serwer iSCSI powodował kernel panic, który prowadził do „wysypania się” systemu operacyjnego serwera. Niestety nie znalazłem rozwiązania tego problemu, więc po raz setny poddałem się z próbą wykorzystania linux’a w codziennym zastosowaniu i wróciłem do tego co jest sprawdzone – czyli Windowsa.

Drugie podejście – Windows Server 2019

Na drugie podejście wpadłem zaraz po tym jak odkryłem, że Pi-hole jest dostępny w postaci kontenera Docker. Z początku myślałem o wykorzystaniu WSL’a skoro Microsoft tak go reklamuje, ale przypomniałem sobie o problemach w wersji pierwszej (chociażby brak możliwości używania systemd w Debianie), a wersja druga dostępna na serwery jest na razie tylko w kompilacji Preview. Natomiast chwilę wcześniej walczyłem z Dockerem przy próbie uruchomienia serwera gry „Plemiona” i nawet spodobało mi się to rozwiązanie. Dodatkowo w domu podstawowym systemem operacyjnym jest Windows, więc Windows Server zapewniłby największą kompatybilność.

I tak po kilku dniach walki z Dockerem i kolejnych kilku z routerem udało się uruchomić Pi-hole’a.

Pi-hole działający na domowym serwerze w ramach kontenera Docker

Na razie dowiedziałem się, że aktualizacja może nie być taka prosta jak w zwykłym linux’ie, ale obecnie jest to problem przyszłości 😉

Napęd DVD został udostępniony w sieci domowej tym razem dzięki usłudze udostępniania folderów dostępnej domyślnie w systemie Windows. Proste i na dzień dzisiejszy wystarczające rozwiązanie. Windows Server również posiada serwer iSCSI, ale do tej pory nie rozgryzłem jak udostępniać z jego wykorzystaniem napędy optyczne (z dyskami nie ma żadnych problemów). No ale jeszcze żadnych płyt nie musiałem nagrywać, więc o to będę martwił się później 😉

Podsumowanie

Na dzień dzisiejszy serwer spełnia swoją rolę.

Średnie dzienne zużycie energii to 0,52 kWh, co daje dzienny koszt działania serwera w wysokości 29 groszy (miesięcznie 8,70 zł). Koszt raczej do przełknięcia. Oby zwrócił się w postaci zaoszczędzonego transferu za Internet.

A co w przyszłości? Aktualnie w domu buduję sobie sieć Casambi z czujnikami (m. in. wilgotności, PM 2.5, PM 10, temperatury). Chciałbym jeszcze dokupić czujnik temperatury na ZigBee, który znajdzie się gdzieś na balkonie (w tym celu zakupiłem już na Aliexpress układ CC2530, który wymaga jeszcze zmiany firmware). Wszystkie dane z czujników planuję gromadzić w bazie danych na serwerze i w jakiś fajny sposób je wizualizować. Zobaczymy co tam do tego czasu jeszcze mi do głowy przyjdzie 🙂

HubScreen – podsumowanie projektu

Wstęp

Projekt HubScreen, pozwalający na szybkie poranne sprawdzenie prognozy pogody oraz drogi do pracy, zakończony 🙂

Po tygodniach prac i zmian udało się uzyskać efekt widoczny na poniższych zdjęciach:

Ekran podczas normalnej pracy
Czego normalnie nie widać 😉

Zmiany względem pierwotnego planu

Ekran miał wisieć w przedpokoju – niestety ilość elementów przyklejona na gorąco nie pozwala na powieszenie w dedykowanym miejscu. Konieczne będzie wykonanie obudowy na drukarce 3D jak już się którejś dorobię 😉

Oszczędzanie energii miało działać w oparciu o czujkę PIR – niestety z racji umieszczenia ekranu w salonie niemożliwym było wykorzystanie czujki PIR, bo byłaby aktywowana przez każdą przebywającą tam osobę. Z tego powodu postanowiłem zamienić czujkę na przycisk, który umieściłem w kartoniku. Dzięki temu ekran uruchamia się po wciśnięciu przycisku (kiedyś popracuję nad estetyką tego rozwiązania) i wyłącza się po minucie bezczynności (możliwe to było poprzez włączanie i wyłączanie wyjścia HDMI za pomocą narzędzia vcgencmd i manipulacji parametru display_power – szczegóły w kodzie źródłowym aplikacji PIRScreenControl).

Miała zostać wykorzystana przeglądarka Chromium – okazało się, że wydajność RPi Zero WH jest daleka od oczekiwań i w przypadku przeglądarki Chromium cała strona ulegała zawieszeniu po pewnym czasie działania. Dodatkowo opracowałem aplikację, która na podstawie stanu wyjścia HDMI minimalizowała lub maksymalizowała okno przeglądarki Chromium (w opraciu o xdotool), a skrypty JS strony WWW zatrzymywały lub wznawiały odświeżanie iframe’ów w zależności od stanu okna, ale niestety taka operacja była bardziej wymagająca dla RPi niż nicnierobienie. Ostatecznie po uruchomieniu systemu otwieram stronę WWW w trybie pełnoekranowym przeglądarki surf i pomimo opóźnienia (bazując na wyświetlanym zegarze w JS) kilku sekund całość działa w sposób akceptowalny. Gdybym mógł dograć do przeglądarki uBlock’a to zapewne działałoby to lepiej, ale nie widziałem takiej możliwości, więc muszę poczekać aż wgram sobie Pi-hole’a na domowy router.

Typowe zużycie zasobów podczas pracy ekranu

Dodatkową energooszczędność (i zabezpieczenie przed awaryjną elektroniką z Chin 😉 ) uzyskuję dzięki inteligentnemu gniazdku, które o północy się wyłącza i włącza z rana, gdy przychodzi pora do wstawania.

A więc jak to ostatecznie działa?

RPi po uruchomieniu systemu wyłącza wyjście HDMI (a więc przy okazji ekran LCD) oraz otwiera przeglądarkę internetową ze stroną internetową znajdującą się na lokalnym serwerze Apache. W ramach tej strony wyświetlane są 3 elementy:

  • Prognoza pogody Google – iframe z wyszukiwarką Google dla hasła „pogoda Gdańsk”. Po wszystkim iframe jest odpowiednio manipulowany, aby wyświetlać na ekranie tylko prognozę pogody.
  • Trasę dojazdu Google Mapy – iframe z Mapą Google wytyczającą najszybszą trasę pomiędzy dwoma punktami. Darmowy iframe można uzyskać poprzez wyznaczenie trasy w zwykłych Mapach Google, wyświetlenie szczegółów jednej z dostępnych tras, a następnie wybranie opcji umieszczania mapy w postaci iframe’a.
  • Godziny odjazdów z wybranego przystanku autobusowego – tabela generowana dzięki projektowi ztmGdanskDepartureBoardParser.

Do włączenia ekranu wykorzystywany jest zwykły przycisk monostabilny NO, którego stan jest odczytywany dzięki przerwaniom pochodzących z biblioteki wiringPi.

Podczas bardzo prostych pomiarów okazało się, że dziennie ekran zużywa ok. 60-70 MB transferu internetowego i 0.01-0.02 kW energii (chociaż wartość jest tak niska, że nie wiem czy nie jest to błąd pomiaru).

Wykorzystany sprzęt i poniesione koszty

  • Ekran LCD Samsung LTN156AT01-U01 – bezpłatnie (z elektrośmieci po starym laptopie)
  • Kontroler ekranu LCD – ~75 zł (Aliexpress)
  • Raspberry Pi Zero WH – 59,90 zł (Botland)
  • Przewód miniHDMI <-> HDMI – 19,90 zł (Komputronik)
  • Zasilacz 12 V 5 A 60 W – 19,50 zł (Allegro)
  • Przetwornica step-down LM2596 3,2-35V 3A Arduino – 3,79 zł (Allegro)
  • Radiatory – ~1,83 zł (Aliexpress)

RAZEM: ~179,92 zł

Kody źródłowe i opracowane pliki

Kody źródłowe i opracowane pliki

PIRScreenControl

Wnioski

  • Raspberry Pi Zero ZH nie nadaje się do pracy z GUI i stronami WWW bazującymi na skryptach JavaScript – do mojego zastosowania RPi działało „na styk”, ale z rozbudową projektu mogą w przyszłości być problemy. Zapewne wystarczyłoby opracowanie aplikacji przetwarzających i/lub prezentujących w prostszy sposób potrzebne informacje, ale wtedy potrzebowałbym chmury Google, a to już nie byłoby darmowe jak w obecnej postaci 😉
  • Układ SMD LM317 w obudowie TO-252, który podebrałem z dawnego robota Minisumo nie nadaje się do zasilania RPi (zamiana 12 V DC na 5 V DC) ze względu na problemy z oddawaniem ciepła (nawet z radiatorem) – niby problemów z działaniem nie było, ale temperatura pracy na zbyt długo nie pozwoliłaby mi się nacieszyć projektem, więc LM317 zamieniłem na LM2596.

Projekt chciałbym w przyszłości rozbudować o obsługę czujników temperatury i otwartych okien na WiFi/BT, ale pewnie trzeba będzie wszystko zacząć od wymiany RPi na mocniejszą wersję.

HubScreen – część wizualna zrobiona

Udało się opracować część programistyczną: stronę WWW wyświetlającą pogodę, trasę dojazdu do pracy i estymowane czasy odjazdów z wybranego przystanku komunikacji miejskiej (wszystko oparte na HTML’u i JavaScipt’ie) oraz usługę (opracowaną w C++ i wykorzystującą wiringPi) odpowiedzialną za włączanie i wyłączanie portu HDMI w zależności od stanu czujki ruchu (kod źródłowy znajduje się tutaj).

Teraz pozostało tylko zadbać o odpowiednie zasilanie (dawny robot minisumo postanowił zostać dawcą), wszystko połączyć i złożyć w jedną całość – szykuje się pracowity weekend 😉

PLCino – opis projektu

Skąd pomysł na projekt?

Od czasów szkoły średniej uwielbiałem programować sterowniki PLC. Powodem takiego stanu rzeczy był fakt, że chodziłem do technikum mechatronicznego i intensywnie pracowaliśmy na sterownikach PLC ze względu na nadchodzący egzamin zawodowy. Również kadra nauczycielska, która posiadała wykształcenie elektryczne, potrafiła posługiwać się głównie tylko graficznymi językami programowania, czyli np. językiem drabinkowym.

Na moich studiach dodatkowo wkręciłem się w „konwencjonalne” programowanie, czyli języki C/C++. Dlatego, gdy przyszedł czas wyboru tematu pracy inżynierskiej, po wcześniejszym pobieżnym research’u w wyniki którego nie znalazłem podobnego rozwiązania, postanowiłem opracować aplikację dla układów Arduino pozwalającą na programowanie w języku drabinkowym.

O aplikacji

Zadaniem aplikacji jest umożliwienie programowania układów Arduino (Leonardo, Nano, Mega) w języku drabinkowym, który stosowany jest głównie przy programowaniu sterowników PLC. PLCino do działania wymaga uprawnień administratora, ponieważ umożliwia kompilowanie kodu i programowanie układów Arduino z poziomu edytora.

Zaimplementowane elementy języka drabinkowego to:

  • styki,
  • cewki,
  • liczniki,
  • timery,
  • operatory porównania.

Aplikacja została opracowana z wykorzystaniem bibliotek Qt w wersji 5.9.1. Przy próbach kompilacji za pomocą nowszych wersji występowały wyjątki przy korzystaniu z funkcji dostarczanych przez biblioteki.

Wadą aplikacji było opracowywanie jej w czasach, gdy prowadzący nie widzieli problemów z nazewnictwem zmiennych czy funkcji w języku polskim (do dzisiaj te długie nazwy kłują mnie po oczach).

Innym problemem była biblioteka Qt. Wtedy wydawało mi się, że jest to coś idealnego dla języka C++, ponieważ pozwalała wykorzystać wspomniany język w operacjach niskopoziomowych jak i wysokopoziomowych (czyli w tym przypadku dobrze wyglądającym GUI – nie to co Windows Forms). Wartością dodaną miała być wieloplatformowość pozwalająca na proste przeniesienie aplikacji PLCino na systemy linux. Niestety ze względu na wykorzystanie aplikacji avrdude nie było to możliwe – gdy chciałem rozbudowywać mój projekt okazało się, że Qt staje się coraz mniej open source i przez to nieznana była przyszłość tych bibliotek, więc postanowiłem wstrzymać się z dalszymi pracami i poczekać, aż sytuacja się wyjaśni.

Aplikacja w obecnej postaci pozwala na programowanie układów Arduino (bezpośrednio z poziomu edytora):

  • Leonardo,
  • Nano,
  • Mega.

TODO

  • Dodanie obsługi kolejnych układów Arduino
  • Dodanie obsługi kolejnych elementów języka drabinkowego
  • Oczyszczenie aplikacji avrdude ze zbędnych bibliotek i kodów źródłowych

Jak używać aplikacji?

Na moim GitHub’ie można znaleźć instalator aplikacji, który jak zawsze został opracowany za pomocą kreatora Inno Setup. Instaluje w systemie operacyjnym aplikację PLCino wraz z niezbędnymi bibliotekami. W przypadku problemów z działaniem należy uruchomić aplikację z uprawnieniami administracyjnymi.

W katalogu „przyklady” (znajdującym się w tym samym katalogu co plik wykonywalny PLCino.exe) można znaleźć przykładowe programy, które prezentują funkcjonalność aplikacji.

Do obwodów tworzonych w aplikacji elementy drabinki dodaje się poprzez wykorzystanie techniki przeciągnij&upuść (drag&drop). Edycji właściwości elementu można dokonać poprzez dwukrotne kliknięcie LPM (lewym przyciskiem myszy) na elemencie w wybranym obwodzie.

Zrzuty ekranu

Kody źródłowe

Kody źródłowe

Aplikacja

Aplikacja