Panduan · 12 mnt baca

Lampu Lalu Lintas Arduino: Rangkaian, Kode, Tombol Pejalan Kaki, dan Persimpangan

Buat lampu lalu lintas Arduino: pengkabelan 3 LED dan 220 Ω, kode delay dan millis, tombol pejalan kaki, persimpangan dua arah, Tinkercad, serta versi ESP32 dan Pico.

Lampu lalu lintas Arduino adalah proyek pertama klasik di elektronika: tiga LED, merah, kuning, dan hijau, menyala dan padam bergantian persis seperti lampu lalu lintas sungguhan. Yang kamu butuhkan hanya Arduino Uno, tiga LED, tiga resistor 220 Ω, dan beberapa kabel jumper, dan versi pertamamu yang berfungsi selesai dalam setengah jam. Namun proyek sederhana ini mengajarkan banyak hal: output digital, hitungan LED dan resistor, pengaturan waktu, membaca tombol, dan state machine, cara paling rapi untuk menyusun kodemu, semuanya muat dalam beberapa LED ini.

Di panduan ini kamu akan melihat dulu dalam urutan apa dan berapa lama lampu lalu lintas sungguhan berganti, lalu merakit rangkaian dan menulis kode paling sederhana dengan delay(). Setelah itu kamu akan menambahkan push button pejalan kaki, menulis ulang logika yang sama dengan millis() dan state machine agar tidak pernah memblokir, dan mengendalikan persimpangan dua arah. Bagian terakhir menunjukkan cara mencoba proyek ini di Tinkercad tanpa menginstal apa pun, versi ESP32 dan Raspberry Pi Pico (MicroPython), serta tips menulis laporan sekolah tentang proyek ini.

LED 5 mm merah, kuning, dan hijau untuk lampu lalu lintas Arduino
LED 5 mm: satu merah, satu kuning, dan satu hijau sudah cukup untuk lampu lalu lintas; siapkan beberapa lagi untuk lampu pejalan kaki dan persimpangan.

Bagaimana cara kerja lampu lalu lintas sungguhan?

Lampu lalu lintas adalah timer yang memberi giliran pada setiap arus lalu lintas. Di Inggris, Jerman, dan Turki siklusnya merah → merah + kuning (amber) → hijau → kuning → merah. Merah dan kuning bersamaan berarti “hijau segera menyala, bersiaplah, tapi jangan jalan dulu”, sedangkan kuning sendirian berarti “lampu akan menjadi merah, bersiaplah berhenti”. Di Amerika Serikat, Prancis, Italia, dan Spanyol tidak ada fase merah + kuning: lampu langsung berpindah dari merah ke hijau. Lama lampu kuning juga tidak asal: aturan Jerman menetapkan kuning 3 detik di jalan dengan batas 50 km/jam, 4 detik di 60 km/jam, dan 5 detik di 70 km/jam, karena pengemudi yang sudah terlalu dekat untuk berhenti ketika kuning menyala harus tetap bisa keluar dari persimpangan dengan aman.

FaseLampu yang menyalaArtiLama di panduan ini
1MerahBerhenti5 dtk
2Merah + kuningHijau segera menyala, bersiaplah1 dtk
3HijauJalan5 dtk
4KuningMerah segera menyala, berhenti3 dtk
Di persimpanganSemua arah merahJeda aman untuk mengosongkan persimpangan1 dtk

Daftar komponen dan perhitungan resistor 220 Ω

KomponenJmlCatatan
Arduino Uno (atau Nano)1ESP32 atau Raspberry Pi Pico juga bisa
LED 5 mm: merah, kuning, hijauMasing-masing 1+1 merah dan +1 hijau untuk lampu pejalan kaki, +1 set untuk persimpangan
Resistor 220 Ω3Satu per LED; 8 untuk semua versi
Push button (6×6 mm)1Hanya untuk versi pejalan kaki
Breadboard1Ukuran setengah (400 lubang) sudah cukup
Kabel jumper10–20Male ke male
Kabel USB1Untuk meng-upload kode dan memberi daya board

LED tidak membatasi arusnya sendiri; LED yang disambungkan langsung ke 5 V menarik arus lebih besar daripada yang sanggup ditahan LED dan pin. Karena itu setiap LED diberi resistor seri. Nilainya kamu cari dengan hukum Ohm: R = (tegangan catu − tegangan maju LED) / arus. Untuk LED merah, (5 V − 2,0 V) / 0,015 A ≈ 200 Ω; dengan nilai standar terdekat, 220 Ω, arusnya sekitar 13,6 mA. Itu cukup untuk menyalakan LED dengan terang dan tetap di bawah 20 mA yang dianjurkan untuk pin Arduino. Resistor 220 Ω ditandai merah-merah-cokelat-emas pada komponen empat gelang dan merah-merah-hitam-hitam-cokelat pada komponen lima gelang; supaya yakin, pakai alat kode warna resistor, dan untuk warna serta tegangan lain pakai kalkulator resistor LED.

Warna LEDTegangan maju (perkiraan)Arus di 5 V (220 Ω)Arus di 3,3 V (220 Ω)
Merah1,8–2,2 V≈ 13,6 mA≈ 5,9 mA
Kuning1,9–2,2 V≈ 13,2 mA≈ 5,5 mA
Hijau (hijau kekuningan)2,0–2,4 V≈ 13,2 mA≈ 5,5 mA
Hijau (terang, hijau murni)2,8–3,4 V≈ 9,1 mA≈ 1,4 mA (sangat redup)

Pengkabelan rangkaian dan tabel pin

Kaki panjang setiap LED (anoda, +) disambungkan lewat resistor ke pin digital Arduino, dan kaki pendeknya (katoda, −) ke GND. Tidak masalah resistornya di sisi anoda atau katoda, asalkan dipasang seri. Di breadboard, cara paling rapi adalah menyambungkan pin GND Arduino ke jalur biru (−) dan membawa kaki pendek ketiga LED ke jalur itu. Tabel di bawah mencantumkan pin yang dipakai semua sketch di panduan ini; sketch pertama hanya memakai tiga baris pertama. Kamu bisa melihat tata letak pin board-mu di alat Pinout.

FungsiArduino UnoESP32Raspberry Pi Pico
Merah kendaraan (arah A)D10GPIO 5GP13
Kuning kendaraan (arah A)D9GPIO 18GP12
Hijau kendaraan (arah A)D8GPIO 19GP11
Merah pejalan kakiD7GPIO 21GP15
Hijau pejalan kakiD6GPIO 22GP14
Tombol pejalan kaki (kaki lainnya ke GND)D2GPIO 23GP4
Merah / kuning / hijau arah BD5 / D4 / D3GPIO 25 / 26 / 27GP8 / GP7 / GP6
Katoda LED dan tombolGNDGNDGND
LED yang terbalik hanya tetap gelap dan tidak rusak, tapi jika kamu lupa resistornya, LED dan pin terbebani berlebihan dan LED bisa cepat meredup. Di Arduino Uno, usahakan paling banyak 20 mA per pin (batas mutlaknya 40 mA) dan jaga total semua pin di bawah 200 mA. Jika tidak ada satu LED pun yang menyala, cek GND dulu: jika jalur biru breadboard tidak tersambung ke pin GND Arduino, rangkaiannya tidak pernah tertutup.

Langkah 1: kode lampu lalu lintas paling sederhana dengan delay()

C++ (Arduino IDE)
1// Arduino trafik lambası: delay() ile en basit sürüm / simplest version with delay()
2const int KIRMIZI = 10;  // kırmızı LED / red LED
3const int SARI = 9;      // sarı LED / yellow LED
4const int YESIL = 8;     // yeşil LED / green LED
5
6// Üç LED'i tek satırda ayarla / set all three LEDs in one line
7void lambalar(int k, int s, int y) {
8  digitalWrite(KIRMIZI, k);
9  digitalWrite(SARI, s);
10  digitalWrite(YESIL, y);
11}
12
13void setup() {
14  pinMode(KIRMIZI, OUTPUT);
15  pinMode(SARI, OUTPUT);
16  pinMode(YESIL, OUTPUT);
17}
18
19void loop() {
20  lambalar(HIGH, LOW, LOW);   // DUR: kırmızı / STOP: red
21  delay(5000);
22  lambalar(HIGH, HIGH, LOW);  // HAZIRLAN: kırmızı + sarı / GET READY: red + yellow
23  delay(1000);
24  lambalar(LOW, LOW, HIGH);   // GEÇ: yeşil / GO: green
25  delay(5000);
26  lambalar(LOW, HIGH, LOW);   // YAVAŞLA: sarı / SLOW DOWN: yellow
27  delay(3000);
28}

Sketch ini mengatur ketiga pin sebagai output di setup() dan menjalankan empat fase berurutan di dalam loop(). Alih-alih menulis tiga baris digitalWrite berulang-ulang, kita memakai fungsi kecil bernama lambalar() (“lampu-lampu”), sehingga setiap fase terbaca sebagai satu baris dan kesalahan mudah terlihat. Untuk meng-upload, pilih Arduino Uno sebagai board dan port yang benar di menu Tools, lalu klik Upload. Jika upload gagal, ikuti daftar periksa di Kode Arduino gagal di-upload. Untuk mengubah waktunya, cukup ubah nilai milidetik di dalam delay(): 5000 berarti 5 detik.

Langkah 2: lampu lalu lintas dengan push button pejalan kaki

Penyeberangan dengan tombol yang kamu lihat di kota membuat mobil tetap mendapat hijau dan hanya memberi giliran pada pejalan kaki ketika seseorang menekan tombol. Di versi ini kita menambahkan lampu pejalan kaki dua LED (merah dan hijau) dan tombol di D2 ke lampu kendaraan. Satu kaki tombol ke D2 dan kaki yang berseberangan secara diagonal ke GND; karena kodenya memakai INPUT_PULLUP, tidak perlu resistor eksternal dan pin terbaca LOW selama tombol ditekan. Kamu bisa membaca lebih lanjut tentang sambungan internal tombol berkaki empat dan tentang debounce di Cara Menghubungkan Push Button ke Arduino.

Push button 6×6 mm berkaki empat
Push button 6×6 mm: keempat kakinya tersambung berpasangan di dalam; jika kamu memakai dua kaki yang berseberangan secara diagonal, pengkabelannya selalu benar.
C++ (Arduino IDE)
1// Yaya butonlu trafik lambası (delay ile) / pedestrian push-button light (with delay)
2const int KIRMIZI = 10, SARI = 9, YESIL = 8;  // araç lambası / vehicle light
3const int YAYA_KIRMIZI = 7, YAYA_YESIL = 6;   // yaya lambası / pedestrian light
4const int BUTON = 2;                          // diğer ucu GND / other leg to GND
5
6void setup() {
7  pinMode(KIRMIZI, OUTPUT);
8  pinMode(SARI, OUTPUT);
9  pinMode(YESIL, OUTPUT);
10  pinMode(YAYA_KIRMIZI, OUTPUT);
11  pinMode(YAYA_YESIL, OUTPUT);
12  pinMode(BUTON, INPUT_PULLUP);               // basılınca LOW okunur / reads LOW when pressed
13  digitalWrite(YESIL, HIGH);                  // araçlar geçer / cars go
14  digitalWrite(YAYA_KIRMIZI, HIGH);           // yayalar bekler / pedestrians wait
15}
16
17void loop() {
18  if (digitalRead(BUTON) == LOW) {            // yaya butona bastı / pedestrian pressed
19    delay(2000);                              // araçlara kısa süre tanı / short grace time for cars
20    digitalWrite(YESIL, LOW);
21    digitalWrite(SARI, HIGH);                 // sarı / yellow
22    delay(3000);
23    digitalWrite(SARI, LOW);
24    digitalWrite(KIRMIZI, HIGH);              // araçlar durur / cars stop
25    delay(1000);                              // tüm kırmızı güvenlik payı / all-red safety gap
26    digitalWrite(YAYA_KIRMIZI, LOW);
27    digitalWrite(YAYA_YESIL, HIGH);           // yayalar geçer / pedestrians cross
28    delay(6000);
29    for (int i = 0; i < 6; i++) {             // yaya yeşili 3 kez yanıp söner / green man flashes 3 times
30      digitalWrite(YAYA_YESIL, i % 2 == 0 ? LOW : HIGH);
31      delay(500);
32    }
33    digitalWrite(YAYA_YESIL, LOW);
34    digitalWrite(YAYA_KIRMIZI, HIGH);
35    delay(1000);                              // tüm kırmızı / all red
36    digitalWrite(SARI, HIGH);                 // kırmızı + sarı / red + yellow
37    delay(1000);
38    digitalWrite(KIRMIZI, LOW);
39    digitalWrite(SARI, LOW);
40    digitalWrite(YESIL, HIGH);                // araçlar yeniden geçer / cars go again
41    delay(8000);                              // en kısa yeşil süresi / minimum green time
42  }
43}

Sketch ini berfungsi, tapi punya kelemahan serius: begitu tombol ditekan, Arduino menghabiskan sekitar 25 detik tertahan di baris-baris delay(). Tekanan kedua selama waktu itu tidak terdeteksi, tidak ada yang bisa dibaca dari port serial, dan tidak ada layar yang bisa diperbarui. Tekanan selama jeda 8 detik di akhir hilang sama sekali: pejalan kaki menekan dan melepas, tidak terjadi apa-apa, dan ia harus menekan lagi. Menambahkan suara atau hitung mundur membuat struktur ini makin sulit dikerjakan. Solusinya adalah berhenti menunggu dan mulai mengukur waktu.

Langkah 3: kode tanpa blocking dengan millis() dan state machine

State machine adalah desain di mana sistem selalu berada di tepat satu keadaan (state) dan berpindah ke keadaan berikutnya ketika syarat tertentu terpenuhi. Lampu lalu lintas adalah contoh sempurna: “hijau untuk mobil”, “kuning untuk mobil”, dan “pejalan kaki menyeberang” masing-masing adalah satu keadaan. Kodenya tidak lagi menunggu dengan delay(); di setiap putaran loop() hanya mengajukan dua pertanyaan: aku di keadaan mana, dan sudah berapa lama aku di sini? Waktu yang berlalu diukur dengan millis() - durumBaslangic (momen keadaan dimulai), dan ketika waktunya habis kode berpindah. Jika millis() masih baru bagimu, baca dulu Arduino millis() vs delay(). Menulis keadaan-keadaan ke dalam tabel sebelum coding membuat pekerjaannya jauh lebih mudah:

KeadaanLampu kendaraanLampu pejalan kakiLamaKeadaan berikutnya
ARAC_YESIL (kendaraan hijau)HijauMerahMinimal 8 dtk, sampai ada permintaanARAC_SARI (kendaraan kuning)
ARAC_SARI (kendaraan kuning)KuningMerah3 dtkYAYA_BEKLE (pejalan kaki menunggu)
YAYA_BEKLE (pejalan kaki menunggu)MerahMerah1 dtkYAYA_GECER (pejalan kaki menyeberang)
YAYA_GECER (pejalan kaki menyeberang)MerahHijau6 dtkYAYA_FLAS (hijau pejalan kaki berkedip)
YAYA_FLAS (hijau pejalan kaki berkedip)MerahHijau berkedip3 dtkYAYA_BITTI (penyeberangan selesai)
YAYA_BITTI (penyeberangan selesai)MerahMerah1 dtkKIRMIZI_SARI (merah + kuning)
KIRMIZI_SARI (merah + kuning)Merah + kuningMerah1 dtkARAC_YESIL (kendaraan hijau)
C++ (Arduino IDE)
1// Yaya butonlu trafik lambası: millis() + durum makinesi / pedestrian light: millis() + state machine
2const int KIRMIZI = 10, SARI = 9, YESIL = 8;  // araç lambası / vehicle light
3const int YAYA_KIRMIZI = 7, YAYA_YESIL = 6;   // yaya lambası / pedestrian light
4const int BUTON = 2;                          // diğer ucu GND / other leg to GND
5
6enum Durum { ARAC_YESIL, ARAC_SARI, YAYA_BEKLE, YAYA_GECER, YAYA_FLAS, YAYA_BITTI, KIRMIZI_SARI };
7const char* const ISIM[] = { "ARAC_YESIL", "ARAC_SARI", "YAYA_BEKLE", "YAYA_GECER",
8                             "YAYA_FLAS", "YAYA_BITTI", "KIRMIZI_SARI" };
9
10// Süreler (ms) / durations (ms)
11const unsigned long MIN_YESIL = 8000;   // araçlara en az yeşil / minimum green for cars
12const unsigned long SARI_SURE = 3000;   // sarı / yellow
13const unsigned long GUVENLIK = 1000;    // tüm kırmızı / all red
14const unsigned long YAYA_SURE = 6000;   // yaya yeşili / pedestrian green
15const unsigned long FLAS_SURE = 3000;   // yanıp sönen yaya yeşili / flashing green man
16const unsigned long KS_SURE = 1000;     // kırmızı + sarı / red + yellow
17
18Durum durum = ARAC_YESIL;
19unsigned long durumBaslangic = 0;       // durumun başladığı an / when the state started
20bool yayaTalebi = false;                // butona basıldı mı? / was the button pressed?
21
22void aracLamba(bool k, bool s, bool y) {
23  digitalWrite(KIRMIZI, k);
24  digitalWrite(SARI, s);
25  digitalWrite(YESIL, y);
26}
27
28void yayaLamba(bool k, bool y) {
29  digitalWrite(YAYA_KIRMIZI, k);
30  digitalWrite(YAYA_YESIL, y);
31}
32
33// Yeni duruma geç: lambaları ayarla, saati başlat / enter a state: set the lamps, restart the clock
34void gec(Durum yeni) {
35  durum = yeni;
36  durumBaslangic = millis();
37  switch (yeni) {
38    case ARAC_YESIL:   aracLamba(0, 0, 1); yayaLamba(1, 0); break;
39    case ARAC_SARI:    aracLamba(0, 1, 0); yayaLamba(1, 0); break;
40    case YAYA_BEKLE:   aracLamba(1, 0, 0); yayaLamba(1, 0); break;
41    case YAYA_GECER:   aracLamba(1, 0, 0); yayaLamba(0, 1); yayaTalebi = false; break;
42    case YAYA_FLAS:    aracLamba(1, 0, 0); yayaLamba(0, 1); break;
43    case YAYA_BITTI:   aracLamba(1, 0, 0); yayaLamba(1, 0); break;
44    case KIRMIZI_SARI: aracLamba(1, 1, 0); yayaLamba(1, 0); break;
45  }
46  Serial.println(ISIM[yeni]);           // durum günlüğü / state log
47}
48
49void setup() {
50  Serial.begin(9600);
51  pinMode(KIRMIZI, OUTPUT);
52  pinMode(SARI, OUTPUT);
53  pinMode(YESIL, OUTPUT);
54  pinMode(YAYA_KIRMIZI, OUTPUT);
55  pinMode(YAYA_YESIL, OUTPUT);
56  pinMode(BUTON, INPUT_PULLUP);
57  gec(ARAC_YESIL);
58}
59
60void loop() {
61  unsigned long gecen = millis() - durumBaslangic;  // bu durumda geçen süre / time spent in this state
62
63  // yaya yeşili yanarken basış yok sayılır / presses during the green man are ignored
64  if (digitalRead(BUTON) == LOW && durum != YAYA_GECER) {
65    yayaTalebi = true;                  // talebi hatırla / remember the request
66  }
67
68  switch (durum) {
69    case ARAC_YESIL:
70      if (yayaTalebi && gecen >= MIN_YESIL) gec(ARAC_SARI);
71      break;
72    case ARAC_SARI:
73      if (gecen >= SARI_SURE) gec(YAYA_BEKLE);
74      break;
75    case YAYA_BEKLE:
76      if (gecen >= GUVENLIK) gec(YAYA_GECER);
77      break;
78    case YAYA_GECER:
79      if (gecen >= YAYA_SURE) gec(YAYA_FLAS);
80      break;
81    case YAYA_FLAS:
82      digitalWrite(YAYA_YESIL, (gecen / 250) % 2 == 0);  // 250 ms'de bir yanıp söner / toggles every 250 ms
83      if (gecen >= FLAS_SURE) gec(YAYA_BITTI);
84      break;
85    case YAYA_BITTI:
86      if (gecen >= GUVENLIK) gec(KIRMIZI_SARI);
87      break;
88    case KIRMIZI_SARI:
89      if (gecen >= KS_SURE) gec(ARAC_YESIL);
90      break;
91  }
92}

Jantung sketch ini adalah fungsi gec() (“pindah ke”): fungsi ini menyimpan keadaan baru, mengulang timer, mengatur lampu untuk keadaan itu, dan mencetak nama keadaan ke Serial Monitor. Switch di dalam loop() hanya mengecek apakah waktunya sudah habis. Menekan tombol tidak langsung memicu apa pun; tombol menaikkan flag yayaTalebi (permintaan pejalan kaki), dan siklus dimulai begitu mobil sudah mendapat hijau minimal 8 detik. Sekarang tekanan tombol tidak pernah hilang, dan karena tombol hanya mengubah flag, pantulan kontak juga tidak menimbulkan masalah. Tekanan ketika lampu hijau pejalan kaki sudah menyala diabaikan; kalau tidak, siklus baru yang tidak perlu akan dimulai tepat setelah pejalan kaki menyeberang. Buka Serial Monitor di 9600 baud untuk melihat nama setiap perpindahan; output ini membantu ketika mencari bug sekaligus untuk laporan sekolahmu.

Ketika kamu ingin menambahkan fitur, tambahkan dulu satu baris di tabel, lalu tulis case di kodenya. Misalnya, kamu bisa menambahkan keadaan malam di mana lampu kuning berkedip dan berpindah ke sana ketika sensor cahaya LDR mendeteksi gelap. Untuk mempelajari state machine lebih dalam, lihat state machine Arduino.

Langkah 4: persimpangan dua arah

Di persimpangan sungguhan, lampu kedua jalan saling terhubung: ketika jalan A hijau, jalan B harus merah. Versi ini memakai enam LED: D10, D9, dan D8 untuk arah A, serta D5, D4, dan D3 untuk arah B. Detail penting adalah jeda pengosongan semua merah yang singkat: ketika satu arah menjadi merah, arah lainnya tidak langsung hijau; pengendali menunggu 1 detik agar kendaraan yang masih di dalam persimpangan bisa keluar. Kali ini keadaan-keadaan masuk ke tabel (array), bukan switch; untuk setiap langkah, lampu yang menyala disimpan sebagai bit dalam satu byte, dan lamanya dalam milidetik.

C++ (Arduino IDE)
1// İki yönlü kavşak: tablo tabanlı durum makinesi / two-way junction: table-driven state machine
2const byte A_KIRMIZI = 10, A_SARI = 9, A_YESIL = 8;  // A yönü (ana yol) / direction A (main road)
3const byte B_KIRMIZI = 5,  B_SARI = 4, B_YESIL = 3;  // B yönü (ara yol) / direction B (side road)
4const byte PINLER[6] = { A_KIRMIZI, A_SARI, A_YESIL, B_KIRMIZI, B_SARI, B_YESIL };
5
6struct Adim {
7  byte maske;            // bit sırası: A_K A_S A_Y B_K B_S B_Y / bit order: A_R A_Y A_G B_R B_Y B_G
8  unsigned long sure;    // ms
9};
10
11const Adim PLAN[] = {
12  { 0b001100, 8000 },   // A yeşil, B kırmızı / A green, B red
13  { 0b010100, 3000 },   // A sarı, B kırmızı / A yellow, B red
14  { 0b100100, 1000 },   // tüm yönler kırmızı / all red
15  { 0b100110, 1000 },   // A kırmızı, B kırmızı + sarı / A red, B red + yellow
16  { 0b100001, 5000 },   // A kırmızı, B yeşil / A red, B green
17  { 0b100010, 3000 },   // A kırmızı, B sarı / A red, B yellow
18  { 0b100100, 1000 },   // tüm yönler kırmızı / all red
19  { 0b110100, 1000 },   // A kırmızı + sarı, B kırmızı / A red + yellow, B red
20};
21const byte ADIM_SAYISI = sizeof(PLAN) / sizeof(PLAN[0]);
22
23byte adim = 0;
24unsigned long adimBaslangic = 0;
25
26void uygula(byte maske) {
27  if ((maske & 0b001000) && (maske & 0b000001)) {  // iki yeşil aynı anda yanamaz / never two greens
28    maske = 0b100100;                              // güvenli durum: tüm kırmızı / fail-safe: all red
29  }
30  for (byte i = 0; i < 6; i++) {
31    digitalWrite(PINLER[i], (maske >> (5 - i)) & 1);  // soldaki bit A_KIRMIZI / leftmost bit is A_RED
32  }
33}
34
35void setup() {
36  for (byte i = 0; i < 6; i++) pinMode(PINLER[i], OUTPUT);
37  uygula(PLAN[0].maske);
38  adimBaslangic = millis();
39}
40
41void loop() {
42  if (millis() - adimBaslangic >= PLAN[adim].sure) {
43    adimBaslangic += PLAN[adim].sure;   // kaymasız zamanlama / drift-free timing
44    adim = (adim + 1) % ADIM_SAYISI;
45    uygula(PLAN[adim].maske);
46  }
47  // Burada buton, sensör ya da ekran işleri çalışabilir / buttons, sensors or a display can run here
48}

Setiap baris array PLAN adalah satu langkah. Pada bilangan biner seperti 0b001100, bit dari kiri ke kanan mewakili A merah, A kuning, A hijau, B merah, B kuning, dan B hijau; 1 berarti nyala dan 0 berarti mati. Fungsi uygula() (“terapkan”) menulis enam bit ini ke pin secara berurutan. Pengecekan di awal fungsi mencegah salah ketik menampilkan hijau di kedua arah sekaligus dan sebagai gantinya membuat persimpangan menjadi semua merah. Pengendali persimpangan sungguhan juga punya rangkaian pengaman terpisah yang menangkap hijau yang bertabrakan. Untuk mengubah waktu atau menambah langkah, kamu hanya mengubah tabelnya dan tidak pernah menyentuh sisa kode. Jika pin-mu habis karena jumlah LED bertambah, shift register 74HC595 memberimu delapan output dari tiga pin.

Coba di Tinkercad: simulasi tanpa komponen apa pun

  1. Buat akun gratis di tinkercad.com dan mulai rangkaian baru di bagian Circuits.
  2. Seret Arduino Uno R3, breadboard, tiga LED, dan tiga resistor dari daftar komponen di sebelah kanan. Klik LED untuk memilih warnanya dan resistor untuk mengatur nilainya menjadi 220 Ω.
  3. Gambar kabelnya: anoda LED lewat resistor ke D10, D9, dan D8, katoda ke GND. Mengatur warna kabel (misalnya hitam untuk GND) membuat skemanya mudah dibaca.
  4. Klik Code, pilih Text dari menu drop-down, hapus kode contoh, dan tempel sketch dari panduan ini.
  5. Klik Start Simulation; LED mulai berganti secara berurutan. Output serial muncul di Serial Monitor di bagian bawah panel kode.

Tinkercad adalah cara termudah untuk menguji pengkabelan dan kode sebelum merakit dengan komponen sungguhan; jika kamu lupa resistor, simulator menampilkan peringatan di LED bahwa arusnya terlalu tinggi. Untuk menguji versi pejalan kaki, cukup klik tombolnya dengan mouse selama simulasi berjalan. Di komputer yang lambat, simulasi bisa berjalan lebih lambat dari waktu nyata, jadi waktunya mungkin terlihat sedikit lebih lama. Untuk tugas sekolah, kamu bisa menyerahkan tautan berbagi Tinkercad atau tangkapan layar rangkaiannya. Untuk petunjuk rinci lihat simulasi Arduino di Tinkercad, dan untuk alternatif yang juga mendukung ESP32 dan Pico, lihat Wokwi.

Lampu lalu lintas ESP32 dengan mode malam

Sketch Arduino di panduan ini juga berjalan di ESP32: pilih ESP32 Dev Module sebagai board di Arduino IDE dan ubah konstanta pin seperti di tabel. Versi di bawah menambahkan satu fitur: mode malam. Pada jam-jam sepi, banyak persimpangan beralih ke kuning berkedip. Board ESP32 DevKit punya tombol BOOT yang tersambung ke GPIO 0, jadi kamu bahkan tidak butuh tombol tambahan: begitu board sudah menyala, tombol itu bisa dibaca seperti input biasa. Setiap tekanan berganti antara mode normal dan mode malam.

C++ (Arduino IDE)
1// ESP32 trafik lambası + gece modu (BOOT düğmesi) / ESP32 traffic light + night mode (BOOT button)
2const int KIRMIZI = 5;      // GPIO 5
3const int SARI = 18;        // GPIO 18
4const int YESIL = 19;       // GPIO 19
5const int BOOT_BUTON = 0;   // kart üzerindeki BOOT düğmesi / on-board BOOT button
6
7struct Adim { bool k, s, y; unsigned long sure; };
8const Adim PLAN[] = {
9  { true,  false, false, 5000 },   // kırmızı / red
10  { true,  true,  false, 1000 },   // kırmızı + sarı / red + yellow
11  { false, false, true,  5000 },   // yeşil / green
12  { false, true,  false, 3000 },   // sarı / yellow
13};
14const int ADIM_SAYISI = sizeof(PLAN) / sizeof(PLAN[0]);
15
16int adim = 0;
17unsigned long adimBaslangic = 0;
18bool geceModu = false;
19int sonOkuma = HIGH, kararli = HIGH;     // debounce için / for debouncing
20unsigned long degisimZamani = 0;
21
22void lambalar(bool k, bool s, bool y) {
23  digitalWrite(KIRMIZI, k);
24  digitalWrite(SARI, s);
25  digitalWrite(YESIL, y);
26}
27
28void setup() {
29  Serial.begin(115200);
30  pinMode(KIRMIZI, OUTPUT);
31  pinMode(SARI, OUTPUT);
32  pinMode(YESIL, OUTPUT);
33  pinMode(BOOT_BUTON, INPUT_PULLUP);
34  lambalar(PLAN[0].k, PLAN[0].s, PLAN[0].y);
35  adimBaslangic = millis();
36}
37
38void loop() {
39  unsigned long simdi = millis();
40
41  // 50 ms kararlı kalan basışı kabul et / accept a press that stays stable for 50 ms
42  int okuma = digitalRead(BOOT_BUTON);
43  if (okuma != sonOkuma) {
44    sonOkuma = okuma;
45    degisimZamani = simdi;
46  }
47  if (simdi - degisimZamani >= 50 && okuma != kararli) {
48    kararli = okuma;
49    if (kararli == LOW) {                  // yeni basış / new press
50      geceModu = !geceModu;
51      Serial.println(geceModu ? "Gece modu / Night mode" : "Normal mod / Normal mode");
52      adim = 0;                            // normal mod kırmızıdan başlar / normal mode restarts on red
53      adimBaslangic = simdi;
54      lambalar(PLAN[0].k, PLAN[0].s, PLAN[0].y);
55    }
56  }
57
58  if (geceModu) {
59    lambalar(false, (simdi / 500) % 2 == 0, false);  // yanıp sönen sarı / flashing yellow
60    return;
61  }
62
63  if (simdi - adimBaslangic >= PLAN[adim].sure) {
64    adimBaslangic = simdi;
65    adim = (adim + 1) % ADIM_SAYISI;
66    lambalar(PLAN[adim].k, PLAN[adim].s, PLAN[adim].y);
67  }
68}

Pembacaan tombol sudah termasuk debounce sederhana: tekanan hanya dihitung jika pembacaannya tidak berubah selama 50 ms. Tabel PLAN yang berisi keadaan lampu adalah bentuk yang lebih mudah dibaca dari ide yang dipakai di sketch persimpangan. Karena pin ESP32 mengeluarkan 3,3 V, LED menarik arus lebih kecil daripada di Arduino dan terlihat sedikit lebih redup. LED merah dan kuning cukup terang dengan 220 Ω, tapi LED hijau terang dengan tegangan maju sekitar 3 V bisa tetap sangat redup; dalam kasus itu turunkan resistor hijau menjadi 100 Ω. Jika kamu baru mengenal ESP32, Apa Itu ESP32? adalah tempat yang bagus untuk mulai, untuk instalasi dan pin yang aman.

Lampu lalu lintas pejalan kaki dengan Raspberry Pi Pico (MicroPython)

Di Raspberry Pi Pico kita menulis state machine yang sama dengan MicroPython. Kali ini keadaan-keadaan disimpan dalam list: setiap baris berisi nama keadaan, nilai kelima lampu, dan lamanya. Tombol memakai interupsi: ketika GP4 turun ke LOW, fungsi buton_kesmesi() (“interupsi tombol”) berjalan dan hanya menaikkan flag permintaan. Jika kamu menyimpan kodenya ke Pico sebagai main.py dengan Thonny, kode itu berjalan otomatis setiap kali board menyala.

MicroPython
1# Raspberry Pi Pico (MicroPython): yaya butonlu trafik lambası / pedestrian traffic light
2from machine import Pin
3import time
4
5yesil = Pin(11, Pin.OUT)              # araç yeşil / vehicle green
6sari = Pin(12, Pin.OUT)               # araç sarı / vehicle yellow
7kirmizi = Pin(13, Pin.OUT)            # araç kırmızı / vehicle red
8yaya_yesil = Pin(14, Pin.OUT)         # yaya yeşil / pedestrian green
9yaya_kirmizi = Pin(15, Pin.OUT)       # yaya kırmızı / pedestrian red
10buton = Pin(4, Pin.IN, Pin.PULL_UP)   # GP4, diğer ucu GND / other leg to GND
11
12# (durum, kırmızı, sarı, yeşil, yaya kırmızı, yaya yeşil, süre ms)
13# (state, red, yellow, green, ped red, ped green, duration ms)
14DURUMLAR = [
15    ("ARAC_YESIL",   0, 0, 1, 1, 0, 8000),   # en az yeşil süresi / minimum green
16    ("ARAC_SARI",    0, 1, 0, 1, 0, 3000),
17    ("YAYA_BEKLE",   1, 0, 0, 1, 0, 1000),   # tüm kırmızı / all red
18    ("YAYA_GECER",   1, 0, 0, 0, 1, 6000),
19    ("YAYA_FLAS",    1, 0, 0, 0, 1, 3000),
20    ("YAYA_BITTI",   1, 0, 0, 1, 0, 1000),   # tüm kırmızı / all red
21    ("KIRMIZI_SARI", 1, 1, 0, 1, 0, 1000),
22]
23
24talep = False
25adim = 0                              # şu anki durumun sırası / index of the current state
26
27def buton_kesmesi(pin):               # kesmede yalnız bayrak kaldır / only set a flag in the IRQ
28    global talep
29    if DURUMLAR[adim][0] != "YAYA_GECER":   # yaya yeşilinde basış yok sayılır / ignored during the green man
30        talep = True
31
32buton.irq(trigger=Pin.IRQ_FALLING, handler=buton_kesmesi)
33
34def uygula(i):
35    global talep
36    ad, k, s, y, yk, yy, _ = DURUMLAR[i]
37    kirmizi.value(k)
38    sari.value(s)
39    yesil.value(y)
40    yaya_kirmizi.value(yk)
41    yaya_yesil.value(yy)
42    if ad == "YAYA_GECER":
43        talep = False                 # talep karşılandı / request served
44    print("Durum / state:", ad)
45
46uygula(adim)
47baslangic = time.ticks_ms()
48
49while True:
50    gecen = time.ticks_diff(time.ticks_ms(), baslangic)   # taşmaya karşı güvenli / wrap-safe
51    ad = DURUMLAR[adim][0]
52
53    if ad == "YAYA_FLAS":
54        yaya_yesil.value((gecen // 250) % 2 == 0)          # yanıp sönen yaya yeşili / flashing green man
55
56    if gecen >= DURUMLAR[adim][6] and (ad != "ARAC_YESIL" or talep):
57        adim = (adim + 1) % len(DURUMLAR)                   # yeşil, talep gelene kadar sürer / green lasts until a request
58        uygula(adim)
59        baslangic = time.ticks_ms()
60
61    time.sleep_ms(10)

Di MicroPython kamu memakai time.ticks_ms() sebagai ganti millis() dan time.ticks_diff() sebagai ganti pengurangan biasa; penghitung ticks kembali ke awal setelah nilai tertentu, jadi mengurangkan dua pembacaan secara langsung bisa memberi hasil yang salah. Buat handler interupsi tetap pendek: tanpa print, tanpa sleep, dan tanpa perhitungan panjang, cukup ubah flag. Pin Pico juga bekerja di 3,3 V, jadi catatan LED hijau dari bagian ESP32 juga berlaku di sini. Kamu akan menemukan cara menginstal MicroPython dan penomoran pin di Apa Itu Raspberry Pi Pico?, dan dasar-dasar bahasanya di dasar-dasar MicroPython.

Kesalahan umum dan cara memperbaikinya

GejalaKemungkinan penyebabSolusi
Tidak ada LED yang menyalaGND tidak tersambung, atau jalur daya breadboard terputus di tengahSambungkan GND Arduino ke jalur biru; jembatani kedua bagian pada breadboard panjang
Satu LED tetap gelapLED terbalik atau tersambung ke pin yang salahKaki panjang (anoda) lewat resistor ke pin, kaki pendek ke GND; cocokkan nomor pin dengan kode
Warna yang salah menyalaPin merah dan hijau tertukar di kodePerbaiki kabel atau konstantanya sesuai tabel pin
LED sangat terang dan menjadi hangatTidak ada resistor yang dipasangTambahkan resistor seri 220 Ω ke setiap LED
Tombol tidak berpengaruh atau selalu terbaca ditekanTombol dipasang di dua kaki yang sudah tersambung di dalam, atau INPUT_PULLUP terlupaPakai kaki diagonal dan tulis pinMode(BUTON, INPUT_PULLUP)
Tidak ada reaksi langsung terhadap tombolWaktu hijau minimum untuk mobil belum habisBukan bug; kecilkan MIN_YESIL
Program kacau setelah beberapa lamaVariabel waktu dideklarasikan sebagai intDeklarasikan setiap variabel yang dipakai dengan millis() sebagai unsigned long

Tips untuk tugas sekolah dan laporan proyekmu

Lampu lalu lintas adalah salah satu tugas Arduino yang paling umum di pelajaran sains, teknologi, dan robotika. Gurumu biasanya ingin melihat bukan hanya rangkaian yang berfungsi, tapi juga bahwa kamu memahaminya dan bisa menjelaskannya. Jika kamu menyusun laporan dengan bagian-bagian berikut, laporanmu akan terlihat rapi dan tidak ada hal penting yang terlewat:

  • Tujuan: Jelaskan dalam satu atau dua kalimat apa yang ditunjukkan proyek ini, misalnya “mengatur waktu lampu lalu lintas dengan output digital”.
  • Daftar komponen: Tulis nama, jumlah, dan nilai (220 Ω) setiap komponen, seperti di tabel di atas.
  • Skema rangkaian: Tambahkan tangkapan layar Tinkercad atau Fritzing; jika kamu menggambarnya dengan tangan, pakai simbol yang benar. Cara membaca skema rangkaian membantu untuk ini.
  • Perhitungan resistor: Tunjukkan R = (5 − 2) / 0,015 ≈ 200 Ω dan jelaskan kenapa kamu memilih 220 Ω.
  • Tabel keadaan atau diagram alir: Sertakan tabel keadaan, lama, dan perpindahannya; ini bukti terkuat bahwa kamu memahami kodenya.
  • Kode dan penjelasan: Sertakan kode lengkap dan jelaskan baris-baris penting dengan kata-katamu sendiri.
  • Pengujian dan pengamatan: Ukur lama setiap fase dengan stopwatch, ukur arus satu LED dengan multimeter, dan bandingkan dengan perhitunganmu.
  • Kesimpulan dan pengembangan: Ceritakan masalah yang kamu temui, cara kamu memecahkannya, dan fitur yang bisa kamu tambahkan (tombol pejalan kaki, suara, mode malam).
Jika kamu ingin menonjol, bandingkan versi delay() pertamamu dengan versi millis(): jelaskan kenapa tekanan tombol terlewat di versi pertama dan tidak pernah terlewat di versi kedua. Video 20–30 detik rangkaian yang sedang bekerja dan tangkapan layar output Serial Monitor membuat laporanmu makin kuat.

Ide untuk mengembangkan lampu lalu lintasmu

  • Layar hitung mundur: Tampilkan sisa detik sampai hijau berakhir di display 7-segmen.
  • Sinyal suara untuk pejalan kaki tunanetra: Selama lampu pejalan kaki hijau, bunyikan buzzer dengan cepat, dan pelan selama merah.
  • Persimpangan pintar: Deteksi mobil yang menunggu di jalan samping dengan sensor jarak HC-SR04 dan beri arah B hijau hanya ketika ada mobil.
  • Mode malam otomatis: Pakai LDR untuk beralih ke kuning berkedip ketika hari gelap.
  • Kendali jarak jauh: Buat halaman web di ESP32 dan ubah mode serta waktunya dari ponselmu.
  • Perlintasan kereta: Pakai logika yang sama untuk lampu perlintasan kereta api dengan dua LED merah yang berkedip bergantian; proyek Knight Rider dan LED berjalan memakai ide pengaturan waktu yang mirip.

Lampu lalu lintas terlihat seperti proyek kecil, tapi ide-ide di dalamnya, state machine, pengaturan waktu tanpa blocking, dan perpindahan yang aman, juga menjadi dasar robot, sistem alarm, dan perangkat rumah pintar yang akan kamu buat nanti. Untuk memilih apa yang dibuat berikutnya, telusuri daftar ide proyek Arduino. Di aplikasi BlueGrays kamu akan menemukan proyek lampu lalu lintas untuk Arduino, ESP32, dan Raspberry Pi Pico, plus lanjutannya seperti Lampu Lalu Lintas Raspberry Pi Pico dengan Pemilih 4 Mode lewat Tombol, masing-masing dengan skema rangkaian langkah demi langkah dan kode siap pakai untuk dicoba di board-mu sendiri.

Pertanyaan umum

Bagaimana cara membuat lampu lalu lintas dengan Arduino?

Sambungkan kaki panjang LED merah, kuning, dan hijau ke pin digital Arduino (misalnya D10, D9, dan D8) lewat resistor 220 Ω dan kaki pendeknya ke GND. Di kode, atur pin-pin itu sebagai OUTPUT dan nyalakan serta padamkan LED secara berurutan di dalam loop(). delay() cukup untuk versi pertama; untuk tombol dan fitur tambahan kamu butuh millis().

Resistor apa yang kubutuhkan untuk LED lampu lalu lintas?

Di Arduino Uno 5 V, 220 Ω per LED adalah pilihan yang umum dan aman; LED merah lalu menarik sekitar 13–14 mA. 330 Ω memberi cahaya yang lebih redup tapi tetap terlihat jelas. 220 Ω juga bisa dipakai di ESP32 dan Pico 3,3 V; hanya jika LED hijau terang tetap redup kamu perlu turun ke 100 Ω.

Kenapa merah dan kuning menyala bersamaan di lampu lalu lintas?

Di negara seperti Inggris, Jerman, dan Turki, merah dan kuning bersamaan memberi tahu bahwa hijau akan segera menyala: pengemudi bersiap tapi tidak bergerak sampai hijau muncul. Amerika Serikat, Prancis, Italia, dan Spanyol tidak memakai fase ini dan langsung berpindah dari merah ke hijau. Di proyek Arduino-mu, kamu bisa memasukkan atau melewatkan fase ini sesukamu.

Sebaiknya pakai delay atau millis untuk lampu lalu lintas Arduino?

Jika kamu hanya menyalakan LED secara berurutan, delay() adalah pilihan paling sederhana dan bekerja dengan baik. Begitu kamu menambahkan tombol, sensor, layar, atau suara, delay() menghentikan program sejenak dan input-input itu terlewat. Kode yang ditulis dengan millis() dan state machine tidak pernah menunggu dan bisa memantau semuanya sekaligus.

Bisakah aku membuat proyek lampu lalu lintas di Tinkercad?

Bisa. Tinkercad Circuits menyediakan Arduino Uno, LED, resistor, dan push button sebagai komponen siap pakai; gambar rangkaiannya, tempel kode di editor Text, lalu mulai simulasi. Ini ideal untuk menguji rangkaian dan kode tanpa komponen sungguhan dan untuk mendapat tangkapan layar atau tautan berbagi untuk tugasmu.

Bagaimana cara kerja lampu lalu lintas pejalan kaki dengan tombol?

Mobil biasanya mendapat hijau, dan menekan tombol mencatat permintaan. Begitu waktu hijau minimum untuk mobil selesai, lampu menjadi kuning, lalu merah, dan setelah jeda aman singkat lampu pejalan kaki menjadi hijau. Di kode panduan ini lampu hijau pejalan kaki berkedip sebelum berakhir, lalu siklus kembali ke mobil.

Lihat semua proyek
Lampu Lalu Lintas
#3Pemula

Lampu Lalu Lintas

Tiruan mini lampu lalu lintas yang kamu lihat di jalan setiap hari. Merah menyala dua detik, kuning menyala sebentar, hijau menyala dua detik, lalu kembali ke merah lewat kuning lagi, terus berulang.

4.8(131)
397
Lampu Lalu Lintas ESP32
#107Pemula

Lampu Lalu Lintas ESP32

Simulasi lampu lalu lintas sungguhan dengan 3 LED merah-kuning-hijau. Pengaturan waktunya mendekati logika lalu lintas sungguhan: merah lama, kuning singkat, hijau lama. Contoh klasik kendali GPIO berurutan.

4.4(21)
44
Simulator Lampu Lalu Lintas Raspberry Pi Pico (3 LED Berurutan)
#150Pemula

Simulator Lampu Lalu Lintas Raspberry Pi Pico (3 LED Berurutan)

Kita menyimulasikan lampu lalu lintas sungguhan dengan LED merah, kuning, dan hijau; proyek 3 LED pertama di seri Pico! Hijau 4 detik "jalan", kuning 1,5 detik "siap", merah 3 detik "berhenti", dan merah+kuning 1 detik "bersiap" (pola Eropa). Pelajari pendefinisian fungsi (def all_off()), logika state machine, dan sinkronisasi beberapa GPIO. 3 LED di GP11 (Hijau), GP12 (Kuning), GP13 (Merah), masing-masing dengan resistor 220Ω, berdampingan di board.

4.0(1)
12
Dua LED Berkedip Bergantian
#2Pemula

Dua LED Berkedip Bergantian

Dua LED berkedip cepat secara bergantian: ketika satu menyala, yang lain mati, seperti sedang saling melempar bola. Arduino menyalakan setiap lampu selama seperlima detik lalu menyerahkannya ke yang l

4.6(105)
343
Kendali LED dengan Tombol Tekan (Tekan)
#9Pemula

Kendali LED dengan Tombol Tekan (Tekan)

Persis seperti bel pintu: lampu tetap menyala selama kamu menekan, dan mati ketika kamu melepasnya. Arduino terus mendengarkan tombol; selama ditekan LED menyala, dan begitu jarimu terangkat LED mati.

4.8(113)
229
Lampu Polisi LED
#4Pemula

Lampu Polisi LED

Persis seperti lampu di mobil polisi: LED merah berkedip tiga kali dengan cepat, lalu LED biru berkedip tiga kali, dan polanya terus berulang tanpa henti. Yang kamu butuhkan hanya dua LED dan dua resi

4.7(103)
258
Lampu Lalu Lintas Raspberry Pi Pico dengan Pemilih 4 Mode lewat Tombol (State Machine)
#158Menengah

Lampu Lalu Lintas Raspberry Pi Pico dengan Pemilih 4 Mode lewat Tombol (State Machine)

4 mode lampu lalu lintas dengan 1 tombol! Setiap tekanan mengganti mode: Siklus normal (merah → kuning → hijau), Hanya Merah (tanda berhenti), Kuning Berkedip (mode malam), Mati (perawatan). Konsep: state machine (variabel mode menentukan perilaku), perputaran mode dengan modulo ((mode + 1) % 4 → 0→1→2→3→0), waktu non-blocking (fase LED dengan time.ticks_ms() + time.ticks_diff(); jeda debounce singkat tetap memakai sleep_ms).

5.0(1)
15