środa, 2 marca 2016

Wyjście - Blink World!

Akcja i reakcja

Człowiek łatwo przyzwyczaja się do luksusu. Pisząc kodzik, którego zadaniem będzie wykonanie jakichś mniej lub bardziej skomplikowanych operacji, nie zawracamy sobie za bardzo głowy tym, w jaki sposób dostrzeżemy wynik tej operacji. Siedzimy przed monitorem, na którym wszystko zobaczymy. Build, Run i wszystko widać. Z mikrokontrolerami jest troszeczkę ciężej. Na początku nie mamy ani kawałka wyświetlacza albo połączenia poprzez port szeregowy. Jedyne, do czego mamy dostęp, do pamięć. Czas zrobić coś, żeby wyniki operacji wykonanych na pokładzie Atmegi były dla nas widoczne gołym okiem


Port

Patrząc na naszego procka, ciężko nie zauważyć "nóżek". Korzystając z noty katalogowej z łatwością odnajdziemy ich opisy. Część z nich posiada opis Pxn - gdzie x to litera od A do D (do F w przypadku Atmegi 128), n numer pinu od 0 do 7. Każdy port ma przypisany swój własny rejestr konfiguracyjny i rejestr odpowiedzialny za sterowanie napięciem na konkretnej nóżce.
Każdy pin z osobna możemy skonfigurować jako pin wyjściowy, wejściowy lub 3-stanowy (0, 1 i High-Z - stan wysokiej impedancji, nieustalony) . Skupmy się na tym pierwszym.

Konfiguracja portów

Żeby skonfigurować port jako wyjście, do rejestru odpowiadającemu naszemu portowi musimy wpisać 1 na pozycji odpowiadającej upatrzonej nóżce...
Aby pin 0 portu B był ustawiony jako wyjście:

DDRB |= (1 << PB0);


Korzystając z operatora przesunięcia bitowego i definicji pinu 0 dostępnej z poziomu biblioteki avr io ustawiamy wpisujemy 1 na pozycję odpowiadającą pinowi do rejestru kierunkowego (Data Direction Register)

Teraz możemy sterować stanem naszego pinu.

PORTB |= (1 << PB0);
PORTB &= ~(1 << PB0);


Wpisując 1 do rejestru PORTB ustawiamy stan wysoki na pinie, wpisując 0, ustawiamy stan niski. Czym są te stany? Niczym innym jak wartościami napięcia, jakie pojawią się na naszej nóżce. Stan wysoki będzie odpowiadał napięciu około napięcia zasilania, stan niski - ok 0.

int main()
{

   DDRB |= (1 << PB0);
   PORTB |= (1 << PB0);

   while (1)
   {

   }
}


Wgrywamy kawałek kodu do procka.

LED

Teraz multimetry w dłoń i sprawdzamy, czy na pinie 0 portu B mamy napięcie zbliżone do napięcia zasilania! Prawdopodobnie mamy. Ale czy za każdym razem będziemy ślęczeć z multimetrem? Nie. Z pomocą przyjdzie nam LED. Świecąca dioda, którą opatrzywszy w rezystor podepniemy do naszego mikrokontrolera.

Kierunek ma znaczenie

Jeżeli podepniemy diodę tak, że krótsza nóżka będzie bliżej mikrokontrolera - by ją zaświecić, trzeba będzie posłać na nią "0" - stan niski.
Jeżeli podepniemy diodę tak, że dłuższa nóżka będzie bliżej mikrokontrolera - by ją zaświecić, trzeba będzie posłać na nią "1" - stan wysoki.

Użyj rezystora - dioda posłuży dłużej

LED potrzebuje około 20mA, żeby ładnie świecić. Nasz Port może "wystawić" aż 100mA. Przy podpiętej 1 diodzie do 1 nóżki, może tam popłynąć prąd o właśnie takim natężeniu. Pięciokrotnie wyższy prąd nie działa dobrze na naszą diodę - zaczyna się po prostu palić. Jak temu zapobiec? Włączyć do walki ruch oporu!

Rezystancja

źródło: http://www.electronics.dit.ie/staff/tscarff/DT089_Physical_Computing_1/LEDS/Leds.htm 
Wspomagając się wykresami możemy wywnioskować, że zielona dioda zaświeci najładniej, gdy dotrze do niej prąd o natężeniu 20mA, a spadek napięcia wyniesie ok. 3.5V. Zasilając naszą Atmegę napięciem 5V, właśnie takie (mniej więcej) napięcie otrzymamy, wykonując instrukcję  PORTB |= (1 << PB0); Jaki rezystor należy zastosować?
Wróćmy na moment na lekcję fizyki. Prawo Ohma. Prosty wzór R = U/I [V/A]. Na naszym "świecącym" układzie wartość U to 5V. Oczekiwany prąd I - 20mA. Na wartość U złożą się napięcie na diodzie i napięcie na rezystorze - oczekiwane napięcie na diodzie znamy - wynosi 3.5V. 5 - 3.5 = 1.5. Podzielmy tę wartość przez 20, pamiętając o jednostkach! 1.5/0,020 = 75 Om.
I co teraz? Potrzebujemy rezystor o takim oporze. W każdym sklepie z rezystorami powinniśmy znaleźć interesujący nas element. A co jeśli okaże się, że nie posiadamy takiego? Weź wyższy - kolejny w szeregu - powinien zadziałać :)

Za te słowa będę się pewnie smażył w elektronicznym piekle.. ale po pewnym czasie przestaniesz zwracać uwagę na to, jaką diodę podpinasz i jaki rezystor do niej dobierasz. Chwycisz pierwszy lepszy rezystor, podepniesz diodę, sprawdzisz, czy świeci i zaczniesz robić ciekawsze rzeczy. Matematyka przyda się, gdy prototyp trzeba będzie przerobić w coś, co ma posłużyć dłużej bez większej ingerencji... Czy to nie brzmi znajomo?

Reasumując:
Q: Co się stanie, gdy rezystor o zbyt niskiej wartości?
A: Dioda zwyczajnie szybciej się zużyje (spali).
Q: Co się stanie, gdy dam rezystor o zbyt wysokiej wartości?
A: Dioda nie zaświeci.


Gdy 100mA to za mało

Jak już wymasterujemy świecenie diodą na wszystkie możliwe sposoby może pojawić się pytanie - i co dalej? Przecież nie podepnę mojego urządzenia do Internetu tylko po to, żeby świecić diodą?
Chcąc wysterować coś więcej niż proste światełko, przyda nam się wiedza o kolejnym elemencie elektronicznym - tranzystorze. Typów tranzystorów jest multum. Skupmy się na jednym NPN. Tranzystor posiada 3 nóżki - bazę, kolektor i emiter (na schemacie B, C i E). Wykorzystamy jego moce, by móc załączać/wyłączać wymagające więcej prądu urządzenia (np. buzzer, przekaźnik albo bagatela silnik DC!). Do bazy koniecznie podpinamy rezystor (patrz przykład z LED, sprawdź w nocie katalogowej, jaki powinien być prąd bazy i nie przekraczaj go), nóżkę emitera do masy (GND, "-" na płytce stykowej), do kolektora układ, który chcemy sterować (zacznij od podpięcia diody :)). Rezystor przy bazie? To rezystor do nóżki! Uruchamiamy układ  - "1" sprawi, że tranzystor "załączy" podpięty do kolektora układ, "0" wyłączy go.

Izolacja galwaniczna

Mikorkontroler to bardzo wrażliwe urządzenie i podpinanie do niego czegokolwiek mniej lub bardziej bezpośrednio może wpłynąć negatywnie na jego pracę - w najgorszym wypadku całkowicie ja zatrzymać... na amen. Na szczęście istnieją metody galwanicznej izolacji! Weźmy taki transoptor. Transoptor to układ składający się z diody i fototranzystora (?!). Jak to działa? Podajemy napięcie na diodę, ta świecąc na fototranzystor "załącza" go lub "wyłącza". Czy można prościej? Proszę bardzo. Weź do ręki pilot od telewizora. W jego górnej części znajdziesz diodę na podczerwień (odkrytą lub zasłoniętą przezroczystym plastikiem w kolorach zbliżonych do czerwonego). Poczuj jedność z pilotem - Ty jesteś mikrokontrolerem i naciskając Power na pilocie, kierujesz go w stronę telewizora i sprawiasz, że telewizor się załącza. Czy istnieje połączenie fizyczne między Tobą a telewizorem? Nie. Czy masz wpływ na działanie telewizora? Tak! Proste, czyż nie?
Podobnie działa przekaźnik - z tą różnicą, że tu wykorzystujemy zjawisko elektromagnetyczne. To tak jakbyś zamiast naciskania przycisku, dokładał jakąś metalową część do obwodu (włączał światło w pokoju za pomocą tego fancy klawisza na ścianie).


Dużo treści... a gdzie kodzik?!

Do pinów 0 i 1 portu B podpiąłem 2 diody.

#define F_CPU 8000000UL
#include <util/delay.h>
#include <avr/io.h>

int main()
{
   DDRB |= (1 << PB0) | (1 << PB1);

   PORTB |= (1 << PB0);
   PORTB &= ~(1 << PB1);

   while (1)
   {
         PORTB ^= (1 << PB0);
         PORTB ^= (1 << PB1);

         _delay_ms(500);
   }
}

Do czego można wykorzystać ten kawałek kodu?
A gdyby tak rozszyfrować protokół pilota od telewizora, podpiąć diodę IR i sterować telewizorem?

Może się przydać:
Atmega 162 - datasheet


Ta wiedza pozwoli Ci rozwijać projekty:
Sterowanie silnikiem krokowym
Zdalnie sterowany pojazd

1 komentarz:

  1. Miesięsty post! Aż dodałem do Instapaper zamiast przejrzeć od razu:)

    OdpowiedzUsuń