Pierwsza sesja z XIAO ESP32‑S3
XIAO ESP32-S3: pierwsza sesja

Część 5 · osobna sesja · slajd 1 z 40

XIAO ESP32-S3: pierwsza sesja

Ta sama droga co z Arduino, na płytce z drona: dioda, dotyk, własne Wi-Fi i radio ESP-NOW między dwiema płytkami. Jedna czynność na slajd.

Ta prezentacja prowadzi Cię krok po kroku przez pierwsze spotkanie z płytką XIAO ESP32-S3. To ta sama płytka, która siedzi w Twoim dronie, więc wszystko, co dziś zrobisz, przyda się przy dronie wprost.

Jak z niej korzystać: jeden slajd to jedna czynność. Najpierw przeczytaj cały tekst na slajdzie, potem zrób to, co opisane, a na końcu sprawdź ramkę „Gotowe, gdy”. Jeśli to, co widzisz, nie zgadza się z ramką, nie idź dalej: wróć o slajd albo napisz do mnie, co dokładnie widzisz (zrzut ekranu lub zdjęcie).

Strzałki na klawiaturze przewijają slajdy, spacja idzie do przodu. Pozycja zapamiętuje się w przeglądarce, więc po przerwie wrócisz w to samo miejsce.

Czego dziś NIE robimy: nie lutujemy, nie dotykamy drona, nie łączymy płytki z niczym poza kablem USB. Wszystko dzieje się na samej płytce, więc nie ma czego zepsuć poza wgraniem złego programu, a to naprawia się wgraniem dobrego.

Po co ta sesja

Wprowadzenie · po co · slajd 2 z 40

Po co ta sesja

XIAO ESP32-S3 to mózg Twojego drona. Zanim go wlutujesz, poznasz go na zapasowej płytce: jak wgrywać, czym różni się od UNO i jak rozmawia bez kabla. Ćwiczenie 4 to dokładnie mechanizm przyszłego nadajnika do drona.

Po co w ogóle ta sesja, skoro masz już za sobą Arduino UNO? Bo dron nie ma w sobie UNO, tylko właśnie XIAO ESP32-S3. UNO było placem zabaw, na którym poznałeś podstawy: że program ma część startową i część powtarzaną w kółko, że płytka może zapalać diodę i wysyłać tekst do komputera. Dziś przenosisz to na płytkę, która poza tym ma radio.

Radio to klucz do drona. Dron rozmawia z telefonem przez własną sieć Wi‑Fi, a w przyszłości z Twoją aparaturą przez łącze radiowe między płytkami (nazywa się ESP‑NOW). W ćwiczeniu 3 zrobisz dokładnie to, co robi dron, gdy udostępnia sieć telefonowi. W ćwiczeniu 4 zrobisz dokładnie to, co będzie robić aparatura: jedna płytka wysyła, druga odbiera, bez kabla.

Dlaczego na zapasowej płytce, a nie na tej z drona? Bo zapasowa nie ma jeszcze nic przylutowanego i nic jej nie grozi. Jeśli coś pójdzie nie tak, wgrywasz program jeszcze raz i tyle. Płytka z drona ma wlutowane piny i zostaje w pudełku do czasu montażu.

Plan dnia w czterech ćwiczeniach: 1) mruganie diodą, czyli sprawdzenie, że umiesz wgrać program; 2) dotyk palcem, bo ta płytka ma prawdziwy czujnik dotyku w środku; 3) własna sieć Wi‑Fi i strona otwierana w telefonie; 4) dwie płytki rozmawiające radiem. Przed ćwiczeniami jest kilkanaście kroków przygotowania: rozpakowanie, antena, instalacja obsługi płytki w programie Arduino IDE.

Co wyjąć z pudełek

Wprowadzenie · co wyjąć · slajd 3 z 40

Co wyjąć z pudełek

Z paczki Seeed: 1 zapasowa XIAO bez pinów (tę z pinami zostaw do drona), 1 antena FPC. Z biurka: mata z opaską, kabel od iPhone’a, MacBook. Do ćwiczenia 4: druga zapasowa XIAO i drugi kabel USB-C, np. od ładowarki MacBooka.

Z paczki od Seeed (chińskiego producenta płytki) wyjmij woreczek z napisem XIAO ESP32S3. W paczce są dwie takie zapasowe płytki, obie bez pinów (bez metalowych nóżek). Do ćwiczeń 1–3 wystarczy jedna. Druga będzie potrzebna dopiero w ćwiczeniu 4, więc na razie zostaw ją w woreczku.

Z tej samej paczki weź jedną antenę. To cienki, płaski, czarny pasek na taśmie z krótkim przewodzikiem zakończonym malutką okrągłą wtyczką. W paczce jest pięć takich anten, wystarczy jedna.

Z biurka: mata antystatyczna (ta niebieska) z opaską na nadgarstek, kabel od iPhone’a (ma końcówkę USB‑C, pasuje do płytki) i MacBook z zainstalowanym programem Arduino IDE, tym samym, którego używałeś przy UNO.

Do ćwiczenia 4 przyda się drugi kabel z końcówką USB‑C, na przykład ten od ładowarki MacBooka, i wolne drugie gniazdo w Macu albo adapter. Jeśli masz tylko jedno gniazdo, też się da, powiem jak na odpowiednim slajdzie.

Czego NIE wyjmować: drona, płytki z wlutowanymi pinami, listew pinów, lutownicy. Dziś nic nie lutujemy.

Mata i opaska jak przy Arduino

Przygotowanie · slajd 4 z 40

Mata i opaska jak przy Arduino

Mata na biurku, opaska na lewym nadgarstku, krokodylek na brzegu maty. XIAO ma odsłonięte pola na krawędziach, więc ładunek z palców jest tu groźniejszy niż przy UNO.

Gotowe, gdy: opaska na ręce, krokodylek zapięty

Rozłóż matę na biurku tak, żeby leżała płasko, bez zagięć. Krokodylek (metalowy zacisk na przewodzie od maty) zapnij na brzegu maty, w miejscu, gdzie jest metalowy zatrzask. Opaskę załóż na lewy nadgarstek, ciasno, żeby metalowa płytka od spodu dotykała skóry, i podepnij jej przewód do maty.

Po co to wszystko. Chodząc po dywanie albo zdejmując sweter, ładujesz się elektrycznie jak balon potarty o włosy. Napięcie takiego ładunku to tysiące woltów, choć prąd jest tak mały, że czujesz najwyżej lekkie ukłucie. Dla układu scalonego w płytce, który pracuje na 3,3 wolta, taki impuls to jak piorun. Mata i opaska odprowadzają ładunek powoli i bezpiecznie, zanim dotkniesz płytki.

Przy XIAO to ważniejsze niż przy UNO. UNO ma nóżki w plastikowych gniazdach, a sam układ jest schowany pod nimi. XIAO ma metalowe pola odsłonięte na obu krawędziach, więc palec trafia prosto w ścieżkę prowadzącą do procesora.

Nawyk na zawsze: zanim dotkniesz jakiejkolwiek płytki, dotknij najpierw maty albo metalowej obudowy MacBooka. To wyrównuje ładunek między Tobą a stołem.

Wyjmij zapasową XIAO bez pinów

Przygotowanie · slajd 5 z 40

Wyjmij zapasową XIAO bez pinów

Z paczki Seeed, woreczek z napisem XIAO ESP32S3. Trzymaj za krawędzie. Połóż na macie gniazdem USB-C w stronę Maca. W pudełku są też antena i dwie listwy pinów: zostaw je.

Gotowe, gdy: płytka leży na macie, widać gniazdo USB-C i dwa małe przyciski

Otwórz woreczek i wyjmij płytkę, trzymając ją za krawędzie, dwoma palcami, jak zdjęcie, którego nie chcesz pobrudzić. Nie dotykaj metalowych pól ani srebrnej puszki na wierzchu. Jeśli płytka leży w woreczku na piance, zostaw piankę w woreczku.

Połóż płytkę na macie, srebrną puszką do góry, gniazdem USB‑C (ten mały prostokątny otwór) w stronę MacBooka. Dzięki temu kabel nie będzie się wyginał.

Co jeszcze jest w pudełku i co z tym zrobić: antena (zaraz ją wepniesz, więc połóż obok), dwie listwy z pinami, czyli po siedem metalowych nóżek w czarnym plastiku (zostaw w pudełku, to na później, do lutowania). Niczego nie wciskaj w płytkę: pola na krawędziach są do lutowania, nie na wcisk.

Rozmiar może Cię zaskoczyć. Płytka ma 21 na 17,5 milimetra, mniej niż znaczek pocztowy. Mimo to jest w niej komputer wielokrotnie mocniejszy od UNO, radio Wi‑Fi, Bluetooth i ładowarka akumulatora. Na tym polega sens tej płytki w dronie: cały mózg waży niecałe trzy gramy.

Poznaj płytkę

Przygotowanie · slajd 6 z 40

Poznaj płytkę

Gniazdo USB-C u góry. Po bokach gniazda dwa malutkie przyciski: R to RESET, B to BOOT. Pod gniazdem metalowa puszka z procesorem. Obok puszki, przy krawędzi, malutkie gniazdko antenowe. Po bokach po 7 pól: lewa strona D0–D6, prawa 5V, GND, 3V3, D10–D7. „D” to tylko nazwa: większość pól umie też mierzyć napięcie i wykrywać dotyk.

Gotowe, gdy: wskażesz palcem RESET, BOOT, gniazdko anteny i pola D0 oraz D1

Obejrzyj płytkę z góry, najlepiej pod lampką, a jeśli masz lupę, to z lupą. Znajdź po kolei:

  • Gniazdo USB‑C: prostokątny otwór na krótszej krawędzi. Tędy idzie zasilanie, program z komputera i tekst z płytki do komputera.
  • Dwa malutkie przyciski po obu stronach gniazda, każdy mniejszy od ziarnka ryżu. Ten z literką R to RESET: restart płytki, jak wyłączenie i włączenie. Ten z literką B to BOOT: przytrzymany podczas podłączania kabla wprowadza płytkę w tryb wgrywania. Przyda się na slajdzie 13, jeśli komputer nie zobaczy płytki.
  • Srebrna puszka pod gniazdem: to osłona procesora. W środku jest układ ESP32‑S3, czyli właściwy komputer, i radio. Metal chroni je przed zakłóceniami i chroni inne urządzenia przed zakłóceniami z płytki.
  • Przy krawędzi, obok puszki, malutkie okrągłe gniazdko wielkości główki od szpilki. To gniazdko antenowe (typu U.FL). Tu wepniesz antenę.
  • Pola na dłuższych krawędziach, po siedem z każdej strony. To wyprowadzenia, do których w dronie lutuje się silniki i czujnik. Lewa strona (gdy gniazdo USB jest u góry): D0, D1, D2, D3, D4, D5, D6. Prawa strona od góry: 5V (zasilanie 5 woltów z USB), GND (masa, czyli „minus”), 3V3 (zasilanie 3,3 wolta), potem D10, D9, D8, D7. Litera D to tylko nazwa pola. Prawie każde pole umie kilka rzeczy naraz, a program decyduje, w jakiej roli pracuje: włączać i wyłączać (cyfrowo) umieją wszystkie; mierzyć napięcie (analogowo, jak A0 na UNO, tylko dokładniej, 4096 stopni do 3,3 wolta) umieją D0–D5 i D8–D10, w programie nazywane wtedy A0–A5 i A8–A10; wykrywać dotyk umieją te same dziewięć pól. D6 i D7 nie mierzą ani nie wykrywają dotyku, bo są przeznaczone do rozmowy tekstem po przewodzie. D4 i D5 służą też do czujników podłączanych dwoma przewodami danych, a D8–D10 do kart pamięci i wyświetlaczy.
  • Dwie diody przy gnieździe: jedna pomarańczowa (to „dioda użytkownika”, którą będziesz zapalać z programu), druga czerwona (ładowanie akumulatora, nie masz go dziś podłączonego).

Pole D1 zapamiętaj szczególnie: to drugie pole od góry po lewej. Będzie Twoim czujnikiem dotyku w ćwiczeniu 2.

Wepnij antenę

Przygotowanie · slajd 7 z 40

Wepnij antenę

Płaska antena FPC z przewodem. Wtyczkę U.FL ustaw dokładnie nad gniazdkiem i wciśnij pionowo paznokciem, aż kliknie. Nie wciskaj pod kątem. Płaską część połóż obok płytki.

Gotowe, gdy: wtyczka siedzi płasko, delikatne pociągnięcie za przewód jej nie zdejmuje

Antena to płaski pasek z przewodzikiem, na końcu malutka okrągła wtyczka. Ta wtyczka wchodzi na gniazdko antenowe na płytce, które oglądałeś przed chwilą. Połączenie jest typu „na wcisk”, jak zatrzask w ubraniu, tylko sto razy mniejsze.

Jak to zrobić: 1) Ułóż płytkę płasko na macie. 2) Weź wtyczkę w palce (albo w pęsetę, jeśli palce są za duże) i ustaw ją dokładnie nad gniazdkiem, równolegle do płytki. 3) Wciśnij pionowo w dół, najlepiej paznokciem albo gumką ołówka, aż poczujesz lub usłyszysz delikatne kliknięcie. Potrzebna jest zauważalna siła, ale nie wielka.

Czego nie robić: nie wciskaj pod kątem, bo zgniatasz gniazdko i antena nie będzie trzymać. Nie ciągnij za przewód, żeby ją zdjąć; do zdejmowania służy podważenie wtyczki paznokciem od spodu. Nie zginaj przewodu na ostro.

Płaską część anteny połóż obok płytki, najlepiej w odległości kilku centymetrów od metalowych rzeczy. Antena jest naklejką (ma folię na spodzie), ale dziś jej nie przyklejaj; w dronie przyklei się do ramy.

Po co antena, skoro ćwiczymy na biurku? Płytka bez anteny ma zasięg kilkudziesięciu centymetrów i czasem gubi pakiety nawet z bliska. Z anteną pracuje tak, jak w dronie. Nawyk: płytka z radiem nigdy nie nadaje bez anteny, bo moc, która nie ma gdzie wyjść, grzeje układ nadawczy.

Dodaj adres pakietu esp32 w Arduino IDE

Przygotowanie · slajd 8 z 40

Dodaj adres pakietu esp32 w Arduino IDE

Arduino IDE → Settings (⌘,) → pole „Additional boards manager URLs”. Wklej: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json → OK.

Gotowe, gdy: adres jest w polu, okno Settings zamknięte

Program Arduino IDE zna z pudełka tylko płytki Arduino. Żeby zobaczył XIAO, musisz mu podać adres, pod którym producent układu (firma Espressif) trzyma pliki z obsługą swoich płytek. To jednorazowa czynność.

Krok po kroku: 1) Otwórz Arduino IDE. 2) W górnym menu Maca kliknij „Arduino IDE”, potem „Settings…” (albo naciśnij ⌘ i przecinek). 3) Na dole okna jest pole „Additional boards manager URLs” (dodatkowe adresy menedżera płytek). 4) Kliknij w to pole i wklej dokładnie ten adres:

https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json

5) Kliknij OK. Jeśli w polu był już jakiś adres, nie kasuj go: kliknij małą ikonę okna obok pola i wpisz nowy adres w kolejnej linii.

Co to za plik. Pod tym adresem leży spis wersji obsługi płytek ESP32 w formacie JSON (tekstowy spis danych). Arduino IDE czyta go, dowiaduje się, skąd pobrać pliki, i pokazuje pakiet na liście w następnym kroku. Sam adres nic nie instaluje.

Jeśli adres się nie wkleja (pole szare, kursor nie miga), zamknij okno ustawień i otwórz je ponownie.

Zainstaluj pakiet esp32

Przygotowanie · slajd 9 z 40

Zainstaluj pakiet esp32

Tools → Board → Boards Manager. Wpisz „esp32”, wybierz „esp32 by Espressif Systems”, Install. Pobiera ok. 300 MB, trwa kilka minut.

Gotowe, gdy: przy pakiecie widać „INSTALLED” z numerem wersji 3.x

Teraz właściwa instalacja. 1) Menu Tools → Board → Boards Manager… (menedżer płytek). Otworzy się panel po lewej stronie okna. 2) W polu wyszukiwania u góry wpisz: esp32. 3) Na liście znajdź pozycję „esp32 by Espressif Systems”. Uwaga: jest też pozycja „Arduino ESP32 Boards” od Arduino. Nie ta. Wybierz tę od Espressif Systems. 4) Kliknij Install.

Pobieranie trwa kilka minut, bo pakiet ma około 300 megabajtów: kompilator (program zamieniający Twój kod na instrukcje dla procesora), narzędzie do wgrywania i opisy wszystkich płytek z tym układem. Na dole okna leci pasek postępu. Nie zamykaj programu i nie usypiaj Maca.

Co się instaluje i po co. Twój program pisany w Arduino IDE to tekst. Procesor ESP32‑S3 rozumie tylko swoje instrukcje w postaci liczb. Kompilator robi to tłumaczenie. Każda rodzina procesorów ma inny kompilator, dlatego dla UNO wystarczył ten wbudowany, a dla XIAO potrzebny jest osobny.

Jeśli pobieranie przerwie się z błędem, kliknij Install jeszcze raz; program dociągnie resztę. Jeśli w ogóle nie widzisz pozycji „esp32 by Espressif Systems”, wróć do poprzedniego slajdu i sprawdź adres, litera po literze.

Podłącz XIAO kablem od iPhone’a

Przygotowanie · slajd 10 z 40

Podłącz XIAO kablem od iPhone’a

Jeden koniec do Maca, drugi do gniazda XIAO. Przytrzymaj płytkę. Na płytce zaświeci czerwona dioda ładowania i zgaśnie po ok. 30 s, bo nie ma akumulatora. To normalne.

Gotowe, gdy: czerwona dioda błysnęła, Mac nie zgłasza błędu

Weź kabel od iPhone’a. Jeden koniec (USB‑C) do gniazda w MacBooku, drugi koniec do gniazda w płytce. Płytkę przytrzymaj drugą ręką za krawędzie, bo jest lekka i wtyczka ją podnosi. Wtyczka USB‑C wchodzi na obie strony, nie trzeba zgadywać.

Co powinno się stać: na płytce zaświeci czerwona dioda i po kilkudziesięciu sekundach zgaśnie. To ładowarka akumulatora, która szuka akumulatora, nie znajduje go i się wyłącza. Zupełnie normalne. Pomarańczowa dioda może świecić albo nie, zależnie od programu, który producent wgrał fabrycznie.

Mac nie powinien nic pokazać. Jeśli pokaże komunikat o akcesorium, które pobiera za dużo prądu, odepnij kabel i spróbuj innego gniazda; taki komunikat przy XIAO oznacza uszkodzony kabel lub gniazdo, nie płytkę.

Czy kabel od telefonu na pewno przesyła dane? Kabel Apple tak. Niektóre tanie kable mają w środku tylko dwa przewody do ładowania i wtedy komputer nigdy nie zobaczy płytki. Jeśli na slajdzie z portem nic się nie pojawi, kabel będzie pierwszym podejrzanym.

Nie przyciskaj płytki do maty podczas wpinania; mata jest lekko przewodząca i po włączeniu zasilania lepiej, żeby odsłonięte pola jej nie dotykały. Połóż płytkę na kartce papieru albo na woreczku, w którym przyszła.

Wybierz płytkę XIAO_ESP32S3

Przygotowanie · slajd 11 z 40

Wybierz płytkę XIAO_ESP32S3

Tools → Board → esp32 → przewiń do „XIAO_ESP32S3”. Lista jest długa, pomaga wpisanie „xiao” w polu wyboru płytki na pasku u góry.

Gotowe, gdy: na pasku u góry widać XIAO_ESP32S3

Powiedz programowi, z jaką płytką pracuje. Są dwie drogi, wybierz wygodniejszą.

Droga 1, przez menu: Tools → Board → esp32 → i teraz długa lista płytek z tym układem, ułożona alfabetycznie. Przewiń do „XIAO_ESP32S3” (jest blisko końca, na literę X). Kliknij.

Droga 2, przez pasek u góry okna: na pasku jest rozwijane pole z nazwą płytki (na początku pewnie „Arduino UNO” z poprzedniej sesji). Kliknij je, wybierz „Select other board and port…”, w polu wyszukiwania wpisz „xiao” i wybierz XIAO_ESP32S3 z listy po lewej. Po prawej pokażą się porty, ale port ustawisz na następnym slajdzie.

Uwaga na podobne nazwy: na liście są też XIAO_ESP32C3 i XIAO_ESP32C6. To inne płytki. Twoja to S3. Zły wybór nie uszkodzi płytki, ale wgrywanie nie zadziała.

Po co ten wybór. Program musi wiedzieć, jaki dokładnie procesor, ile pamięci, która nóżka to dioda użytkownika i jak wgrywać. Gdy wybierzesz XIAO_ESP32S3, słowo LED_BUILTIN w programie będzie oznaczać właściwą pomarańczową diodę, a program wgra się przez wbudowane w procesor USB.

Wybierz port usbmodem

Przygotowanie · slajd 12 z 40

Wybierz port usbmodem

Tools → Port → pozycja z „usbmodem” w nazwie. XIAO nie ma mostka CH340: procesor sam rozmawia z USB, dlatego nazwa jest inna niż przy klonie.

Gotowe, gdy: na dole okna: XIAO_ESP32S3 on /dev/cu.usbmodem…

Teraz wskaż programowi gniazdo, w którym siedzi płytka. Tools → Port. Na liście szukaj pozycji, która ma w nazwie „usbmodem”, na przykład /dev/cu.usbmodem101 albo z dłuższym numerem. Kliknij ją.

Skąd ta nazwa. Przy klonie UNO port nazywał się „wchusbserial”, bo w klonie siedzi osobny układ pośredniczący (CH340), który tłumaczy USB na język procesora. W XIAO takiego pośrednika nie ma: procesor ESP32‑S3 sam rozmawia przez USB. Mac widzi go wtedy jako „modem USB”, stąd usbmodem. Jeśli masz podłączone też UNO, zobaczysz dwa porty; wybierz usbmodem.

Sprawdzenie: na samym dole okna Arduino IDE, w prawym rogu, powinno być napisane „XIAO_ESP32S3 on /dev/cu.usbmodem…”. Jeśli jest, przygotowanie prawie skończone.

Jeśli na liście nie ma żadnego usbmodem: 1) sprawdź, czy kabel siedzi do końca po obu stronach; 2) spróbuj innego gniazda w Macu; 3) spróbuj innego kabla; 4) jeśli nadal nic, przejdź do następnego slajdu, tryb BOOT rozwiązuje większość takich przypadków.

Gdy portu nie ma: tryb BOOT

Przygotowanie · slajd 13 z 40

Gdy portu nie ma: tryb BOOT

Odepnij kabel. Przytrzymaj mały przycisk B, wepnij kabel, puść B. Płytka wchodzi w tryb wgrywania i port się pojawia. Po wgraniu programu naciśnij R.

Gotowe, gdy: port usbmodem jest na liście

Ten slajd jest na wypadek, gdy komputer nie widzi płytki, albo gdy wgrywanie przerywa się błędem w stylu „Failed to connect” (nie udało się połączyć). Jeśli port się pojawił i wgrywanie działa, pomiń ten slajd.

Co się dzieje. Program fabrycznie wgrany w płytkę może nie zgłaszać się komputerowi jako port. Procesor ma jednak zaszyty na stałe, w samym krzemie, tryb awaryjny do wgrywania. Nazywa się BOOT i nie da się go zepsuć żadnym programem. Wchodzi się w niego przyciskiem B.

Krok po kroku: 1) Odepnij kabel od płytki. 2) Znajdź malutki przycisk z literką B (po jednej stronie gniazda USB). 3) Naciśnij go paznokciem i TRZYMAJ. 4) Trzymając, wepnij kabel. 5) Odczekaj sekundę i puść przycisk. 6) W Arduino IDE sprawdź Tools → Port: usbmodem powinien się pojawić. Wybierz go.

W trybie BOOT płytka nic nie robi poza czekaniem na program. Po wgraniu programu nowy program nie wystartuje sam: naciśnij krótko przycisk R (reset) albo odepnij i wepnij kabel. Od tej chwili płytka zgłasza się normalnie i tryb BOOT nie będzie już potrzebny.

Drugi sposób na wejście w BOOT bez odpinania kabla: trzymaj B, naciśnij i puść R, puść B.

Czym XIAO różni się od UNO

Teoria 1 · slajd 14 z 40

Czym XIAO różni się od UNO

Procesor ESP32-S3: dwa rdzenie 240 MHz, 8 MB flash, 8 MB RAM, Wi-Fi i Bluetooth. UNO: 16 MHz, 32 KB, 2 KB. Piny pracują na 3,3 V, nigdy nie podawaj 5 V z UNO. USB jest w procesorze, więc nie ma CH340 ani bootloadera do zepsucia: wgrywanie przez wbudowany w krzem tryb BOOT. Dioda użytkownika świeci przy LOW, odwrotnie niż L na UNO.

Zanim wgrasz pierwszy program, kilka różnic, które będą miały praktyczne skutki w ćwiczeniach.

Moc. UNO ma procesor taktowany 16 milionów razy na sekundę, 32 kilobajty miejsca na program i 2 kilobajty pamięci roboczej. XIAO ESP32‑S3 ma dwa rdzenie po 240 milionów taktów, 8 megabajtów na program i 8 megabajtów pamięci roboczej. To tysiące razy więcej. Dlatego mieści się w niej jednocześnie Wi‑Fi, strona internetowa i program sterujący dronem.

Napięcie. UNO pracuje na 5 woltach. XIAO na 3,3 wolta. Jeśli kiedyś połączysz je ze sobą przewodem, 5 woltów z UNO może uszkodzić wejście XIAO. Dziś nic nie łączysz, ale zapamiętaj: do XIAO nigdy nie podawaj 5 woltów na pola D0–D10. Pole oznaczone 5V to wyjście zasilania z USB, nie wejście do nóżek.

USB. W UNO między kablem a procesorem siedzi pośrednik, a w pamięci procesora mały program rozruchowy (bootloader), który można przypadkiem nadpisać. W XIAO USB jest wbudowane w procesor, a tryb wgrywania jest zaszyty w krzemie. Praktyczny skutek: nie da się „zablokować” płytki złym programem; zawsze ratuje przycisk BOOT.

Dioda. Na UNO dioda L świeciła, gdy nóżka była w stanie wysokim (HIGH). Na XIAO pomarańczowa dioda użytkownika świeci, gdy nóżka jest w stanie niskim (LOW). Zobaczysz to w programie mrugania: LOW zapala, HIGH gasi. To nie błąd, tak producent podłączył diodę.

Prędkość rozmowy z komputerem. Przy UNO ustawiałeś 9600. Przy XIAO ustawiaj 115200. Tekst idzie prosto z procesora przez USB, więc może iść szybciej.

Wgraj mruganie

Ćwiczenie 1 · slajd 15 z 40

Wgraj mruganie

File → New Sketch, wklej program 01_mrugaj_xiao (na następnym slajdzie), Save As… (Shift‑⌘S) jako mrugaj_xiao, Upload. Wgrywanie trwa dłużej niż na UNO, w Output leci procent.

Gotowe, gdy: pomarańczowa dioda użytkownika mruga: krótko świeci, długo zgaszona

Pierwszy program. Zrób dokładnie tak: 1) Menu File → New Sketch (File → New Sketch). Otworzy się okno z pustym szablonem: dwie funkcje, setup i loop. 2) Zaznacz wszystko w tym oknie (⌘A) i skasuj. 3) Przejdź do następnego slajdu, skopiuj z niego cały program i wklej do pustego okna (⌘V). 4) Zapisz: ⌘S, nazwa „mrugaj_xiao”, Save. 5) Wróć na ten slajd.

6) Kliknij strzałkę w prawo na pasku u góry okna Arduino IDE (Upload, wgraj). Program najpierw się kompiluje, czyli tłumaczy na instrukcje procesora. Trwa to dłużej niż przy UNO, nawet 30–60 sekund za pierwszym razem, bo kompilator musi przygotować także obsługę Wi‑Fi. Potem w dolnym panelu Output lecą procenty: 10 %, 20 %… to właściwe wgrywanie.

Co powinieneś zobaczyć na końcu: w panelu Output linijki „Hash of data verified” i „Hard resetting via RTS pin…”, a na płytce pomarańczowa dioda zaczyna mrugać: krótki błysk, dłuższa przerwa.

Jeśli zamiast tego pojawi się czerwony błąd: a) „No such file or directory” lub podobny przy nazwie pliku: zapisałeś szkic pod nazwą z polskimi znakami lub spacją, zapisz jeszcze raz prostą nazwą; b) „Failed to connect” lub „No serial data received”: płytka nie weszła w tryb wgrywania, zrób slajd o trybie BOOT i kliknij Upload ponownie; c) błąd w treści programu z numerem linii: wklejenie się nie udało w całości, skopiuj program jeszcze raz.

Nie wyłączaj niczego w trakcie procentów. Jeśli przerwiesz, nic się nie zepsuje, ale trzeba będzie zacząć od BOOT.

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(115200);
  delay(500);
  Serial.println("XIAO ESP32-S3: start");
}

void loop() {
  digitalWrite(LED_BUILTIN, LOW);   // LOW = swieci!
  delay(200);
  digitalWrite(LED_BUILTIN, HIGH);  // HIGH = zgaszona
  delay(800);
  Serial.println("mrugniecie");
}

Ćwiczenie 1 · slajd 16 z 40

Program: mruganie

Zwróć uwagę na odwrotną logikę: LOW zapala. Serial Monitor przy 115200 pokazuje „mrugniecie”, dane idą prosto z procesora przez USB.

Gotowe, gdy: w Serial Monitor lecą napisy

Czytaj program od góry, linijka po linijce. Dwie kreski // zaczynają komentarz: tekst dla człowieka, procesor go pomija.

void setup() { … } to część wykonywana raz, po włączeniu zasilania lub resecie. pinMode(LED_BUILTIN, OUTPUT) mówi: nóżka, do której podłączona jest dioda użytkownika, ma być wyjściem, czyli płytka będzie nią sterować, a nie z niej czytać. LED_BUILTIN to nazwa, którą program Arduino IDE zamienia na właściwy numer nóżki dla wybranej płytki (dla XIAO ESP32‑S3 to nóżka 21). Serial.begin(115200) włącza rozmowę z komputerem z prędkością 115200 znaków na sekundę. delay(500) czeka pół sekundy, żeby komputer zdążył otworzyć połączenie. Serial.println wysyła tekst i przechodzi do nowej linii.

void loop() { … } to część powtarzana w kółko, dopóki jest zasilanie. digitalWrite(LED_BUILTIN, LOW) ustawia nóżkę w stan niski, czyli zero woltów, i na tej płytce to ZAPALA diodę. delay(200) czeka 200 milisekund, czyli jedną piątą sekundy. digitalWrite(LED_BUILTIN, HIGH) ustawia 3,3 wolta i gasi diodę. delay(800) czeka 0,8 sekundy. Potem program wysyła do komputera słowo „mrugniecie” i wraca na początek loop.

Zobacz tekst z płytki: Tools → Serial Monitor (Serial Monitor). Otworzy się panel na dole. Po prawej stronie panelu ustaw prędkość 115200 baud, inaczej zobaczysz krzaczki. Co sekundę powinno przybywać słowo „mrugniecie”.

Mały eksperyment, który wiele uczy: zmień 200 na 50 i 800 na 950, Save (⌘S), Upload ponownie. Dioda będzie błyskać krótko jak lampka ostrzegawcza. Potem zamień LOW i HIGH miejscami: dioda będzie świecić długo i gasnąć na chwilę. To pokazuje odwróconą logikę tej płytki lepiej niż jakikolwiek opis.

Prawdziwy czujnik dotyku

Teoria 2 · slajd 17 z 40

Prawdziwy czujnik dotyku

ESP32-S3 ma w środku układ pomiaru pojemności na pinach D0–D5 i D8–D10. Pin ładuje się i rozładowuje tysiące razy na sekundę; palec dokłada pojemność, więc cykl trwa dłużej, a touchRead() zwraca większą liczbę. Nie ma zakłóceń jak na pływającym A0 w UNO: to pomiar, nie przypadek. Tak działają przyciski dotykowe w sprzęcie AGD.

Na UNO „czujnik dotyku” był sztuczką: nóżka A0 wisiała w powietrzu i łapała zakłócenia z Twojego ciała, głównie 50 drgań na sekundę z instalacji elektrycznej w ścianach. Działało, ale przypadkiem. XIAO ma w środku prawdziwy układ do wykrywania dotyku, taki sam jak w płycie indukcyjnej czy w przyciskach lampki nocnej, które reagują na muśnięcie.

Jak to działa, bez wzorów. Każde pole na płytce razem z otoczeniem tworzy malutki kondensator, czyli coś, co potrafi zgromadzić odrobinę ładunku elektrycznego. Układ w procesorze ładuje to pole i rozładowuje tysiące razy na sekundę i mierzy, ile to trwa. Gdy zbliżasz palec, Twoje ciało dokłada do tego pola swoją pojemność (ciało człowieka to całkiem spory kondensator), więc ładowanie trwa dłużej. Program dostaje większą liczbę. Nie musisz niczego dotykać metalem: pojemność działa przez powietrze i przez cienki izolator, dlatego czujnik zadziała także przez kartkę papieru.

Które pola to potrafią: D0, D1, D2, D3, D4, D5 oraz D8, D9, D10. Pola D6 i D7 nie, bo są przeznaczone do innej rozmowy (tej, którą prowadzi tekst przez przewody). Dziś używamy D1, drugiego pola od góry po lewej.

W programie służy do tego funkcja touchRead(D1). Zwraca liczbę: w spoczynku na tej płytce zwykle kilkadziesiąt tysięcy, przy dotyku wyraźnie więcej. Dokładne wartości zależą od wilgotności, od tego, czy płytka leży na macie, nawet od pogody. Dlatego program nie ma wpisanej na sztywno granicy, tylko przez pierwszą sekundę mierzy, jaki jest spoczynek, i ustawia granicę 30 % wyżej. To tak zwana kalibracja i jest w każdym prawdziwym czujniku.

Gdzie to się przyda: przycisk dotykowy w pluszaku (Twój pomysł P3), aparatura bez mechanicznych przycisków, a nawet prosty czujnik poziomu wody, bo woda też ma pojemność.

const int PAD = D1;
uint32_t prog = 0;

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);
  Serial.begin(115200);
  delay(2000);                 // zdejmij palec po R
  for (int i = 0; i < 20; i++) { touchRead(PAD); delay(20); }  // rozgrzewka
  uint32_t suma = 0;
  for (int i = 0; i < 20; i++) { suma += touchRead(PAD); delay(20); }
  prog = suma / 20 * 13 / 10;   // spoczynek + 30 %
  Serial.print("prog: "); Serial.println(prog);
}

void loop() {
  uint32_t x = touchRead(PAD);
  Serial.println(x);
  digitalWrite(LED_BUILTIN, x > prog ? LOW : HIGH);
  delay(20);
}

Ćwiczenie 2 · slajd 18 z 40

Program: dotyk na D1

File → New Sketch dotyk_xiao, wklej, Upload. Program przez pierwszą sekundę mierzy spoczynek i ustawia próg 30 % wyżej. Nie dotykaj płytki w tej sekundzie.

Gotowe, gdy: wgrane, dioda zgaszona

Wgraj drugi program tak samo jak pierwszy: File → New Sketch, zaznacz wszystko i skasuj, wklej program z tego slajdu, Save As… jako „dotyk_xiao”, Upload. Zanim klikniesz Upload, przeczytaj poniżej, co program robi, bo pierwsza sekunda po wgraniu ma znaczenie.

const int PAD = D1; to nazwa dla pola, którego używamy. Jeśli kiedyś zechcesz użyć innego pola, zmieniasz tylko tę linijkę. uint32_t prog = 0; to miejsce na liczbę graniczną (próg). uint32_t znaczy „liczba całkowita bez znaku, 32‑bitowa”, czyli od zera do ponad czterech miliardów; touchRead zwraca duże liczby, więc zwykły int by nie wystarczył.

W setup: dioda ustawiona jako wyjście i zgaszona (HIGH gasi, pamiętasz), rozmowa z komputerem 115200, pół sekundy przerwy. Potem pętla for wykonuje 20 razy: dodaj odczyt touchRead do sumy, odczekaj 20 milisekund. Po pętli suma dzielona przez 20 to średni odczyt w spoczynku. Mnożenie przez 13 i dzielenie przez 10 daje 130 %, czyli próg 30 % powyżej spoczynku. Program wypisuje próg do komputera, żebyś widział, jaką granicę ustalił.

W loop: zmierz (x = touchRead(PAD)), wypisz liczbę do komputera, a potem jedna linijka z pytajnikiem: digitalWrite(LED_BUILTIN, x > prog ? LOW : HIGH). Czytaj: jeśli x jest większe od progu, ustaw LOW (zapal), w przeciwnym razie HIGH (zgaś). Potem 20 milisekund przerwy, czyli 50 pomiarów na sekundę.

WAŻNE przy wgrywaniu i po każdym naciśnięciu R: program czeka 2 sekundy, potem wyrzuca 20 pierwszych odczytów (po starcie bywają zawyżone) i dopiero kalibruje. Przez te 2 sekundy odsuń rękę od płytki. Przycisk R leży tuż obok pól D0 i D1, więc kciuk, który go nacisnął, łatwo zostaje nad polem i program uzna dotyk za spoczynek; wtedy próg wychodzi ogromny i żaden dotyk go nie przebije (16.10 wyszło 89 963 przy spoczynku 15 997). Sprawdzaj w Serial Monitor: „spoczynek” około kilkunastu tysięcy, „prog” o 30 % większy. Jeśli jest inaczej, naciśnij R, odsuń rękę i odczekaj.

Dotknij pola D1

Ćwiczenie 2 · slajd 19 z 40

Dotknij pola D1

Tools → Serial Plotter, 115200. D1 to drugie pole od góry po lewej stronie. Dotknij go palcem: wykres skacze w górę, dioda się zapala. Puść: wraca. Spróbuj przez kartkę papieru: nadal działa, bo pojemność przenika przez izolator.

Gotowe, gdy: dioda reaguje na palec, także przez kartkę

Otwórz wykres: Tools → Serial Plotter (Serial Plotter). Po prawej u góry panelu ustaw 115200. Zobaczysz linię biegnącą mniej więcej poziomo: to kolejne odczyty dotyku w spoczynku. Zauważ, że linia nie jest idealnie prosta, drga o kilka procent. To naturalny szum pomiaru.

Teraz dotknij palcem pola D1, czyli drugiego pola od góry po lewej stronie (gdy gniazdo USB jest u góry). Linia na wykresie skacze w górę, a pomarańczowa dioda się zapala. Puść: linia wraca, dioda gaśnie. Zrób to kilka razy, żeby zobaczyć, jak szybko płytka reaguje (50 razy na sekundę, więc dla oka natychmiast).

Eksperyment 1: połóż na płytce kartkę papieru i dotknij przez kartkę w miejscu pola D1. Dioda nadal się zapala, może trochę słabiej reaguje. To dowód, że czujnik mierzy pojemność, a nie przepływ prądu przez palec: papier nie przewodzi prądu, a pojemność przez niego przenika.

Eksperyment 2: zbliż palec na kilka milimetrów, nie dotykając. Linia podnosi się, ale może nie przekroczyć progu. Gdybyś chciał czujnik zbliżeniowy, zmieniłbyś w programie 13/10 na np. 11/10 (próg 10 % wyżej). Spróbuj, jeśli masz ochotę, to jedna liczba i ponowne wgranie.

Eksperyment 3: dotknij innego pola, np. D3. Nic się nie dzieje, bo program czyta tylko D1. Procesor umie czytać wszystkie dziewięć pól naraz, tylko program o to nie prosi.

Jeśli dioda świeci cały czas albo nie reaguje wcale: najpewniej kalibracja odbyła się, gdy płytka była dotykana lub leżała inaczej. Naciśnij R, nie dotykaj przez sekundę, spróbuj ponownie.

Płytka jako punkt dostępu Wi-Fi

Teoria 3 · slajd 20 z 40

Płytka jako punkt dostępu Wi-Fi

XIAO może sama rozgłaszać sieć Wi-Fi, bez routera: tryb AP (Access Point). Telefon łączy się jak z każdą siecią, a płytka dostaje adres 192.168.4.1. Program uruchamia mały serwer HTTP: na żądanie strony odsyła kawałek HTML z aktualnym odczytem. Dokładnie tak dron rozgłasza sieć ESP-DRONE i tak aplikacja w telefonie się z nim łączy.

Do tej pory płytka rozmawiała tylko z komputerem przez kabel. Teraz zrobi coś, czego UNO nie potrafi: rozgłosi własną sieć Wi‑Fi. W menu Wi‑Fi telefonu pojawi się sieć o nazwie, którą wpiszesz w programie, dokładnie tak, jak pojawia się sieć domowego routera.

Dwa tryby pracy radia Wi‑Fi. Tryb „klient” (po angielsku station): płytka łączy się z istniejącą siecią, jak laptop. Tryb „punkt dostępu” (access point, w skrócie AP): płytka sama jest siecią i inne urządzenia łączą się z nią. Dziś używamy drugiego trybu, bo nie chcemy być zależni od routera. Dron robi dokładnie to samo: rozgłasza sieć o nazwie ESP‑DRONE, a aplikacja w telefonie się z nią łączy.

Adresy. Każde urządzenie w sieci ma adres IP, cztery liczby oddzielone kropkami. Płytka w trybie punktu dostępu zawsze bierze sobie 192.168.4.1, a telefonowi przydziela następny, np. 192.168.4.2. Dlatego w Safari wpiszesz właśnie 192.168.4.1.

Strona internetowa z płytki. W programie działa malutki serwer WWW: program, który czeka na pytanie „daj mi stronę” i odsyła tekst w języku HTML, czyli w tym samym, w którym napisane są wszystkie strony w internecie. Przeglądarka w telefonie rysuje z tego tekstu nagłówek, liczbę i dwa przyciski. Gdy klikniesz przycisk, telefon wysyła do płytki pytanie o adres /on albo /off, a program w odpowiedzi zapala lub gasi diodę. Cała ta „strona” to kilkanaście linijek tekstu w programie.

Czego się spodziewać: telefon ostrzeże, że sieć nie ma dostępu do internetu. To prawda, płytka nie jest podłączona do internetu. Zostań w tej sieci mimo ostrzeżenia. Telefon może po jakimś czasie sam wrócić do domowego Wi‑Fi, wtedy połącz ponownie.

Bezpieczeństwo: hasło 12345678 jest tylko na czas ćwiczenia. Sieć ma zasięg kilkunastu metrów i każdy, kto zna hasło, może zapalić Ci diodę, nic więcej.

#include <WiFi.h>
#include <WebServer.h>
WebServer serwer(80);
const int PAD = D1;

String strona() {
  String s = "<!doctype html><html><head><meta charset='utf-8'>";
  s += "<meta http-equiv='refresh' content='2'>";
  s += "<style>body{font-family:sans-serif;font-size:28px;padding:20px}";
  s += "a{display:block;padding:20px;background:#1f2a33;color:#fff;";
  s += "text-decoration:none;margin:10px 0;border-radius:12px;text-align:center}";
  s += "</style></head><body><h1>XIAO ESP32-S3</h1>";
  s += "<p>Dotyk D1: " + String(touchRead(PAD)) + "</p>";
  s += "<a href='/on'>Zapal diode</a><a href='/off'>Zgas diode</a></body></html>";
  return s;
}

void setup() {
  pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, HIGH);
  Serial.begin(115200); delay(500);
  WiFi.softAP("XIAO-Maciek", "12345678");
  Serial.println(WiFi.softAPIP());
  serwer.on("/",    []() { serwer.sendHeader("Connection", "close"); serwer.send(200, "text/html", strona()); });
  serwer.on("/on",  []() { digitalWrite(LED_BUILTIN, LOW);  serwer.sendHeader("Location", "/"); serwer.sendHeader("Connection", "close"); serwer.send(303); });
  serwer.on("/off", []() { digitalWrite(LED_BUILTIN, HIGH); serwer.sendHeader("Location", "/"); serwer.sendHeader("Connection", "close"); serwer.send(303); });
  serwer.begin();
}

void loop() { serwer.handleClient(); }

Ćwiczenie 3 · slajd 21 z 40

Program: własna sieć i strona

File → New Sketch wifi_xiao, wklej, Upload. Długie linie w programie są w pliku ~/projects/robotics/arduino/xiao/03_wifi_xiao.

Gotowe, gdy: wgrane; w Serial Monitor adres 192.168.4.1

Trzeci program jest dłuższy, ale składa się z tych samych klocków. Upload: File → New Sketch, zaznacz wszystko i skasuj, wklej, Save As… jako „wifi_xiao”, Upload. Kompilacja potrwa dłużej (dochodzi obsługa Wi‑Fi), nawet minutę. Jeśli wklejenie ze slajdu połamie długie linijki, skopiuj program z pliku ~/projects/robotics/arduino/xiao/03_wifi_xiao/03_wifi_xiao.ino na Macu (jest tam po skopiowaniu projektu).

Co jest w programie, od góry. #include <WiFi.h> i #include <WebServer.h> dołączają gotowe biblioteki: pierwsza obsługuje radio Wi‑Fi, druga serwer stron. WebServer serwer(80); tworzy serwer słuchający na porcie 80, standardowym dla stron WWW (dlatego w adresie nie trzeba dopisywać portu). const int PAD = D1; znasz.

Funkcja strona() składa tekst strony w języku HTML: nagłówek, linijkę „Dotyk D1:” z aktualną liczbą z touchRead i dwa odnośniki wyglądające jak przyciski, prowadzące do adresów /on i /off. Linijka z „refresh content=2” każe przeglądarce odświeżać stronę co 2 sekundy, dzięki czemu liczba się aktualizuje.

W setup: dioda jak zwykle, rozmowa z komputerem, a potem WiFi.softAP("XIAO-Maciek", "12345678") tworzy sieć o tej nazwie i haśle. Możesz zmienić nazwę, hasło musi mieć co najmniej 8 znaków. Program wypisuje do komputera adres strony. Trzy linijki serwer.on(…) mówią: gdy ktoś poprosi o „/”, odeślij stronę; gdy o „/on”, zapal diodę i odeślij z powrotem na „/”; gdy o „/off”, zgaś i odeślij. serwer.begin() uruchamia nasłuch.

W loop jest tylko serwer.handleClient(): obsłuż, jeśli ktoś właśnie pyta. Płytka wykonuje tę linijkę tysiące razy na sekundę i większość czasu nikt nie pyta.

Po wgraniu otwórz Serial Monitor (115200). Powinien pokazać: „Adres strony: http://192.168.4.1”. Jeśli widzisz ten napis, sieć działa i możesz brać telefon.

Linijki serwer.sendHeader("Connection", "close") każą płytce zamykać połączenie zaraz po odpowiedzi. Bez nich serwer trzyma połączenie otwarte 5 sekund, a że obsługuje jednego klienta naraz, kliknięcie przycisku w telefonie czeka te 5 sekund w kolejce. Odkryte 16.10 na żywo: dioda reagowała z opóźnieniem 5 s, logi w monitorze pokazały, że płytka odpowiada natychmiast, a czeka samo połączenie.

Połącz telefon z siecią XIAO

Ćwiczenie 3 · slajd 22 z 40

Połącz telefon z siecią XIAO

iPhone → Settings → Wi‑Fi → sieć „XIAO-Maciek”, hasło 12345678. Telefon ostrzeże, że sieć nie ma internetu: zostań w niej.

Gotowe, gdy: telefon pokazuje połączenie z XIAO-Maciek

Weź iPhone’a. Settings → Wi‑Fi. Po kilku sekundach na liście sieci pojawi się „XIAO-Maciek” (jeśli nie zmieniłeś nazwy w programie). Dotknij ją. Wpisz hasło: 12345678. Dotknij Dołącz.

Telefon połączy się i prawdopodobnie pokaże pod nazwą sieci napis „Brak połączenia z Internetem” albo wyświetli okno z pytaniem, czy używać tej sieci mimo braku internetu. Wybierz, że chcesz zostać w tej sieci (np. „Używaj bez Internetu”). To ważne: iPhone lubi po cichu wracać do sieci z internetem; jeśli to zrobi, strona z płytki przestanie się otwierać i trzeba będzie połączyć ponownie.

Co się właśnie stało, krok po kroku: płytka co chwilę wysyła w eter krótki komunikat „jestem siecią XIAO-Maciek”. Telefon go usłyszał i pokazał na liście. Gdy wpisałeś hasło, telefon i płytka uzgodniły szyfrowanie i płytka przydzieliła telefonowi adres w swojej malutkiej sieci. Od tej chwili telefon i płytka mogą wysyłać sobie dane radiem, bez udziału jakiegokolwiek innego urządzenia.

Jeśli sieci nie ma na liście: 1) sprawdź w Serial Monitor na Macu, czy jest napis z adresem (jeśli nie ma, program nie wystartował, naciśnij R); 2) wyłącz i włącz Wi‑Fi w telefonie; 3) sprawdź, czy antena jest wpięta.

Mac też może się połączyć z tą siecią, ale wtedy straci internet. Zostaw Maca na domowym Wi‑Fi, do ćwiczenia wystarczy telefon.

Otwórz stronę płytki w Safari

Ćwiczenie 3 · slajd 23 z 40

Otwórz stronę płytki w Safari

W Safari wpisz http://192.168.4.1. Strona pokazuje odczyt dotyku i odświeża się co 2 s. Kliknij „Zapal diodę”: dioda na płytce się zapala. Dotknij D1 i patrz na liczbę w telefonie.

Gotowe, gdy: dioda reaguje na przycisk w telefonie, liczba rośnie przy dotyku

Na iPhonie otwórz Safari. W pasku adresu wpisz dokładnie: http://192.168.4.1 i zatwierdź. Napisz „http://” z przodu, bo Safari bez tego może próbować „https”, a płytka obsługuje tylko zwykłe, nieszyfrowane połączenie.

Powinna pojawić się prosta strona: duży nagłówek „XIAO ESP32-S3”, linijka „Dotyk D1:” z liczbą i dwa ciemne przyciski „Zapal diode” i „Zgas diode”. Strona jest brzydka celowo, żeby program był krótki.

Zrób trzy rzeczy: 1) Dotknij „Zapal diode”. Pomarańczowa dioda na płytce zapala się. Dotknij „Zgas diode”: gaśnie. Właśnie sterujesz płytką z telefonu przez radio. 2) Patrz na liczbę przy „Dotyk D1” i dotknij palcem pola D1 na płytce. Po najdalej 2 sekundach (tyle trwa odświeżanie) liczba w telefonie wyraźnie wzrośnie. 3) Odejdź z telefonem kilka metrów, do drugiego pokoju. Strona nadal działa, bo radio Wi‑Fi ma zasięg kilkunastu metrów przez ściany.

Co właściwie się dzieje, gdy klikasz przycisk: telefon wysyła radiem do płytki krótki tekst „GET /on”. Program w płytce ma zapisane, co robić przy „/on”: zapala diodę i odsyła telefonowi polecenie „wróć na stronę główną”. Telefon prosi o stronę główną, płytka składa ją na nowo z aktualną liczbą i odsyła. Całość trwa ułamek sekundy.

Dowód do dziennika: zrób zrzut ekranu telefonu ze stroną (przyciski boczne iPhone’a) i zdjęcie zapalonej diody. To podnosi na mapie umiejętność „Własna sieć Wi‑Fi i strona internetowa na płytce” na poziom 2.

Jeśli strona nie otwiera się („Safari nie może otworzyć strony”): sprawdź, czy telefon nadal jest w sieci XIAO-Maciek (często wraca do domowej), i czy wpisałeś http, a nie https.

ESP-NOW: radio bez sieci

Teoria 4 · slajd 24 z 40

ESP-NOW: radio bez sieci

ESP-NOW to protokół Espressifa: płytki ESP32 wysyłają sobie krótkie pakiety, do 250 bajtów, bezpośrednio, bez routera i bez łączenia z siecią. Opóźnienie kilka ms, zasięg ok. 200 m z anteną. Adresatem jest adres MAC drugiej płytki albo adres rozgłoszeniowy FF:FF:FF:FF:FF:FF, który słyszą wszyscy. To jest łącze przyszłego nadajnika do drona: 50 razy na sekundę 8 kanałów drążków.

Rysunek obok pokazuje, jak płytka nadaje: 1) metronom, czyli obwód drgający z kwarcem i pętlą, który tylko wyznacza rytm; 2) pompa, czyli dwa zawory (tranzystory) w układzie scalonym, które w tym rytmie przepychają elektrony między miedzią masy a anteną, biorąc energię z zasilania USB; 3) antena, pasek o długości ćwierci fali ze ślepym końcem, na którym elektrony się piętrzą i zawracają. Elektrony nigdzie nie krążą w kółko i nigdzie nie uciekają: przelewają się tam i z powrotem. W powietrze wychodzi pole, nie elektrony. Oba obiegi elektronów (zielony i niebieski) są rozdzielone; łączy je tylko sygnał rytmu.

Czwarte ćwiczenie to serce przyszłej aparatury do drona. Dwie płytki będą rozmawiać ze sobą radiem bez żadnej sieci, bez routera, bez logowania. Nazywa się to ESP‑NOW i jest wymysłem firmy Espressif, producenta układu. Działa tylko między płytkami z układami tej firmy, ale to nam wystarcza: dron i aparatura mają ten sam układ.

Czym to się różni od Wi‑Fi z poprzedniego ćwiczenia. Wi‑Fi to sieć: ktoś musi ją rozgłaszać, ktoś się dołączać, uzgadniać hasło i adresy, a każde przesłanie danych idzie przez kilka warstw. To trwa i wprowadza opóźnienia rzędu dziesiątek milisekund, czasem więcej. ESP‑NOW to radiowa krótkofalówka: płytka po prostu nadaje krótką paczkę danych, do 250 bajtów, i każda płytka w zasięgu nastawiona na ten sam kanał może ją odebrać. Opóźnienie to pojedyncze milisekundy. Zasięg z anteną na otwartej przestrzeni to około 200 metrów.

Adresowanie. Każde urządzenie radiowe ma na stałe wpisany numer fabryczny, zwany adresem MAC, sześć par znaków, np. 34:85:18:7B:2C:F1. Paczkę można zaadresować do konkretnego numeru albo do adresu specjalnego FF:FF:FF:FF:FF:FF, który znaczy „do wszystkich”. Dziś używamy „do wszystkich”, żeby nie przepisywać numerów; w aparaturze do drona wpisze się konkretny adres drona, żeby nikt inny go nie słuchał.

Niezawodność. Paczka może zginąć (zakłócenie, za daleko). ESP‑NOW ma w każdej paczce sumę kontrolną: odbiornik sprawdza, czy dane doszły bez przekłamań, i jeśli nie, wyrzuca paczkę. Nadajnik w naszym programie wysyła stan dotyku 20 razy na sekundę, więc zgubienie jednej paczki nic nie zmienia, następna za 50 milisekund ją zastąpi. Dokładnie na tej zasadzie działa aparatura: wysyła położenie drążków w kółko, a dron bierze ostatnie, które doszło.

Kanał. Radio Wi‑Fi ma 13 kanałów (częstotliwości). Obie płytki muszą być na tym samym. W programie jest „channel = 0”, co znaczy „bieżący kanał płytki”; po włączeniu obie płytki są na kanale 1, więc się słyszą. Gdyby jedna z nich była jednocześnie połączona z routerem na innym kanale, przestałyby się słyszeć. To pierwsza rzecz do sprawdzenia, gdy łączność nie działa.

#include <WiFi.h>
#include <esp_now.h>

void odbior(const esp_now_recv_info_t *info, const uint8_t *dane, int dl) {
  if (dl < 1) return;
  digitalWrite(LED_BUILTIN, dane[0] ? LOW : HIGH);
  Serial.printf("odebrano: %d\n", dane[0]);
}

void setup() {
  pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, HIGH);
  Serial.begin(115200); delay(500);
  WiFi.mode(WIFI_STA);
  WiFi.setSleep(false);   // radio słucha bez przerwy
  esp_now_init();
  esp_now_register_recv_cb(odbior);
  Serial.print("Odbiornik, MAC: "); Serial.println(WiFi.macAddress());
}

void loop() { delay(100); }

Ćwiczenie 4 · slajd 25 z 40

Program: odbiornik

Do PIERWSZEJ XIAO, tej już podłączonej: File → New Sketch espnow_odbiornik, wklej, Upload. Potem odepnij ją od Maca.

Gotowe, gdy: wgrane; w Serial Monitor „Odbiornik, MAC: …”

Najpierw odbiornik, do tej płytki, która jest już podłączona i ma antenę. File → New Sketch, zaznacz wszystko i skasuj, wklej program z tego slajdu, Save As… jako „espnow_odbiornik”, Upload.

Co jest w programie. #include <esp_now.h> dołącza bibliotekę łącza. Funkcja odbior(…) to tak zwana funkcja zwrotna: nie wywołujesz jej sam, procesor wywołuje ją sam za każdym razem, gdy przyjdzie paczka. Dostaje informacje o nadawcy (info), wskaźnik na dane (dane) i ich długość (dl). Jeśli długość jest mniejsza niż 1, nic nie robi. W przeciwnym razie czyta pierwszy bajt: jeśli jest różny od zera, zapala diodę (LOW), jeśli zero, gasi (HIGH). Potem wypisuje do komputera, od jakiego adresu MAC przyszła paczka i co w niej było. %02X w printf znaczy „wypisz liczbę szesnastkowo, dwoma znakami”.

W setup: dioda, rozmowa z komputerem, potem WiFi.mode(WIFI_STA): radio włączone w trybie klienta, ale bez łączenia z żadną siecią; ESP‑NOW tego wymaga. esp_now_init() uruchamia łącze; jeśli się nie uda, program wypisuje błąd i zatrzymuje się na zawsze (while (true)), żebyś to zauważył. esp_now_register_recv_cb(odbior) mówi: gdy coś przyjdzie, wywołaj funkcję odbior. Na końcu program wypisuje własny adres MAC.

W loop jest tylko delay(100), bo cała robota dzieje się w funkcji zwrotnej. To częsty wzorzec: program główny nic nie robi, a reaguje na zdarzenia.

Po wgraniu otwórz Serial Monitor (115200). Powinien pokazać „Odbiornik gotowy, MAC: …” z sześcioma parami znaków. Zapisz sobie ten adres gdzieś na kartce: w przyszłości, przy aparaturze, taki adres wpisuje się do nadajnika. Potem odepnij tę płytkę od Maca i odłóż na kartkę papieru. Będzie potrzebna za dwa slajdy.

Linijka WiFi.setSleep(false) wyłącza drzemkę radia. Bez niej odbiornik słucha tylko co jakiś czas (oszczędzanie energii z normalnego Wi‑Fi, gdzie router czeka z paczkami), więc krótki dotyk nadajnika ginie, a długi dociera z opóźnieniem kilku sekund i dioda świeci, aż odbiornik złapie „zero”. Odkryte na żywo 16.10 u Wojtka. W aparaturze do drona ta linijka jest obowiązkowa.

Podłącz drugą XIAO

Ćwiczenie 4 · slajd 26 z 40

Podłącz drugą XIAO

Druga zapasowa XIAO bez pinów, drugi kabel USB-C, np. od ładowarki MacBooka, do drugiego portu Maca. Tools → Port: wybierz nowy usbmodem. Antena dla drugiej płytki nie jest potrzebna na odległość biurka.

Gotowe, gdy: druga płytka widoczna jako nowy port

Teraz druga zapasowa płytka, ta z woreczka. Wyjmij ją tak samo za krawędzie i połóż na kartce. Antena dla niej nie jest konieczna na odległość biurka, ale jeśli chcesz, wepnij drugą z paczki tak jak poprzednio.

Podłącz ją drugim kablem USB‑C (np. od ładowarki MacBooka) do drugiego gniazda w Macu. Jeśli masz tylko jedno wolne gniazdo: nic nie szkodzi, odbiornik jest już odpięty, więc użyj tego samego gniazda i tego samego kabla od iPhone’a. Ważne jest tylko, żeby w tej chwili do Maca była podłączona jedna płytka, ta druga.

W Arduino IDE: Tools → Port → wybierz usbmodem. Jeśli druga płytka dostała inny numer portu niż pierwsza (to normalne), wybierz ten, który jest na liście teraz. Płytka też jest XIAO_ESP32S3, więc wyboru płytki nie zmieniasz.

Jeśli portu nie ma, zrób tryb BOOT jak na slajdzie 13: odepnij kabel, trzymaj przycisk B, wepnij, puść. Zupełnie nowa płytka z programem fabrycznym czasem tego wymaga.

Nawyk na przyszłość: przy dwóch płytkach łatwo wgrać program nie na tę, co trzeba. Przed każdym Upload spójrz na dół okna, który port jest wybrany, i którą płytkę trzymasz w ręce.

#include <WiFi.h>
#include <esp_now.h>

const int PAD = D1;
uint8_t WSZYSCY[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
uint32_t prog = 0;

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(115200); delay(500);
  WiFi.mode(WIFI_STA);
  WiFi.setSleep(false);   // radio słucha bez przerwy
  esp_now_init();
  esp_now_peer_info_t p = {};
  memcpy(p.peer_addr, WSZYSCY, 6);
  p.channel = 0; p.encrypt = false;
  esp_now_add_peer(&p);
  uint32_t suma = 0;
  for (int i = 0; i < 20; i++) { suma += touchRead(PAD); delay(20); }
  prog = suma / 20 * 13 / 10;
}

void loop() {
  uint8_t dotyk = touchRead(PAD) > prog ? 1 : 0;
  esp_now_send(WSZYSCY, &dotyk, 1);
  digitalWrite(LED_BUILTIN, dotyk ? LOW : HIGH);
  delay(50);   // 20 razy na sekunde
}

Ćwiczenie 4 · slajd 27 z 40

Program: nadajnik

Do DRUGIEJ XIAO: File → New Sketch espnow_nadajnik, wklej, Upload. Nadajnik 20 razy na sekundę wysyła 1 lub 0 do wszystkich w zasięgu.

Gotowe, gdy: wgrane, dioda nadajnika zgaszona

Program nadajnika do DRUGIEJ płytki. File → New Sketch, zaznacz wszystko i skasuj, wklej, Save As… jako „espnow_nadajnik”, Upload. Tak jak przy dotyku: przez pierwszą sekundę po starcie nie dotykaj płytki, bo program kalibruje czujnik.

Co jest w programie. Na początku to samo co w odbiorniku plus dwie rzeczy z programu dotyku: PAD = D1 i próg. uint8_t WSZYSCY[6] = {0xFF, …} to adres „do wszystkich”, sześć bajtów o wartości FF (szesnastkowo), czyli 255.

W setup po uruchomieniu łącza program dodaje tak zwanego partnera (peer): strukturę p z adresem WSZYSCY, kanałem 0 (czyli „bieżący”) i bez szyfrowania. ESP‑NOW wymaga, żeby każdy adresat był wcześniej dodany; adres „do wszystkich” też. Potem kalibracja dotyku jak w ćwiczeniu 2 i wypisanie własnego adresu MAC.

W loop: zmierz dotyk, zamień na 1 (dotyk) albo 0 (brak) i wyślij: esp_now_send(WSZYSCY, &dotyk, 1), czyli „wyślij do wszystkich jeden bajt spod adresu zmiennej dotyk”. Zapal własną diodę, gdy dotyk, żebyś widział, co nadajnik wysyła. Odczekaj 50 milisekund, czyli 20 paczek na sekundę. Aparatura do drona będzie robić dokładnie to samo, tylko zamiast jednego bajta z dotykiem wyśle kilkanaście bajtów z położeniem drążków, 50 razy na sekundę.

Po wgraniu Serial Monitor pokaże „Nadajnik gotowy, MAC: …”. Dioda nadajnika powinna być zgaszona, dopóki nie dotkniesz D1.

Tu też WiFi.setSleep(false), żeby obie płytki pracowały jednakowo i nadajnik nie przysypiał między paczkami.

Zasil odbiornik i dotknij nadajnika

Ćwiczenie 4 · slajd 28 z 40

Zasil odbiornik i dotknij nadajnika

Odbiornik wepnij z powrotem do Maca albo do ładowarki przez adapter: wystarczy mu prąd. Dotknij pola D1 na nadajniku. Dioda na odbiorniku zapala się bez żadnego kabla między płytkami. Odejdź z nadajnikiem do drugiego pokoju: nadal działa.

Gotowe, gdy: dioda odbiornika zapala się, gdy dotykasz nadajnika

Zasil odbiornik, czyli pierwszą płytkę. Nie musi już rozmawiać z komputerem, potrzebuje tylko prądu. Trzy sposoby: a) wepnij ją do drugiego gniazda Maca; b) wepnij do ładowarki od telefonu przez kabel; c) wepnij do powerbanku. Po włączeniu program wystartuje sam, bo jest zapisany w pamięci płytki na stałe.

Teraz dotknij palcem pola D1 na nadajniku (druga płytka, podłączona do Maca). Patrz na odbiornik: jego pomarańczowa dioda zapala się w tej samej chwili, mimo że między płytkami nie ma żadnego kabla. Puść: gaśnie. Zapala się też dioda nadajnika, więc widzisz obie strony.

Jeśli odbiornik jest podłączony do Maca, możesz dodatkowo otworzyć Serial Monitor na jego porcie: przy każdym dotyku zobaczysz linijki „od 34:85:…: 1”, a po puszczeniu „: 0”, dwadzieścia na sekundę. To adres MAC nadajnika. Wyjmij kartkę z adresem odbiornika i porównaj: różne płytki, różne adresy.

Eksperyment z zasięgiem: weź nadajnik z powerbankiem albo z kablem od ładowarki (do działania nie potrzebuje Maca, program jest już w nim) i odejdź do drugiego pokoju. Dotykaj D1 i proś kogoś, żeby patrzył na odbiornik, albo zostaw odbiornik w widocznym miejscu i patrz przez drzwi. Łącze działa przez ściany na kilkanaście metrów, z anteną na obu płytkach więcej.

To jest cała zasada aparatury do drona: aparatura wysyła, dron odbiera i reaguje. Różnica tylko w tym, co jest w paczce (położenie drążków zamiast dotyku) i że dron ma wpisany konkretny adres aparatury.

Dowód do dziennika: krótki film telefonem, w którym widać palec na nadajniku i zapalającą się diodę odbiornika. To podnosi na mapie „Łączność radiowa między płytkami” na poziom 2 i zamyka kamień M3.

Jeśli nie działa: 1) obie płytki zasilone (diody ładowania błysnęły)? 2) nadajnik: czy jego własna dioda zapala się przy dotyku? Jeśli nie, problem jest w kalibracji dotyku, naciśnij R na nadajniku i nie dotykaj przez sekundę. 3) Jeśli nadajnik świeci, a odbiornik nie: naciśnij R na odbiorniku. 4) Obie płytki na kanale 1 są automatycznie, chyba że któryś program łączył się z routerem, a nasze nie.

Jak dane przeżywają zakłócenia

Teoria 5 · slajd 29 z 40

Jak dane przeżywają zakłócenia

Numer paczki pokazuje dziury (zgubione). Suma kontrolna pokazuje przekłamania (uszkodzone). Nadajnik celowo psuje co 50. paczkę, żebyś zobaczył, jak odbiornik ją łapie.

Dwie proste sztuczki, z których korzysta każde łącze cyfrowe, od Wi‑Fi po sondy kosmiczne. Zobaczysz je na własnych płytkach.

Numer paczki. Nadajnik numeruje paczki 1, 2, 3… Odbiornik pamięta ostatni numer; jeśli przyjdzie 7, a ostatni był 4, to 5 i 6 zginęły. Tak liczy się „zgubione”. W aparaturze do drona ten sam licznik mówi dronowi, czy łącze jeszcze żyje; gdy przez pół sekundy nic nie przychodzi, dron włącza bezpieczne lądowanie.

Suma kontrolna. Nadajnik dodaje do siebie wszystkie bajty paczki i wysyła wynik jako dodatkowy bajt. Odbiornik liczy to samo i porównuje. Jeśli po drodze zmienił się choć jeden bit, sumy się nie zgodzą i paczka idzie do kosza, zamiast zapalić diodę na podstawie śmieci. To najprostsza suma, jaka istnieje; Wi‑Fi używa mądrzejszej (CRC), która łapie też zamiany miejscami, ale zasada jest ta sama.

Celowe psucie. Radio samo w sobie rzadko przekłamuje bajty (ma własną sumę kontrolną w środku), więc żeby zobaczyć wykrywanie, nadajnik psuje co 50. paczkę sam, już po policzeniu sumy. Odbiornik powinien liczyć „uszkodzone” równo o 1 co 2,5 sekundy. Jeśli tak jest, Twoja suma kontrolna działa.

Czego tu nie ma: naprawy. Zepsutą paczkę tylko wyrzucamy, bo za 50 milisekund przyjdzie następna. Naprawianie błędów (bity naprawcze) ma sens, gdy powtórka jest droga, np. z sondy za Marsem. To temat na osobny dzień, na kartce.

#include <WiFi.h>
#include <esp_now.h>

const int PAD = D0;
uint8_t WSZYSCY[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
uint32_t prog = 0;
uint16_t numer = 0;

struct Paczka { uint16_t nr; uint8_t dotyk; uint8_t suma; };   // 4 bajty

uint8_t policzSume(const Paczka &p) {            // suma bajtów nr+dotyk, reszta z 256
  const uint8_t *b = (const uint8_t *)&p;
  uint8_t s = 0;
  for (int i = 0; i < 3; i++) s += b[i];
  return s;
}

void setup() {
  pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, HIGH);
  Serial.begin(115200); delay(2000);
  WiFi.mode(WIFI_STA); WiFi.setSleep(false);
  esp_now_init();
  esp_now_peer_info_t p = {}; memcpy(p.peer_addr, WSZYSCY, 6); p.channel = 0; p.encrypt = false;
  esp_now_add_peer(&p);
  for (int i = 0; i < 20; i++) { touchRead(PAD); delay(20); }
  uint32_t suma = 0;
  for (int i = 0; i < 20; i++) { suma += touchRead(PAD); delay(20); }
  prog = suma / 20 * 13 / 10;
}

void loop() {
  Paczka pk;
  pk.nr = ++numer;
  pk.dotyk = touchRead(PAD) > prog ? 1 : 0;
  pk.suma = policzSume(pk);
  if (numer % 50 == 0) pk.dotyk ^= 0x02;         // CELOWE PRZEKŁAMANIE po policzeniu sumy
  esp_now_send(WSZYSCY, (uint8_t *)&pk, sizeof(pk));
  digitalWrite(LED_BUILTIN, pk.dotyk & 1 ? LOW : HIGH);
  delay(50);
}

Ćwiczenie 5 · slajd 30 z 40

Program: nadajnik z numerem i sumą

Okno nadajnika, port nadajnika. Paczka ma 4 bajty: numer (2), dotyk (1), suma (1). Co 50. paczka ma celowo zepsuty jeden bit po policzeniu sumy.

Gotowe, gdy: wgrane; dioda nadajnika reaguje na dotyk D0

Wklej do okna nadajnika, sprawdź port nadajnika na dole, Upload. Po starcie 2 sekundy bez dotykania.

Nowe rzeczy w programie. struct Paczka to opis, jak wyglądają 4 bajty paczki: nr (2 bajty, do 65535), dotyk (1 bajt), suma (1 bajt). policzSume dodaje trzy pierwsze bajty i zostawia resztę z dzielenia przez 256, bo tyle mieści 1 bajt. W loop: numer rośnie o 1 przy każdej paczce (++numer), dotyk jak dotąd, suma policzona, a potem linijka z „^= 0x02”: jeśli numer dzieli się przez 50, odwróć jeden bit w bajcie dotyk. To przekłamanie celowe, już po policzeniu sumy, więc odbiornik musi je wykryć.

esp_now_send wysyła teraz 4 bajty zamiast jednego: adres, wskaźnik na paczkę, rozmiar. Dioda nadajnika pokazuje bit dotyku (& 1 odcina zepsuty bit, żeby dioda nie mrugała przy psuciu).

#include <WiFi.h>
#include <esp_now.h>

struct Paczka { uint16_t nr; uint8_t dotyk; uint8_t suma; };

volatile uint32_t odebrane = 0, zgubione = 0, uszkodzone = 0;
volatile uint16_t ostatniNr = 0;
volatile bool pierwsza = true;

uint8_t policzSume(const Paczka &p) {
  const uint8_t *b = (const uint8_t *)&p;
  uint8_t s = 0;
  for (int i = 0; i < 3; i++) s += b[i];
  return s;
}

void odbior(const esp_now_recv_info_t *info, const uint8_t *dane, int dl) {
  if (dl != sizeof(Paczka)) return;
  Paczka pk; memcpy(&pk, dane, sizeof(pk));
  odebrane++;
  if (policzSume(pk) != pk.suma) { uszkodzone++; return; }
  if (!pierwsza && pk.nr > ostatniNr + 1) zgubione += pk.nr - ostatniNr - 1;
  pierwsza = false;
  ostatniNr = pk.nr;
  digitalWrite(LED_BUILTIN, pk.dotyk ? LOW : HIGH);
}

void setup() {
  pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, HIGH);
  Serial.begin(115200); delay(500);
  WiFi.mode(WIFI_STA); WiFi.setSleep(false);
  esp_now_init();
  esp_now_register_recv_cb(odbior);
}

void loop() {
  delay(1000);
  Serial.printf("odebrane: %lu  zgubione: %lu  uszkodzone: %lu  ostatni nr: %u\n",
                (unsigned long)odebrane, (unsigned long)zgubione, (unsigned long)uszkodzone, ostatniNr);
}

Ćwiczenie 5 · slajd 31 z 40

Program: odbiornik ze statystykami

Okno odbiornika, port odbiornika. Funkcja odbioru tylko sprawdza i liczy; raport co sekundę w loop.

Gotowe, gdy: w monitorze co sekundę: odebrane / zgubione / uszkodzone / ostatni nr

Wklej do okna odbiornika, sprawdź port odbiornika, Upload.

W funkcji odbioru: sprawdź, czy paczka ma dokładnie 4 bajty (inne wyrzuć), przepisz do struktury, policz odebrane. Policz sumę i porównaj z przysłaną: różna → uszkodzone++ i koniec. Jeśli ostatni numer był 4, a przyszedł 7, dolicz 2 zgubione. Zapamiętaj numer, ustaw diodę. Żadnego wypisywania tutaj: funkcja ma być błyskawiczna, bo blokuje odbiór kolejnych paczek (o tym przekonałeś się przy 10‑sekundowym opóźnieniu).

W loop: raz na sekundę jedna linijka z czterema liczbami. volatile przy zmiennych mówi kompilatorowi, że zmieniają się „z zewnątrz” (w funkcji odbioru), żeby nie optymalizował odczytów. (unsigned long) w printf to tylko dopasowanie typu do %lu.

Test zasięgu po domu

Ćwiczenie 5 · slajd 32 z 40

Test zasięgu po domu

Płytki obok siebie: odebrane +20/s, zgubione ~0, uszkodzone +1 co 2,5 s. Potem odchodź z nadajnikiem (powerbank/ładowarka) i co 1–2 min zapisz: miejsce → odebrane/zgubione.

Gotowe, gdy: masz 3–4 pary liczb z różnych miejsc; wiesz, gdzie łącze zaczyna gubić

Krok 1, kalibracja oka: płytki obok siebie, monitor na porcie odbiornika. Odebrane rośnie o ~20 na sekundę, zgubione stoi, uszkodzone rośnie o 1 co 2,5 s. Dotknij D0 nadajnika: dioda odbiornika reaguje od razu.

Krok 2, zasięg: nadajnik na powerbanku albo ładowarce (program działa bez komputera), odbiornik przy Macu z monitorem. Odchodź: ten sam pokój, za ścianę, korytarz, piętro, ogród. W każdym miejscu stań na minutę i zapisz różnicę: ile odebranych przybyło, ile zgubionych. Zdrowe łącze: zgubione poniżej 1 % odebranych. Granica zasięgu: zgubione rosną szybciej niż odebrane, dioda zaczyna „zacinać”.

Krok 3, antena: zamień role płytek (antena po stronie nadajnika) i powtórz dwa miejsca. Zobaczysz, czy antena bardziej pomaga przy nadawaniu, czy przy odbiorze (podpowiedź: tak samo, bo łącze jest symetryczne, ale z jedną anteną i tak ogranicza płytka bez niej).

Zapisz 3–4 pary „miejsce → odebrane/zgubione” i prześlij. To dowód na poziom 3 w węźle „Jak dane przeżywają zakłócenia” i zamknięcie kamienia M3.

Dwa przewody dla wielu układów

Teoria 6 · slajd 33 z 40

Dwa przewody dla wielu układów

Wyświetlacz OLED rozmawia przez magistralę dwuprzewodową (I2C): jeden przewód danych, jeden zegara. Na tej samej parze może wisieć kilkadziesiąt układów, każdy ma swój numer (adres). Dziś na płytce UNO, bo XIAO nie ma jeszcze szpilek. To dzień 1 planu w Warsztacie (17.10): dowód zgłaszasz tam, karta dnia prowadzi z powrotem do tego slajdu.

To jest pierwszy element z planu „jeden element dziennie”. Robisz go na płytce UNO, nie na XIAO, z prostego powodu: XIAO nie ma jeszcze przylutowanych szpilek, więc nie da się do niego wpiąć przewodów. W poniedziałek, przy nowej lampie, szpilki dolutujesz i od tego dnia każdy moduł będzie można przepinać między UNO (5 V) a XIAO (3,3 V).

Czym jest OLED. Malutki ekran 128 na 64 punkty. Każdy punkt to osobna dioda organiczna, która sama świeci; nie ma podświetlenia, dlatego czarne tło jest naprawdę czarne i ekran prawie nic nie bierze prądu, gdy pokazuje mało. Wyświetlacz z paczki IMZ jest jednokolorowy, niebieski.

Jak wyświetlacz rozmawia z płytką. Na module są cztery szpilki, widoczne na zdjęciu: GND (masa), VCC (zasilanie), SCL (zegar) i SDA (dane). Dwie ostatnie to cała magistrala, czyli wspólna „szyna”, po której płytka rozmawia z układami. Nazywa się I2C (czyta się „i kwadrat ce”) i spotkasz tę nazwę na każdym drugim module z Twoich paczek: czujnik ruchu z drona, czujnik ciśnienia, kompas, zegar, czujnik laserowy.

Dlaczego dwa przewody wystarczą dla wielu układów. Przewód zegara wybija takt: płytka na nim rytmicznie podnosi i opuszcza napięcie, a przy każdym takcie na przewodzie danych jest jeden bit. Płytka zaczyna każdą rozmowę od wysłania numeru układu, z którym chce mówić (adresu, liczby od 1 do 126). Wszystkie układy słuchają, ale odpowiada tylko ten, którego numer padł. Reszta milczy. Dokładnie jak w pokoju pełnym ludzi, gdy ktoś woła po imieniu.

Skąd układ ma numer. Jest wpisany w fabryce. Wyświetlacz ma zwykle 0x3C (zapis szesnastkowy, dziesiętnie 60). Czujnik ruchu 0x68, czujnik ciśnienia 0x76, kompas 0x1E. Dwa identyczne układy mają ten sam numer i wtedy odpowiedzą oba naraz, co dziś zobaczysz na własne oczy w ostatnim kroku.

Jedna rzecz, która zaskakuje. Na obu przewodach żaden układ nigdy nie „pcha” napięcia w górę; każdy umie tylko ściągać przewód do masy albo go puścić. W górę ciągną przewód dwa oporniki (podciągające), które są już na module wyświetlacza. Dzięki temu dwa układy mówiące naraz nie zwierają się ze sobą; wygrywa ten, który ściąga do masy. To jest też powód, dla którego długie przewody na tej magistrali nie działają: oporniki nie nadążają podnosić napięcia. 20 cm jest w porządku, metr już nie.

Napięcie. Moduł IMZ ma na pokładzie własny obniżacz i działa od 3,3 V do 5 V, więc na UNO podajesz 5 V, a po przeniesieniu na XIAO 3,3 V, bez żadnych przeróbek. Na przewodach danych wyświetlacz tylko ściąga do masy, więc nie wyśle do XIAO nic wyższego niż 3,3 V. Lekcja o napięciach z wczoraj w praktyce: ten moduł jest bezpieczny po obu stronach.

Połącz wyświetlacz z UNO czterema przewodami

Ćwiczenie 6 · slajd 34 z 40

Połącz wyświetlacz z UNO czterema przewodami

Z paczki IMZ: jeden wyświetlacz OLED 0,96"; z paczki Robogeek: przewody męsko‑żeńskie (koniec z gniazdkiem na szpilki wyświetlacza, koniec ze szpilką w gniazdo UNO). Płytka UNO (klon z gniazdem USB‑C) odłączona od komputera. GND → GND, VCC → 5V, SCL → A5, SDA → A4. Z magazynu: 4‑B1 OLED ×1 (pudełko 4 „moduły małe, część 2”), 6‑* przewody męsko‑żeńskie ×4 (pudełko 6 „przewody”), 9‑A2 klon UNO (pudełko 9 „płytki”).

Gotowe, gdy: cztery przewody siedzą pewnie na obu końcach, żaden nie dotyka sąsiada; zasilanie jeszcze odłączone

Wyjmij z paczki IMZ jeden wyświetlacz OLED 0,96 cala (drugi zostaw na ostatni krok), a z paczki Robogeek taśmę przewodów męsko‑żeńskich (40 sztuk, 20 cm: z jednej strony szpilka, z drugiej gniazdko). UNO ma gniazda, więc do niego wchodzi koniec ze szpilką; wyświetlacz ma szpilki, więc na nie nakładasz koniec z gniazdkiem. Przewody męsko‑żeńskie z paczki IMZ tu nie pasują. Z pudełka klona UNO (płytka z gniazdem USB‑C, ta z pierwszego dnia) weź samą płytkę. Nie podłączaj jeszcze do komputera: łączy się bez zasilania, żeby pomyłka przewodu nie kosztowała modułu.

Przewody w taśmie da się odrywać po jednym; oderwij cztery, najlepiej w czterech kolorach, i umów się ze sobą: czarny = masa, czerwony = zasilanie, dwa inne = zegar i dane. Taka umowa oszczędza godzin szukania błędów przez następne dwa tygodnie.

Na module szpilki są podpisane, patrz zdjęcie z poprzedniego slajdu: GND, VCC, SCL, SDA. Uwaga: różni producenci dają inną kolejność (bywa VCC, GND, SCL, SDA), więc zawsze czytaj napisy, nie pozycje.

Na płytce UNO gniazda są podpisane białym drukiem wzdłuż krawędzi. W rzędzie zasilania (obok napisu POWER): GND i 5V. W rzędzie analogowym (druga strona tej samej krawędzi): A4 i A5.

  • GND wyświetlacza → GND na UNO (w rzędzie POWER są dwa gniazda GND obok siebie, dowolne).
  • VCC wyświetlacza → 5V na UNO.
  • SCL wyświetlacza → A5 na UNO (zegar).
  • SDA wyświetlacza → A4 na UNO (dane).

Wciśnij każde gniazdko do oporu. Przewód męsko‑żeński trzyma się na tarcie, więc delikatnie pociągnij: ma stawiać opór. Sprawdź wzrokiem, czy żadne metalowe gniazdko nie dotyka sąsiedniego. Jeśli pomylisz GND z VCC, moduł zwykle przeżyje chwilę, ale nie warto sprawdzać.

Po co tu płytka UNO, a nie płytka stykowa. Płytki stykowej jeszcze nie masz (jest w paczce GOTRONIK, w drodze). Nie szkodzi: moduły mają szpilki, UNO ma gniazda, a przewód z dwoma gniazdkami łączy jedno z drugim bez niczego pośrodku.

UNO do Maca, płytka i port w Arduino IDE

Ćwiczenie 6 · slajd 35 z 40

UNO do Maca, płytka i port w Arduino IDE

Kabel USB‑C od iPhone’a do klona UNO. W Arduino IDE: Tools → Board → Arduino AVR Boards → Arduino Uno; Tools → Port → nowy /dev/cu.usbserial… albo usbmodem…

Gotowe, gdy: na pasku IDE widać „Arduino Uno” i port; na UNO świeci dioda zasilania, wyświetlacz na razie ciemny

Podłącz klona UNO kablem USB‑C (kabel od iPhone’a, ten sam co przy XIAO) do Maca. Na płytce zapali się dioda zasilania „ON”. Wyświetlacz zostaje ciemny: to normalne, bo nikt jeszcze nic do niego nie wysłał. Jeśli któraś dioda na module OLED by świeciła, to znak, że to inny moduł; OLED nie ma diod kontrolnych.

W Arduino IDE wybierz płytkę: Tools → Board → Arduino AVR Boards → Arduino Uno. To inna rodzina niż wczoraj (wczoraj było „esp32” → XIAO_ESP32S3). Jeśli w menu nie ma „Arduino AVR Boards”, zainstaluj je w Boards Manager (ikona z płytką na lewym pasku, wpisz „AVR”, Install). Przy pierwszym dniu z UNO to już było zrobione, więc powinno być na miejscu.

Port: Tools → Port. Klon UNO zgłasza się zwykle jako /dev/cu.usbserial‑XXXX (ma osobny układ do rozmowy po USB) albo /dev/cu.usbmodemXXXX. Jeśli nie widać nowego portu, zmień kabel: tanie kable USB‑C bywają tylko do ładowania. Na dole okna IDE, na pasku, ma być „Arduino Uno on /dev/cu…”.

Różnica względem XIAO, którą warto zapamiętać: UNO nie potrzebuje trybu BOOT, wgrywanie zawsze działa z marszu, a po wgraniu Serial Monitor nie gubi połączenia. Prościej, ale 15 razy wolniej i bez radia.

#include <Wire.h>

void setup() {
  Wire.begin();                 // UNO: SDA = A4, SCL = A5
  Serial.begin(115200);
  delay(500);
  Serial.println("Skaner magistrali dwuprzewodowej (I2C)");
}

void loop() {
  int znalezione = 0;
  for (byte adres = 1; adres < 127; adres++) {
    Wire.beginTransmission(adres);   // "halo, numer X?"
    if (Wire.endTransmission() == 0) { // ktoś odpowiedział
      Serial.print("Odpowiada adres 0x");
      Serial.println(adres, HEX);
      znalezione++;
    }
  }
  if (znalezione == 0) Serial.println("Nikt nie odpowiada: sprawdź przewody");
  Serial.println("---");
  delay(3000);
}

Ćwiczenie 6 · slajd 36 z 40

Program: skaner adresów

File → New Sketch, wklej, Upload, potem Tools → Serial Monitor i 115200 baud. Pyta po kolei 126 numerów i wypisuje, kto odpowiedział.

Gotowe, gdy: w monitorze co 3 s: „Odpowiada adres 0x3C” (rzadziej 0x3D)

Zanim pokażesz cokolwiek na ekranie, upewnij się, że płytka w ogóle „słyszy” wyświetlacz. Do tego służy skaner: program, który po kolei woła wszystkie 126 możliwych numerów i wypisuje te, które odpowiedziały. To najlepsze pierwsze narzędzie do każdego nowego modułu na tej magistrali.

File → New Sketch (nie nowa zakładka w starym szkicu, pamiętasz błąd „redefinition of setup”). Wklej program, Ctrl+U albo strzałka w prawo, poczekaj na „Done uploading”. Otwórz Serial Monitor (ikona lupy w prawym górnym rogu albo Tools → Serial Monitor), ustaw 115200 w prawym dolnym rogu.

Co ma się pokazać: co trzy sekundy linia „Odpowiada adres 0x3C”. Niektóre egzemplarze mają 0x3D; zapisz, który masz, bo za chwilę wpiszesz go do programu zegara.

Jeśli jest „Nikt nie odpowiada”: w 9 przypadkach na 10 zamienione A4 z A5 albo luźne gniazdko. Odłącz USB, popraw, podłącz. Jeśli dalej nic: sprawdź, czy VCC naprawdę siedzi w 5V, nie w VIN i nie w 3.3V (3,3 V też by zadziałało, ale chodzi o to, by wiedzieć, gdzie jest).

Jak to działa w środku: Wire.beginTransmission(adres) wysyła na przewód danych numer, a endTransmission zwraca 0, gdy jakiś układ „potwierdził” (ściągnął przewód danych do masy w dziewiątym takcie zegara). Właśnie to potwierdzenie jest całą sztuczką: płytka wie, że ktoś jest, zanim wyśle mu choć jeden bajt treści. Ten sam skaner przyda Ci się jutro przy czujniku ruchu (powinien dojść drugi adres, 0x68) i przy każdym kolejnym module.

Zainstaluj biblioteki wyświetlacza

Ćwiczenie 6 · slajd 37 z 40

Zainstaluj biblioteki wyświetlacza

Lewy pasek IDE → ikona książek (Library Manager (menedżer bibliotek)) → wpisz „SSD1306” → „Adafruit SSD1306” → Install → zgódź się na „Install all” (doinstaluje Adafruit GFX i BusIO).

Gotowe, gdy: Menedżer pokazuje „Adafruit SSD1306” i „Adafruit GFX Library” jako zainstalowane

Wyświetlacz dostaje od płytki obraz punkt po punkcie: 128 × 64 = 8192 punkty, po jednym bicie każdy, czyli 1024 bajty na każdą klatkę. Pisanie tego ręcznie nie ma sensu, od tego jest biblioteka. Dwie, bo producent rozdzielił je na: rysowanie (linie, czcionki, prostokąty: Adafruit GFX) i rozmowę z konkretnym układem sterującym ekranem (SSD1306, taki jest na module).

Na lewym pasku Arduino IDE kliknij ikonę książek (Library Manager (menedżer bibliotek)). W pole szukania wpisz „SSD1306”. Na liście znajdź „Adafruit SSD1306” (autor Adafruit) i kliknij Install. Pojawi się pytanie, czy doinstalować zależności („Install all”): zgódź się, dojdą Adafruit GFX Library i Adafruit BusIO.

Instalacja zajmuje kilkanaście sekund; na dole okna leci dziennik. Po niej w menu File → Examples pojawi się pozycja „Adafruit SSD1306” z przykładem ssd1306_128x64_i2c: można go wgrać dla zabawy, pokazuje wszystkie możliwości ekranu (animacje, czcionki, bitmapy). Nasz zegar na następnym slajdzie jest krótszy i da się go zrozumieć w całości.

Pojęcie na przyszłość: „sterownik ekranu” (SSD1306) to osobny układ przyklejony do szybki wyświetlacza, widoczny na zdjęciu jako brązowa taśma z czipem u dołu. To on pamięta obraz i odświeża diody; płytka UNO tylko przysyła mu nowe dane, kiedy chce coś zmienić.

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

Adafruit_SSD1306 ekran(128, 64, &Wire, -1);   // 128x64 punktów, bez nóżki reset

void setup() {
  Serial.begin(115200);
  if (!ekran.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {   // adres ze skanera
    Serial.println("Brak wyświetlacza pod 0x3C");
    while (true) delay(100);
  }
  ekran.clearDisplay();
  ekran.setTextColor(SSD1306_WHITE);
  ekran.setTextSize(1);
  ekran.setCursor(0, 0);
  ekran.println("Czas od wlaczenia");
  ekran.display();
}

void loop() {
  unsigned long s = millis() / 1000;
  char bufor[9];
  snprintf(bufor, sizeof bufor, "%02lu:%02lu", s / 60, s % 60);   // mm:ss

  ekran.fillRect(0, 20, 128, 44, SSD1306_BLACK);   // czyść tylko pole zegara
  ekran.setTextSize(3);
  ekran.setCursor(10, 28);
  ekran.print(bufor);
  ekran.display();                                  // dopiero tu obraz idzie przewodami
  delay(200);
}

Ćwiczenie 6 · slajd 38 z 40

Program: zegar od włączenia

File → New Sketch, wklej, Upload. Jeśli skaner pokazał 0x3D, zmień adres w begin. Napis małą czcionką u góry, minuty i sekundy dużą pod spodem.

Gotowe, gdy: na wyświetlaczu biegną sekundy mm:ss; po naciśnięciu przycisku RESET na UNO zegar startuje od 00:00

File → New Sketch, wklej program, Upload. Jeśli skaner pokazał 0x3D zamiast 0x3C, popraw liczbę w wywołaniu begin. Po wgraniu na ekranie u góry napis „Czas od wlaczenia”, a pod nim duże cyfry mm:ss, które biegną.

Dlaczego bez polskich znaków: wbudowana czcionka biblioteki ma tylko podstawowe litery łacińskie. Polskie ogonki wymagają osobnej czcionki, to temat na inny dzień.

Jak to działa. Obiekt ekran trzyma w pamięci UNO kopię całego obrazu (te 1024 bajty). Wszystkie polecenia rysowania (print, fillRect, setCursor) zmieniają tylko tę kopię. Dopiero ekran.display() wysyła kopię przewodami do sterownika w module i wtedy obraz się zmienia. Dlatego bez display() nic nie widać, i dlatego nie wołamy display() częściej niż trzeba: jedna klatka to 1024 bajty przez magistralę o prędkości 100 tysięcy bitów na sekundę, czyli około 80 milisekund. Więcej niż 10 klatek na sekundę tą drogą nie przejdzie, chyba że przyspieszysz magistralę (Wire.setClock(400000) po begin; układ to umie).

Dlaczego czyścimy tylko prostokąt zegara (fillRect), a nie cały ekran: nagłówek się nie zmienia, więc nie ma po co go przerysowywać. Przy większych programach to nawyk, który odróżnia płynny ekran od migającego.

Test: naciśnij przycisk RESET na UNO. Program startuje od nowa i zegar wraca do 00:00. Czas liczy millis(), czyli licznik milisekund od startu płytki, zrobiony na wewnętrznym rezonatorze UNO. Ten licznik po 50 dniach się przekręca, i w dniu 12 planu porównasz go z prawdziwym zegarem z własnym kwarcem (DS3231), żeby zobaczyć, o ile dziennie ucieka.

Ten program zostaje jako „ramka”: jutro w miejsce zegara wejdzie kąt przechyłu z czujnika ruchu, pojutrze odległość z czujnika, potem ciśnienie. Zmienia się tylko to, co liczysz w loop, a ekran i magistrala zostają.

Drugi wyświetlacz na tych samych przewodach

Ćwiczenie 6 · slajd 39 z 40

Drugi wyświetlacz na tych samych przewodach

Nie wyłączaj. Weź drugi OLED i cztery kolejne przewody. GND i 5V: w rzędzie zasilania UNO są po dwa gniazda GND, a 5V jedno, więc drugi wyświetlacz zasil z gniazda 3.3V (moduł IMZ działa od 3,3 V). Dane i zegar: UNO ma drugą parę gniazd SDA/SCL obok przycisku RESET, to te same linie co A4/A5.

Gotowe, gdy: oba wyświetlacze pokazują ten sam zegar w tej samej sekundzie; zdjęcie obu = dowód

Teraz rzecz, której nie da się przewidzieć bez zobaczenia: dwa identyczne układy na jednej parze przewodów. Nie wyłączaj płytki (dopinanie na żywo do tej magistrali jest bezpieczne, bo sygnały są niskoprądowe; przy zasilaniu uważaj tylko, żeby nie zewrzeć 5V z GND końcówką przewodu).

Weź drugi OLED i cztery nowe przewody. Masa: w rzędzie POWER są dwa gniazda GND, drugi wyświetlacz dostaje drugie. Zasilanie: gniazdo 5V jest jedno i już zajęte, więc użyj gniazda 3.3V obok; moduł działa od 3,3 V, i przy okazji zobaczysz, że dwa wyświetlacze na dwóch różnych napięciach zasilania rozmawiają po tej samej magistrali bez problemu, bo oba tylko ściągają linie do masy. Dane i zegar: na UNO R3 obok przycisku RESET, na końcu górnej listwy, są dwa dodatkowe gniazda podpisane SDA i SCL. To nie są nowe linie, to te same A4 i A5 wyprowadzone drugi raz właśnie na takie sytuacje. Drugi wyświetlacz: SDA → SDA, SCL → SCL.

Co się stanie: drugi wyświetlacz od razu, bez wgrywania niczego, pokaże dokładnie ten sam zegar, w tej samej sekundzie. Płytka woła numer 0x3C, oba układy mają ten numer, oba słuchają i oba rysują. Płytka nawet nie wie, że są dwa. Uruchom na chwilę skaner z poprzedniego kroku: nadal pokaże jeden adres, bo potwierdzenie od dwóch układów naraz wygląda jak jedno.

Z tego wynika zasada, na którą trafisz jutro i pojutrze: dwa różne układy z tym samym numerem na jednej magistrali gryzą się. Czujnik ruchu (0x68) i zegar DS3231 (0x68) nie mogą wisieć razem; rozwiązuje się to mostkiem zmieniającym adres (na wielu modułach jest pole „ADDR” albo „AD0”), osobną magistralą, albo przełącznikiem magistrali. Na odwrocie niektórych OLED jest taki mostek do przestawienia na 0x3D; obejrzyj przez lupę, czy Twój go ma.

Dowód do historii: zdjęcie obu wyświetlaczy z tym samym czasem obok płytki UNO, plus zrzut monitora ze skanerem. To zamyka węzeł „Magistrala dwuprzewodowa” na poziomie 2 i pierwszy dzień planu. Jutro: czujnik ruchu z drona na tych samych dwóch przewodach, obok wyświetlacza.

Co umiesz po tej sesji

Podsumowanie · slajd 40 z 40

Co umiesz po tej sesji

Wgrywać program na ESP32-S3 i wchodzić w tryb BOOT. Używać prawdziwego czujnika dotyku. Rozgłaszać własną sieć Wi-Fi i sterować płytką z telefonu. Łączyć dwie płytki radiem ESP-NOW. Podpinać układy do magistrali dwuprzewodowej i pokazywać liczby na wyświetlaczu OLED. Następny krok: dron z firmware ESP-Drone, a potem nadajnik z joystickami na tej samej zasadzie co ćwiczenie 4.

Co masz za sobą, jeśli wszystkie cztery ramki „Gotowe, gdy” się zgodziły:

  • Zainstalowałeś obsługę płytek ESP32 w Arduino IDE i umiesz wgrać program na XIAO ESP32‑S3, także awaryjnie przez przycisk BOOT. To umiejętność, której będziesz używać przy każdym programie na dronie.
  • Użyłeś prawdziwego czujnika dotyku i zobaczyłeś, czym jest kalibracja: program sam ustala, co znaczy „spoczynek”, zamiast mieć wpisaną liczbę na sztywno.
  • Uruchomiłeś własną sieć Wi‑Fi i stronę, którą sterowałeś z telefonu. To dokładnie ta droga, którą aplikacja w telefonie rozmawia z dronem.
  • Połączyłeś dwie płytki radiem bez żadnej sieci. To dokładnie ta droga, którą Twoja przyszła aparatura będzie rozmawiać z dronem.

Dowody do przesłania mi (zrzuty i zdjęcia): Serial Monitor z „mrugniecie”, strona w Safari i zapalona dioda, film z dwoma płytkami. Każdy podnosi poziom na mapie umiejętności; komplet zamyka kamień M3 „Płytka XIAO i radio bez Wi‑Fi”.

Co dalej. Najbliższe: ćwiczenia lutowania 1–2 na starym kablu (dzisiaj lub jutro), potem ćwiczenia 3–5 na płytce uniwersalnej, gdy przyjdzie paczka. Potem piny do zapasowej XIAO, montaż drona i pierwszy lot z telefonu. A potem aparatura: ten sam program nadajnika, tylko z drążkami zamiast dotyku.

Na koniec odepnij obie płytki, włóż je z powrotem do woreczków (antena może zostać wpięta) i zdejmij opaskę.