Analogowe wejście/wyjście
Układy ARDUINO umożliwiają obsługę sygnałów analogowych. W przypadku sygnałów wejściowych mamy do dyspozycji przetwornik A/C (analogowo-cyfrowy), w przypadku wyjść możliwa jest modulacja PWM (modulacja szerokości impulsów). Dokładniejsze informacje można znaleźć na stronie pl.wikipedia.org:
W przypadku ARDUINO, którego sercem jest jeden z układów ATMEGA mamy do dyspozycji jeden 10-bitowy przetwornik A/C. Oznacza to, że wartość odczytanego napięcia może zawierać się w przedziale 0 - 1023. W zależności od napięcia odniesienia 1024 wartości przetwornika A/C rozłożone zostaną na odpowiedni zakres. W efekcie możemy otrzymać różną dokładność i różny zakres napięć odczytywanych przez przetwornik. W przypadku podania napięcia odniesienia 1,024V każdej kolejnej wartości odczytanej z przetwornika będzie odpowiadał 1mV. W przypadku, gdy napięcie referencyjne wzrośnie do 5V każda kolejna wartość będzie odpowiadała ok. 5mV. Należy zaznaczyć, że przetworniki A/C nie mają idealnej charakterystyki liniowej. Oznacza to, że w pewnych przedziałach mogą wystąpić różnice pomiędzy napięciem podanym, a wartością napięcia odczytanego. Jak widać z powyższego zwiększając zakres pomiarowy tracimy na jakości pomiaru, zmniejszając zakres zwiększamy dokładność pomiaru.
Uwaga: ARDUINO posiada kilka (w zależności od wersji) wejść analogowych, jednak przetwornik A/C jeden. Oznacza to, że jeden przetwornik może odczytywać jednocześnie wartość napięcia analogowego z jednego wybranego pinu A0 - A5... (A0 - A15 dla ARDUINO MEGA)
analogReference()
Do prawidłowej pracy przetwornika analogowo - cyfrowego wymagane jest podanie napięcia odniesienia (referencyjnego). W przypadku ARDUINO napięcie referencyjne może zawierać się w przedziale 0 - 5V(lub 0 - 3,3V dla układów zasilanych tym napięciem). W zależności od typu wykorzystanego mikrokontrolera możemy dysponować różnymi napięciami odniesienia. Dodatkowo można korzystać z wewnętrznego lub zewnętrznego źródła napięcia odniesienia. Funkcja analogReference() umożliwia ustawienie odpowiedniego napięcia odniesienia. Do dyspozycji są następujące opcje:
- DEFAULT: napięcie odniesienia wynosi 5V lub 3,3V - w zależności od zasilania układu - czyli jest równe napięciu zasilania układu,
- INTERNAL: napięcie odniesienia wynosi 1.1V dla ATmega168 i ATmega328 i 2.56V dla ATmega8,
- INTERNAL1V1: napięcie odniesienia wynosi 1.1V - tylko ARDUINO MEGA,
- INTERNAL2V56: napięcie odniesienia wynosi 2.56V - tylko ARDUINO MEGA,
- EXTERNAL: napięcie podłączone do pinu AREF - 0 do 5V.
Opcję DEFAULT wybieramy, by skorzystać z napięcia odniesienia 5V (zasilanie układu). Jest to najprostsza metoda, jednocześnie najmniej dokładna. Wymaga zapewnienia dobrej stabilizacji układu. Jedna z opcji INTERNAL jest dobrym rozwiązaniem, w sytuacji, gdy tworzymy układ dedykowany dla konkretnej wersji ARDUINO. Wewnętrzne napięcie odniesienia jest w miarę stabilne i wystarcza w większości zastosowań. Najdokładniejszym rozwiązaniem jest zastosowanie zewnętrznego źródła napięcia odniesienia. Dostępne są specjalne układy podające wymagane stabilne napięcie odniesienia. Minusem tego rozwiązania jest ewentualny koszt układu. Dodatkowym plusem jest możliwość uzyskania wymaganego dokladnego napięcia odniesienia np. 1,024V czy 2,048V, co ułatwia interpretację odczytanych danych z przetwornika A/C.
Składnia funkcji analogReference() pokazana została na poniższym przykładzie:
analogReference(DEFAULT); //napięcie odniesienia = napięcie zasilania
analogReference(INTERNAL); //napięcie odniesienia = 1,1V lub 2,56V
analogReference(EXTERNAL); //napięcie odniesienia = napięcie na AREF
analogRead()
Funkcja analogRead() umożliwia odczytanie wartości z jednego z pinów analogowych. Wartość odczytana jest z przedziału 0 - 1023 (10-bitowy przetwornik). Należy podać numer wejścia analogowego, z którego nastąpi odczyt danych. Poniższy przykład ilustruje sposób wykorzystania wejść analogowych:
#define analogPin 0 // potencjometr podłączony do A0
int val = 0; // zmienna przechowująca odczytaną wartość
void setup()
{
Serial.begin(9600); // inicjalizacja portu szeregowego
}
void loop()
{
val = analogRead(analogPin); // odczyt wartości napięcia z portu A0
Serial.println(val); // wysłanie odczytanej wartości na terminal
}
Jak widać na powyższym przykładzie odczytana wartość podanego napięcia jest przesyłana poprzez port szeregowy do komputera. W przykładzie nie wykorzystano funkcji analogReference(), ponieważ domyślnie układ pobiera napięcie odniesienia z zasilania. Warto jednak w funkcji setup dodać jawnie wybór napięcia odniesienia, ponieważ ułatwia to zrozumienie kodu oraz jego modyfikację w przyszłości.
analogWrite() - PWM
Funkcja analogWrite() umożliwia sterowanie wyściem za pomocą sygnału PWM, co często jest stosowane jako zamiennik typowego sygnału analogowego. W zależności od typu zastosowanego w ARDUINO mikrokontrolera zmiena się liczba dostępnych pinów mogących pracować jako wyjścia PWM. Układy z mikrokontrolerem ATMEGA8 udostępniają piny 9, 10, 11. ATMEGA 168 i 328 pozwala na skorzystanie z pinów 3, 5, 6, 9, 10, i 11, natomiast wersje ARDUINO MEGA (ATMEGA 1280, itp.) udostępniają PWM na pinach 2 do 13 i 44 do 46. Częstotliwość kluczowania sygnału PWM większości pinów to 490Hz. Stopień wypełnienia kształtowany jest za pomocą liczb z przedziału 0 do 255. 0 - brak wypełnienia, 255 - pełne wypełnienie. Jeżeli podłączymy diodę LED do pinu PWM i będziemy zmieniać wypełnienie sygnału, to zaobserwujemy zmianę intensywności świecenia LED. Poniżej znajduje się przykładowy program sterujący diodą LED:
#define ledPin 11 // LED podpięte do pinu 11
#define analogPin 0 // potencjometr na A0
int val = 0; // zmienna przechowująca wartość z A0
void setup()
{
pinMode(ledPin, OUTPUT); // pin 11 jako wyjście
}
void loop()
{
val = analogRead(analogPin); // odczyt z potencjometru
analogWrite(ledPin, val / 4); // zapis do PWM
}
Jak widać wartość odczytana z wejścia analogowego zostaje zamieniona na odpowiadającą jej wartość PWM. Ze względu na przedział - wartość z A0 należy podzielić przez cztery, żeby proporcjonalnie działał PWM. W tym przykładzie zastosowano proste dzielenie. ArduinoIDE udostępnia również specjalną funkcję do tworzenia proporcji (czyli proporcjonalnego przeliczania wartości) o nazwie map(), zostanie ona opisana w innym miejscu kursu.