Hazır proje · Arduino Uno R3

Arduino Uno'da trafik ışığı

Bir Uno, WAIT lambasını doğrudan butondan yakan bir 74HC04 ile bir yaya geçidi çalıştırır. Tüm yapım, bir Arduino Uno ve 12 parça daha, aşağıdaki firmware üzerinde tarayıcında çalışır; kablolamayı ya da kodu değiştirmek ve yeniden çalıştırmak için düzenleyicide aç.

Öğretiyor musun? Tek tıkla sınıfına ata.

Orta About 30 minutes to build and run. Tarayıcında çalışır. Ücretsiz, hesap gerekmez.

Parçalar yaklaşık $33'a satılıyor. Mokxi'de ücretsiz.

Adım adım, bağlantı ve yaygın hatalarla: Yaya Butonlu Arduino Trafik Işığı Kodu

Trafik ışığı · Arduino Uno R3live0.000 s 0.00x
Butona basılı tut
Devrenin kendisi, burada simülatörde çalışıyor. Basılabilecek şeylere bas; düzenleyicide açmak için başka bir şeye tıkla.

What you'll learn

  • Interrupts that catch a press during delay
  • Minimum and maximum timing for a phase
  • A traffic light sequence
  • Using a logic chip instead of code
  • Pull-up inputs and active low buttons
  • Difficulty: Orta
  • Time: About 30 minutes
  • Board: Arduino Uno R3
  • Parts: 14

Nasıl çalışır

The Uno runs a pelican crossing. Green is the resting state, on pin 10. Pressing the button on pin 2 triggers an interrupt that sets a flag, even while the sketch is waiting. Green lasts: least 3 seconds, and at most 9 seconds if no one presses. konumunda

Then amber shows for 1.5 seconds, red and the walk lamp on pin 11 show for 4 seconds, and flashing amber with a flashing walk lamp runs for 6 seconds. The blue WAIT lamp is not controlled by the Uno, all adresinde: a 74HC04 inverter lights it straight from the button line.

Wiring table

Every connection, pin by pin, read from the circuit itself. Each row joins the pin on the left to the pin on the right, by a jumper wire or a breadboard strip.

Parça ve pinConnects to
74HC04 hex inverter pin GNDArduino Uno R3 pin GND
Pushbutton pin 2aArduino Uno R3 pin GND
LED, red pin CArduino Uno R3 pin GND
LED, yellow pin CArduino Uno R3 pin GND
LED, green pin CArduino Uno R3 pin GND
LED, white pin CArduino Uno R3 pin GND
LED, blue pin CArduino Uno R3 pin GND
Resistor, 220 Ω (4) pin 1Arduino Uno R3 pin 11
Resistor, 220 Ω (3) pin 1Arduino Uno R3 pin 10
Resistor, 220 Ω (2) pin 1Arduino Uno R3 pin 9
Resistor, 220 Ω (1) pin 1Arduino Uno R3 pin 8
74HC04 hex inverter pin 1AArduino Uno R3 pin 2
Pushbutton pin 1aArduino Uno R3 pin 2
74HC04 hex inverter pin VCCArduino Uno R3 pin 5V
Resistor, 220 Ω (5) pin 174HC04 hex inverter pin 1Y
LED, red pin AResistor, 220 Ω (1) pin 2
LED, yellow pin AResistor, 220 Ω (2) pin 2
LED, green pin AResistor, 220 Ω (3) pin 2
LED, white pin AResistor, 220 Ω (4) pin 2
LED, blue pin AResistor, 220 Ω (5) pin 2

Kod

Düzenleyicinin açtığı şekliyle firmware. Orada bir satırı değiştir ve Çalıştır'a bas: tarayıcıda derlenir.

sketch.ino · Arduino Uno R3
// Traffic light: a pelican crossing with a button that actually does
// something.
//
//   pin 8   red      pin 11  walk
//   pin 9   amber    pin 2   request button, to GND, internal pull-up
//   pin 10  green
//
// The button is on INT0, so a press is caught by the interrupt even while
// loop() is asleep inside delay(). Without that the sketch would only notice a
// press if you happened to be holding the button when it got round to looking,
// which is exactly the bug every first crossing sketch has.
//
// Green is the resting state and it waits there for a request, but never for
// less than MIN_GREEN: a crossing that stopped the traffic the instant anyone
// asked would never let a car through.
//
// The WAIT lamp on the breadboard is not driven from here at all. It hangs off
// a 74HC04 inverter wired straight to the button line, so it lights the moment
// the contact closes, a reminder that not everything has to be the
// microcontroller's job.

const int RED = 8;
const int AMBER = 9;
const int GREEN = 10;
const int WALK = 11;
const int BUTTON = 2;

const unsigned long MIN_GREEN = 3000;
const unsigned long MAX_GREEN = 9000;
const unsigned long AMBER_MS = 1500;
const unsigned long WALK_MS = 4000;

volatile bool requested = false;

static void onPress() { requested = true; }

static void lights(int red, int amber, int green) {
  digitalWrite(RED, red ? HIGH : LOW);
  digitalWrite(AMBER, amber ? HIGH : LOW);
  digitalWrite(GREEN, green ? HIGH : LOW);
}

// Hold green until someone asks, or until the maximum runs out.
static void waitForRequest() {
  unsigned long started = millis();
  for (;;) {
    unsigned long waited = millis() - started;
    if (waited >= MAX_GREEN) return;
    noInterrupts();
    bool asked = requested;
    interrupts();
    if (asked && waited >= MIN_GREEN) return;
    delay(20);
  }
}

void setup() {
  pinMode(RED, OUTPUT);
  pinMode(AMBER, OUTPUT);
  pinMode(GREEN, OUTPUT);
  pinMode(WALK, OUTPUT);
  pinMode(BUTTON, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(BUTTON), onPress, FALLING);
  Serial.begin(115200);
  Serial.println("Mokxi Arduino Uno: crossing ready, press the button");
}

void loop() {
  lights(0, 0, 1);
  Serial.println("green");
  waitForRequest();

  lights(0, 1, 0);
  Serial.println("amber");
  delay(AMBER_MS);

  lights(1, 0, 0);
  digitalWrite(WALK, HIGH);
  Serial.println("walk");
  delay(WALK_MS);

  // the flashing period at the end of the walk phase
  // The pelican's own ending: the walk lamp flashes to say "finish crossing"
  // while the drivers get a flashing amber, which means "go if the crossing
  // is clear". Then straight back to green. (A red-and-amber pair before
  // green is the junction signal's sequence, not a crossing's.)
  Serial.println("flashing amber");
  for (int i = 0; i < 12; i++) {
    int on = (i & 1) ? LOW : HIGH;
    digitalWrite(WALK, on);
    lights(0, on == HIGH, 0);
    delay(500);
  }
  digitalWrite(WALK, LOW);
  noInterrupts();
  requested = false;
  interrupts();
}

Code walkthrough

The key functions of the sketch, and what each one does.

onPress sketch.ino

The interrupt handler. It only sets the volatile flag requested to true. Keeping it tiny is the rule for interrupt code.

static void onPress() { requested = true; }

waitForRequest sketch.ino

Holds green. It returns when MAX_GREEN has passed, or when a request exists and MIN_GREEN has passed. It copies the flag with interrupts off so the read is safe.

// Hold green until someone asks, or until the maximum runs out.
static void waitForRequest() {
  unsigned long started = millis();
  for (;;) {
    unsigned long waited = millis() - started;
    if (waited >= MAX_GREEN) return;
    noInterrupts();
    bool asked = requested;
    interrupts();
    if (asked && waited >= MIN_GREEN) return;
    delay(20);
  }
}

lights sketch.ino

Sets the red, amber and green pins in one call. A non-zero argument turns that lamp on.

static void lights(int red, int amber, int green) {
  digitalWrite(RED, red ? HIGH : LOW);
  digitalWrite(AMBER, amber ? HIGH : LOW);
  digitalWrite(GREEN, green ? HIGH : LOW);
}

loop sketch.ino

Runs the whole sequence once per pass: green, amber, red with walk, then twelve half second flashes. At the end it clears the request flag.

void loop() {
  lights(0, 0, 1);
  Serial.println("green");
  waitForRequest();

  lights(0, 1, 0);
  Serial.println("amber");
  delay(AMBER_MS);

  lights(1, 0, 0);
  digitalWrite(WALK, HIGH);
  Serial.println("walk");
  delay(WALK_MS);

  // the flashing period at the end of the walk phase
  // The pelican's own ending: the walk lamp flashes to say "finish crossing"
  // while the drivers get a flashing amber, which means "go if the crossing
  // is clear". Then straight back to green. (A red-and-amber pair before
  // green is the junction signal's sequence, not a crossing's.)
  Serial.println("flashing amber");
  for (int i = 0; i < 12; i++) {
    int on = (i & 1) ? LOW : HIGH;
    digitalWrite(WALK, on);
    lights(0, on == HIGH, 0);
    delay(500);
  }
  digitalWrite(WALK, LOW);
  noInterrupts();
  // ... 3 more lines in the editor

Troubleshooting

The usual mistakes with this circuit, and the fix for each.

  • A press is ignored. This project
    The button must be on pin 2, the interrupt pin. It joins pin 2 to GND.
  • The WAIT lamp does not light. This project
    It comes from the 74HC04, not the sketch. Check 5 V and GND on the chip, and the button line into 1A.
  • The crossing never leaves green. This project
    That only happens before MIN_GREEN has passed. Wait three seconds after a press.
  • The outputs are random or noisy. 74HC04 hex inverter
    Tie every unused input to GND or VCC. A floating CMOS input can oscillate, draw extra current and give random outputs.
  • The chip behaves badly or an LED is too dim. 74HC04 hex inverter
    Add a 0.1 uF capacitor between VCC (pin 14) and GND (pin 7). Run it on 2 V to 6 V. An output gives only a few milliamps, so use a resistor with any LED.
  • The input reads random HIGH and LOW when the button is not pressed. Buton
    A floating pin picks up noise. Add a 10 k pull-down or pull-up resistor, or use INPUT_PULLUP and wire the button between the pin and GND. Then pressed reads LOW.
  • The button seems always pressed, or never changes. Buton
    A 4-leg tactile switch has legs joined in pairs. Place it across the breadboard center gap so the pairs sit on different rows. Wired along one side, the legs are already connected.
  • The LED is dim, burns out, or the pin reads wrong because the resistor value is off. Resistor
    Read the color bands again. A 220 ohm to 330 ohm resistor suits a typical LED on 5 V. 10k is a common pull-up or pull-down value. Check with a multimeter if unsure.

Değiştir ve sakla

Düzenleyicide aç, devreyi ya da kodu değiştir ve sürümünü ücretsiz bir hesapta sakla.