Pilot na podczerwień – TSOP22xx
Czyli wykorzystujemy bibliotekę IRLib wraz z czujką TSOP22xx. Przy tej okazji pokazałem, jak instalowac biblioteki w Arduino IDE na 2 sposoby: z pliku zip, oraz ze środowiska.
Cujka TSOP22xx pożera bardzo mało prądu (jedynie 5 mA – patrz nota katalogowa) i dlatego zdecydowałem się pokazać Wam podłączenie jej bezpośrednio do płytki Arduino (czyli bez przewodów lub płytki stykowej). Jedna nóżka czujki siedziała w GND, druga w pinie numer 13 (zasilanie VCC) a trzecia – sygnałowa – w pinie 12 Arduino – bardzo stabilna konfiguracja. Należało tylko włączyć zasilanie na 13-tce aby odbiornik podczerwieni pracował – ale to już powinniśmy umieć (ponownie: pamiętacie „zabawy” z LED-ami? no właśnie po to one wszystkie…).
Nasz pierwszy projekt polegał na odczytywaniu kodów klawiszy z domowego pilota, a potem sterowanie trzema LEDami. Przy tej okazji poznaliśmy też wygodny zamiennik instrukcji if/else w języku C – a mianowicie switch/case.
Dzielnik napięć
Wróciliśmy do dzielnika aby pobawić się miernikami oraz… aby za chwilę wykorzystać je w projekcie inteligentnego oświetlenia sterowanego Arduio. Ale to za chwilę. Najpierw fajna (mam nadzieję) zabawa z multimetrem 😉
Dzielnik napięć – bardzo podstawowa wiedza, ale niezbędna podczas zabawy z Arduino i podobnymi. Dlatego zajęcia rozpoczęliśmy od dwóch rezystorów o tej samej wartości, wówczas ze wzoru na dzielnik Uwy= Uwe*R/(R+R1)= 0.5*Uwe i przy pomocy miernika uniwersalnego mierzyliśmy napięcie Uwy. Jako źródło mieliśmy do dyspozycji baterie AAA (różnie – jedni 2 sztuki, inni 4) o różnych napięciu. Dlatego aby prawidłowo wykonać to ćwiczenie trzeba było najpierw zmierzyć napięcie źródła. Dzielnik napięć zbudowaliśmy na płytce stykowej, o tak:
Gdy już prawidłowo zbudowaliśmy dzielnik napięć i rozumieliśmy co się dzieje z mierzonym napięciem, zastąpiliśmy fotorezystorem.
Fotorezystor
Oświetlenie fotorezystora powoduje zmniejszenie jego rezystancji (a tym samym zwiększenie płynącego przez niego prądu, jeśli mamy stałe napięcie zasilania). Oświetlenie zmienialiśmy albo zasłaniając ręką fotorezystor, albo oświetlając go latarką z telefonu komórkowego. Dalej zamieniliśmy jeden z rezystorów z naszego dzielnika napięć na fotoopornik i przeprowadziliśmy pomiary napięcia. Układy doświadczalne prezentowały się w ten oto sposób:
Warto podkreślić, że istotne jest który rezystor zastępujemy fotoopornikiem. Rysunki poniżej przedstawiają dwa podobne układy dzielnika napięć – zwróć uwagę na wskazania napięcia przy zmianie oświetlenia:
Czyli w jednej konfiguracji napięcie rosło oświetlając dzielnik, w drugiej – napięcie malało. Najpierw każdy z nas ustalił więc, co ma na swojej płytce aby kontrolować swój układ.
Odczyt zastanego oświetlenia
W tym ćwiczeniu do zbudowanego układu podłączyliśmy Arduino z pinem analogowym i odczytywaliśmy napięcie, niezależnie od miernika – to ważne, aby kontrolować to co wypisuje nam Arduino niezależnym miernikiem (u nas multimetrem). Ponownie okazało się, że aby otrzymać wyniki bardzo zbliżone do multimetru należało najpierw upewnić się jakie mamy faktycznie napięcie 5V w naszym Arduino (wiadomo – uczniowie/studenci popełniają błędy – a kto nie! – i płytka się uszkadza…. są więc płytki z napięciem 4.7V zamiast katalogowych 5V).
Inteligentne oświetlenie
Do układu podłączyliśmy LEDa, którego jasnością sterowaliśmy poprzez Arduino z pinem PWM (poprzednie zajęcia z przykładem Fade). Zabawa miała polegać na oprogramowaniu układu tak, aby LED gasł gdy jest dużo światła zastanego (mierzonego przez fotorezystor i wejście analogowe Arduino), oraz aby LED świecił mocniej i mocniej gdy światła zastanego braknie. Takie proste, ale inteligentne oświetlenie 😉
Tutaj poznaliśmy nową funkcję z biblioteki Arduino: map(). Funkcja ta przeskalowywała (liniowo) podaną wartość z pewnego zakresu (dziedziny, poniżej oznaczonej jako wartości od min_x do max_x), na inna wartość z innego zakresu (przeciwdziedzina, od min_y do max_y). Formalnie wygląda to następująco:
map(war, min_x, max_x, min_y, max_y)
co oznacza, że chcemy przeskalować wartość war z zakresu min_x do max_x, na wartość z przedziału min_y do max_y. W naszym przykładzie chodziło o przeskalowanie wartości odczytywanych przez analogRead (czyli wartości od 0 do 1023) do wartości podawanych do sterowania jasnością LEDa (przez PWM, czyli z zakresu 0..255). Dlatego skalowaliśmy
war2= map(war, 0, 1023, 255, 0);
To liniowe skalowanie przez funkcję map() nie ma „magii” w sobie, to proste wykorzystanie funkcji liniowej y=ax+b, znanej Wam z lekcji matematyki plus umiejętność rozwiązania układu równań. Dopowiadając: w liniowym skalowaniu mamy 2 nieznane parametry – współczynniki a i b prostej. Musimy więc podać dwa równania aby je wyznaczyć (chyba każdy pamięta, że do narysowania prostej potrzebne są tylko dwa punkty? więc stąd dwa równania…). Posługuję się wartościami krańcowymi, oczywistymi przy naszym zagadnieniu: chcę bowiem, by do PWMa trafiło 255 gdy na wejściu z analogRead-a było 0 (pierwsze równanie: y=255 gdy x=0), oraz chcę, by mieć wartość y=0 gdy podaję x=1023 (drugie równanie). Oba punkty podstawiam do niewiadomego y=a*x+b i otrzymuję układ równań. Funkcja map() znajduje a i b za nas i wyznacza każdą inną wartość leżącą na tej prostej.
UWAGA: map() działa tylko na liczbach całkowitych!
Przyjrzyjcie się ponownie mojemu rysunkowi – to prosta matematyka w zastosowaniu 😉
Sterowanie jasnością LDEa przez PWM robiliśmy poleceniem analogWrite(9, war2);
Okazało się, że aby wszystko działało dość widowiskowo należało najpierw wyskalować nasze odczyty jasności zastanej zmniejszając zakres…. W wielu przypadkach było więc potrzebne:
war2 = map(war, 400, 800, 255, 0);
co sprawdziło się metodą prób-i-błędów – w tym celu mocno debugowaliśmy nasz kod wypisując na ekran monitora odczytywane liczby.
Serwo silnik (a właściwie mikro-serwo)
Czyli silnik, który obraca się od 0 do 180 stopni (ma blokadę na inne wychylenia). Potem utrzymuje swoją pozycję. Służy do tworzenia obrotowych ramion itd…
Trzy przewody – zasilanie (czerowny +5V, czarny/brązowy GND) oraz jeden sterujący – musi być PWM. Za dużo nie wnikałem o co chodzi w sterowaniu tym silnikiem, tylko wspomniałem o potencjometrze wewnątrz i o wypełnieniu sygnału sterującego… więcej może później? Zobaczymy.
Do sterowania tym silnikiem użyliśmy 2 nowych funkcji z nowej biblioteki:
- #include <Servo.h> – na początku programu informujemy, że chcemy funkcje z tej nowej biblioteki
- Servo silniczek; tworzymy zmienną typu silnik-serwo, czyli właśnie o to nam chodzi!
- silniczek.attach(3); powoduje przekazanie informacji do Arduino, że sterujemy silnikiem przez pin numer 3 (przypominam: musi być to pin PWM, czyli jak nie 3, to 5,9…)
- silniczek.write(133); ustawia nasz silnik w pozycji 133 stopni. Albo na dowolny inny z zakresu 0..180 stopni. Dziecinie proste 😉
Serwo sterowane z klawiatury
Przypomnieliśmy sobie jak odczytywać liczby z klawiatury (funkcja parseInt() dla obiektu Serial) i stworzyliśmy program ustawiający silnik w pozycji wczytanej z klawiatury. Proste a przyjemne. No i zawsze warto powtarzać wiedzę 😉
Prąd „zjadany” przez serwo – mierzymy!
W skrajnych ustawieniach serwa (tj. w okolicy 0 stopni, oraz w okolicach 180 stopni) słyszymy buczenie/piszczenie serwo-silnika. Coś się dzieje. Amperomierz w garść i mierzymy prąd.
Przyjrzyj się uważnie obrazkowi i zwróć uwagę, jak podłączony jest amperomierz.
Oczywiście w wirtualnym Arduino silniczek serwo jest idealny i nie widzimy tego, co było u nas na zajęciach….
Dodatkowo: w przypadku mierników uniwersalnych ustaw największą wartość prądu, jaką się spodziewasz dostać – nie odwrotnie! W przeciwnym przypadku zwiększając zakres przepalisz bezpiecznik w multimetrze…
Serwo sterowane pilotem na podczerwień
W tym przykładzie wróciliśmy do początku zajęć i ponownie wykorzystaliśmy pilot od telewizora – tym razem czytywaliśmy klawisze i ustawialiśmy serwo na konkretną wartość kąta. Dwa przyciski obracały serwo w lewo i w prawo, trzeci zaś ustawiał serwo w pozycję 90 stopni.
Serwo pracy ciągłej (aka 360 stopni)
Poznaliśmy też serwa obracające się „w kółko”, ale z kontrolą szybkości swoich obrotów. Sterowanie polegało na używaniu funkcji writeMicroseconds(), w której komenda STOP dla silnika wymagała podania wypełnienia 1500 ms, natomiast wypełnienie z zakresu 1501-2000 ms oznaczało obrót w prawą stronę z prędkością proporcjonalną do tego wypełnienia (i analogicznie z obrotami w lewą stroną – wypełnienie z przedziału 1000-1499 ms).
Ta sama funkcja writeMicroseconds() może być przydatna w korygowaniu niedoskonałości tanich, chińskich serw, które nie trzymają katalogowych parametrów – obrót od 0 do 180 stopni. Proszę tylko obchodzić się z nią ostrożnie, bo z poprzedniego ćwiczenia – gdzie mierzyliśmy prąd zjadany przez serwo – wiemy, że dużo się dzieje w skrajnych położeniach.
Koniec? Początek!
Z wielkim niedosytem kończymy nasze spotkania w ramach Talentów XXI w. Niedosyt bierze się z faktu, że umiemy obsługiwać kilka fajnych „klocków” i aż się prosi, aby je teraz połączyć w jakąś całość (samochodzik sterowany pilotem, albo obrotowa wieżyczka z laserem). Ale czas naszych spotkań dobiegł końca. Cóż… zachęcam do samodzielnej pracy i koniecznie pochwalcie się swoimi osiągnięciami – dlatego dla Was jest to początek przygody z Arduino (mam nadzieję!). Proszę śmiało pisać do mnie na email! Pozdrawiam i dziękuję za wspólną pracę, K. Gawryluk