Tijekom pandemije COVID-19, e-radionica.com nastavlja s normalnim radom. Sve mjere opreza se redovno poduzimaju te su naručeni paketi sigurni. Opcija dostave uslugama Hrvatske Pošte i osobno preuzimanje privremeno su onemogućeni iz sigurnosnih razloga.

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 Croduino Basic, Basic2, Pico, Damba, 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 Croduino 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:

int ulaz = A0;
void setup() {
pinMode(ulaz, INPUT); // nije nuzno
Serial.begin(9600); // započinjem serijsku komunikaciju
}
void loop() {
int digOcitanje = digitalRead(ulaz); // spremam digitalno očitanje pina A0 u varijablu digOcitanje
int anaOcitanje = analogRead(ulaz); // spremam analogno očitanje pina A0 u varijablu anaOcitanje
// ispisujem očitane vrijednost u Serial Monitoru
Serial.print("Digitalno ocitanje: ");
Serial.println(digOcitanje);
Serial.print("Analogno ocitanje: ");
Serial.println(anaOcitanje);
delay(100);
}

Ako imate potenciometar pri ruci spojite ga prema slici dolje, mijenjajte položaj i pratite promjene u Serial Monitoru.
 
Potenciometar na A0 pinu

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 Croduinu 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
 
potenciometar i ledica

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
}

Uploadajte kod i promatrajte što se događa. Pri punom okretu potenciometra čak četiri puta se ledica ugasila, iako smo očekivali da će se vrijednost mijenjati od ugašeno do maksimalno upaljeno. Razlog tome je kada varijabla ocitanje dobije vrijednost 256 (za PWM maksimalno je 255) analogWrite() je definira kao 0, odnosno potpuno ugasi ledicu, jer PWM prihvaća samo 8bitne(0-255) vrijednosti. Dakle, 256 postaje 0, 257 postaje 1, 258 postaje 2 i td.
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
// );
int mapiranaVrijednost = map(ocitanje, 0, 1023, 0, 255);

Odnosno, u primjeru s potenciometrom i LED diodom:

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
int mapiranaVrijednost = map(ocitanje, 0, 1023, 0, 255);
analogWrite(led, mapiranaVrijednost); // stanje ledice postavljamo prema vrijednostii analognog ocitanja pina A0
}

Zanimljivo!

 
Znate li da je u jednoj liniji koda moguće mijenjati stanja OUTPUT pina te koristiti digitalRead() s OUTPUT pinovima?

digitalWrite(13, !digitalRead(13));

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);
}

2 thoughts on “Arduino IDE: INPUT/OUTPUT”

  • Ivan Stanisic
    Ivan Stanisic 7.07.2017 at 10:32

    Postovani, zanima me koje su mogucnosti Croduina u procesima kucne automatizacije, tacnije u implementaciji Croduino mikrokontrolera u smart home sistemiima?
    Pozdrav!

    Reply
Leave a Reply