Semafor za automobile i pješake
Arduino upravlja semaforom za automobile, pješačkim svjetlom i zvučnim signalom, a vlastita funkcija drži program kratkim i čitljivim

Semafor na križanju izgleda jednostavno: tri svjetla koja se pale redom. Ipak, iza njega stoji program koji mora točno znati koje svjetlo smije svijetliti, koliko dugo i smiju li pješaci u tom trenutku krenuti.
Danas ćemo takav semafor izgraditi korak po korak. Najprije ćemo Arduinom upravljati 3D-printanim semaforom za automobile. Zatim ćemo dodati pješački semafor, a na kraju i zvučni signal koji pomaže osobama slabijeg vida.
Najvažnija programska tehnika današnje radionice je vlastita funkcija. Vidjet ćemo kako nam jedna dobro osmišljena funkcija omogućuje da semaforu dodamo potpuno novo ponašanje, a da glavni dio programa uopće ne mijenjamo.
Kako radi naš semafor?
Semafor prolazi kroz stanja. Stanje je jedna kombinacija upaljenih svjetala koja traje neko vrijeme.
| Korak | Automobili | Pješaci | Trajanje |
|---|---|---|---|
| 1 | crveno | stoje | 4 s |
| 2 | crveno + žuto | stoje | 1 s |
| 3 | zeleno | hodaju | 4 s |
| 4 | zeleno trepće | stoje | 2 s |
| 5 | žuto | stoje | 1 s |
| ⇒ | povratak na korak 1 |
Zamisli križanje. Naši automobili voze ravno kroz križanje, a naši pješaci hodaju pločnikom uz njih, istim smjerom, i prelaze poprečnu ulicu po pješačkom prijelazu. Automobili i pješaci tako idu jedni pored drugih i njihovi se putovi ne križaju. Zato pješaci smiju krenuti kada automobili imaju zeleno. Kada zeleno počne treptati, pješaci više ne kreću.
Pješaci ne prelaze cestu ispred naših automobila. Za njih bi vrijedilo obrnuto pravilo: smiju krenuti tek kada automobili imaju crveno.

Najvažnija pravila našeg semafora:
- crveno i zeleno za automobile nikada ne svijetle zajedno;
- pješaci hodaju samo kada automobili imaju mirno zeleno.
Na jednoj od sljedećih radionica od ovakvih semafora složit ćemo pravo križanje. Svaki Arduino upravljat će semaforom za automobile i pješačkim semaforom za jedan smjer, točno kao danas.
Pješaci i automobili koji skreću
Na pravim križanjima automobil koji skreće može prijeći preko pješačkog prijelaza na kojem pješaci upravo imaju zeleno. Tada vozač mora propustiti pješake. Zato pravi semafori često imaju dodatna svjetla i složenija pravila. Naš model je jednostavniji, da bismo najprije razumjeli osnovnu logiku.
Materijal
Svaki polaznik dobiva:
- Arduino Uno i USB kabel
- veliki breadboard
- 3D-printani semafor s četiri žice: crvenom, žutom, zelenom i crnom
- crvenu i zelenu LED-icu za pješake
- 5 × otpornik 220 Ω (crveno-crveno-smeđe)
- aktivnu zujalicu i otpornik 68 Ω (plavo-sivo-crno)
- spojne žice
Pravila za spajanje
- Dok spajamo, Arduino je odspojen s USB kabela.
- Na breadboard ne spajamo 5 V. LED-ice i zujalicu napajaju pinovi Arduina, pa nam s Arduina treba samo GND. Ako na ploči nema 5 V, ne može nastati ni kratki spoj između 5 V i GND.
- GND Arduina spajamo na (–) liniju. Sve što ide na GND ide u tu liniju.
- Na mnogim velikim breadboardima linije su prekinute na sredini ploče (vidi se po razmaku u obojenoj liniji). Zato sve spajamo u gornjoj polovici ploče, u retke 1 do 30 (ili ćemo kratkim žicama prespojiti prekide).
- Svaka LED-ica ima svoj otpornik.
- Prije uključivanja voditelj pregleda spoj.
Ako trebaš podsjetnik kako su spojene rupice na ploči, pogledaj Breadboard.
Vježba 1: Semafor za automobile

Spajanje
Svaki otpornik postavljamo preko središnjeg utora ploče, u isti redak. Žica s Arduina ulazi u lijevu polovicu retka (stupci a–e), a žica semafora u desnu polovicu (stupci f–j). Otpornik tako spaja lijevu i desnu polovicu retka.
| Svjetlo | Arduino pin | Žica s Arduina | Otpornik 220 Ω | Desna strana |
|---|---|---|---|---|
| Crveno | D10 | a5 | e5–f5 | crvena žica semafora u j5 |
| Žuto | D9 | a9 | e9–f9 | žuta žica semafora u j9 |
| Zeleno | D8 | a13 | e13–f13 | zelena žica semafora u j13 |
| Zajednički GND | GND | desna – linija | – | crna žica semafora u – liniju |

Koliko struje teče kroz LED-icu? Na crvenoj LED-ici ostaje oko 2 V, pa na otporniku ostaje približno 5 V – 2 V = 3 V. Prema Ohmovu zakonu iz lekcije 1.2 (I = U / R), kroz otpornik i LED-icu teče oko 3 V / 220 Ω = 14 mA. To je ispod preporučenih 20 mA po pinu Arduina.
Zašto baš D10, D9 i D8? Pinove D0 i D1 Arduino koristi za komunikaciju s računalom preko USB-a, a D3 i D11 ostavljamo slobodnima jer naredba koju ćemo koristiti za zvuk utječe na njih.
Nakon spajanja provjeri:
- crna žica semafora je u – liniji, a GND Arduina u istoj liniji;
- svaka boja ima svoj otpornik;
- nijedna žica nije spojena na 5 V;
- voditelj je pregledao spoj.
Test boja
Prvi program pali svjetla jedno po jedno, kako bismo provjerili je li svaka boja na pravom pinu.
// C++
const int crvenoAuti = 10;
const int zutoAuti = 9;
const int zelenoAuti = 8;
void setup() {
pinMode(crvenoAuti, OUTPUT);
pinMode(zutoAuti, OUTPUT);
pinMode(zelenoAuti, OUTPUT);
}
void loop() {
digitalWrite(crvenoAuti, HIGH);
delay(1000);
digitalWrite(crvenoAuti, LOW);
digitalWrite(zutoAuti, HIGH);
delay(1000);
digitalWrite(zutoAuti, LOW);
digitalWrite(zelenoAuti, HIGH);
delay(1000);
digitalWrite(zelenoAuti, LOW);
}
Svjetla se moraju paliti redom: crveno, žuto, zeleno. Ako je redoslijed drukčiji, ne mijenjamo program, nego provjeravamo žice.
U imenima varijabli ne koristimo slova č, ć, đ, š i ž jer ih Arduino u imenima ne prihvaća. Zato pišemo zutoAuti, a ne žutoAuti.
Što je novo u programu?
digitalWrite(crvenoAuti, HIGH);– Uključuje pin: na njemu je oko 5 V i LED-ica svijetli.digitalWrite(crvenoAuti, LOW);– Isključuje pin: na njemu je 0 V i LED-ica je ugašena.- U prošloj lekciji
analogWrite()je imao 256 razina, od 0 do 255.digitalWrite()zna samo dvije:HIGHiliLOW. Za semafor je to dovoljno, jer svjetlo ili svijetli ili ne svijetli.
Što će se dogoditi ako greškom zamijenimo crvenu i žutu žicu semafora?
Vježba 2: Cijeli ciklus
Sada želimo da semafor prolazi kroz sva stanja iz tablice stanja.
U svakom stanju moramo postaviti sva tri svjetla, jer ne želimo da ostane upaljeno svjetlo iz prethodnog stanja. Samo prva dva stanja izgledala bi ovako:
// C++
digitalWrite(crvenoAuti, HIGH); // crveno
digitalWrite(zutoAuti, LOW);
digitalWrite(zelenoAuti, LOW);
delay(4000);
digitalWrite(crvenoAuti, HIGH); // crveno + žuto
digitalWrite(zutoAuti, HIGH);
digitalWrite(zelenoAuti, LOW);
delay(1000);
Za cijeli ciklus, s treptanjem, trebalo bi nam tridesetak gotovo jednakih redaka. Lako je negdje pogrešno napisati HIGH umjesto LOW i takvu grešku teško je pronaći. Zato ćemo napisati vlastitu funkciju: novu naredbu koja odjednom postavlja sva tri svjetla.
Zašto pišemo vlastite funkcije?
Funkcija je skupina naredbi kojoj damo ime. Kada je jednom napišemo, pozivamo je po imenu, kao da je nova naredba jezika C++. Funkcije već koristimo: digitalWrite(), delay() i analogRead() napisali su drugi programeri, a mi ih samo pozivamo. Ako ste bili na micro:bit radionici, tamo smo istu ideju složili od blokova u funkciji Svjetlo.
Što dobivamo vlastitom funkcijom svjetlo() za naš semafor?
- Kraći program. Tri naredbe za tri svjetla napišemo samo jednom, a ne u svakom stanju.
- Čitljiv program. Poziv
svjetlo(HIGH, HIGH, LOW)čita se kao jedan redak tablice stanja: crveno da, žuto da, zeleno ne. - Manje grešaka. Svaki poziv postavlja sva tri svjetla, pa ne možemo zaboraviti ugasiti jedno od njih.
- Jedno mjesto za promjene. Ako želimo promijeniti kako se svjetla pale, mijenjamo samo funkciju, a ciklus u
loop()ostaje isti. Upravo to ćemo danas iskoristiti kada semaforu dodamo pješake i zvuk.
Programeri kažu da funkcija skriva kako se nešto radi, a ostatak programa govori samo što želimo.
// C++
const int crvenoAuti = 10;
const int zutoAuti = 9;
const int zelenoAuti = 8;
void svjetlo(int crveno, int zuto, int zeleno) {
digitalWrite(crvenoAuti, crveno);
digitalWrite(zutoAuti, zuto);
digitalWrite(zelenoAuti, zeleno);
}
void setup() {
pinMode(crvenoAuti, OUTPUT);
pinMode(zutoAuti, OUTPUT);
pinMode(zelenoAuti, OUTPUT);
}
void loop() {
svjetlo(HIGH, LOW, LOW); // crveno
delay(4000);
svjetlo(HIGH, HIGH, LOW); // crveno + žuto
delay(1000);
svjetlo(LOW, LOW, HIGH); // zeleno
delay(4000);
for (int i = 0; i < 4; i++) { // zeleno trepće 4 puta
svjetlo(LOW, LOW, LOW);
delay(250);
svjetlo(LOW, LOW, HIGH);
delay(250);
}
svjetlo(LOW, HIGH, LOW); // žuto
delay(1000);
}
Što je novo u programu?
void svjetlo(int crveno, int zuto, int zeleno) { ... }– Ovako stvaramo vlastitu funkciju.svjetloje njezino ime, a između vitičastih zagrada{ }su naredbe koje izvršava. Funkciju pišemo iznadsetup(), kao i u prošloj lekciji.void– Znači da funkcija samo nešto napravi i ne vraća rezultat.int crveno, int zuto, int zeleno– To su parametri: prazna mjesta koja popunimo kada funkciju pozovemo. Unutar funkcije koristimo ih kao obične varijable.svjetlo(HIGH, HIGH, LOW);– Poziv funkcije. Vrijednosti se predaju redom: prva ide ucrveno, druga uzuto, treća uzeleno.for (int i = 0; i < 4; i++) { ... }– Petlja ponavlja naredbe između{ }zadani broj puta. U zagradi su tri dijela: odakle krećemo (i = 0), dokle ponavljamo (i < 4) i korak (i++povećavaiza jedan, kao suprotnost naredbicount--iz prošle lekcije). Brojač ide 0, 1, 2, 3, dakle četiri puta.
Koliko traje jedan cijeli ciklus semafora?
Vježba 3: Igra s parametrima
Parametri funkcije ne moraju biti samo HIGH i LOW. Funkciji ćemo dodati još dvije stvari:
trajanje– četvrti parametar koji govori koliko stanje traje. Čekanje tako ulazi u funkciju iloop()više ne trebadelay().TREPCE– za Arduino jeHIGHzapravo broj 1, aLOWbroj 0. Mi ćemo izmisliti treću vrijednost, broj 2, koja znači trepće. Kada je funkcija dobije, sama će odraditi treptanje.
Konstante pinova i setup() ostaju isti. Ispod konstanti dodaj TREPCE, a funkciju svjetlo() i loop() zamijeni ovima:
// C++
const int TREPCE = 2; // treća vrijednost uz LOW (0) i HIGH (1)
void svjetlo(int crveno, int zuto, int zeleno, int trajanje) {
digitalWrite(crvenoAuti, crveno);
digitalWrite(zutoAuti, zuto);
if (zeleno == TREPCE) {
for (int t = 0; t < trajanje; t = t + 500) {
digitalWrite(zelenoAuti, LOW);
delay(250);
digitalWrite(zelenoAuti, HIGH);
delay(250);
}
} else {
digitalWrite(zelenoAuti, zeleno);
delay(trajanje);
}
}
void loop() {
svjetlo(HIGH, LOW, LOW, 4000); // crveno
svjetlo(HIGH, HIGH, LOW, 1000); // crveno + žuto
svjetlo(LOW, LOW, HIGH, 4000); // zeleno
svjetlo(LOW, LOW, TREPCE, 2000); // zeleno trepće
svjetlo(LOW, HIGH, LOW, 1000); // žuto
}
Što je novo u programu?
int trajanje– Četvrti parametar: koliko milisekundi stanje traje.const int TREPCE = 2;– Ime za broj 2. Pišemo ga velikim slovima jer je iste vrste kaoHIGHiLOW: ime za broj koji ima posebno značenje.if (zeleno == TREPCE) { ... } else { ... }– Ako zeleno treba treptati, funkcija ga pali i gasi. Inače (else) zeleno samo postavi i čeka. Izvršava se uvijek samo jedan od ta dva dijela.for (int t = 0; t < trajanje; t = t + 500)– Ista petlja kao prije, ali s drukčijim korakom. Jedan krug traje 250 + 250 = 500 ms, patbroji koliko je vremena prošlo.loop()je sada pet redaka i izgleda gotovo kao tablica stanja: jedno stanje, jedan redak.
Eksperimenti
Za svaki eksperiment mijenjamo samo loop(). Funkciju ne diramo.
1. Brzi i spori semafor
Promijeni brojeve trajanja. Pokušaj napraviti semafor kojem cijeli ciklus traje 6 s, pa onda jedan kojem traje 20 s.
2. Noćni režim
Noću semafori na nekim križanjima samo trepću žuto. Zamijeni cijeli loop() ovim:
// C++
void loop() {
svjetlo(LOW, HIGH, LOW, 500); // žuto
svjetlo(LOW, LOW, LOW, 500); // sve ugašeno
}
Potpuno novo ponašanje dobili smo samo drukčijim parametrima.
3. Pokvareni semafor
Upiši u loop() redak svjetlo(HIGH, LOW, HIGH, 3000);. Program ga bez pogovora izvrši: crveno i zeleno svijetle zajedno.
Zašto je pokvareni semafor opasan i tko bi trebao spriječiti takvu grešku?
Koliko puta trepne zeleno ako napišemo svjetlo(LOW, LOW, TREPCE, 1700)?
t ima vrijednosti 0, 500, 1000 i 1500, a sljedeća vrijednost, 2000, više nije manja od 1700. Treptanje zato stvarno traje 2000 ms, a ne 1700 ms.Prije sljedeće vježbe vrati loop() s pet stanja.
Vježba 4: Pješački semafor

Spajanje
Na breadboard dodajemo dvije LED-ice, svaku sa svojim otpornikom od 220 Ω. Spajamo ih na isti način kao svjetla semafora, ali sada LED-ica stoji izravno na ploči:
| Svjetlo | Arduino pin | Žica s Arduina | Otpornik 220 Ω | Desna strana |
|---|---|---|---|---|
| Pješaci crveno | D7 | a18 | e18–f18 | crvena LED-ica: dulja nožica u j18, kraća u desnu – liniju |
| Pješaci zeleno | D6 | a22 | e22–f22 | zelena LED-ica: dulja nožica u j22, kraća u desnu – liniju |

Kod semafora za automobile polaritet LED-ica riješen je unutar modela. Ovdje moramo paziti sami:
- dulja nožica (anoda) ide prema otporniku i pinu;
- kraća nožica (katoda), na strani gdje je rub kućišta ravan, ide prema GND.
Okrenuta LED-ica neće svijetliti, ali se neće ni pokvariti. Ako ne svijetli, okreni je.
Istodobno sada svijetle najviše tri LED-ice, na primjer crveno i žuto za automobile i crveno za pješake. To je ukupno oko 40 mA, što Arduino Uno bez problema daje.
Pravilo za pješake
Gdje u programu napisati to pravilo? U loop() bismo morali dopisati pješake u svako stanje. Ali postoji bolje mjesto: funkcija svjetlo(). Ona jedina u svakom trenutku zna koja svjetla automobili upravo dobivaju.
Izmjena programa
Ispod konstanti za automobile dodaj:
// C++
const int crvenoPjesaci = 7;
const int zelenoPjesaci = 6;
U setup() dodaj:
// C++
pinMode(crvenoPjesaci, OUTPUT);
pinMode(zelenoPjesaci, OUTPUT);
U funkciju svjetlo() dodaj blok označen s NOVO, iza postavljanja crvenog i žutog, a prije dijela koji čeka:
// C++
void svjetlo(int crveno, int zuto, int zeleno, int trajanje) {
digitalWrite(crvenoAuti, crveno);
digitalWrite(zutoAuti, zuto);
// NOVO: pješaci hodaju samo kada automobili imaju mirno zeleno.
if (zeleno == HIGH && crveno == LOW && zuto == LOW) {
digitalWrite(crvenoPjesaci, LOW);
digitalWrite(zelenoPjesaci, HIGH);
} else {
digitalWrite(crvenoPjesaci, HIGH);
digitalWrite(zelenoPjesaci, LOW);
}
if (zeleno == TREPCE) {
for (int t = 0; t < trajanje; t = t + 500) {
digitalWrite(zelenoAuti, LOW);
delay(250);
digitalWrite(zelenoAuti, HIGH);
delay(250);
}
} else {
digitalWrite(zelenoAuti, zeleno);
delay(trajanje);
}
}
loop() nismo promijenili ni za jedan znak. Semafor je dobio potpuno novu ulogu, a ciklus je ostao isti. To je ono što smo dobili vlastitom funkcijom.
Što je novo u programu?
&&– Znači i. Uvjet je ispunjen samo ako su istiniti svi dijelovi: zeleno je upaljeno i crveno je ugašeno i žuto je ugašeno.else– U svim ostalim stanjima pješaci dobivaju crveno. Ne moramo nabrajati svako stanje posebno.- Zašto pješaci stoje dok zeleno trepće? Tada je parametar
zelenojednakTREPCE(2), a neHIGH(1), pa uvjet nije ispunjen. Vrijednost koju smo izmislili za treptanje sada nam besplatno razlikuje mirno i trepćuće zeleno. - Zašto provjeravamo i crveno i žuto? Zbog pokvarenog semafora iz Vježbe 3. Ako netko pozove
svjetlo(HIGH, LOW, HIGH, 3000), pješaci ipak ostaju na crvenom. Funkcija štiti pješake i od pogrešnog poziva. - Zašto blok ide prije čekanja? Dok traje
delay(), Arduino ne radi ništa drugo. Sve odluke moraju biti donesene prije nego što počnemo čekati.
Što pješaci vide kada semafor radi u noćnom režimu iz Vježbe 3?
Vježba 5: Zvučni signal za pješake
Osoba slabijeg vida ne vidi pješački semafor. Zato mnogi semafori daju i zvučni signal. Naš će biti kratak i tih:
- kada pješaci dobiju zeleno: kratki viši zvuk, kreni;
- kada pješaci izgube zeleno: kratki niži zvuk, stani;
- u ostalim trenucima: tišina.
Aktivna zujalica
Aktivna zujalica ima u sebi mali elektronički sklop koji proizvodi ton. Kada dobije napon, sama zuji, uvijek istim tonom. Visinu tog tona ne možemo promijeniti.
Ipak, možemo je vrlo brzo paliti i gasiti. Tada čujemo novi zvuk: kada je palimo i gasimo brže, zvuk je viši, a kada to radimo sporije, zvuk je dublji i hrapaviji. To nisu čisti tonovi kao kod glazbenog instrumenta, ali jasno se razlikuju.

Spajanje
| Dio | Arduino pin | Žica s Arduina | Otpornik 68 Ω | Desna strana |
|---|---|---|---|---|
| Zujalica | D5 | a27 | e27–f27 | + nožica zujalice u j27, druga nožica u – liniju |

- Zujalica ima polaritet. Nožica + je dulja, a oznaka + nalazi se i na gornjoj strani kućišta. Okrenuta zujalica šuti.
- Otpornik od 68 Ω smanjuje struju kroz pin i ujedno stišava zujalicu.
Pravilo za zvuk
Zašto moramo pamtiti što su pješaci radili? Funkcija svjetlo() poziva se pet puta u svakom ciklusu, a u četiri od tih poziva pješaci imaju crveno. Bez pamćenja bi niži zvuk zazujao četiri puta u ciklusu. Zvuk želimo samo onda kada se stanje pješaka promijeni.
Izmjena programa
Ispod ostalih konstanti dodaj:
// C++
const int zujalica = 5;
bool pjesaciHodaju = false; // pamti jesu li pješaci imali zeleno
U setup() dodaj pinMode(zujalica, OUTPUT);, a u funkciji svjetlo() pješački blok dopuni ovako:
// C++
// Pješaci hodaju samo kada automobili imaju mirno zeleno.
if (zeleno == HIGH && crveno == LOW && zuto == LOW) {
digitalWrite(crvenoPjesaci, LOW);
digitalWrite(zelenoPjesaci, HIGH);
if (!pjesaciHodaju) { // upravo su dobili zeleno
tone(zujalica, 800, 60); // kratki viši zvuk: kreni
pjesaciHodaju = true;
}
} else {
digitalWrite(crvenoPjesaci, HIGH);
digitalWrite(zelenoPjesaci, LOW);
if (pjesaciHodaju) { // upravo su dobili crveno
tone(zujalica, 150, 150); // kratki niži zvuk: stani
pjesaciHodaju = false;
}
}
I ovdje loop() ostaje isti.
Što je novo u programu?
tone(zujalica, 800, 60);– 60 milisekundi pali i gasi zujalicu 800 puta u sekundi. Čujemo kratki, viši zvuk.tone(zujalica, 150, 150);– 150 milisekundi pali i gasi zujalicu samo 150 puta u sekundi. Čujemo nešto dulji, dublji i hrapaviji zvuk.tone()svira u pozadini: program ne čeka da zvuk završi, nego odmah nastavlja. Zato se svjetla zbog zvuka ne zakoče.bool pjesaciHodaju = false;– Logička varijabla koja pamti prethodno stanje pješaka, kaoledModeu prošloj lekciji. Na početku pješaci stoje, pa je vrijednostfalse.if (!pjesaciHodaju)– Znak!znači nije: „ako pješaci do sada nisu hodali”.- Zvukovi se razlikuju i po visini i po trajanju. Kratki znači kreni, a nešto dulji stani. Tako ih lakše prepoznaje i netko kome je teško razlikovati visinu zvuka.
Pazimo na buku
Aktivne zujalice su glasne, a u prostoriji ih radi mnogo istodobno. Naš semafor zato zvuči samo dvaput u ciklusu od 12 sekundi i svaki zvuk traje kraće od petine sekunde.
- Ako je zujalica i dalje preglasna, preko njezina otvora zalijepi komadić ljepljive trake.
- Dok eksperimentiraš s trajanjima ili s programom, izvuci žicu zujalice iz pina D5.
Kako zvuče pravi semafori?
Pravi zvučni semafori za osobe slabijeg vida obično stalno kucaju: sporo dok pješaci imaju crveno, a brzo dok imaju zeleno. Po sporom kucanju osoba može pronaći stup semafora, a brzo kucanje joj govori da smije prijeći cestu. Naš semafor koristi tišu inačicu s dva kratka zvuka.
Zašto se niži zvuk čuje točno u trenutku kada zeleno za automobile počne treptati?
zeleno jednakim TREPCE, pa uvjet za pješake nije ispunjen i program ulazi u dio else. U prethodnom stanju pješaci su hodali, pa je pjesaciHodaju još true: program pusti niži zvuk i zapamti da pješaci sada stoje. U sljedećim stanjima pjesaciHodaju je false, pa zvuka više nema.Cijeli program
// C++
const int crvenoAuti = 10;
const int zutoAuti = 9;
const int zelenoAuti = 8;
const int crvenoPjesaci = 7;
const int zelenoPjesaci = 6;
const int zujalica = 5;
const int TREPCE = 2; // treća vrijednost uz LOW (0) i HIGH (1)
bool pjesaciHodaju = false; // pamti jesu li pješaci imali zeleno
void svjetlo(int crveno, int zuto, int zeleno, int trajanje) {
digitalWrite(crvenoAuti, crveno);
digitalWrite(zutoAuti, zuto);
// Pješaci hodaju samo kada automobili imaju mirno zeleno.
if (zeleno == HIGH && crveno == LOW && zuto == LOW) {
digitalWrite(crvenoPjesaci, LOW);
digitalWrite(zelenoPjesaci, HIGH);
if (!pjesaciHodaju) { // upravo su dobili zeleno
tone(zujalica, 800, 60); // kratki viši zvuk: kreni
pjesaciHodaju = true;
}
} else {
digitalWrite(crvenoPjesaci, HIGH);
digitalWrite(zelenoPjesaci, LOW);
if (pjesaciHodaju) { // upravo su dobili crveno
tone(zujalica, 150, 150); // kratki niži zvuk: stani
pjesaciHodaju = false;
}
}
if (zeleno == TREPCE) {
for (int t = 0; t < trajanje; t = t + 500) {
digitalWrite(zelenoAuti, LOW);
delay(250);
digitalWrite(zelenoAuti, HIGH);
delay(250);
}
} else {
digitalWrite(zelenoAuti, zeleno);
delay(trajanje);
}
}
void setup() {
pinMode(crvenoAuti, OUTPUT);
pinMode(zutoAuti, OUTPUT);
pinMode(zelenoAuti, OUTPUT);
pinMode(crvenoPjesaci, OUTPUT);
pinMode(zelenoPjesaci, OUTPUT);
pinMode(zujalica, OUTPUT);
}
void loop() {
svjetlo(HIGH, LOW, LOW, 4000); // crveno
svjetlo(HIGH, HIGH, LOW, 1000); // crveno + žuto
svjetlo(LOW, LOW, HIGH, 4000); // zeleno
svjetlo(LOW, LOW, TREPCE, 2000); // zeleno trepće
svjetlo(LOW, HIGH, LOW, 1000); // žuto
}
Ako nešto ne radi
- Nijedno svjetlo ne svijetli ⇒ Je li GND Arduina spojen na istu – liniju kao crna žica semafora? Je li linija prekinuta na sredini ploče?
- Svjetla se pale pogrešnim redom ⇒ Žice semafora zamijenjene su redcima. Usporedi spoj s tablicom u Vježbi 1.
- Jedna pješačka LED-ica ne svijetli ⇒ Vjerojatno je okrenuta. Dulja nožica ide prema otporniku.
- Zujalica šuti ⇒ Provjeri polaritet zujalice i je li žica u pinu D5.
- Zujalica zuji cijelo vrijeme, a utihne kada bi trebala zazujati ⇒ Neki moduli zujalica rade obrnuto: zuje kada je pin
LOW. Javi se voditelju. - Program se ne može učitati ⇒ Provjeri jesu li u Arduino IDE-u odabrani ploča Arduino Uno i pravi port.
Dodatni izazovi
- Umjesto jednog višeg zvuka za kreni pusti dva, a između njih stavi
delay(150);. Primjećuješ li da zeleno za automobile sada pali malo kasnije? Zašto? Što bi mogao napraviti u programu da se ne dogodi da su sva svjetla ugašena za to kratko vrijeme? - Promijeni trajanja tako da zeleno za automobile, zajedno s treptanjem, traje točno pola cijelog ciklusa.
Što smo naučili?
digitalWrite()postavlja digitalni pin naHIGH(oko 5 V) iliLOW(0 V).- Svaka LED-ica treba svoj otpornik. Uz 220 Ω i 5 V kroz LED-icu teče oko 14 mA.
- Na breadboard ne spajamo 5 V kada nam ne treba, a GND svih dijelova mora biti zajednički.
- Vlastita funkcija skupina je naredbi s imenom. Parametri su prazna mjesta koja popunimo pri pozivu.
- Funkcija skraćuje program, čini ga čitljivijim i daje nam jedno mjesto za promjene: pješake i zvuk dodali smo bez ijedne promjene u
loop(). - Petlja
forponavlja naredbe zadani broj puta ili dok ne prođe zadano vrijeme. if ... elsebira jedan od dva puta, a&&znači i.- Parametru možemo dati i vlastitu vrijednost s posebnim značenjem, kao što je
TREPCE. - Logička varijabla može pamtiti prethodno stanje, pa program reagira samo na promjenu.
tone()pali i gasi zujalicu u pozadini, a aktivna zujalica tako dobiva viši ili niži zvuk.
Mali kviz
1. Koja je razlika između digitalWrite() i analogWrite()?
digitalWrite() zna samo dva stanja, HIGH i LOW: pin je uključen ili isključen. analogWrite() šalje PWM signal s 256 razina (0–255), pa LED-ica može svijetliti slabije ili jače.2. Što su parametri funkcije?
svjetlo(HIGH, HIGH, LOW, 1000) parametar crveno dobiva HIGH, zuto dobiva HIGH, zeleno dobiva LOW, a trajanje dobiva 1000. Vrijednosti se predaju redom kojim su parametri napisani.3. Zašto smo pješake mogli dodati bez promjene u loop()?
svjetlo(). Ona pri svakom pozivu zna kakva svjetla automobili dobivaju, pa u njoj možemo odlučiti i što vide pješaci. loop() samo govori što se događa (koje stanje i koliko dugo), a funkcija kako se to prikazuje.4. Kada je uvjet zeleno == HIGH && crveno == LOW && zuto == LOW ispunjen?
zeleno je jednako TREPCE, a ne HIGH, pa uvjet nije ispunjen.