Wróć do katalogu
Season 47 7 Odcinki 28 min 2026

CircuitPython

Wersja 10.1 — Edycja 2026. Techniczny kurs audio omawiający CircuitPython, doświadczenie programisty, architekturę, sterowanie sprzętem oraz skalowanie za pomocą Blinka. Zaktualizowano dla wersji 10.1 (2026).

Systemy wbudowane Mikrokontrolery
CircuitPython
Teraz odtwarzane
Click play to start
0:00
0:00
1
Dysk CIRCUITPY
Ten odcinek wprowadza w CircuitPython i jego unikalny przepływ pracy oparty na pamięci masowej USB. Słuchacze dowiedzą się, jak zapisanie prostego pliku tekstowego natychmiast uruchamia kod na mikrokontrolerze, bez potrzeby używania kompilatorów czy narzędzi do flashowania.
4m 01s
2
Sprzęt jako kod
Zanurz się we wbudowanych modułach, które dają CircuitPython moc kontrolowania fizycznego świata. Słuchacze dowiedzą się, jak wchodzić w interakcję z fizycznymi pinami sprzętowymi za pomocą modułów board, digitalio oraz time.
4m 10s
3
Konsola szeregowa i REPL
Odkryj interaktywne debugowanie w CircuitPython za pomocą konsoli szeregowej (Serial Console) oraz Read-Evaluate-Print-Loop (REPL). Słuchacze dowiedzą się, jak wstrzymać wykonywanie kodu i sterować swoim sprzętem na żywo.
3m 58s
4
Ekosystem bibliotek
Zarządzaj zewnętrznymi zależnościami w CircuitPython za pomocą pakietu bibliotek. Słuchacze poznają kluczową różnicę między surowymi plikami Pythona a skompilowanym kodem bajtowym (bytecode), aby zoptymalizować zużycie pamięci.
3m 36s
5
Zamrożone biblioteki
Odkryj magię zamrożonych bibliotek w CircuitPython dla płytek o ograniczonej pamięci. Słuchacze zrozumieją priorytety plików bibliotek oraz to, jak moduły wbudowane w firmware zwalniają miejsce w systemie plików.
3m 48s
6
CircuitPython vs MicroPython
Przeanalizuj różnice architektoniczne między CircuitPython a jego projektem macierzystym, MicroPython. Słuchacze dowiedzą się, dlaczego Adafruit stworzyło fork tego języka, aby zbudować ujednolicone, przyjazne dla początkujących API sprzętowe.
4m 13s
7
Blinka i komputery jednopłytkowe
Skaluj swój kod CircuitPython na pełnoprawne maszyny z systemem Linux za pomocą Adafruit Blinka. Słuchacze dowiedzą się, jak ta warstwa kompatybilności pozwala na używanie API mikrokontrolerów na komputerach jednopłytkowych, takich jak Raspberry Pi.
4m 19s

Odcinki

1

Dysk CIRCUITPY

4m 01s

Ten odcinek wprowadza w CircuitPython i jego unikalny przepływ pracy oparty na pamięci masowej USB. Słuchacze dowiedzą się, jak zapisanie prostego pliku tekstowego natychmiast uruchamia kod na mikrokontrolerze, bez potrzeby używania kompilatorów czy narzędzi do flashowania.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. CircuitPython, odcinek 1 z 7. Jeśli przychodzisz ze świata tradycyjnych systemów embedded, konfiguracja toolchaina zazwyczaj zajmuje więcej czasu niż napisanie pierwszego programu. Spędzasz godziny, walcząc z kompilatorami, sterownikami urządzeń i dedykowanymi narzędziami do flashowania, żeby przetestować jedną linijkę logiki. Dysk CIRCUITPY pozwala to wszystko całkowicie pominąć. Programiści embedded, zaczynając nowy projekt, często instynktownie szukają flash toola, kompilatora albo konkretnego IDE. Z CircuitPythonem wcale ich nie potrzebujesz. Nie ma tu etapu kompilacji. Proces deployu jest obsługiwany przez system plików twojego systemu operacyjnego. Kiedy podłączasz mikrokontroler kompatybilny z CircuitPythonem do komputera kablem USB, płytka przedstawia się w systemie operacyjnym jako standardowe urządzenie pamięci masowej USB. Ten dysk wymienny montuje się automatycznie i nazywa się CIRCUITPY. Dla twojego komputera, niezależnie czy używasz Windowsa, macOS, czy Linuxa, wygląda to dokładnie jak zwykły pendrive. Możesz go otworzyć w eksploratorze plików, przeglądać zawartość i ją modyfikować. Najważzym plikiem na tym dysku jest plik tekstowy, zazwyczaj o nazwie code.py. Ten plik działa jako entry point dla twojej aplikacji. Możesz go otworzyć w dowolnym standardowym edytorze tekstu. Nie potrzebujesz do tego specjalistycznej aplikacji; zwykły edytor tekstu sprawdzi się idealnie. Kiedy piszesz prosty program — na przykład pętlę, która wypisuje tekst albo wchodzi w interakcję z płytką — i wciskasz zapisz, cykl deployu rozpoczyna się automatycznie. I tu jest kluczowa sprawa. Nie musisz klikać przycisku build ani uruchamiać narzędzia z linii komend, żeby wrzucić kod na sprzęt. W momencie, gdy zapisujesz plik, mikrokontroler wykrywa aktywność systemu plików przez połączenie USB. To zachowanie jest napędzane przez mechanizm o nazwie auto-reload. CircuitPython aktywnie monitoruje stan połączenia pamięci masowej USB. Kiedy inicjujesz operację zapisu w edytorze tekstu, komputer zapisuje dane na dysku CIRCUITPY. CircuitPython czeka, aż zapis w systemie plików zostanie zakończony. Kiedy zapis pliku dobiegnie końca, system auto-reload wyzwala soft reboot mikrokontrolera. Ten soft reboot jest niezwykle szybki. Przerywa wszystko, co mikrokontroler w danej chwili robił, bezpiecznie zamyka obecny stan i całkowicie czyści pamięć. Następnie natychmiast parsuje i wykonuje nowo zapisany plik code.py od początku. Mechanizm auto-reload tworzy bardzo ciasną pętlę iteracji. Edytujesz kod, zapisujesz plik i obserwujesz reakcję sprzętu w mniej niż sekundę. Jeśli w nowo zapisanym kodzie jest błąd składniowy, wykonywanie zostaje bezpiecznie zatrzymane. Możesz zobaczyć output błędu przez połączenie szeregowe. Poprawiasz literówkę, ponownie zapisujesz plik, a płytka natychmiast się rebootuje, żeby wypróbować zaktualizowany kod. Dysk CIRCUITPY to również mechanizm do zarządzania zależnościami. Jeśli twój projekt wymaga zewnętrznego kodu pomocniczego dla konkretnego sprzętu, nie używasz package managera z linii komend. Po prostu przeciągasz i upuszczasz potrzebne pliki bibliotek bezpośrednio do dedykowanego folderu o nazwie lib na dysku CIRCUITPY. System auto-reload śledzi zmiany również w tym katalogu. Zanim skończymy, jeśli podobają ci się te techniczne odcinki i chcesz wesprzeć program, możesz wyszukać DevStoriesEU na Patreonie. Fundamentalna zmiana polega na tym, że sam system plików działa jako deployment pipeline, zamieniając każdą maszynę z podstawowym edytorem tekstu i portem USB we w pełni funkcjonalną stację roboczą do developmentu embedded, bez instalowania ani jednego sterownika. To wszystko w tym odcinku. Dzięki za wysłuchanie i koduj dalej!
2

Sprzęt jako kod

4m 10s

Zanurz się we wbudowanych modułach, które dają CircuitPython moc kontrolowania fizycznego świata. Słuchacze dowiedzą się, jak wchodzić w interakcję z fizycznymi pinami sprzętowymi za pomocą modułów board, digitalio oraz time.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. CircuitPython, odcinek 2 z 7. Piszesz skrypt, który włącza światło, zapisujesz plik, a światło miga przez ułamek sekundy, po czym natychmiast gaśnie. Twój kod jest całkowicie poprawny. Problem polega na tym, że gdy skrypt dobiegnie końca i zakończy działanie, system automatycznie resetuje stan sprzętu. Aby urządzenie działało, musisz uniemożliwić zakończenie skryptu. Tu właśnie pojawia się koncepcja Hardware as Code. W tradycyjnym programowaniu twój kod manipuluje danymi w pamięci. W programowaniu wbudowanym kod manipuluje fizycznymi sygnałami elektrycznymi. CircuitPython ukrywa tę złożoność, wykorzystując trzy wbudowane moduły: board, digitalio i time. Nie musisz ich instalować. Są one wbudowane bezpośrednio w firmware. Moduł board działa jak mapa sprzętowa dla twojego konkretnego mikrokontrolera. Wie, który wewnętrzny routing odpowiada fizycznym pinom. Odwołując się do board dot LED, pobierasz prawidłowy adres sprzętowy wbudowanej diody, niezależnie od tego, jaki fizyczny model płytki masz w rękach. Moduł digitalio udostępnia klasy potrzebne do sterowania przepływem prądu. Tłumaczy obiekty Pythona na sygnały cyfrowe. Na koniec, moduł time zarządza tempem. Mikrokontrolery wykonują miliony instrukcji na sekundę. Bez modułu time, który pauzuje wykonywanie kodu, migająca dioda przełączałaby się tak szybko, że dla ludzkiego oka wyglądałaby na stale przyciemnioną. Oto, jak te trzy moduły współpracują ze sobą, aby wbudowana dioda LED zaczęła migać. Najpierw importujesz board, digitalio i time. Następnie konfigurujesz sprzęt. Tworzysz nowy obiekt za pomocą klasy DigitalInOut z modułu digitalio i przekazujesz mu pin board dot LED. Teraz masz obiekt Pythona reprezentujący to konkretne fizyczne połączenie. Piny mogą albo nasłuchiwać prądu wchodzącego, albo wysyłać prąd na zewnątrz. Musisz jawnie wskazać CircuitPythonowi, co ten pin ma robić. Ustawiasz właściwość direction swojego nowego obiektu pinu na output. To mówi mikrokontrolerowi, aby podał napięcie na diodę LED. Oto kluczowa sprawa. Po skonfigurowaniu pinu jako output, sterowanie fizycznym sygnałem elektrycznym wygląda dokładnie tak samo, jak przypisanie wartości do zmiennej. Aby włączyć diodę LED, ustawiasz właściwość value obiektu pinu na True. Pod spodem CircuitPython przekształca to proste przypisanie typu boolean na sygnał wysokiego napięcia, przepuszczając prąd przez obwód i zapalając diodę LED. Aby ją wyłączyć, ustawiasz właściwość value na False, co powoduje spadek napięcia do zera. Wróćmy teraz do problemu, od którego zaczęliśmy. Jeśli po prostu ustawisz wartość na True, a potem na False, skrypt się zakończy. CircuitPython sprząta po sobie, resetując wszystkie piny, i twoja płytka przestaje działać. Aby dioda LED migała nieprzerwanie, musisz uwięzić sekwencję wykonywania kodu. Zamykasz swoje polecenia w nieskończonej pętli while True. Wewnątrz tej pętli ustawiasz wartość pinu na True. Następnie używasz time dot sleep, aby wstrzymać skrypt na pół sekundy. Ustawiasz wartość pinu na False. Pauzujesz na kolejne pół sekundy. Ponieważ jest to nieskończona pętla, skrypt nigdy nie dociera do końca, sprzęt nigdy się nie resetuje, a dioda LED miga tak długo, jak płytka ma zasilanie. Pisząc Hardware as Code, nie tylko przesuwasz bajty. Fizycznie otwierasz i zamykasz bramki elektryczne, przypisując True i False do obiektów Pythona. Dzięki za uwagę. Do następnego razu!
3

Konsola szeregowa i REPL

3m 58s

Odkryj interaktywne debugowanie w CircuitPython za pomocą konsoli szeregowej (Serial Console) oraz Read-Evaluate-Print-Loop (REPL). Słuchacze dowiedzą się, jak wstrzymać wykonywanie kodu i sterować swoim sprzętem na żywo.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. CircuitPython, odcinek 3 z 7. Większość debugowania w systemach wbudowanych polega na modyfikowaniu linijki kodu, czekaniu na rekompilację, flashowaniu płytki i liczeniu na to, że twój output log wyłapie buga. A co, gdybyś mógł wstrzymać wykonywanie kodu i sterować sprzętem na żywo? Właśnie na to pozwalają ci Serial Console i REPL. Kiedy podłączasz płytkę CircuitPython do komputera, nawiązuje ona dwukierunkowe połączenie szeregowe przez USB. Możesz uzyskać do niego dostęp używając programu terminalowego, takiego jak PuTTY na Windowsie, albo komendy screen na macOS i Linuxie. Wiele połączeń szeregowych wymaga od ciebie ustawienia konkretnego baud rate, zazwyczaj 115200. CircuitPython tak naprawdę ignoruje to ustawienie przez USB, ale standardową praktyką jest i tak skonfigurowanie twojego terminala na tę prędkość. Serial Console to twoje główne tekstowe okno na płytkę. Za każdym razem, gdy twój skrypt wykonuje instrukcję print, output pojawia się właśnie tutaj. Co ważniejsze, jeśli twój kod napotka fatal error i zcrashuje, Pythonowy traceback zostanie wypisany w tej konsoli. Bez otwartego połączenia szeregowego, zcrashowana płytka nie daje ci żadnych informacji diagnostycznych. Po prostu przestaje działać. Serial Console to także twoja brama do REPL. REPL to skrót od Read, Evaluate, Print, Loop. To interaktywny prompt Pythona działający bezpośrednio na samym chipie mikrokontrolera. Tradycyjny firmware development wymaga pisania kodu na maszynie hosta, kompilowania go i transferowania pliku binarnego. REPL całkowicie zmienia tę dynamikę. Wpisujesz komendę, płytka ją czyta, ewaluuje logikę, printuje wynik i wraca do pętli, czekając na twoją kolejną komendę. Rozważmy praktyczny scenariusz. Masz odpalony skrypt na swojej płytce, ale musisz ustalić, który hardware pin steruje wbudowanym LED-em. Otwierasz swój terminal szeregowy i wciskasz Control C. To natychmiast przerywa działający skrypt. Dostajesz prompt, żeby wcisnąć dowolny klawisz, co wrzuca cię do REPL. Wiesz, że jesteś we właściwym miejscu, kiedy widzisz standardowy prompt Pythona, czyli trzy nawiasy ostre. Teraz wpisujesz import board. Żeby odkryć, jaki hardware jest dostępny, przekazujesz moduł board do wbudowanej funkcji dir. REPL printuje listę nazw wszystkich aktywnych pinów dla twojego konkretnego hardware'u. Widzisz na liście pin LED. Dokładnie tam, w prompcie, importujesz moduł digital IO. Tworzysz obiekt pinu dla LED-a, ustawiasz jego direction na output, a jego value na true. Fizyczny LED na twoim biurku natychmiast się włącza. Właśnie ręcznie wysterowałeś hardware'em, linijka po linijce. Oto kluczowa sprawa. Kod wpisany w REPL jest ulotny. Istnieje tylko w aktywnej pamięci tej konkretnej sesji. Jeśli odłączysz płytkę albo ją zrestartujesz, wszystko, co wpisałeś, znika. REPL to narzędzie do eksploracji. To sandbox, w którym możesz testować limity hardware'u, weryfikować nazwy pinów albo sprawdzać składnię w locie. Kiedy już znajdziesz dokładną sekwencję komend, która osiąga twój cel, musisz ręcznie odtworzyć tę logikę w swoim pliku code dot py na dysku USB, żeby zapisać ją na stałe. Kiedy skończysz testowanie, wychodzisz z REPL i restartujesz swój zapisany kod, wciskając Control D. To wyzwala soft reboot, przeładowując twój plik code dot py od zera. REPL zmienia hardware development z powolnego cyklu zgadywania w natychmiastową, interaktywną eksplorację. Dzięki za wysłuchanie, udanego kodowania wszystkim!
4

Ekosystem bibliotek

3m 36s

Zarządzaj zewnętrznymi zależnościami w CircuitPython za pomocą pakietu bibliotek. Słuchacze poznają kluczową różnicę między surowymi plikami Pythona a skompilowanym kodem bajtowym (bytecode), aby zoptymalizować zużycie pamięci.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. CircuitPython, odcinek 4 z 7. Mikrokontrolery mają niesamowicie ograniczony RAM, co oznacza, że stosunkowo krótki skrypt może nagle wyczerpać całą pamięć i scrashować twojego boarda przed wykonaniem choćby jednego polecenia. Winowajcą jest często sposób, w jaki board przetwarza zewnętrzny kod, który do niego wrzucasz, a rozwiązanie tego bottlenecku pamięci to właśnie główny cel ekosystemu bibliotek. CircuitPython ma core'owe moduły wbudowane w firmware, ale do konkretnego hardware'u, takiego jak czujniki temperatury czy wyświetlacze LED, potrzebujesz zewnętrznych bibliotek. W przeciwieństwie do standardowego środowiska desktopowego Pythona, nie ma tu żadnego package managera. Nie odpalasz komendy, żeby automatycznie pobrać driver. Dependency management jest tutaj z założenia manualny. Kiedy podłączasz swój mikrokontroler przez USB, pojawia się on jako flash drive. W roocie tego dysku znajduje się directory o nazwie po prostu lib. Ten folder to dedykowane miejsce na wszystkie twoje zewnętrzne dependencies. Żeby go zapełnić, pobierasz Adafruit Library Bundle, ogromne archiwum ZIP zawierające setki oficjalnych driverów i helperów. I tu jest kluczowa sprawa. Kiedy chcesz pobrać ten bundle, zobaczysz kilka dostępnych wersji. Częstym błędem jest po prostu pobranie najnowszego bundle'a ze strony. Jeśli twój board działa na CircuitPythonie w wersji ósmej, ale pobierzesz bundle w wersji dziewiątej, twój kod wywali błąd. Major version tego bundle'a musi dokładnie pasować do major version firmware'u CircuitPython zainstalowanego na twoim boardzie. Jeśli do siebie nie pasują, system rzuca błędy o niekompatybilnym bytecode'zie i odmawia uruchomienia. W tym pasującym bundle'u znajdziesz biblioteki w dwóch różnych formatach plików: standardowych plikach dot py i plikach dot mpy. Pliki dot py to surowy, czytelny dla człowieka source code Pythona. Chociaż twój board może je uruchomić, mikrokontroler musi załadować cały ten surowy tekst do swojej malutkiej pamięci RAM i skompilować go do bytecode'u on the fly. Ten overhead kompilacji zżera pamięć niesamowicie szybko. Pliki dot mpy rozwiązują ten problem. To prekompilowany bytecode. Ten ciężki krok translacji został już wykonany na komputerze, zanim w ogóle pobrałeś plik zip. Kiedy mikrokontroler ładuje plik dot mpy, wykonuje instrukcje bezpośrednio, całkowicie pomijając fazę parsowania tekstu. Powiedzmy, że podłączasz taśmę LED NeoPixel do swojego boarda. Piszesz swój skrypt sterujący, ale system potrzebuje hardware'owego drivera, żeby wiedzieć, jak komunikować się z tymi konkretnymi LED-ami. Otwierasz swój poprawnie zwersjonowany library bundle, znajdujesz plik o nazwie neopixel dot mpy i przeciągasz go bezpośrednio do directory lib na boardzie. Gdybyś zamiast tego przeciągnął surowy plik neopixel dot py, twojemu mikrokontrolerowi mogłoby łatwo zabraknąć pamięci przy samej próbie zinterpretowania kodu drivera. Używając prekompilowanego pliku dot mpy, board oszczędza krytyczny RAM na twoją właściwą logikę aplikacji i natychmiast zapala piksele. Manualny dependency management zmusza cię do bycia bardzo świadomym tego, jaki kod żyje na twoim urządzeniu. Poleganie na prekompilowanym bytecode'zie to jedyny sposób na wyabstrahowanie złożonych operacji hardware'owych bez natychmiastowego wyczerpania malutkiej pamięci mikrokontrolera. To wszystko w tym odcinku. Dzięki za wysłuchanie i keep building!
5

Zamrożone biblioteki

3m 48s

Odkryj magię zamrożonych bibliotek w CircuitPython dla płytek o ograniczonej pamięci. Słuchacze zrozumieją priorytety plików bibliotek oraz to, jak moduły wbudowane w firmware zwalniają miejsce w systemie plików.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. CircuitPython, odcinek 5 z 7. Czasami usunięcie biblioteki z mikrokontrolera sprawia, że twój projekt działa lepiej. Usuwasz duże dependency z dysku, restartujesz płytkę, a twój kod magicznie nadal działa. Dzieje się tak dzięki funkcji o nazwie Frozen Libraries. Mikrokontrolery, zwłaszcza te mniejsze, jak Circuit Playground Express, działają przy ekstremalnych ograniczeniach sprzętowych. Każdy plik standardowej biblioteki w folderze lib zajmuje fizyczne miejsce na malutkim dysku flash. Co ważniejsze, kiedy twój kod się uruchamia, urządzenie musi załadować ten cały plik do pamięci RAM. Jeśli załadujesz zbyt wiele plików lub pliki będą zbyt duże, brakuje ci pamięci i program się crashuje. Developerzy firmware'u rozwiązują ten problem, zamrażając core'owe biblioteki bezpośrednio w buildzie CircuitPython. Zamiast istnieć jako niezależny plik na widocznym dysku USB, kod biblioteki jest prekompilowany i pakowany bezpośrednio do bazowego pliku firmware'u, który na początku wgrywasz na płytkę. To daje ogromną przewagę. Frozen libraries nie zajmują w ogóle miejsca w twoim widocznym systemie plików. Ponieważ są częścią core'owego obrazu systemu, mikrokontroler wykonuje kod bezpośrednio z pamięci flash. Całkowicie pomija proces kopiowania biblioteki do pamięci RAM. To prowadzi do częstej pułapki. Wielu developerów pobiera ogromny bundle bibliotek, kopiuje wszystko, co wydaje im się potrzebne, do folderu lib i przypadkowo duplikuje biblioteki, które są już frozen w ich firmware'ze. To marnuje cenne miejsce w systemie plików. Jeśli usuniesz bibliotekę z folderu lib, a twój projekt nadal działa bez zarzutu, oznacza to, że ta biblioteka była frozen. Oto kluczowa kwestia. Aby zrozumieć, jak uniknąć tego nakładania się, musisz zrozumieć kolejność priorytetów importu kontrolowaną przez system path. Kiedy twój kod importuje moduł, CircuitPython nie bierze po prostu pierwszego dopasowania, jakie znajdzie. Przeszukuje lokalizacje w ściśle określonej kolejności. Najpierw sprawdza root directory twojego dysku. Po drugie, sprawdza folder lib. Po trzecie, i tylko wtedy, gdy nie znajdzie biblioteki w pierwszych dwóch lokalizacjach, sprawdza frozen libraries ukryte w firmware'ze. Ta kolejność priorytetów oznacza, że każdy plik, który umieścisz na dysku, nadpisuje wersję frozen. Jeśli umieścisz przestarzałą lub customową wersję biblioteki w folderze lib, CircuitPython uruchomi ten plik. Całkowicie ignoruje zoptymalizowaną, oszczędzającą pamięć wersję frozen w firmware'ze. Płacisz koszt pamięci za plik, którego wcale nie musiałeś dostarczać. Wewnątrz tych katalogów, rozszerzenia plików również podlegają ścisłej regule priorytetów. Plik źródłowy w postaci plain text zawsze wygrywa ze skompilowanym plikiem. Jeśli w dokładnie tym samym katalogu masz zarówno standardowy plik tekstowy, jak i skompilowaną wersję tej samej biblioteki, CircuitPython załaduje nieskompilowany plik tekstowy. Aby dowiedzieć się dokładnie, co jest wbudowane w twoją konkretną płytkę, możesz otworzyć interaktywny prompt i wpisać słowo help, przekazując słowo modules w nawiasach. To wypisze pełną listę wszystkich frozen libraries dostępnych dla ciebie od razu. Najmądrzejszym sposobem na zarządzanie pamięcią na urządzeniu z ograniczeniami jest pozwolenie, aby to firmware odwalił czarną robotę. Dokładna wiedza o tym, co jest już frozen, zapobiega duplikowaniu plików, powstrzymuje przypadkowe overrides i utrzymuje twoją dostępną pamięć wolną dla właściwej logiki aplikacji. Dzięki za wysłuchanie. Trzymajcie się wszyscy.
6

CircuitPython vs MicroPython

4m 13s

Przeanalizuj różnice architektoniczne między CircuitPython a jego projektem macierzystym, MicroPython. Słuchacze dowiedzą się, dlaczego Adafruit stworzyło fork tego języka, aby zbudować ujednolicone, przyjazne dla początkujących API sprzętowe.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. CircuitPython, odcinek 6 z 7. Patrzysz na projekt hardware'owy i widzisz, że developerzy celowo usunęli z core'a języka zaawansowane funkcje, takie jak hardware interrupts. Możesz pomyśleć, że to okaleczyło platformę, ale w rzeczywistości sprawiło, że odniosła gigantyczny sukces. Na tym właśnie polega architektoniczna rozbieżność między CircuitPythonem a MicroPythonem. Developerzy często zakładają, że te dwie platformy są identyczne. Obie odpalają Pythona na mikrokontrolerach, a CircuitPython początkowo powstał jako fork MicroPythona. Jednak przyświecają im zupełnie inne filozofie. MicroPython został zaprojektowany tak, aby udostępnić surową moc i specyficzne funkcje danego mikrokontrolera. Z kolei CircuitPython ma za zadanie wymusić ścisły, ujednolicony standard dla całego hardware'u. Pierwszą różnicą, którą zauważysz, jest biblioteka standardowa. MicroPython używa konwencji nazewnictwa, która dodaje do standardowych modułów prefiks w postaci litery u, aby wskazać wersję micro. Importujesz uos albo utime. CircuitPython całkowicie z tego rezygnuje. Wymusza standardowe, desktopowe nazewnictwo z CPythona. Po prostu importujesz os albo time. Jeśli jesteś developerem, który portuje skrypt z MicroPythona na CircuitPython, będziesz musiał zmienić nazwy tych importów. W zamian za tę drobną poprawkę, twój kod staje się wysoce przenośny. Ta przenośność to główny feature CircuitPythona. MicroPython udostępnia konkretne rejestry sprzętowe i numery pinów specyficzne dla danego chipu. CircuitPython całkowicie abstrahuje hardware, używając zunifikowanego API skupionego wokół modułu o nazwie board. Zamiast pisać kod, który przełącza pin GPIO 15 na ESP32, mówisz CircuitPythonowi, żeby przełączył board kropka D4. Jeśli przeniesiesz ten sam skrypt na zupełnie inną architekturę mikrokontrolera, na przykład na standardowy chip ARM Cortex, kod hardware'owy odpali się całkowicie bez zmian. Aby utrzymać tę spójność, CircuitPython wymusza pewne wybory architektoniczne, które w MicroPythonie są opcjonalne. Na przykład, MicroPython pozwala ci skompilować firmware bez wsparcia dla liczb zmiennoprzecinkowych, żeby zaoszczędzić pamięć. CircuitPython wymusza wsparcie dla liczb zmiennoprzecinkowych w każdym pojedynczym buildzie. Operacje matematyczne zachowują się dokładnie tak samo, niezależnie od tego, jak bardzo ograniczony jest hardware. CircuitPython standaryzuje również komunikaty o błędach, dostarczając szczegółowy, zlokalizowany tekst zamiast lakonicznych błędów pamięci typu bare-metal. Oto kluczowy wniosek. Najbardziej polaryzującą różnicą jest to, jak oba rozwiązania radzą sobie z concurrency. MicroPython w pełni wspiera hardware interrupts. Interrupt pozwala, aby fizyczna zmiana stanu na pinie natychmiast wstrzymała główny program, wykonała określoną funkcję, a następnie wznowiła działanie. Zapewnia to wysoką wydajność czasową, ale wprowadza również złożone race conditions i nieprzewidywalne stany pamięci, które są niezwykle trudne do zdebugowania. CircuitPython celowo usuwa wsparcie dla hardware interrupts. Nie możesz wyzwolić kodu w Pythonie bezpośrednio z pinu hardware interrupt. Zamiast tego wymusza cooperative multitasking. Zarządzasz concurrency, używając standardowych feature'ów asyncio albo poprzez sekwencyjne sprawdzanie stanów w twojej main loop. Porzucając interrupts, CircuitPython zapewnia, że execution flow pozostaje całkowicie przewidywalny i eliminuje ogromną kategorię cichych crashy. MicroPython daje ci klucze do bare metal, stawiając na pierwszym miejscu surową wydajność i kontrolę nad hardwarem. CircuitPython wymienia tę kontrolę na środowisko, w którym twój kod jest całkowicie przenośny, przewidywalny i zachowuje się dokładnie tak samo, jak standardowy Python, którego odpalasz na desktopie. Dzięki za wysłuchanie, happy coding wszystkim!
7

Blinka i komputery jednopłytkowe

4m 19s

Skaluj swój kod CircuitPython na pełnoprawne maszyny z systemem Linux za pomocą Adafruit Blinka. Słuchacze dowiedzą się, jak ta warstwa kompatybilności pozwala na używanie API mikrokontrolerów na komputerach jednopłytkowych, takich jak Raspberry Pi.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. CircuitPython, odcinek 7 z 7. Spędzasz dni na pisaniu i testowaniu kodu do obsługi czujnika na małym, pięciodolarowym mikrokontrolerze. Później wymagania projektu się zmieniają i nagle potrzebujesz mocy obliczeniowej komputera z pełnym Linuksem, żeby logować te dane do zdalnej bazy w chmurze. Zazwyczaj przejście z mikrokontrolera typu bare-metal na pełny system operacyjny oznacza całkowite przepisanie kodu do obsługi sprzętu. Twoja platforma docelowa ma teraz kernel systemu operacyjnego, który zarządza dostępem do sprzętu, co wymaga zupełnie innych sterowników i bibliotek. Ale co, jeśli dokładnie ten sam skrypt w Pythonie mógłby działać bez zmian na obu platformach? Właśnie to umożliwia Adafruit Blinka. Zanim wyjaśnię, jak to działa, rozwiejmy pewien powszechny mit. Blinka nie zastępuje systemu operacyjnego Linux na twoim Raspberry Pi, BeagleBone czy innym komputerze jednopłytkowym. Nie flashujesz pliku firmware'u CircuitPythona na kartę SD, tak jak robisz to w przypadku mikrokontrolera. Zamiast tego, Blinka to po prostu paczka Pythona. Instalujesz ją za pomocą standardowego pipa. Działa jako warstwa kompatybilności uruchamiana w standardowym, desktopowym CPythonie. Jej jedynym zadaniem jest tłumaczenie wywołań API CircuitPythona na standardowe wywołania systemowe Linuksa, wymagane do sterowania sprzętem. Kiedy piszesz kod do obsługi sprzętu na mikrokontrolerze, CircuitPython zarządza bezpośrednim dostępem do sprzętu. W systemie Linux sprzętem steruje kernel, a programy użytkownika muszą prosić o dostęp. Blinka wypełnia tę lukę. Kiedy twój kod importuje moduł board albo używa modułu digitalio do przełączania pinu, Blinka przechwytuje te polecenia. Mapuje nazwy pinów z CircuitPythona na konkretny układ sprzętowy twojego komputera jednopłytkowego, kierując żądanie przez odpowiednie podsystemy Linuksa. Zastanów się, jak to wygląda w praktyce z naszym czujnikiem temperatury. Na małym mikrokontrolerze twój kod importuje moduł board, konfiguruje szynę I2C i w pętli odczytuje wartości temperatury. Żeby przeskalować tę operację na Raspberry Pi 5, fizycznie podłączasz czujnik do pinów GPIO na Pi. Następnie w terminalu Linuksa używasz pipa, żeby zainstalować paczkę Adafruit Blinka i konkretny sterownik Pythona dla twojego czujnika temperatury. Kopiujesz swój oryginalny skrypt w Pythonie, nie zmieniając w nim ani jednej linijki. Kiedy odpalasz skrypt używając standardowego Pythona 3, moduł board dynamicznie wykrywa, że działa na Raspberry Pi 5. Automatycznie dostarcza poprawne definicje pinów dla tej konkretnej płytki. Moduł busio płynnie tłumaczy twoje żądania odczytu I2C na standardowe wywołania urządzeń I2C w Linuksie. Twój skrypt odczytuje dane z czujnika dokładnie tak samo, jak wcześniej. I tu robi się ciekawie. Ponieważ teraz odpalasz standardowy CPython na pełnoprawnej maszynie z Linuksem, nie ograniczają cię już limity pamięci mikrokontrolera. Twój skrypt może odczytywać dane z czujnika używając warstwy translacji Blinka, a następnie od razu przekazywać je do ciężkich, desktopowych bibliotek. Możesz użyć standardowych requestów sieciowych, żeby wypchnąć metryki do bazy danych w chmurze, przetwarzać telemetrię narzędziami data science, a nawet serwować to wszystko przez lokalny web framework. Oto kluczowy wniosek. Kod do obsługi sprzętu pozostaje identyczny na zupełnie różnych architekturach obliczeniowych. Dzięki odseparowaniu logiki czujnika od warstwy systemu operacyjnego, Blinka pozwala ci tanio prototypować na środowiskach bare-metal i skalować się do pełnych środowisk linuksowych z zerową potrzebą przepisywania kodu sprzętowego. To już koniec naszej serii o CircuitPythonie. Zachęcam cię do przejrzenia oficjalnej dokumentacji, samodzielnego spróbowania konfiguracji czujnika z Blinką, albo odwiedzenia DEV STORIES DOT EU, żeby zasugerować tematy do przyszłych serii. To wszystko w tym odcinku. Dzięki za wysłuchanie i twórzcie dalej!