Jest to przedmiot składający się z dwóch form dydaktycznych: wykładu oraz laboratoriów
Zasady zaliczenia są następujące:
obowiązkowe zaliczenie 1. części laboratorium ("Autka 1"), plus ew. projekt laboratoryjny ("Autka 2")
kolokwium (termin TBA)
oddany projekt (omówienie na wykładzie)
Z w/w form są wystawiane punkty, odpowiednio:
L (laboratorium - 2.0 do 5.5)
K (kolokwium - 0 - 5.0, przy braku podejścia przyjmuję 2.0)
P (projekt - 2.0 do 5.5)
Ocena ostateczna wyliczna jest jako średnia
ważona: aL + bK + cP; (a,b,c - ustalone w terminie późniejszym); wynik zaokrąglany jest w górę.
Wykład
Wykład odbywa się w środy o godz. 9.15 w sali 29/D1. Slajdy do wykładów (hasło przekażę drogą pantoflową):
(4,11 marca) Wprowadzenie o systemach wbudowanych, omówienie projektu
(18 marca) Komunikacja: UART || kod klasy Ticker (można uruchomić na Wokwi)
W ramach wykładu studenci realizują zadanie projektowe. Kolejne listy będą publikowane
poniżej.
Lista 1. (do 21 marca) -- wymyślenie systemu, analiza, opis słowny, podstawowe wymagania. W razie wątpliwości „czy taki system może być” proszę pisać.
Uwaga. Gotowe listy proszę przesyłać we wskazanym terminie na mój adres e-mail.
W temacie proszę podać nazwę systemu, poprzedzając ją przedrostkiem "[Projekt]".
Ogólne zasady zaliczenia laboratoriów. Poniżej, dla każdego tygodnia (lub dwóch) będą pojawiać
się zadania/listy. Wszystkie te listy będą zawierać zestaw poleceń i kod do rozbudowania wraz z instrukcjami lub
wprowadzeniem teoretycznym. List będzie 6-8, ich zaliczenie skutkuje zdobyciem 4 punktów z laboratoriów. Osoby chcące zdobyć
większą liczbę punktów, po zaliczeniu list podstawowych muszą samodzielnie rozbudować autko (na podstawie listy dodatkowej, która
zostanie opublikowana w maju), lub zrobić niezależny od niego projekt - po konsultacji z prowadzącym.
Szczegółowe zasady dotyczące zaliczenia list ustala każdy prowadzący laboratoria.
Obejrzyj dokładnie płytkę Arduino UNO oraz dostępne Ci inne podzespoły pojazdu.
Wykorzystaj opis płytki w sieci, aby zidentyfikować: główny mikrokontroler, piny we/wy
(jakie mają funkcje?), diodę LED (ile ich jest? do czego służą?), zasilanie, reset.
Uruchom środowisko programistyczne Arduino (możesz uruchomić na swoim laptopie).
Połącz płytkę arduino przewodem USB z komputerem. Upewnij się, że w menu
Narzędzia/Płytka oraz Narzędzia/Port wybrane są, odpowiednio,
"Arduino/Genuino Uno" oraz port w stylu /dev/ttyACM0. Możesz sprawdzić, czy wszystko
działa za pomocą Narzędzia/Pobierz informacje o płytce.
Uruchom przykład Przykłady/Basics/Blink i zapoznaj się z kodem oraz
samouczkiem. Zajrzyj też
do odnośników z rozdziału "Learn more".
Skompiluj kod (znaczek "ptaszka" z lewej strony belki menu). Sprawdź, jakie informacje
o skompilowanym kodzie otrzymasz. Przeanalizuj je. Następnie wgraj (przycisk obok)
kod na płytkę przyglądając się temu, co się z nią w tym czasie dzieje (wgrywanie
możesz powtórzyć, żeby się upewnić). Sprawdź, czy Twoje domysły na temat kodu i faktyczne
jego działanie są zbieżne. Jeśli nie - rozwiąż konflikt :)
Pobierz ten kod i
otwórz w środowisku. Ponownie przeanalizuj kod, postaw
tezę co do tego, co on robi. Skompiluj i wgraj na płytkę. Wybierz
Narzędzia/Monitor portu szeregowego (Ctrl+Shift+M), ustaw odpowiedni baudrate
i zweryfikuj swoje domysły co do programu.
Korzystając z dwóch przedstawionych programów, napisz swój, który:
pobierze literę przez port szeregowy,
wymruga ją za pomocą diody w kodzie Morse'a.
Pojawiło się zasilanie bateryjne, podłączone do silników. Mogą one obracać kołami, w
związku z tym, aby nie spowodować niekontrolowanego ruszenia pojazdu stojącego
na biurku, przed włączeniem zasilania należy ustawić pojazd na podstawie z gąbki!
Dostępny jest wyłącznik główny, odcinający zasilanie bateryjne. Jeśli Arduino podłączone jest
przez kabel USB, to nadal będzie zasilane (ale tylko płytka).
Widok wnętrza autka. Pokazane rozprowadzenie zasilania. Prześledź drogę od baterii (od przełącznika - '+' baterii to czerwony przewód)
do układu N298. Uwaga. Na fotografii powyżej przewody zasilające silniki są podwójne i wielokolorowe. Na tym zdjęciu są tylko czarno-czerwone.
To jest obecna konfiguracja autek.
Ta lista poświęcona jest sterowaniu silnikami. Pojazd wyposażony jest w cztery silniki połączone parami tak, że
każda para napędza dwa koła po każdej stronie (a zatem koła obracają się jak w czołgu -- koła po jednej stronie
mogą obracać się tylko w tą samą stronę).
W jaki
sposób sterować silnikiem? Oczywiście przez podanie napięcia na jego dwa bieguny (są też inne silniki,
posiadające więcej wejść, ale o tych innym razem). Chcielibyśmy, aby to Arduino sterowało silnikiem, podobnie
jak w poprzednim tygodniu sterowało diodą (włącz/wyłącz).
Jednakże nie można podłączyć silnika bezpośrednio do któregoś z pinów Arduino: mikrokontroler nie jest
w stanie dostarczyć wystarczająco dużo prądu, by poruszyć silnikiem..
Dlatego też w autku zamontowany jest moduł z układem L298, który będzie pośredniczył pomiędzy Arduino a silnikiem
i odpowiednio włączał/wyłączał zasilanie pobierane bezpośrednio z baterii przez stabilizator napięcia, utrzymujący
stałe napięcie 6V (dwa akumulatory połączone szeregowo dają maksymalnie ok. 8.4V -- to nieco za dużo dla silnika).
Układ N298. Pobierz
specyfikację układu. Przeanalizuj schemat na pierwszej stronie. Potraktuj obecne tam
tranzystory NPN jako elektronicznie
włączniki: jeśli na bazie (B) jest „HIGH”, to tranzystor przewodzi między emiterem (E) a kolektorem (C).
Przeanalizuj, co się stanie, jeśli na „In1”, „In2”, „EnA” pojawią się różne kombinacje stanów LOW i HIGH.
(W tym schemacie zasilanie z baterii podłączane jest do „+Vs” (na środku u góry) i do wspólnej „ziemi” --
symbol krótkiej, grubej, poziomej kreski np. na dole schematu). Silnik podłączany jest do wyjść „OUT1” i
„OUT2”. Spróbuj wyobrazić sobie, jak za pomocą tego układu można sterować kierunkiem obracania się kół.
Programowanie ruchu. Na autku znajdziesz taśmę 6 przewodów, które „pod pokładem” są połączone jak
na powyższej fotografii.
Uwaga. Autka w wersji 2.0 mogą mieć odwrócone kolory taśmy!
Korzystając z dotychczas osiągniętych wyników, spróbuj podłączyć te przewody do
pinów 2-13 na Arduino tak, by móc sterować jazdą w przód i do tyłu silnikami po prawej i lewej stronie.
(Podpowiedź: przewody biały i żółty [wejścia „EnA” i „EnB” układu N298] podłącz do pinów zasilania „+5V”
w okolicach baterii. Po podłączeniu pozostałych przewodów możesz na nich ustawiać stany „HIGH” i „LOW”
tak, jak w przypadku świecenia diodą LED.)
Sterowanie prędkością. Odłącz teraz przewody żółty i biały od zasilania „+5V” i podłącz je do pinów
Arduino oznaczonych falką (~), są to: 3, 5, 6, 9, 10, 11. Są to piny, na których można wykonać operację
analogWrite(), co spowoduje, że średnie napięcie na tym pinie można zmieniać
pomiędzy 0V („LOW”) a 5V („HIGH”). [Więcej o tej technice, zwanej PWM - Pulse Coded Modulation
na wykładzie.] Przetestuj, jak kręcą się koła dla różnych wartości zapisywanych do pinów En1 i En2
(zapisanie za niskich wartości może sprawić, że koła nie będą się poruszać).
Rozbudowa biblioteki. Pobierz archiwum, rozpakuj i otwórz
w środowisku Arduino. Przeanalizuj kod i uruchom go ustawiwszy uprzednio autko na podstawce!
Dopisz do klasy Wheels metodę goForward(int cm)
oraz goBack(int cm), której wywołanie spowoduje, że autko przemieści się o
liczbę centymetrów podaną jako parametr.
Pora ułatwić sobie życie, tym bardziej, że autko powoli zaczyna stawiać samodzielne pierwsze kroki...
Dołączymy mu moduł LCD 2x 16 znaków oparty na kontrolerze
HD44780U. Żeby zaoszczędzić
piny na płytce Arduino, skorzystamy z
konwertera I2C-LCD.
Zapoznaj się z biblioteką
LiquidCrystal I2C (autor: Marco Schwartz). UWAGA! Jest wiele klonów, które
dodają różne funkcjonalności - jeśli chcesz, to możesz użyć innej (ale support tu się kończy :)). Jeśli to potrzebne, ściągnij
pliki tej biblioteki do swojego środowiska.
Uruchom program pokazowy. Poeksperymentuj z nim -- co jest nie tak? Zaproponuj zmiany.
Uwaga 1. Musisz poszukać, jak podłączyć konwerter do płytki -- oznaczenia na konwerterze są jasne, co do Arduino - zachęcam do szukania
w dokumentacji.
Uwaga 2. Jeśli program pokazowy nie działa, sprawdź, czy adres urządzenia I2C jest poprawny. Użyj skanera (Plik->Przykłady->Wire->i2c_scanner).
Uwaga 3. Jeśli na wyświetlaczu w obu liniach widzisz tylko prostokąty, użyj potencjometru z tyłu (niebieska kostka), by zmienić kontrast.
Uzupełnij swój kod autka tak, by w sposób ciągły wyświetlał na LCD pomiar odległości, którą auto ma jeszcze przejechać (podawanej jako argument
do poprzednio napisanego goForward()/goBack()).
Wykorzystując drugą linię wyświetlacza, zbuduj "deskę rozdzielczą" -- na dwóch końcach linii wyświetlaj, co aktualnie autko robi z silnikami
(prawa-lewa: przód/tył/stop a na środku linii -- zaproponuj animację wskazującą jazdę (przód/tył).
(Uwaga. Gdy koła kręcą się w tył, ich prędkość powinna być wyświetlana jako ujemna.)
Przypomnij sobie pierwsze laboratoria (mruganie diodą): interwał pomiędzy
przełączeniem diody był określany przez delay(). Ta sama funkcja definiowała
okres między rozpoczęciem jazdy i zatrzymaniem się (drugie laboratoria). Stąd powstaje problem: jeśli
procesor ma „nie robić nic”, gdy auto jedzie, to jak go zmusić do mrugania diodą? W idealnym świecie
rozwiązaniem byłyby wątki (sprzętowe lub jako mechanizm systemu operacyjnego), ale kontroler w Arduino
nie posiada takich dóbr. Posiada natomiast typowe dla mikrokontrolerów mechanizmy: liczniki i
system przerwań. Do wykonania poniższych zadań pobierz kod.
Na rozgrzewkę możesz też przeczytać tę lekcję.
Zadanie polega na usprawnieniu pojazdu tak, by przy jeździe wstecz robił „bip-bip”, tak
jak porządna ciężarówka. Dodatkowo należy modyfikować częstotliwość „bipów” w zależności
od prędkości. Mamy do wykorzystania tylko kilka głośniczków, jeśli Tobie zabraknie - możesz użyć
diody LED (pin 13). Otwórz szkic "beepInterrupt".
Przeanalizuj kod (przeczytaj dokumentację dla TimerOne!) i uruchom go na płytce.
Obserwując działanie (bipy lub mruganie diody), modyfikuj
okres działania. Wyślij też dłuższy ciąg (dowolnych) znaków z konsoli (odczytaj je przez Serial)
na płytkę: czy okres mrugania uległ zaburzeniu?
Wykorzystując ten program, zrealizuj zadanie główne - zaktualizuj metodę back()
tak, by auto mrugało/bipało przy jeździe wstecz.
Teraz zadanie polega na udoskonaleniu metod moveForward(), moveBack(), które
powstały na poprzednich laboratoriach. Uwaga. W każdym miejscu, gdzie używasz obiektu Serial spróbuj też
wykorzystać obiekt LCD z listy 2. -- zobacz, czy odczyty obrotów (o tym już za chwilę) są różne,
gdy wykorzystujesz komunikację z komputerem i bezpośrednie wyświetlanie na ekranie.
W autkach na osiach przednich kół zostały zamontowane kółka
z wyciętymi szczelinami (do wglądu u prowadzącego), oraz
czujniki szczelinowe. Idea ich działania jest prosta: jeśli czujnik „widzi” szczelinę w kółku,
to jego wyjście DO jest równe HIGH. Jeśli nie, to DO jest LOW.
Szczegóły podłączenia: Do sensorów połączone są dwie splecione, trójkolorowe wiązki:
VCC - czerwony, GND - czarny, DO - żółty.
Na zielonej płytce wiązki te wchodzą w gniazda oznaczone KOŁO PRAWE" i KOŁO LEWE
(zwróć uwagę na poaryzację (GND do GND).
Następnie sygnały DO wyprowadzone są na złączu "Sygnały" jako PRAWE i LEWE, skąd możesz
je odebrać kabelkiem żeńsko-męskim i doprowadzić do płytki Arduino na odpowiednie piny.
Musimy więc umożliwić Arduino reagowanie na zmianę poziomu DO, ale tak, by nie kolidowało to z
innymi zadaniami mikrokontrolera (np. rozmowa przez UART, obliczenia, etc.). Wykorzystamy do tego przerwania
zewnętrzne, a w szczególności przerwanie wywoływane przez zmianę stanu pinu (Pin Change Interrupt - PCI).
Wykorzystamy piny A0 i A1 - po jednym na czujnik. Przeanalizuj
obrazek.
Tym pinom przypisane są, odpowiednio, przerwania PCINT8 i PCINT9. Spróbujmy uruchomić mechanizm przerwań
dla tych pinów. Jest wiele sposobów na zakodowanie tego, my pójdziemy edukacyjną (trudniejszą) drogą,
a potem prostszą.
Trudniejsza: będziemy pracować ze
specyfikacją ATmega328P
(strony od 56.). Odnośny kod znajdziesz w szkicu "wheelSensorHard".
Spójrz najpierw na rejestr PCICR i opisy jego poszczególnych bitów. To bit PCIE1 uruchamia
przerwania dla PCINT8 i PCINT9 (oraz kilku innych). Ustawmy go w kodzie: PCICR = 0x02.
Druga rzecz, którą trzeba ustawić, to dla którego spośród pinów, dla których PCIE1 uruchamia przerwanie -
ma być wywołana procedura obsługi. Dalsza analiza specyfikacji (punkt 10.2.7) wykazuje, że jest za to
odpowiedzialny rejestr PCMSK1. Chcemy uruchomić przerwania dla PCINT8 i PCINT9, a zatem:
PCMSK1 = 0x03. Uwaga. Możliwe jest też wykonanie operacji:
PCMSK1 |= (1 << PCINT8) | (1 << PCINT9); z tym samym skutkiem.
Za każdym razem, gdy coś się zmieni na A0 i A1 (bo to Pin Change), zostanie wywołana obsługa
przerwania ISR(PCINT1_vect). To, co ta procedura wykona, zależy już od konkretnego
zadania, jakie ma obsłużyć, ale regułą jest nie używanie operacji buforowanych i o nieznanych czasach
wykonania (np. operacji we/wy). Zwykłe zwiększenie licznika jest OK (pamiętaj, że taka zmienna musi być
zadeklarowana jako volatile. UWAGA. Wywołanie obsługi przerwania w naszym
wypadku oznacza, że któryś z pinów A0, A1 zarejestrował zmianę. Określenie który to z nich - wymaga
po prostu sprawdzenia ich stanu.
Łatwiejsza: użyjemy gotowej biblioteki
PinChangeInterrupt. Przykładowy kod
znajdziesz w szkicu "wheelSensorEasy".
Otwórz szkic i w razie potrzeby zainstaluj bibliotekę (Narzędzia -> Zarządzaj bibliotekami).
Cała reszta jest prosta i czysta, jeśli wersja "trudna" jest dla Ciebie zrozumiała.
Porównaj jednak rozmiary kodów wynikowych w wersji trudniejszej
i prostszej. Którą wersję wybierzesz dla jakich przypadków?
Problem. Zauważ, że w przypadku wykorzystania procedury ISR(PCINT1_vect)
w takiej formie, jak podałem w przykładowym kodzie powoduje, że liczniki dla obu stron „rozjeżdżają” się,
i to znacznie! Przepisz procedurę na taką:
i sprawdź, czy coś się poprawiło. Jak myślisz, dlaczego?
Mając dwa sposoby na zliczanie impulsów z tarczy na osiach kół, rozbuduj bibliotekę
Wheels o udoskonaloną wersję poruszania się o daną odległość i możliwości skrętu.
(Jako wisienka na torcie) Dysponując możliwością kontroli rzeczywistej prędkości poruszania się
autka - narysuj wykres zależności prędkości od parametru funkcji Wheels::setSpeed(int).
Lista części składowych autka. Linki prowadzą do przykładów w jednym ze sklepów internetowych.
(pokaż)
Lista dodatkowych komponentów, które można użyć do zbudowania swojego własnego projektu
(pokaż)
(linki prowadzą do strony jednego ze sklepów, znajdują się tam podstawowe opisy modułów)
Możliwe jest użycie własnych komponentów. Jeśli będzie potrzebne lutowanie, proszę o kontakt.
Liczniki sprzętowe -- Dla ambitnych/na projekt: jak wykorzystać liczniki sprzętowe do dokładnego pomiaru prędkości autka (w związku z listami 2. i 3.).