Witaj ponownie! Tegoroczna edycja Hacktoberfestu dobiegła już końca, czas więc, żebym podzielił się z Tobą częścią efektów mojej pracy. W tym roku skupiłem się na stworzeniu przykładowych projektów demonstrujących podstawy obsługi cyfrowych wejść i wyjść w Arduino. W poprzednich wpisach chciałem nauczyć Cię podstaw programowania w C, stosowania instrukcji sterujących, warunków logicznych itp. Można powiedzieć, że pokazywałem Ci jak działają podstawowe „klocki” z których można zbudować kod, realizujący pewne zadania.
Już samo podstawowe wykorzystanie języka C umożliwia stworzenie ciekawych i użytecznych programów. W poście zapowiadającym kurs obiecałem jednak, że będziemy uczyć się przez wykonywanie bardziej złożonych projektów. Czas najwyższy zabrać się za realizację tej obietnicy! Przy okazji dowiesz się, co ma wspólnego Dawid Podsiadło i Arduino! 😉
Aby móc zacząć tworzyć urządzenia wykorzystujące Arduino, musimy zacząć poznawać możliwości sprzętowe, które oferuje nam płytka NodeMCU oraz zawarty w niej mikrokontroler. Absolutną podstawą są tutaj cyfrowe porty wejścia i wyjścia, które są wykorzystywane właściwie we wszystkich projektach – choćby do obsługi przycisków. Sprawdźmy więc, które piny naszej płytki bazowej mogą nam posłużyć jako cyfrowe wejścia/wyjścia (z ang. digital I/O – digital Input/Output) oraz co musimy wiedzieć, aby bezpiecznie z nich korzystać i uniknąć frustracji. 🙂
Potrzebne materiały
Uwaga! Poniższe linki to tak zwane „linki afiliacyjne”. Oznacza to, że jeśli zamówisz przedmioty z ich pomocą, otrzymam prowizję od sklepu internetowego. Ciebie nie kosztuje to ani grosza więcej, dodatkowo oszczędzam Ci czasu na wyszukiwanie dobrej oferty na dany produkt, za to wspierasz rozwój bloga! 🙂
- płytka stykowa: Aliexpress
- zestaw łączówek: Aliexpress
- microswitche (minimum 1, optymalnie 4)
- dioda LED
- brzęczyk piezo bez wbudowanego generatora
Porty cyfrowych wejść i wyjść w Arduino Uno i NodeMCU
Płytki wykorzystywane w Arduino mają wiele wyprowadzeń, to na pewno jest łatwo zauważalne. Nie jest jednak taką oczywistością fakt, że większość z tych wyprowadzeń może pełnić wiele różnych funkcji w zależności od tego jak zostaną przez nas skonfigurowane. Dodatkowo każde wyprowadzenie ma swoje charakterystyczne cechy, ograniczenia i specyficzne zachowania. Z tego względu na tę chwilę ograniczymy ten temat, rozwinę go jednak ze szczegółami w kolejnym poście.
Na rzecz dzisiejszych eksperymentów staraj się łączyć układy ściśle według zamieszczonych schematów i grafik. Pamiętaj też o prawidłowej biegunowości w przypadku diody LED oraz stosowaniu rezystorów ograniczających prąd.
Konfiguracja początkowa pinów
Zanim zaczniemy wykorzystywać piny naszej płytki jako cyfrowe wejścia lub wyścia, musimy wykonać początkową konfigurację. Polega ona na wskazaniu które piny naszej płytki chcemy wykorzystywać, oraz w jakim trybie. Służy do tego instrukcja pinMode, którą możesz pamiętać z wcześniejszych części kursu, na przykład z postu o nadajniku kodu Morse’a. Składnia tej instrukcji prezentuje się następująco:
pinMode(numer_pinu, tryb_działania);
Jak widzisz, wywołując metodę pinMode, musisz wskazać numer pinu, czyli wyprowadzenia płytki bazowej, które chcesz skonfigurować oraz jeden z możliwych trybów działania. Dostępne wartości, które możesz podać żeby wybrać tryb działania pinu, to:
- OUTPUT – czyli z angielskiego wyjście,
- INPUT – czyli wejście, oraz
- INPUT_PULLUP – czyli wejście z dołączeniem wbudowanych w mikrokontrolerze rezystorów podciągających.
Omówmy teraz po kolei wszystkie tryby wraz z prostymi przykładami ich wykorzystania.
Tryb OUTPUT – wyjście cyfrowe
Zacznijmy od najprostszego w działaniu trybu OUTPUT. Tak naprawdę wielokrotnie już stosowaliśmy wyjście cyfrowe, nigdy jednak nie zanurzyliśmy się głębiej w szczegóły jego działania. Przypomnę Ci najpierw, jak możesz skonfigurować wybrany pin mikrokontrolera jako wyjście cyfrowe:
void setup() { pinMode(5, OUTPUT); }
Powyższy komendy ilustrują cały kod potrzebny do skonfigurowania pinu o numerze 5 (czyli D5 na płytce NodeMCU) jako wyjście cyfrowe. Oczywiście, jeśli będziesz chciał skonfigurować większą ilość wyprowadzeń, będziesz musiał zawrzeć w funkcji setup więcej wywołań funkcji pinMode. Skupmy się jednak na tym jakie cechy posiada skonfigurowane w ten sposób wyjście mikrokontrolera.
Piny skonfigurowane w trybie OUTPUT pracują w tak zwanym trybie niskiej impedancji. Oznacza to, że mogą dostarczyć do układu lub pobrać z niego dość duże ilości prądu. Wartości te mogą znacząco różnić się w zależności od stosowanej przez Ciebie płytki oraz zawartego w niej mikrokontrolera. Przykładowo, mikrokontrolery ATMega stosowane w płytkach Arduino Uno mogą być obciążone prądem o wartości ok. 40mA. Dla płytek wykorzystujących układ ESP8266, jak na przykład NodeMCU, ta wartość to już zaledwie 12mA. Nadmierny pobór prądu potrafi doprowadzić do trwałego uszkodzenia wyprowadzenia lub całego mikrokontrolera. Z tego względu, musisz pamiętać, że:
Wszelkie urządzenia pobierające prąd z wyjść cyfrowych mikrokontrolera powinny być dołączane przez rezystory o niewielkiej wartości oporu, a dodatkowo urządzenia pobierające duże ilości prądu (np. wentylatory, silniki, żarówki) powinny być sterowane przez dodatkowe układy przełączające z wykorzystaniem np. tranzystora. Pamiętaj też, że piny skonfigurowane jako wyjścia cyfrowe mogą zostać uszkodzone jeśli zostaną zwarte do dodatniej szyny zasilania lub masy (w zależności od stanu wyjścia).Jako ciekawostkę podpowiem Ci, że niebieska dioda zawarta na płytce NodeMCU jest dołączona do dodatniej szyny zasilania 3.3V za pomocą rezystora 470Ohm. Zabezpiecza to zarówno diodę jak i wyjście mikrokontrolera.
Ustawianie stanu wyjścia cyfrowego
Do zmiany stanu wyjścia cyfrowego służy funkcja digitalWrite, której składnię znajdziesz poniżej:
digitalWrite(numer_pinu, stan);
Funkcja ta przyjmuje dwa argumenty – numer pinu, co jest już dość oczywiste oraz pożądany stan wyjścia. Zmienna symbolizująca stan wyjścia reprezentowana jest przed dwie wartości stałe stosowane w Arduino: HIGH oraz LOW. Oznacza to, że żeby ustawić stan wysoki na pinie 5, musimy wywołać funkcję następująco:
digitalWrite(5, HIGH);
Znaczenie stałych HIGH oraz LOW zmienia się nieco w zależności od tego, czy pin jest skonfigurowany jako wyjście, czy wejście. W przypadku wyprowadzenia skonfigurowanego jako wyjście sprawa jest dosyć prosta:
- stała HIGH oznacza, że na wyjściu mikrokontrolera pojawi się napięcie 5V (np. na Arduino Uno, Nano) lub 3.3V (np. na płytce NodeMCU i innych wykorzystujących mikrokontrolery dostosowane do tego poziomu napięcia) względem masy układu, oznacza to, że pin może być źródłem prądu dla diody LED dołączonej przez rezystor szeregowy do masy.
- stała LOW oznacza, że na wyjściu mikrokontrolera napięcie wynosi 0V, wyjście mikrokontrolera w tym stanie może pobierać prąd, czyli np. dioda LED dołączona przez rezystor szeregowy do dodatniej szyny zasilania zacznie świecić.
Domyślam się, że może być dla Ciebie nieco niezrozumiałe, że w obu przypadkach stała HIGH lub LOW może doprowadzić do zaświecenia diody LED. W dużym skrócie istnieją dwa podejścia do sterowania układami wykonawczymi – sterowanie stanem niskim, lub sterowanie stałym wysokim. Póki co jednak nie będę Ci niepotrzebnie mieszał tym w głowie, postaram się za to konsekwentnie stosować jeden typ logiki. Pamiętaj jednak, że w modułach różnych producentów może wystąpić konieczność zmiany logiki sterującej wyjściami lub wejściami.
Przykład 1 – Sterowanie wyjściem cyfrowym i podłączanie diody LED
Poniższy rysunek przedstawia sposób złożenia układu na płytce uniwersalnej. Przy budowaniu układu koniecznie zwróć uwagę na biegunowość diody LED! Kod umożliwiający przełączanie stanu wyjścia znajdziesz poniżej:
void setup() { pinMode(D1, OUTPUT); //Skonfiguruj pin D1 jako wyjście } void loop() { digitalWrite(D1, HIGH); //włącz diodę delay(1000); //Odczekaj sekundę digitalWrite(D1, LOW); //wyłącz diodę delay(1000); }
W ramach samodzielnych ćwiczeń i eksperymentów sprawdź jak będzie działał układ, kiedy wykomentujesz jedną z linijek zawierających wywołanie funkcji digitalWrite. Pozwoli Ci to lepiej zapamiętać i zrozumieć działanie wyjścia cyfrowego oraz stanów HIGH i LOW.
Następnie sprawdź przy jakiej najmniejszej wartości opóźnienia w funkcji delay będziesz dostrzegał miganie diody.
Dobrze byłoby też, gdybyś ten sam eksperyment przeprowadził podłączając diodę według następującego schematu (zwróć uwagę na odwróconą biegunowość diody LED);
Sprawdź też co się stanie, jeśli wywołanie funkcji digitalWrite umieścisz w ciele funkcji setup().
Tryb INPUT – cyfrowe wejście
Jak pewnie się domyślasz, aby skonfigurować piny jako cyfrowe wejście, musisz napisać następujący fragment kodu:
void setup() { pinMode(5, INPUT); }
Wyprowadzenie mikrokontrolera skonfigurowane w trybie INPUT ma kilka ciekawych cech. Zacznę nieco nietypowo, od omówienia jakie znaczenie w przypadku wejść cyfrowych mają stałe LOW i HIGH. Pomoże nam to w zrozumienia pozostałych cech charakterystycznych pinów skonfigurowanych w trybie INPUT.
Wartości LOW i HIGH dla cyfrowych wejść
W poprzednich akapitach wspominałem, że stałe LOW oraz HIGH dla pinów w trybie OUTPUT są określane jako konkretne, stałe wartości napięcia wyjściowego. Nieco inaczej jest w przypadku trybu INPUT. Źródła sygnałów sterujących zazwyczaj nie są idealne. Poziomy napięć przez nie generowanych mogą zmieniać się w zależności od wielu czynników, między innymi temperatury. W wyniku tego, wejścia cyfrowe muszą mieć pewną tolerancję, aby umożliwić prawidłowe działanie pomimo tego typu różnic. W przypadku Arduino działa to podobnie, a stany HIGH oraz LOW są ustawiane dla następujących zakresów wartości:
- stan HIGH wykrywany jest na danym wejściu, jeżeli zostanie do niego doprowadzone napięcie powyżej 3.0V – w przypadku płytek przystosowanych do zasilania napięciem 5V, lub powyżej 2.0V – dla płytek zasilanych napięciem 3.3V,
- stan LOW wykrywany jest na wejściu, jeżeli zostanie na nim wykryte napięcie poniżej 1.5V – dla płytek zasilanych napięciem 5V, lub poniżej 1.0V dla płytek dostosowanych do napięcia zasilającego 3.3V.
Dalsze cechy wejść cyfrowych
W przeciwieństwie do trybu OUTPUT, wejście cyfrowe jest w stanie wysokiej impedancji. Oznacza to, że stanowi dla dołączonego do niego układu bardzo niewielkie obciążenie, za to idealnie nadaje się do pełnienia roli czujnika/miernika. Skutkuje to również tym, że cyfrowe wejście, które nie jest dołączone do żadnej z szyn zasilania znajduje się w tak zwanym „stanie pływającym”. Oznacza to, że poziom napięcia odczytywany z tego wejścia przez mikrokontroler może zmieniać się w nieprzewidziany sposób. Przykładowo, jeśli dotkniesz nóżki mikrokontrolera palcem, lub zbliżysz inne, pracujące urządzenie elektroniczne, może to wpłynąć na odczytywany stan wejścia. Problem ten możesz rozwiązać stosując tak zwane rezystory podciągające lub ściągające.
Rezystory podciągające oraz ściągające
W praktyce, wyprowadzenia skonfigurowane w trybie INPUT będziesz najczęściej wykorzystywał do obsługi wszelkiego rodzaju przycisków i przełączników. Załóżmy, że podłączysz przycisk tak jak na poniższym schemacie:
Działanie takiego układu jest dosyć proste – kiedy naciśniesz przycisk, czyli zewrzesz jego styki, spowodujesz, że na wejściu mikrokontrolera pojawi się napięcie 0V. Spowoduje to zmianę stanu wejścia na LOW. W kodzie programu, po wykryciu tego stanu będziesz mógł wykonać jakieś działanie, na przykład zwiększyć wartość licznika. Zwróć jednak uwagę, że kiedy przycisk nie jest naciśnięty, pin do którego przycisk jest podłączony niejako „wisi w powietrzu”. Zgodnie z tym co wcześniej pisałem, napięcie wykrywane na tym pinie będzie zmieniało się w zależności od występowania różnych czynników zewnętrznych. Może to doprowadzić do nieprawidłowego działania Twojego układu.
Rezystory podciągające/ściągające
W celu uniknięcia opisanych wcześniej efektów możesz zastosować wspomniane już przeze mnie rezystory podciągające lub ściągające. Mają one na celu zapewnienie występowania na wejściu znanego, ustalonego stanu (napięcia) w czasie, gdy przycisk nie jest wciśnięty. Rezystory podciągające oznaczają, że przy rozwartych stykach przycisku wejście układu jest „podciągnięte w górę” do stanu wysokiego (z ang. HIGH). Analogicznie rezystory ściągające służą do „ściągania wejścia w dół” do stanu niskiego (z ang. LOW). Jak pewnie się już domyślasz wybór pomiędzy stosowaniem rezystorów podciągających i ściągających jest znowu zależny od stosowania sterowania stanem niskim lub wysokim w układzie. Typowo wartość rezystorów obu typów wynosi około 10kOhm. Jest to wartość umożliwiająca kompromis pomiędzy poziomem poboru prądu, a pewnością odczytu stanu wejścia.
Schematy obu sposobów podłączenia przycisku do pinu mikrokontrolera znajdziesz poniżej. Nie chciałbym jednak zbyt mocno zagłębiać się w tłumaczenie zagadnień związanych typowo z elektroniką, odsyłam więc do kursów na innych stronach.
Tryb INPUT_PULLUP – cyfrowe wejście + wbudowane rezystory podciągające
Zanim przejdziemy do tego jak odczytywać stan wejść cyfrowych, czas na małą niespodziankę! Mikrokontrolery stosowane w płytkach Arduino posiadają zazwyczaj możliwość włączenia wbudowanych rezystorów podciągających! Oznacza to, że możesz uniknąć dołączania zewnętrznych rezystorów podciągających. Wystarczy, że ustawisz pin w tryb INPUT_PULLUP, co obrazuje poniższy fragment kodu:
void setup() { pinMode(5, INPUT_PULLUP); }
Możesz wówczas podłączyć przycisk według poniższego schematu:
Wiesz już jak konfigurować wejścia cyfrowe oraz jak podłączyć do nich przyciski. Nie pozostaje już nic innego, jak dowiedzieć się jak odczytywać stan wejść.
Przykład 2 – Microswitch jako przełącznik chwilowy
Odczytywania stanu wejść nauczymy się na prostym, praktycznym przykładzie. Zbuduj układ według następującego schematu:
Naszym pierwszym celem będzie zaprogramowanie płytki tak, aby dioda świeciła się tak długo, jak naciśnięty jest przycisk. Metodę setup napisz samodzielnie, podpowiem Ci tylko, że przycisk nie posiada zewnętrznego rezystora, musisz więc skonfigurować wejście w trybie INPUT_PULLUP. Pamiętaj też, że przy konfigurowaniu możesz użyć jako nazwy pinu stałej D5.
Kod funkcji loop() możesz znaleźć poniżej:
void loop() { int buttonState = digitalRead(buttonPin); if buttonState == LOW { digitalWrite(ledPin, HIGH); } else { digitalWrite(ledPin, LOW); } }
W razie problemów, cały kod programu znajdziesz poniżej:
Przeanalizujmy teraz razem działanie programu. Na początku pętli odczytywany jest stan wejścia, do którego dołączony jest przycisk. Odczytana wartość zostaje zapisana w zmiennej lokalnej buttonState, typu int. Następnie porównujemy wartość zmiennej buttonState ze stałą HIGH, oczywiście za pomocą instrukcji if. Jeśli wykryjemy stan LOW, co oznacza naciśnięcie przycisku, ustawiamy wyjście w stan HIGH, co powoduje zaświecenie diody.
Jak widzisz, ten bardzo prosty program umożliwia wykorzystanie przycisku microswitch, w typowej dla niego roli przełącznika chwilowego. Pewne działanie wykonywane jest tylko w przypadku, kiedy przytrzymujemy wciśnięty przycisk. Działanie to będzie jednak powtarzane w bardzo krótkich odstępach czasu (rzędu mikrosekund, jeśli nie stosujemy opóźnień w głównej pętli programu) tak długo, jak długo będzie wykonywana funkcja loop, co nie zawsze będzie przez nas pożądane. W kolejnym przykładzie pokażę Ci więc jak reagować wyłącznie na zmianę stanu przycisku.
Przykład 3 – Reagowanie na zmianę stanu przycisku
Przy realizacji tego przykładu wykorzystamy ten sam układ co poprzednio. Jako punkt wyjścia wykorzystamy też kod z poprzedniego przykładu. W funkcji setup() dodaj inicjalizację modułu UART, tak jak robiliśmy to na przykład w tym wpisie. Następnie dodaj zmienną globalną typu int o nazwie counter (z ang. licznik) o wartości początkowej równej 0.
W bloku kodu odpowiadającym za włączanie diody LED dodaj linię kodu zwiększającą wartość zmiennej counter o 1. Dodaj też wyświetlanie wartości tej zmiennej przez port szeregowy. Uruchom program i sprawdź co się dzieje w monitorze portu szeregowego, kiedy naciskasz i przytrzymujesz przycisk. W razie problemów kod programu znajdziesz poniżej:
Jeśli czujesz się na siłach, spróbuj przerobić ten program tak, aby wartość zmiennej counter była zwiększana tylko w momencie zmiany stanu przycisku, z rozwartego na zwarty. Podpowiedzi jak to zrobić znajdziesz poniżej:
Konieczne jest dodanie drugiej zmiennej globalnej, która będzie przechowywała poprzedni stan przycisku. Zmienna ta musi być nadpisywana bieżącym stanem przycisku na koniec wykonywania pętli programu. Musisz też zawrzeć sprawdzanie obecnego stanu przycisku wewnątrz drugiej komendy if, sprawdzającej czy bieżący stan przycisku jest inny niż w poprzedniej iteracji pętli. Wewnątrz tego bloku if warto również dodać na samym końcu komendę delay(50); aby uniknąć tzw. efektu drgania styków.Jeśli nie masz pomysłu jak wykonać to zadanie, możesz podejrzeć gotowy kod tutaj:
Jak widzisz cała modyfikacja jest bardzo prosta i sprowadza się do „opakowania” komendy if w kolejne sprawdzenie logiczne. Dodana przez nas komenda if sprawdza, czy aktualny stan przycisku różni się od stanu odczytanego w poprzednim obiegu głównej pętli programu. Oznacza to oczywiście, że na koniec głównej pętli programu musimy zaktualizować wartość zmiennej globalnej przechowującej stan przycisku.
Zjawisko drgań styków
Zwróć uwagę na instrukcję delay(50) – jest to celowe wprowadzenie opóźnienia 50ms. Opóźnienie to jest tzw. software’owym sposobem redukcji efektu drgań styków. W dużym skrócie – przy zwieraniu lub rozwieraniu styków przełączników pojawiają się bardzo szybkie, chwilowe zmiany poziomów napięcia. Mogą one powodować nieprawidłowe działanie programu fałszując na przykład odczyt ilości naciśnięć przycisku. Opóźnienie 50ms pozwala na bezpieczne „przeczekanie” tego efektu.
Przykład 4 – Microswitch jako przełącznik bistabilny
Kod z poprzedniego przykładu jest dobrym wstępem, do wykonania znacznie bardziej użytecznego programu. Bardzo często będziemy chcieli uzyskać efekt trwałego przełączania stanu układu na podstawie krótkiego naciśnięcia przycisku. Przykładowo, po pierwszym naciśnięciu przycisku lampka będzie włączona, a po kolejnym naciśnięciu lampka się wyłączy. Do osiągnięcia takiego efektu, wystarczy naprawdę w niewielkim stopniu rozszerzyć kod z poprzedniego przykładu. Zachęcam Cię do próby samodzielnego rozbudowania programu, jeśli jednak nie dasz rady wymyślić czego brakuje, poniżej znajdziesz podpowiedź:
Jeśli wciąż nie wiesz jak napisać ten program, możesz podejrzeć kod poniżej:
Rozbudowa kodu jest bardzo niewielka. Jedyne co dodaliśmy, to instrukcja if sprawdzająca wartość operacji counter % 2 == 0. „% 2” oznacza operację modulo 2 – rezultat tego działania, to reszta z dzielenia wartości zmiennej counter przez 2. Jak widzisz wraz z kolejnymi naciśnięciami przycisku wartość ta będzie przełączała się pomiędzy 0 a 1 (co jak przypominam odpowiada wartościom false oraz true) i powodowała zaświecenie lub wyłączenie diody. Nie jest to najbardziej elegancki sposób na osiągnięcie tego efektu, ale jest to najprostszy sposób na rozszerzenie kodu z poprzedniego przykładu.
Projekt – Mini Keyboard Arduino
Uff, ten wpis zostanie chyba póki co rekordzistą pod względem długości! 😉 Ale to jeszcze nie koniec, mam jeszcze dla Ciebie propozycję małego projektu, który jednak może dać sporo frajdy! Do wykonania układu będziesz potrzebował brzęczyka piezo bez wbudowanego generatora. Razem z kilkoma przyciskami oraz płytką NodeMCU, pozwoli nam on stworzyć prosty instrument muzyczny. Schemat układu i sposób montażu na płytce stykowej możesz znaleźć poniżej:
Żeby zmusić nasz buzzer do wydawania dźwięków użyjemy metody Arduino o nazwie tone. Przykładowe wywołanie tej funkcji wygląda następująco:
tone(pin, czestotliwosc_Hz, czas_trwania);
Funkcja ta przyjmuje 3 argumenty: numer pinu, częstotliwość wyrażoną w Hertzach oraz czas trwania dźwięku wyrażony w milisekundach (ostatni argument jest opcjonalny, można go pominąć).
Cały nasz projekt, będzie polegał na obsłudze czterech przycisków tak, aby powodowały one generowanie czterech różnych dźwięków. Cała ta funkcjonalność może zostać zrealizowana dzięki napisaniu jednej prostej funkcji przyjmującej dwa argumenty. Jeśli nie masz już siły na napisanie tego projektu samodzielnie, możesz zajrzeć na repozytorium.
Przykład działania urządzenia możesz znaleźć poniżej:
Jeśli nie poznajesz, jest to „solo” Dawida Podsiadło z utworu Początek, będącego utworem promującym trasę Męskie Granie 2018. Oto cała zagadka mojego clickbaita, mam nadzieję, że mi wybaczycie ten mały żarcik! 😉
Podsumowanie
Uff, znowu wyszedł mi strasznie długi post, jednak wciąż nie wyczerpuje on zagadnienia cyfrowych portów wejść/wyjść w Arduino! 🙂 Póki co mam jednak nadzieję, że te informacje zaspokoją Twoją ciekawość i pozwolą stworzyć jakieś ciekawe projekty. Zgodnie z tym co ostatnio zapowiadałem, następny post będzie miał nieco lżejszą tematykę. Będzie on dotyczył oszczędzania na zakupach związanych z nauką Arduino, myślę więc, że przyda się on wszystkim początkującym! Póki co, pochwal się w komentarzach swoimi projektami z wykorzystaniem portów cyfrowych wejść/wyjść i do zobaczenia! 😉
Świetny tutorial.
Dziękuję za lekcję 🙂