ARDUINO IDE: INPUT/OUTPUT

UVOD
Arduino mikrokontroleri imaju hrpu I/O pinova od kojih neki imaju mogućnost “analognog”. Iako Arduino funkcija pinMode() postavlja pinove kao ulazne (input) ili izlazne (output), niti ih je uvijek potrebno postavljati niti će uvijek raditi kako očekujemo. Cilj ovog tutoriala je rasjasniti upotrebu i ponašanje I/O pinova na 8bitnim AVR Arduino pločicama, kao što su Dasduino Core, Dasduino Lite, Arduino Uno, Mega i drugi.
POČETNO STANJE
Pri pokretanju Arduina svi pinovi postavljeni su kao INPUT. Kao INPUT, pinovi se nalaze u stanju visoke impedancije, što onemogućava kratke spojeve. Kada bi čitali stanje ovih pinova ne bi bilo stablilno, odnosno pin bi floatao između LOW i HIGH. Više o toj pojavi pročitajte u tutorialu o pull-up otpornicima.
Izuzetak je digitalni pin13, koji je definiran kao OUTPUT. Razlog tomu je što Arduino pri svakom pokretanju pokreće program bootloader čija je svrha osluškivanje serial pinova kako bi registrirali novi kod u PROGMEMu. Probajte resetirati Dasduino i primjetiti ćete da je narančasta ledica na 13tom pinu zablinkala. Nakon završetka, pin13 se vraća u INPUT stanje te ga možete nastaviti koristiti kao i svaki drugi I/O pin.
INPUT
INPUT je svaki pin definiran da čita ulazno stanje, npr. foto-otpornik, tipkalo, potenciometar i neki senzori. Stanje pina se određuje tako da mikrokontroler čita napon na pinu. Razlikujemo analogni i digitalni ulaz. Analogni su, za razliku od digitalnih, spojeni na muliplekser, a svaki od njih na A/D (analog to digital) konverter.
analogRead() prema referentnom naponu daje 32bitne vrijednost(0-1023). Zadana vrijednost referentnog napona je 5V. To znači ako mikrokontroler očita napon od 0V dodjeliti će mu analognu vrijednost 0, dok 1023 označava 5V. Za ostale vrijednost proporcionalno tome. Referentni napon možemo sami zadati tako da ga dovedemo na aref pin Arduina, naravno pod pretpostavkom da nije veći od maksimalnog koje mikrokontroler može podnijeti (5V).
digitalRead() sve napone iznad 3V (za 5V pločice) definira kao HIGH, a sve ispod toga kao LOW. NAPOMENA: praksa je da se pinove definira kao HIGH/LOW, iako će ispravno raditi i 1/0 (kako ih prikazuje i Serial Monitor) ili true/false.
pinMode() možemo koristiti za definiranje pinova kao INPUT, iako je dobro imati na umu:
1. pinMode() definira pinove kao digitalne, ne analogne inpute.
2. Kada se pozove analogRead(), pin se automatski rekonfigurira u pin za input
Bez obzira na navedeno, preporuka je koristiti pinMode() pri definiranju ulaznih pinova zbog preglednosti koda. Kod će biti pregledniji tako što ćemo znati koje pinove i na koji način koristimo.
Primjer:
OUTPUT
OUTPUT definiramo izlazne pinove, odnosno izlazni napon. Kao i kod ulaznih razlikujemo digitalne i “analogne”(PWM) pinove. Primjer komponenti i modula koje koristimo kao OUTPUT: LED diode, buzzer, releji, motori i dr.
analogWrite() radi s pinovima koji podržavaju PWM (Puls-Width Modulation). Na Dasduinu to su digitalni pinovi 3, 5, 6, 9, 10 i 11, a označeni su apostrofom(‘). Pogledaj pin-out. Kao i kod analogRead(), analogWrite() postavlja pin kao OUTPUT. Vrijednost koju možemo zadavati s analogWrite je 8bitna (0-255).
digitalWrite “šalje” 5V (HIGH) ili 0V (LOW) na pin.
Primjer:
Spojimo katodu(kraću nožicu) LED diode preko 330ohm otpornika na gnd, a anodu(dužu nožicu) na digitalni pin(PWM)9 kako prikazuje slika dolje
int
led = 9;
// ledica na PWM pinu 9
int
pwnVrijednost = 153;
// definiramo pwm vrijednost (između 0 i 255)
// 0 = 0V; 255 = 5V i proporcionalno
void
setup
() {
pinMode
(led,
OUTPUT
);
// definiramo ledicu kao OUTPUT
}
void
loop
() {
digitalWrite
(led,
HIGH
);
// prvi argument je pin, drugi LOW/HIGH; palimo(5V) ledicu
delay
(500);
// zaustavljamo program na 500ms = 0.5sek
digitalWrite
(led,
LOW
);
// gasimo(0V) ledicu
delay
(1000);
analogWrite
(led, pwmVrijednost);
// prvi argument je pin, drugi vrijednost između 0 i 255, palimo(3v) ledicu
delay
(500);
analogWrite
(led, 0);
// gasim(0V) ledicu
delay
(1000);
}
NAPOMENA(u primjeru iznad): 153(PWM) je ekvivaletno naponu od 3V. To smo dobili iz omjera: x/5V = 153/255. Dakle x = 153*5V/255= 3V. *(znamo da je 0V = 0(PWM) i da je 5V = 255(PWM))
KAKO ANALOGNO OČITANJE PRETVORITI U PWM?
Za kraj pokazati ćemo kako analogna očitanja(0-1023) pretvoriti u PWM(0-255). Iz primjera s potenciometrom i LED diodom koju smo koristili za testiranje INPUT/OUTPUT, očitavati ćemo stanje potenciometra i ovisno o njemu pojačavati/smanjivati svjetlost LED diode. Iako na prvi pogled izgleda vrlo jednostavno i banalno, problem se može pojaviti zbog raspona. Pogledajmo na primjeru dolje, koji NIJE ISPRAVAN:
int
led = 9;
// ledica na pinu 9
int
ulaz = A0;
// potenciometar na pinu A0
void
setup
() {
pinMode
(ulaz,
INPUT
);
pinMode
(led,
OUTPUT
);
}
void
loop
() {
int
ocitanje =
analogRead
(ulaz);
// definiramo novu varijablu ocitanje
// u kojoj se sprema analogno ocitanje(0-1023) potenciometra
analogWrite
(led, ocitanje);
// stanje ledice postavljamo prema vrijednostii analognog ocitanja pina A0
}
Kako bismo izbjegli ovo uvodimo integriranu funkciju map(), koja će nam mapirati vrijednost u zadani raspon. Koristimo je na sljedeći način:
// varijabla u koju spremamo novu vrijednost =
// map(
// varijabla koju želimo mapirati, minimalna vrijednost koju mapiramo, max vrijednost koju mapiramo,
// minimalna vrijednost u koju mapiramo, maksimalna vrijednost u koju mapiramo
// );
Odnosno, u primjeru s potenciometrom i LED diodom:
ZANIMLJIVO
Znate li da je u jednoj liniji koda moguće mijenjati stanja OUTPUT pina te koristiti digitalRead() s OUTPUT pinovima?
Prva stvar koju primječujete je kako se digitalRead() koristi za definiranje stanja pina13. Znači li to da se pin koristi kao INPUT i OUTPUT u isto vrijeme? Ne. Zapravo, čini se kada pozivamo digitalRead() na pinu koji je definiran kao OUTPUT čitamo status registra PORTx unutar ATmega mikrokontrolera.
Postoji nekoliko takvih registra unutra mikrokontrolera(x predstavlja “B, C, D”), a sadrže trenutno stanje pinova. Konkretno pin13 se nalazi na PORTB. Kada je pin definiran kao OUTPUT, digitalWrite() komunicira s PORTom kako bi ga promijenio tj. omogućio HIGH ili LOW. Kada pozove digitalRead(), PORTx registar se mijenja u trenutnu vrijednost, ako je digitalWrite() postavljen u LOW digitalRead() će vratiti LOW, i obratno. Zanimljivo!
Još je potrebno objasniti “!“. Njega zovemo još NOT operator ili bang, a zapravo je najbrži način za invertiranje vrijednosti. HIGH pretvara u LOW, i obratno.
Za kraj, isprobajte kod:
void
setup
() {
pinMode
(13,
OUTPUT
);
// koristimo narančastu ledicu na Croduino pločici
}
void
loop
() {
digitalWrite
(13, !
digitalRead
(13));
delay
(1000);
}