Kurs Arduino – #6 – kontynuacja UART, serwomechanizmy

Kurs Arduino – #6 – kontynuacja UART, serwomechanizmy

W tej części zajmiemy się kilkoma tematami. Po pierwsze wrócimy na chwilę do UART, omówimy również nowe instrukcje sterujące. Na koniec praktyczne zastosowanie dla serwa.

Przed czytaniem upewnij się, że znasz podstawy opisane w dotychczasowych częściach naszego darmowego kursu Arduino dla każdego!

Reprezentacja liczb w terminalu

W trzeciej części kursu wykorzystywaliśmy interfejs UART do komunikacji z komputerem. Były tam używane funkcje do nadawania oraz odbierania informacji. Jednak nie omówiłem wtedy wszystkich możliwości jakie daje nam pozornie prosta funkcja println. W przykładach, które pojawiły się do tej pory wykorzystana była ona w najprostszej formie, czyli z jednym argumentem - liczbą lub ciągiem znaków, który ma zostać przesłany.

Wszystkie wartości, które przesyłaliśmy w realizowanych zadaniach wyświetlaliśmy w systemie dziesiętnym. Co jeśli zależałoby nam na wyświetlaniu liczb np.: binarnych? Czy musimy stworzyć własne funkcje zamieniające reprezentację wartości na inne systemy? Nie!

Na szczęście biblioteki Arduino zawierają szereg udogodnień dla użytkowników końcowych. W tym wsparcie kilku systemów reprezentacji liczb. Gdy przesyłamy za pomocą println jakąś wartość, to możemy zadecydować jak ma być ona wyświetlana na komputerze:

Jak widać było to w eksperymentach z poprzednich części domyślnie liczby wyświetlane są w formie dziesiętnej, ale do wyboru mamy jeszcze system: szesnastkowy, ósemkowy oraz binarny. W praktyce najczęściej wykorzystywać będziesz zapewne domyślną, dziesiątkową reprezentację oraz binarną.

Zestaw elementów do kursu

Gwarancja pomocy na forum Błyskawiczna wysyłka

Teraz możesz kupić zestaw ponad 70 elementów niezbędnych do przeprowadzenia ćwiczeń z kursu u naszych dystrybutorów!

Kup w Botland.com.pl

Precyzja liczb niecałkowitych

Jak było omawiane we wcześniejszych częściach kursu, możliwa jest również deklaracja zmiennej, które będzie przechowywała liczbę niecałkowitą, np.: 3,141592. Do tej pory nie zajmowaliśmy się takimi przykładami, bo dobrą praktyką jest unikanie na mikrokontrolerach liczb z częścią ułamkową.

Załóżmy jednak, że koniecznie chcemy wyświetlić taką liczbę. Mógłby do tego posłużyć bardzo krótki, poniższy program:

Uruchomienie powyższego programu, powinno przynieść następujący efekt:

Precyzja wyświetlanych liczb.

Precyzja wyświetlanych liczb.

Jak widać, jeśli przesyłamy liczbę, to dodatkowym parametrem może być cyfra określająca z jaką precyzją mają być wyświetlane wartości. Należy przy tym pamiętać, że zmienne typu float są reprezentowane na maksymalnie 7 cyfrach - niezależnie od tego ile jest ich za, a ile przed przecinkiem. Przykładowo:

  • float liczba1 = 0.123456 - poprawnie
  • float liczba2 = 12345.6 - poprawnie
  • float liczba3 = 123.456 - poprawnie
  • float liczba4 = 1234567.8 - błędnie

Wróćmy jeszcze na chwilę do powyższego programu, konkretnie do zagadkowej linijki:

Dlaczego komenda ta spowodowała wyświetlenie wartości 3.14? Nawet nigdzie nie deklarowaliśmy takiej zmiennej. Otóż wartość liczby Pi jest tak często używana, że w wielu językach znaleźć można gotowe stałe, które są równie przybliżeniu liczby Pi. W przypadku jest to PI, które w dowolnym miejscu programu zostanie zamienione na odpowiednią wartość.

Przykładowo, dążąc do wysokiej precyzji naszego programu moglibyśmy wywołanie funkcję:

Ku naszemu zadowoleniu na ekranie pojawi się wtedy bardzo dokładna wartość:

3.1415927410125732421875

Wróćmy jednak pamięcią do maksymalnych precyzji jakie oferują nam mikrokontrolery, okazuje się, że stała PI ma właściwości zmiennej float, czyli przyjmuje tylko 7 cyfr! Każda kolejna jest błędna, ponieważ najbardziej dokładny zapis wartości niecałkowitych w systemie binarnym nie pozwala na uzyskanie odpowiedniego, "prawdziwego Pi". Więcej na ten temat można zobaczyć w specjalnym kalkulatorze, który zasugerował w komentarzach czytelnik atmel21.

 Poniższe zestawienie to nasza wyświetlona liczba oraz prawdziwe Pi:

3.14159274101257324218750
3.14159265358979323846264

Wszystko od nowej linii?

Do tej pory każda wyświetlana w terminalu wartość pojawiała się w nowej linii. Było to czytelne, ale nie zawsze użyteczne. Co w przypadku, gdy chcielibyśmy wyświetlić kilka zmiennych oraz tekstów obok siebie? Z pomocą przychodzi bliźniacza do println funkcja print (bez końcówki ln od line).

Posiada ona dokładnie te same wartości, co używana do tej pory println. Oprócz tego, że każda wysłana wartość pojawia się w nowej linii. Przykład:

Program nie zachwyca swoim działaniem, ale demonstruje to, co najważniejsze (brak nowej linii):

Funkcja print w praktyce.

Funkcja print w praktyce.

Jak można przejść do nowej linii w wybranym miejscu? Na trzy sposoby:

Zdecydowanie najciekawszy sposób, to ten ostatni. Pojawia się tam nowy symbol \n. Jest on spotykany nie tylko w Arduino i oznacza przejście do nowej linii. Jak widać jest bardzo wygodny ponieważ pozwala na łamanie wiersza w dowolnym momencie.

Czy istnieją inne przydatne symbole tego typu? Tak! Do formatowania wyświetlanego tekstu może przydać się jeszcze możliwość używania tabulacji (wcięcia, dużego odstępu). Jeśli będziemy chcieli przesunąć w prawo, to zamiast nieładnego wpisywania kilku spacji należy wykorzystać symbol \t - tabulator.

Nowa informacje o UART w praktyce

Pora na wykorzystanie powyższych informacji w praktyce. Celem naszego programu jest pomiar wartości napięcia na pinie A5, a następnie wyświetlenie go w terminalu. Jednak tym razem nie wystarczy wyświetlenie liczby w systemie dziesiętnym. Dodatkowo - w jednym wierszu - mają być wyświetlane wartości w HEX, OCT oraz BIN. Oczywiście całość ma być ładnie sformatowana!

Na początku należy podłączyć prosty układ. Ja do zmiany napięcia wykorzystałem potencjometr. Jednak równie dobrze możesz w tym miejscu umieścić dzielnik napięcia z fotorezystorem. Jeśli nie pamiętasz jak, to zajrzyj do 4 części kursu.

Potencjometr podłączony do A5.

Potencjometr podłączony do A5.

Mam nadzieję, że wcześniejsze informacje nie sprawiły Ci dużo problemów, więc pozwolę sobie na umieszczenie od razu gotowego programu. Oczywiście, koniecznie przeanalizuj jego działanie i napisz samodzielnie podobny program!

Po uruchomieniu programu, w terminalu, powinniśmy obserwować ładnie sformatowane wartości ADC pokazywane w różnych systemach zapisu liczb:

Arduino - różna reprezentacja liczb.

Arduino - różna reprezentacja liczb.

Zachęcam do eksperymentów we własnym zakresie. Jest to również idealna okazja do ćwiczenia ręcznej konwersji liczb na różne systemy. Na tym zakończymy część o UART, pora iść dalej.

Zadanie domowe 6.1

Napisz program, który odczytuje informację dwóch fotorezystorów oraz potencjometru. Następnie po wciśnięciu przycisku podłączonego do Arduino wysyłaj jeden raz linijkę zawierającą informacje:

"Fotorezystor 1: XXX, fotorezystor: XXX, potencjometr: XXX, przycisk wciśnięto XX razy"

Gdzie zamiast X pojawią się oczywiście właściwe wartości.

Instrukcja sterująca switch

Pora na omówienie bardzo często używanej instrukcji sterującej switch. Jest ona wykorzystywana w sytuacjach, gdy na podstawie jednej zmiennej wykonujemy kilka różnych akcji uzależnionych od wartości, którą sprawdzaliśmy.

W celu zrozumienia instrukcji switch posłużę się przykładem, który następnie zostanie rozwiązany na dwa sposoby - tradycyjnie oraz nową metodą. Załóżmy więc, że chcemy napisać program, który odczyta wartość ADC, a następnie odeśle ją do nas w formie liczby dziesiętnej, szesnastkowej, ósemkowej lub binarnej. Wszystko zależy od naszego wyboru.

Dysponując aktualną wiedzą moglibyśmy napisać program korzystający z warunków:

Wykonalne? Tak. Wygodne? Średnio, szczególnie gdyby warunków było dużo więcej lub nagle konieczna byłaby zmiana warunków. Z pomocą przychodzi nowa instrukcja sterująca switch-case. Wygląda ona następująco:

Na początku piszemy słowo kluczowe switch, następnie w nawiasie okrągłym podajemy zmienną, którą chcemy sprawdzić. W analogicznym przykładzie do poprzedniego z if'ami byłoby to:

Następnie otwieramy nawiasy klamrowe. W ich wnętrzu możemy wpisać dowolną ilość warunków, które będą kolejno sprawdzane. Robimy to pisząc słowo case, a po spacji wstawiamy wartość, której musi być równa sprawdzana zmienna. Całość kończymy znakiem dwukropka ":".

Jeśli warunek zostanie spełniony to wykona się kod od momentu warunku do najbliższego słowa break, które spowoduje wyjście z całego switcha. Gdy warunek nie będzie spełniony, to część kodu jest ignorowana i mikrokontroler przechodzi do sprawdzenia kolejnego warunku (case).

Na końcu opcjonalnie możemy umieścić kod pomiędzy default oraz break. Zostanie on wykonany, gdy żaden z wcześniejszych warunków nie został spełniony. Zdaje sobie sprawę, że może brzmieć to skomplikowanie dlatego przejdziemy teraz do przykładu praktycznego i przerobimy wcześniejszy program.

Mała uwaga, instrukcja sterująca switch działa tylko na podstawie porównywania liczb. Dlatego w tym przykładzie litery, którymi sterujemy: d, h, o, b musimy traktować nie jako litery, a jako kody ASCII. Zapis litery w pojedynczych apostrofach, obok case, powoduje, że są one traktowane właśnie jako kody ASCII.

Co więcej zamiast poprzednio używanej funkcji odczytującej dane:

Wykorzystana została prostsza wersja funkcji, które odczytuje jedynie pierwszy bajt (znak) danych:

Dzięki temu mogliśmy porównywać przesyłane komendy i wykonywać odpowiednie operacje. Mam nadzieję, że instrukcja switch będzie dla Ciebie jeszcze bardziej zrozumiała, gdy wykonamy kolejne przykłady praktyczne.

Zadanie domowe 6.2

Wróć do zadania domowego nr 2.4, które znajduje się w trzeciej części kursu Arduino i wykonaj je tym razem z wykorzystaniem instrukcji switch.

Serwomechanizm w praktyce - wskaźnik światła

Pora na obiecane wykorzystanie serwomechanizmu w praktyce. Aktualnie coraz więcej informacji prezentowanych jest w sposób cyfrowy, czyli na wyświetlaczu.

Jednak niektóre wartości, takie jak temperatura, intensywność oświetlenia itd. lepiej prezentują się na tradycyjnych analogowych wskaźnikach. Czyli takich ze wskazówką:

Wskaźniki analogowe.

Wskaźniki analogowe.

Dlatego teraz zbudujemy analogowy wskaźnik nasłonecznienia z wykorzystaniem microserwa. Wskazówka umieszczona na jego ramieniu będzie wskazywała ilość światła padającą na czujnik. Potrzebne do tego będzie Arduino z podłączonym fotorezystorem w układzie dzielnika napięcia oraz serwomechanizm.

Schemat montażowy gotowego urządzenia prezentuje się tak, jak poniżej:

Schemat montażowy.

Schemat montażowy.

Jest on odrobinę zawiły, jednak tak naprawdę składa się z dwóch prostych schematów. Pierwszy to podłączenie serwomechanizmu wraz z zasilaniem ze stabilizatora. Dodatkowo dwa kondensatory pojawiły się zaraz obok tego regulatora napięcia. podobny schemat znaleźć można w poprzedniej części kursu Arduino, natomiast więcej o samych stabilizatorach zostało napisane w odpowiednim odcinku kursu elektroniki.

Druga część schematu to podłączenie rezystora i fotorezystora w dzielnik napięcia. Dokładniejsze informacje na ten temat znaleźć można w części dotyczącej ADC w Arduino.

Cześć mechaniczna projektu

Warto od razu pomyśleć nad "profesjonalną" tarczą i wskazówką. Ja tarczę wykonałem z kilku sklejonych wizytówek oraz wydrukowanej skali. Strzałka została wykonana w podobny sposób. Do łączenia elementów polecam klej na ciepło (z pistoletu) lub taśmę dwustronną.

Jakość wykonania nie jest najwyższa, jednak są to tylko eksperymenty i liczy się efekt:

Gotowy wskaźnik analogowy.

Gotowy wskaźnik analogowy.

Program jest stosunkowo prosty. Jego zadaniem jest cykliczny pomiar światła padającego na fotorezystor oraz sterowanie wychyleniem serwomechanizmu. Głównie zostały wykorzystane do tego poznane już wcześniej funkcje:

Wyjaśnienia może wymagać nowa funkcja abs(). Jest ona bardzo użyteczna w sytuacjach jak powyższa ponieważ zwraca wartość bezwzględną. Czyli niezależnie czy odejmiemy liczbę mniejszą od większej, czy odwrotnie, to uzyskamy wynik dodatni.

W przypadku tego programu zapamiętujemy również aktualną pozycję serwa, do zmiennej globalnej pozycjaPoprzednia. Dzięki temu w kolejnym obiegu pętli ruch wykonamy tylko przy dużej zamianie natężenia światła. W przeciwnym wypadku nasza wskazówka mogłaby drgać. Polecam eksperymenty z wartością, od której wykonujemy ruch.

Program jest bardzo prosty, więc nie ma mechanizmów kalibracji autoamtycznej. W związku z tym, przez UART, wysyła do komputera aktualną wartość odczytaną z czujnika światła. Najszybsza kalibracja może polegać na podejrzeniu jaką najniższą i najwyższą wartość obserwujemy podczas zasłaniania oraz oświetlania czujnika. Następnie należy uwzględnić je w tej linijce:

Po kilku minutach prób i regulacji mój wskaźnik był gotowy do działania. Efekt widoczny jest na poniższej animacji. Fotorezystor był zasłaniany ręką, a następnie stopniowo oświetlany latarką.

Wskaźnik analogowy z wykorzystaniem Arduino.

Wskaźnik analogowy z wykorzystaniem Arduino.

Zachęcam do zmian ustawień i testowania nowych programów. Odradzam jednak zbyt szybkie ruszanie serwem. Może to wprowadzać pewne problemy lub uszkodzić stosunkowo delikatny silnik. proponuję nie schodzić poniżej 100 ms ustawianych w tej linijce:

Zadanie domowe 6.3

Dopracuj układ ze wskaźnikiem analogowym. Spróbuj dodać mechanizm kalibracji. Znajdź inne praktyczne zastosowanie dla takiego układu!

Zadanie domowe 6.4

Wstaw w komentarzu zdjęcie przygotowanego przez siebie wskaźnika!

Podsumowanie

Część dodatkowa, uzupełniająca wyszła całkiem długa. Mam jednak nadzieję, że będzie pomocna. Ze smutkiem po raz kolejny ze smutkiem stwierdzam, że rozpisałem się zbyt mocno. W związku z tym część materiału została przesunięta do kolejnego artykułu. Konkretnie chodzi o sterowanie silnikami DC. Zagadnienie to jest (nie)stety zbyt ważne, aby potraktować je skrótowo.

Pamiętaj, że komplet elementów niezbędnych do przeprowadzenia wszystkich ćwiczeń jest dostępny w Botlandzie. Zakup zestawów wspiera kolejne publikacje na Forbocie!

Nawigacja kursu

Najbliższe części kursu, to demonstracja wykorzystanie wyświetlacza tekstowego, który dołączony jest do zestawu. Jak zawsze zachęcam do robienia zadań domowych oraz zadawania pytań w komentarzu.

Autor: Damian (Treker) Szymański

PS Nie chcesz przeoczyć kolejnych części naszego darmowego kursu programowania Arduino? Skorzystaj z poniższego formularza i zapisz się na powiadomienia o nowych publikacjach!

arduino, fotorezystor, komunikacja, kursArduino, PWM, serwo, serwomechanizmy, uart