Masz wrażenie, że Twoja malinka “myśli w Pythonie” i zastanawiasz się, czy Raspberry Pi to to samo co Python? Z tego tekstu dowiesz się, jak to naprawdę wygląda, jak łączy się Raspberry Pi z językiem Python i co zrobić, żeby budować sensowne aplikacje sterujące i HA na RPi. Przy okazji dostaniesz konkretne wskazówki, jak ogarnąć pętle, wątki i instalację Home Assistanta.
Czym jest Raspberry Pi, a czym jest Python?
Raspberry Pi to mały komputer jednopłytkowy, na którym uruchamiasz system operacyjny (np. Raspberry Pi OS, dawniej Raspbian). Python to język programowania wysokiego poziomu. Nie są tym samym. Raspberry Pi to sprzęt, system i GPIO. Python to narzędzie, którym sterujesz tym sprzętem. Możesz zainstalować na RPi różne języki: Python, C++, a nawet środowiska typowo PLC, ale malinka sama z siebie “nie jest Pythonem”.
W praktyce wygląda to tak: system Raspberry Pi OS instaluje interpreter Pythona (często Python 3.9 lub 3.11 w nowszych wydaniach), a Ty piszesz kod, który ten interpreter uruchamia. To dlatego na forach pojawia się tyle pytań o python3.8 -m venv i wersje Pythona – to zależy od tego, jaka wersja jest dostępna w systemie i jak został skonfigurowany PATH. Raspberry Pi nie ogranicza Cię do jednego języka, ale Python jest najczęściej wybierany, bo ma ogromne wsparcie bibliotek, też dla GPIO i automatyki.
Raspberry Pi to platforma sprzętowa, a Python to wygodny język, który tę platformę “ożywia” – szczególnie gdy chodzi o GPIO, sterowanie i prototypy automatyki.
W automatyce łatwo to porównać: PLC to trochę “Raspberry Pi + system RT + środowisko LAD/FBD/ST”. Python na RPi to z kolei “język wysokiego poziomu + system ogólnego przeznaczenia”, co daje sporą elastyczność, ale wymaga innego podejścia niż OB Main w Siemensie.
Jak zaprojektować pętlę główną na Raspberry Pi w Pythonie?
W sterownikach Siemens czy Codesys pracujesz zwykle z OB Main albo cyklicznym programem, który wykonuje się w pętli, z pewnym czasem cyklu. Na Raspberry Pi w Pythonie robisz bardzo podobnie, tylko musisz sam zadbać o to, żeby pętla była stabilna i nie zjadała 100% CPU. Najprostszy schemat, który większość osób testuje na początku, to:
while True + sleep() – klasyka Pythona na RPi. W każdej iteracji pętli odczytujesz wejścia GPIO, przeliczasz logikę, sterujesz wyjściami, a na końcu dajesz time.sleep(), żeby procesor miał oddech i żeby cykl był w miarę powtarzalny.
Żeby to miało sens w automatyce, dobrze jest narzucić sobie docelowy czas cyklu. Przykładowo, jeśli chcesz mieć “skan” zbliżony do 10 ms, to:
- mierzysz czas rozpoczęcia cyklu,
- wykonujesz logikę,
- obliczasz ile czasu zostało do zadanych 10 ms,
- śpisz tylko tyle, ile trzeba, żeby całkowity czas cyklu był zbliżony do 10 ms.
Taka prosta pętla nie zrobi z Raspberry Pi systemu real-time jak PLC z RTOS, ale przy rozsądnej logice potrafi dać stabilny cykl, wystarczający do wielu zadań: sterowanie silnikami krokowymi, reagowanie na przyciski, przełączanie wyjść cyfrowych. Trzeba tylko pilnować, żeby w pętli nie uruchamiać ciężkich operacji jak IO dyskowe albo zbyt częste odświeżanie GUI.
Jak unikać nadmiernego obciążenia procesora?
Gdy w kodzie Pythona zrobisz while True bez sleep(), procesor szybko dobije do 100% użycia. W PLC masz “z góry” narzucony czas cyklu i system dba o zadania w tle. Na Raspberry Pi Ty musisz to zaplanować. Dobrą praktyką jest rozdzielenie cyklicznej logiki sterującej od innych zadań, które nie muszą działać tak często, na przykład:
W jednej pętli wątku głównego możesz skupić się na:
- odczycie stanów wejść cyfrowych GPIO,
- przeliczeniu logiki sterowania (np. kierunek, kroki, limity),
- wysterowaniu wyjść (GPIO.output),
- krótkim sleepie rzędu 5–20 ms.
W drugim wątku, albo w timerach GUI, warto wykonywać czynności rzadziej: odświeżanie wizualizacji, zapis do JSON lub SQL, komunikację sieciową. Takie rozwiązanie zmniejsza ryzyko, że nagły skok obciążenia GUI zniszczy płynność ruchu silników krokowych.
Jak połączyć pętlę nieskończoną z obsługą zdarzeń?
W PLC kliknięcie przycisku to często po prostu zmiana bitu na wejściu. W Pythona i GUI (np. Qt) wchodzi dodatkowo model zdarzeniowy: przycisk GUI generuje sygnał, zdarzenie z klawiatury czy myszy wywołuje callback. Jak to sensownie połączyć z pętlą typu OB Main?
Jedno podejście jest takie: logika sterująca działa w tle jako osobny wątek, a GUI w Qt korzysta z pętli zdarzeń frameworka. Gdy wciśniesz przycisk “X+”, handler przycisku zmienia stan zmiennej, np. x_plus_pressed = True. Wątek sterujący w każdej iteracji pętli sprawdza tę zmienną i jeśli jest True, generuje kroki dla silnika krokowego tak długo, aż przycisk zostanie puszczony. I odwrotnie – zwolnienie przycisku zmienia zmienną na False i pętla przestaje generować ruch.
Podobną logikę możesz zastosować dla wejść cyfrowych GPIO. W PLC co skan odczytujesz wejścia. Na RPi w Pythonie robisz to samo w pętli, a jeśli zależy Ci na reakcji natychmiastowej, warto sięgnąć po przerwania GPIO (np. w bibliotece RPi.GPIO lub gpiozero), które wywołują callback, gdy stan wejścia się zmienia.
Jak zbliżyć się do czasu rzeczywistego na Raspberry Pi?
Raspberry Pi z Linuxem nie jest twardym systemem czasu rzeczywistego. I nie stanie się nim tylko dlatego, że piszesz w C++ zamiast w Pythonie. Ale możesz dobrać techniki, które ograniczą opóźnienia i jitter na tyle, że dla wielu projektów automatyki będzie to całkowicie wystarczające. Z punktu widzenia automatyka szczególnie istotne są:
priorytety procesów, prosty model zadań i ograniczenie ilości “śmieci” w tle. Odinstalowanie zbędnych usług, wyłączenie ciężkich środowisk graficznych albo przesunięcie ich na inny komputer HMI potrafi zrobić różnicę. Sterowanie możesz zostawić na gołym Raspberry Pi OS Lite, a GUI odpalić jako zdalną wizualizację.
W samej aplikacji w Pythonie pomoże:
- jak najmniej operacji blokujących w pętli sterującej,
- brak długich operacji sieciowych w głównym wątku,
- oddzielenie GPIO od interfejsu użytkownika,
- możliwie prosta logika sterowania bez rekursji i skomplikowanych struktur.
Jeśli naprawdę zależy Ci na bardzo krótkich czasach reakcji, możesz użyć hybrydy: krytyczne elementy napisać w C/C++ (np. jako moduł Pythona), a część “nad sterownikiem” w Pythonie. W świecie hobbystycznym często wystarcza jednak dobrze napisana pętla w Pythonie z rozsądnym time.sleep().
Multiprocessing, threading czy jedno procesowe podejście?
Wspomniałeś o multiprocessing i threading. To dwie różne drogi. Threading tworzy wątki w ramach jednego procesu, dzielące pamięć i zasoby. W Pythonie blokuje je GIL, ale do I/O (GPIO, sieć, pliki) wątki sprawdzają się całkiem dobrze. Multiprocessing tworzy osobne procesy z osobną pamięcią i komunikacją między nimi. Jest cięższy, ale potrafi lepiej wykorzystać kilka rdzeni.
Na Raspberry Pi, szczególnie słabszych modelach, zwykle wystarcza:
- jeden wątek na logikę sterowania i odczyt GPIO,
- wątek GUI (Qt) zarządzany przez sam framework,
- ewentualnie dodatkowy wątek na zadania okresowe, np. zapis do JSON lub SQL.
Dopiero gdy logika robi się bardzo ciężka obliczeniowo, warto sięgnąć po multiprocessing. Dla typowych projektów “2 silniki krokowe + kilka wejść” zwykle nie jest to konieczne. Taki podział zadań pomaga zachować czytelność kodu i łatwiej go debugować niż jedną wielką pętlę z dziesiątkami stanów.
Jak odświeżać GUI i sterować z Qt na Raspberry Pi?
Qt to solidne środowisko do budowy interfejsu HMI na Raspberry Pi. Możesz je łączyć z Pythonem (PyQt, PySide) lub z C++. Niezależnie od wyboru języka, logika jest podobna: Qt ma własną pętlę zdarzeń, która dba o obsługę przycisków i odświeżanie ekranu. Twoim zadaniem jest zsynchronizować ją z logiką sterującą.
Dobrym wzorcem jest podejście “sterownik w tle, GUI jako klient”. Aplikacja HMI po stronie Qt nie steruje silnikami krokowymi bezpośrednio. Zamiast tego ustawiasz zmienne sterujące i odczytujesz stany, które obsługuje wątek logiki. W Pythonie zwykle realizujesz to przez zwykłe zmienne i blokady, a w C++ czasem przez sygnały/sloty lub kolejki zdarzeń.
Jak często odświeżać wizualizację GUI?
W PLC ustawiasz czas odświeżania HMI na 100 ms, 500 ms czy 1 s. W Qt masz do dyspozycji np. QTimer, który wywołuje funkcję co zadany czas. Dobre ustawienia to:
Dla wartości procesowych (np. prędkości, pozycje, stany wejść) zwykle wystarcza 100–200 ms. Dla danych archiwalnych czy energii spokojnie starczy 1 s lub dłużej. Za częste odświeżanie tylko niepotrzebnie obciąża procesor i generuje mruganie, które i tak nie jest zauważalne dla użytkownika.
Odświeżanie GUI nie powinno nigdy zatrzymywać logiki sterującej. Dlatego nie wywołuj blokujących funkcji w handlerach sygnałów Qt. Lepiej trzymać dane stanu w lekkich strukturach, a w GUI tylko je odczytywać. Gdy musisz coś policzyć dłużej, przenieś to do osobnego wątku, a do GUI wyślij gotowy wynik.
Jak obsłużyć przyciski typu “X+” w GUI?
Twój przykład z przyciskiem “X+” to klasyczne zadanie z automatyki HMI: napęd ma jechać tak długo, jak długo przycisk jest wciśnięty. W Qt można to zrobić na kilka sposobów. Jedna z prostszych dróg to:
Przypisujesz do przycisku akcje:
- onPressed – ustawiasz we wspólnej strukturze x_plus_pressed = True,
- onReleased – ustawiasz x_plus_pressed = False,
- wątki sterowania w pętli sprawdzają ten stan i generują kroki tak długo, jak zmienna jest True.
Dzięki temu GUI sygnalizuje tylko intencję użytkownika, a całą “precyzję” ruchu bierze na siebie kod sterujący. Masz wtedy bardzo podobny model jak w PLC: przycisk to bit, który “żyje” tak długo, jak jest fizycznie wciśnięty. Aplikacje w Pythonie czy C++ mogą w prosty sposób odwzorować ten schemat, jeśli trzymasz się zasady rozdziału warstwy prezentacji i sterowania.
Jak przechowywać zmienne podtrzymywane na Raspberry Pi?
W świecie PLC mówisz o zmiennych podtrzymywanych, które zachowują się nawet po zaniku zasilania. Na Raspberry Pi nie masz tego w standardzie, ale szybko możesz to zasymulować. Popularne formaty to txt, JSON, pickle i SQL. Każde z nich ma swoje plusy i minusy, które warto uporządkować.
Dobrym sposobem, żeby zebrać to w jedno miejsce, jest prosta tabela porównawcza:
| Format | Zastosowanie | Zalety / wady |
| TXT | Proste listy wartości | Łatwy do odczytu, ale brak struktury |
| JSON | Ustawienia, parametry, stany | Czytelny, obsługa w Pythonie, dobry do konfiguracji |
| Pickle | Serializacja obiektów Pythona | Bardzo wygodny, ale mały poziom przenośności i bezpieczeństwa |
| SQL (SQLite) | Historia danych, logi, długoterminowe archiwum | Struktura, zapytania, ale trochę więcej kodu na start |
Dla zmiennych podtrzymywanych – jak ostatnia pozycja osi, parametry ruchu czy stany liczników – najlepiej sprawdza się JSON lub mała baza SQLite. JSON jest prosty i bardzo dobrze wspierany w Pythonie. Ustawiasz słownik, zapisujesz go na koniec programu lub co kilka sekund. Po starcie odczytujesz plik i bezpośrednio wypełniasz swoje zmienne.
Jeśli chcesz przechowywać dłuższą historię, np. logi z Home Assistanta, odczyty z czujników czy zdarzenia, lepiej od razu sięgnąć po SQL – chociażby w wersji SQLite dostępnej w standardowej bibliotece Pythona. Dzięki temu łatwo analizujesz dane i przenosisz je na inny system, co dla automatyka bywa bardzo wygodne przy diagnostyce.
Jak poprawnie zainstalować Home Assistant na Raspberry Pi OS?
Instalacja Home Assistant na Raspberry Pi to osobny temat, ale łączy się bezpośrednio z Pythonem i wersjami interpretera. W pytaniach na forach bardzo często pojawia się komenda python3.8 -m venv . i problemy typu “zmieniłem na 3.9, raz zadziałało, po restarcie cisza”. To zwykle sygnał, że:
wersja Pythona w systemie nie zgadza się z wersją używaną w poradniku. Raspberry Pi OS bywa aktualizowany, więc starszy artykuł może zakładać Pythona 3.8, a w Twoim obrazie jest już 3.9 albo 3.11. Wtedy wirtualne środowisko tworzone inną wersją niż ta zainstalowana globalnie potrafi się zachowywać dziwnie po restarcie, zwłaszcza gdy PATH nie jest ustawiony na binarkę z venv.
Bez wchodzenia w szczegóły konkretnych poradników, przy instalacji HA na Raspberry Pi OS warto dopilnować kilku rzeczy:
- sprawdź, jaką wersję Pythona naprawdę masz – python3 –version,
- twórz venv tą samą wersją, której używasz do uruchamiania HA,
- po restarcie zawsze aktywuj venv, zanim wpiszesz komendę hass,
- upewnij się, że hass jest w PATH aktywnego venv, a nie w innym katalogu,
- rozważ uruchamianie HA jako usługa systemd, żeby startował po bootowaniu.
Trochę inaczej wygląda sytuacja, gdy wybierasz instalację w Dockerze lub Home Assistant OS. Ty wskazałeś, że wolisz instalację bez Dockera, bo obawiasz się narzutu. Docker faktycznie wprowadza pewną warstwę abstrakcji, ale na nowszych RPi często jest akceptowalny. Jeśli jednak stawiasz na “goły” Raspberry Pi OS, trzeba szczególnie pilnować wersji Pythona i środowisk wirtualnych.
Komenda python3.8 -m venv z poradnika zadziała tylko wtedy, gdy rzeczywiście masz zainstalowanego Pythona 3.8. Jeśli system dostarcza 3.9 lub 3.11, lepiej użyć python3 -m venv i oprzeć się na domyślnej wersji.
Dodatkowo warto zaplanować, gdzie fizycznie instalujesz Home Assistanta. Osobny katalog na HA, jedno venv tylko dla tej aplikacji i skrót/alias do uruchamiania ułatwiają późniejszą diagnostykę. Jeśli po restarcie HA się nie ładuje, zwykle wystarczy aktywować venv i uruchomić hass ręcznie, żeby zobaczyć błędy na konsoli.
Raspberry Pi nie jest Pythonem, ale Python jest mocnym sprzymierzeńcem na malince – zarówno przy prostych projektach automatyki z GPIO, jak i przy budowie domowego systemu Home Assistant. Dobrze rozdzielone pętle, przemyślane wątki i świadomy dobór wersji Pythona sprawiają, że malinka zaczyna zachowywać się dużo bardziej “jak PLC”, nawet jeśli pod spodem cały czas działa zwykły Linux.