An Arduino traffic light, with a crossing button that works
Orta
Ya da tüm dersleri gör.
- 503parça tezgahta
- 44kart şu an çalışıyor
- 1.00xgerçek zamanlı, her kartta
Trafik ışığı, hemen her Arduino kursunun ikinci haftasında başvurduğu projedir, çünkü üç LED ve bir avuç delay'dir ve yine de bir şeye benzer. Yukarıdaki sürüm çoğundan bir adım ileri gider: yaya lambalı, istek butonlu ve yeşilin hiçbir zaman olması gerekenden önce bitmediği kuralına sahip bir yaya geçididir. Şu anda, bu sayfanın ilerisinde okuyabileceğin aynı kod üzerinde, simüle edilmiş bir Arduino Uno'da çalışıyor.
Breadboard'daki butona bas ve ne olduğunu izle. Mavi WAIT lambası kontak kapandığı anda yanar, yeşil asgari süresini doldurana kadar tutar, sonra sarı, sonra beyaz yürüme lambasıyla kırmızı, sonra yanıp sönen aşama ve yeşile dönüş. Zamanlamalardan herhangi birini değiştirmek ve yeniden çalıştırmak için düzenleyicide aç.
What you need
- Bir Arduino Uno
- Beş LED: kırmızı, sarı, yeşil, beyaz ve mavi
- Beş adet 220 ohm'luk direnç, LED başına bir
- Bir buton
- WAIT lambası için bir 74HC04 altılı evirici
- Bir breadboard ve jumper kablolar
Wiring
| Parça ve pin | Gittiği yer | Not |
|---|---|---|
| Kırmızı LED, 220 ohm üzerinden | Pin 8 | Trafik kırmızısı |
| Sarı LED, 220 ohm üzerinden | Pin 9 | Trafik sarısı |
| Yeşil LED, 220 ohm üzerinden | Pin 10 | Trafik yeşili |
| Beyaz LED, 220 ohm üzerinden | Pin 11 | Yürüme lambası |
| Buton, bir taraf | Pin 2 | Diğer taraf GND'ye; kod dahili pull-up'ı açar |
| 74HC04 girişi | Buton hattı | Çıkışı, kod olmadan mavi WAIT lambasını sürer |
| 74HC04 pin 14 ve pin 7 | 5 V ve GND | Çip ikisi de bağlanana kadar hiçbir şey yapmaz |
Dizi nasıl kurulur
Bir geçidin tek bir dinlenme durumu vardır, trafik için yeşil, ve bu durumdan yalnızca biri istediğinde çıkar. Kod bunu dört aşamalı bir döngü olarak yazar: bir istek gelene kadar yeşil (ama asla üç saniyeden az ve dokuz saniyeden fazla değil), bir buçuk saniye sarı, yürüme lambasıyla dört saniye kırmızı, sonra sarı ve yürüme lambasının birlikte on iki kez yarım saniyelik yanıp sönmesi; gerçek bir yaya geçidi yürüme aşamasının sonunda bunu yapar.
Her aşama, kırmızıyı, sarıyı ve yeşili tek seferde ayarlayan küçük bir lights() yardımcısına yapılan bir çağrıdır. Üç lambayı her seferinde birlikte yazmak, en yaygın trafik ışığı hatasını önler; bu hatada bir aşama kendinden önceki lambayı kapatmayı unutur ve iki renk birden yanar.
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);
}Buton neden bir kesmede
Çoğu insanın yazdığı ilk geçit kodu butonu loop() içinde bir yerde digitalRead() ile kontrol eder. Butona basılı tutarak test ettiğinde çalışır ve biri dokunur dokunmaz başarısız olur, çünkü döngünün çoğunda kart bir delay() içindedir ve pine hiç bakmaz. Kırmızı aşamadaki bir dokunuş hiç görülmez.
Bu kod butonu Uno'nun INT0 pini olan pin 2'ye koyar ve düşen kenarına bir kesme bağlar. İşleyici tek bir şey yapar: requested adlı bir bayrağı ayarlar. Ana döngü bir delay içinde beklemek dahil ne yapıyor olursa olsun, basış yakalanır. Döngü sonra bayrağı kesmeler kısa süre kapalıyken okur, böylece yarım yazılmış bir değer okumaz ve döngünün sonunda temizler.
Bayrak volatile olarak tanımlanır; bu, derleyiciye programın normal akışı dışındaki bir şeyin onu değiştirebileceğini söyler. Bu kelimeyi atarsan, optimize eden bir derleyici değişkeni bir kez okuyup bir daha bakmayabilir.
volatile bool requested = false;
static void onPress() { requested = true; }
void setup() {
pinMode(BUTTON, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(BUTTON), onPress, FALLING);
}Kod gerektirmeyen lamba
Mavi WAIT lambasını Uno hiç sürmez. Doğrudan buton hattına bağlı bir 74HC04 eviricinin bir kapısına asılıdır: hat pull-up ile yüksek durur, buton onu düşük çeker, evirici bu düşüğü yükseğe çevirir ve lamba yanar. Kod bir şeyi fark edecek fırsatı bulmadan nanosaniyeler içinde tepki verir.
Her işin mikrodenetleyiciye ait olmadığının bir hatırlatması olarak devrededir. Ayrıca simülatör hakkında bir şey gösterir: buradaki 74HC04, beslemesi pin 14 ve 7'de olan gerçek bir 14 pinli çiptir ve düzenleyicide besleme kablolarından birini silersen lamba, masada olacağı gibi tam olarak çalışmayı bırakır.
Düzenleyicide dene
Devreyi düzenleyicide aç ve MIN_GREEN'i 3000'den 500'e değiştir. Yeşil yanar yanmaz butona bas; geçit artık trafiği neredeyse hemen durdurur, gerçek geçitlerin bir asgari süresi olmasının tam nedeni budur.
Sonra bilerek boz. Kesmeyi waitForRequest() içindeki pin 2'nin sade bir digitalRead()'iyle değiştir ve kırmızı aşamada butona dokun. Basış kaybolur. Kesmeyi geri koy ve her seferinde yakalanır.
Son olarak parça kutusundan bir mantık analizörü sürükle ve dört kanalını pin 8, 9, 10 ve 11'e tutturt. Tüm dizi bir zamanlama diyagramı olarak görünür, yanıp sönme aşaması düzgün bir darbe sırası olarak; bu, zamanlamaları kontrol etmenin lambaları izlemekten çok daha hızlı bir yoludur.
Common mistakes
Bir LED'de direnç olmaması. Buradaki her lambanın kendi 220 ohm'luk direnci vardır ve 5 voltluk bir pinden akımı yaklaşık 14 miliampere tutar. Doğrudan bir pine bağlanan bir LED, pinin vermesi gerekenden çok daha fazlasını almaya çalışır.
Butonu yalnızca delay'ler arasında okumak, yukarıda anlatıldığı gibi. Bir basış bazen yok sayılıyorsa neredeyse her zaman nedeni budur.
Butonun basılınca HIGH okumasını beklemek. INPUT_PULLUP ile pin boştayken yüksektir ve basış onu toprağa çeker, yani basılı LOW'dur. Kesme aynı nedenle düşen kenardadır.
Aynı anda iki renk yanması, çünkü bir aşama bir lambayı açtı ve sonraki onu hiç kapatmadı. Üçünü tek bir fonksiyonda birlikte ayarlamak bu hata sınıfının tamamını ortadan kaldırır.
Sorular
Butonsuz basit bir trafik ışığı kurabilir miyim?
Evet. Butonu ve waitForRequest() çağrısını sil ve yeşile kendi sabit delay()'ini ver. Sonuç klasik üç LED'li dizidir. Buton sürümü fazladan birkaç satıra değer, çünkü gerçek geçitler böyle davranır.
Buton için neden pin 2?
Bir Uno'da yalnızca 2 ve 3 numaralı pinlerin kendi harici kesmeleri vardır: INT0 ve INT1. Herhangi bir pin digitalRead() ile okunabilir, ama yalnızca bu ikisi değiştikleri anda bir fonksiyon çağırabilir.
Bu gerçek bir Arduino Uno'da değişmeden çalışır mı?
Kod yalnızca standart Arduino çağrılarını kullanır: pinMode, digitalWrite, delay, millis ve attachInterrupt. Arduino IDE'den yükleyeceğin aynı koddur.
Dört yollu bir kavşağı nasıl yaparım?
Üç pin daha üzerinde ikinci bir üç lamba takımı ekle ve her aşamaya, her yol için bir tane olmak üzere iki çağrı ver. Bir kavşakta ayrıca yeşilden önce kırmızı ve sarı bir aşama da vardır; yaya geçidinde bu yoktur.
Devam et
Bunu gerçekten kur
Düzenleyiciyi aç, bir değeri değiştir ve sayının onunla birlikte oynadığını izle. Kurulacak bir şey yok ve hesap gerekmez.