Belajar

An Arduino traffic light, with a crossing button that works

Menengah

Atau lihat semua pelajaran.

  • 503komponen di meja kerja
  • 44board sedang berjalan
  • 1.00xwaktu nyata, di semua board
Arduino Uno: penyeberangan pelikanlive0.000 s 0.00x
Tekan tombolnya untuk minta menyeberang
Contoh traffic, berjalan di ATmega328P simulasi. Tekan tombol di breadboard untuk minta menyeberang.

Lampu lalu lintas adalah proyek yang dipilih hampir setiap kursus Arduino di minggu keduanya, karena isinya cuma tiga LED dan beberapa delay tapi hasilnya tetap terlihat keren. Versi di atas selangkah lebih jauh dari kebanyakan: ini adalah penyeberangan pelikan, dengan lampu pejalan kaki, tombol permintaan, dan aturan bahwa lampu hijau tidak pernah berakhir lebih cepat dari seharusnya. Proyek ini sedang berjalan di Arduino Uno simulasi sekarang, dengan sketch yang sama dengan yang bisa kamu baca di bagian bawah halaman ini.

Tekan tombol di breadboard dan lihat apa yang terjadi. Lampu biru WAIT menyala begitu kontaknya tertutup, hijau bertahan sampai waktu minimumnya terpenuhi, lalu kuning, lalu merah bersama lampu putih tanda jalan, lalu fase berkedip, dan kembali ke hijau. Buka di editor untuk mengubah pengaturan waktu mana pun, lalu jalankan lagi.

What you need

  • Arduino Uno
  • Lima LED: merah, kuning, hijau, putih, dan biru
  • Lima resistor 220 ohm, satu per LED
  • Satu tombol tekan
  • Satu inverter hex 74HC04, untuk lampu WAIT
  • Breadboard dan kabel jumper

Wiring

Komponen dan pinDisambung keCatatan
LED merah, lewat 220 ohmPin 8Lampu merah kendaraan
LED kuning, lewat 220 ohmPin 9Lampu kuning kendaraan
LED hijau, lewat 220 ohmPin 10Lampu hijau kendaraan
LED putih, lewat 220 ohmPin 11Lampu tanda jalan
Tombol tekan, satu sisiPin 2Sisi lainnya ke GND; sketch menyalakan pull-up internal
Input 74HC04Jalur tombolOutput-nya menyalakan lampu biru WAIT, tanpa kode sama sekali
74HC04 pin 14 dan pin 75 V dan GNDChip ini tidak melakukan apa-apa sampai keduanya tersambung

Cara urutannya disusun

Sebuah penyeberangan punya satu keadaan diam, hijau untuk kendaraan, dan hanya meninggalkan keadaan itu kalau ada yang meminta. Sketch menuliskannya sebagai loop dengan empat fase: hijau sampai ada permintaan (tapi tidak pernah kurang dari tiga detik dan tidak pernah lebih dari sembilan), kuning selama satu setengah detik, merah bersama lampu tanda jalan selama empat detik, lalu dua belas kedipan setengah detik dari lampu kuning dan lampu tanda jalan bersamaan, seperti yang dilakukan penyeberangan pelikan sungguhan di akhir fase jalannya.

Setiap fase adalah panggilan ke helper kecil lights() yang mengatur merah, kuning, dan hijau sekaligus. Menulis ketiga lampu bersamaan, setiap kali, adalah cara mencegah bug lampu lalu lintas yang paling umum, yaitu saat sebuah fase lupa mematikan lampu dari fase sebelumnya sehingga dua warna menyala bersamaan.

Empat fase, dari contoh traffic (dipersingkat)
void loop() {
  lights(0, 0, 1);          // green
  waitForRequest();

  lights(0, 1, 0);          // amber
  delay(AMBER_MS);

  lights(1, 0, 0);          // red, and walk
  digitalWrite(WALK, HIGH);
  delay(WALK_MS);

  for (int i = 0; i < 12; i++) {   // the flashing phase
    int on = (i & 1) ? LOW : HIGH;
    digitalWrite(WALK, on);
    lights(0, on == HIGH, 0);
    delay(500);
  }
  digitalWrite(WALK, LOW);
}

Kenapa tombolnya memakai interrupt

Sketch penyeberangan pertama yang ditulis kebanyakan orang mengecek tombol dengan digitalRead() di suatu tempat di loop(). Cara itu berhasil saat diuji dengan menahan tombol, dan gagal begitu seseorang hanya mengetuknya, karena hampir sepanjang siklus board sedang berada di dalam delay() dan sama sekali tidak melihat pin-nya. Ketukan di fase merah tidak pernah terlihat.

Sketch ini memasang tombol di pin 2, yaitu pin INT0 milik Uno, dan memasang interrupt di edge turunnya. Handler-nya hanya melakukan satu hal: memasang penanda bernama requested. Apa pun yang sedang dikerjakan loop utama, termasuk sedang diam di dalam delay, tekanannya tertangkap. Loop lalu membaca penanda itu sambil menahan interrupt sebentar, jadi tidak pernah membaca nilai yang baru setengah ditulis, dan menghapusnya di akhir siklus.

Penanda itu dideklarasikan volatile, yang memberi tahu compiler bahwa ada sesuatu di luar alur normal program yang bisa mengubahnya. Kalau kata itu tidak ditulis, compiler yang melakukan optimasi boleh membaca variabelnya sekali dan tidak pernah melihatnya lagi.

Permintaannya, tertangkap apa pun yang sedang dikerjakan loop()
volatile bool requested = false;

static void onPress() { requested = true; }

void setup() {
  pinMode(BUTTON, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(BUTTON), onPress, FALLING);
}

Lampu yang tidak butuh kode

Lampu biru WAIT sama sekali tidak dikendalikan oleh Uno. Lampu ini tergantung di satu gerbang inverter 74HC04 yang disambung langsung ke jalur tombol: jalurnya berada di high lewat pull-up, tombol menariknya ke low, inverter mengubah low itu menjadi high, dan lampunya menyala. Reaksinya dalam hitungan nanodetik, sebelum sketch sempat menyadari apa pun.

Lampu ini ada di rangkaian sebagai pengingat bahwa tidak semua tugas harus dikerjakan mikrokontroler. Lampu ini juga menunjukkan sesuatu tentang simulatornya: 74HC04 di sini adalah chip 14 pin sungguhan dengan catu daya di pin 14 dan 7, dan kalau kamu menghapus salah satu kabel catu dayanya di editor, lampunya berhenti bekerja, persis seperti di meja sungguhan.

Coba di editor

Buka rangkaiannya di editor dan ubah MIN_GREEN dari 3000 menjadi 500. Tekan tombolnya begitu lampu hijau menyala, maka sekarang penyeberangan menghentikan kendaraan hampir seketika, dan itulah alasan penyeberangan sungguhan punya waktu minimum.

Lalu sengaja rusak. Ganti interrupt dengan digitalRead() biasa pada pin 2 di dalam waitForRequest() dan ketuk tombolnya di fase merah. Tekanannya hilang. Pasang kembali interrupt-nya, maka tekanannya tertangkap setiap kali.

Terakhir, seret logic analyzer dari kotak komponen dan jepitkan keempat channel-nya ke pin 8, 9, 10, dan 11. Seluruh urutannya muncul sebagai diagram waktu, dengan fase berkedip sebagai deretan pulsa yang rapi, cara yang jauh lebih cepat untuk mengecek pengaturan waktunya daripada menonton lampu.

Common mistakes

LED tanpa resistor. Setiap lampu di sini punya resistor 220 ohm sendiri, yang menahan arus di sekitar 14 miliampere dari pin 5 volt. LED yang disambung langsung ke pin akan mencoba menarik arus jauh lebih besar daripada yang seharusnya diberikan pin.

Membaca tombol hanya di antara delay, seperti dijelaskan di atas. Kalau tekanan kadang diabaikan, hampir selalu inilah penyebabnya.

Mengira tombol terbaca HIGH saat ditekan. Dengan INPUT_PULLUP, pin diam di high dan tekanan menariknya ke ground, jadi saat ditekan terbaca LOW. Interrupt dipasang di edge turun karena alasan yang sama.

Dua warna menyala bersamaan, karena satu fase menyalakan lampu dan fase berikutnya tidak pernah mematikannya. Mengatur ketiganya bersamaan dalam satu fungsi menghilangkan seluruh jenis bug ini.

Pertanyaan

Bisakah aku membuat lampu lalu lintas sederhana tanpa tombol?

Bisa. Hapus tombol dan panggilan waitForRequest(), lalu beri lampu hijau delay() tetapnya sendiri. Hasilnya adalah urutan tiga LED yang klasik. Versi dengan tombol layak ditambah beberapa baris karena begitulah cara kerja penyeberangan sungguhan.

Kenapa tombolnya di pin 2?

Di Uno, hanya pin 2 dan 3 yang punya interrupt eksternal sendiri, INT0 dan INT1. Pin mana pun bisa dibaca dengan digitalRead(), tapi hanya kedua pin itu yang bisa memanggil fungsi begitu nilainya berubah.

Apakah ini berjalan di Arduino Uno sungguhan tanpa diubah?

Sketch-nya hanya memakai panggilan Arduino standar: pinMode, digitalWrite, delay, millis, dan attachInterrupt. Ini kode yang sama dengan yang akan kamu upload dari Arduino IDE.

Bagaimana cara membuatnya jadi persimpangan empat arah?

Tambahkan satu set tiga lampu lagi di tiga pin lain dan beri setiap fase dua panggilan, satu untuk setiap jalan. Persimpangan juga punya fase merah-dan-kuning sebelum hijau, yang tidak ada di penyeberangan pelikan.

Rakit versi nyatanya

Buka editor, ubah sebuah nilai, dan lihat angkanya ikut berubah. Tidak ada yang perlu dipasang, dan tidak perlu akun.