Arduino Programming for Beginners: Traffic Light Controller Project Tutorial
Whatsapp Pinterest
Advertisement

The Arduino traffic light is a fun little project that you can build in under an hour. Here’s how to build your own using an Arduino, and how to change the circuit for an advanced variation.

If you’d rather watch this as tutorial as a video, we have you covered:

What You Need to Build a Traffic Light Controller

Apart from the basic Arduino, you’ll need:

  • 1 x 10k-ohm resistor
  • 1 x pushbutton switch
  • 6 x 220-ohm resistors
  • A breadboard
  • Connecting wires
  • Red, yellow and green LEDs

Almost any Arduino will work for this project, providing it has enough pins. Make sure you read our Arduino buying guide Arduino Buying Guide: Which Board Should You Get? Arduino Buying Guide: Which Board Should You Get? There are so many different kinds of Arduino boards out there, you'd be forgiven for being confused. Which should you buy for your project? Let us help, with this Arduino buying guide! Read More if you are not sure what model you need. You may already have these parts in your Arduino starter kit What's in Your Arduino Starter Kit? [Arduino Beginners] What's in Your Arduino Starter Kit? [Arduino Beginners] Faced with a box full of electronic components, it's easy to be overwhelmed. Here's a guide to exactly what you'll find in your kit. Read More .

Arduino Traffic Light: The Basics

Let’s start small. A basic, single traffic light is a good place to start. Here’s the circuit:

Circuit diagram for basic Arduino traffic light

Connect the anode (long leg) of each LED to digital pins eight, nine, and ten (via a 220-ohm resistor). Connect the cathodes (short leg) to the Arduino’s ground.

Code for the Arduino Traffic Light

Start by defining variables so that you can address the lights by name rather than a number. Start a new Arduino project, and begin with these lines:

int red = 10;
int yellow = 9;
int green = 8;

Next, let’s add the setup function, where you’ll configure the red, yellow and green LEDs to be outputs. Since you have created variables to represent the pin numbers, you can now refer to the pins by name instead:

void setup(){
    pinMode(red, OUTPUT);
    pinMode(yellow, OUTPUT);
    pinMode(green, OUTPUT);
}

The pinMode function configures the Arduino to use a given pin as an output. You have to do this for your LEDs to work at all. Now for the actual logic of the traffic light. Here’s the code you need. Add this below your variable definitions and setup function:

void loop(){
    changeLights();
    delay(15000);
}

void changeLights(){
    // green off, yellow on for 3 seconds
    digitalWrite(green, LOW);
    digitalWrite(yellow, HIGH);
    delay(3000);

    // turn off yellow, then turn red on for 5 seconds
    digitalWrite(yellow, LOW);
    digitalWrite(red, HIGH);
    delay(5000);

    // red and yellow on for 2 seconds (red is already on though)
    digitalWrite(yellow, HIGH);
    delay(2000);

    // turn off red and yellow, then turn on green
    digitalWrite(yellow, LOW);
    digitalWrite(red, LOW);
    digitalWrite(green, HIGH);
    delay(3000);
}

Upload this code to your Arduino, and run (make sure to select the correct board and port from the Tools > Board and Tools > Port menus). You should have a working traffic light that changes every 15 seconds, like this (sped up):

Arduino traffic light in action

Let’s break down this code. The changeLights function performs all the hard work. This rotates the traffic light through yellow and red, then back to green. As this gets called inside the loop function, the Arduino will run this code forever, with a 15-second pause every time.

The changeLights function consists of four distinct steps:

  • Green on, yellow off
  • Yellow off, red on
  • Yellow on, red on
  • Green on, red off, yellow off

These four steps replicate the process used in real traffic lights. For each step, the code is very similar. The appropriate LED gets turned on or off using digitalWrite. This is an Arduino function used to set output pins to HIGH (for on), or LOW (for off).

After enabling or disabling the required LEDs, the delay makes the Arduino wait for a given amount of time. Three seconds in this case.

Going Deeper: Arduino Pedestrian Crossing

Now that you know the basics, let’s improve it. Add in a pushbutton for pedestrians to change the light whenever they like:

Circuit diagram for Arduino pedestrian crossing

Notice how the traffic light is exactly the same as the previous example. Connect the button to digital pin 12. You’ll notice that the switch has a high-impedance 10k-ohm resistor attached to it, and you may be wondering why. This is a pull-down resistor.

A switch either lets the current flow or doesn’t. This seems simple enough, but in a logic circuit, the current should be always flowing in either a high or low state (remember, 1 or 0, HIGH or LOW). You might assume that a pushbutton switch that isn’t actually pressed would be in a LOW state, but in fact, it’s said to be ‘floating’, because no current gets drawn at all.

In this floating state, it’s possible that a false reading will occur as it fluctuates with electrical interference. In other words, a floating switch is giving neither a reliable HIGH nor LOW reading. A pull-down resistor keeps a small amount of current flowing when the switch gets closed, thereby ensuring an accurate low state reading.

In other logic circuits, you may find a pull-up resistor instead, and this works on the same principle, but in reverse, making sure that particular logic gate defaults to high.

Now, in the loop part of the code, instead of changing the lights every 15 seconds, you’re going to read the state of the pushbutton switch instead, and only change the lights when it’s activated.

Code for the Arduino Pedestrian Crossing

Start by adding a new variable to store your button pin:

int button = 12; // switch is on pin 12

Now, in the setup function, add a new line to declare the switch as an input. Add a line to set the traffic lights to the green stage. Without this initial setting, they would off until the first time changeLights runs.

pinMode(button, INPUT);
digitalWrite(green, HIGH);

Change the entire loop function to the following instead:

void loop() {
    if (digitalRead(button) == HIGH){
        delay(15); // software debounce
        if (digitalRead(button) == HIGH) {
            // if the switch is HIGH, ie. pushed down - change the lights!
            changeLights();
            delay(15000); // wait for 15 seconds
        }
    }
}

That should do it. You may be wondering why the button checking happens twice (digitalRead(button)), separated by a small delay. This is debouncing. Much like the pull-down resistor for the button, this simple check stops the code detecting minor interference as a button press.

By waiting inside the if statement for 15 seconds, the traffic lights can’t change for at least that duration. Once 15 seconds is over the loop restarts. Each restart of the loop, it reads the state of the button again, but if it isn’t pressed, the if statement never activates, the lights never change, and the program restarts again.

Here’s how this looks (sped up):

Arduino pedestrian crossing in action

Arduino Traffic Light with Junction

Let’s try a more advanced model. Instead of a pedestrian crossing, change your circuit to have two traffic lights:

Cricuit diagram for Arduino traffic lights with junction

Connect the second traffic light to digital pins 11, 12, and 13.

Code for the Arduino Traffic Light with Junction

First, assign your new traffic light pins to variables, and configure them as outputs, like in the first example:

// light one
int red1 = 10;
int yellow1 = 9;
int green1 = 8;

// light two
int red2 = 13;
int yellow2 = 12;
int green2 = 11;

void setup(){
    // light one
    pinMode(red1, OUTPUT);
    pinMode(yellow1, OUTPUT);
    pinMode(green1, OUTPUT);

    // light two
    pinMode(red2, OUTPUT);
    pinMode(yellow2, OUTPUT);
    pinMode(green2, OUTPUT);
}

Now, update your loop to use the code from the first example (instead of the pedestrian crossing):

void loop(){
    changeLights();
    delay(15000);
}

Once again, all the work is carried out in the changeLights function. Rather than going red > red & yellow > green, this code will alternate the traffic lights. When one is on green, the other is on red. Here’s the code:

void changeLights(){
    // turn both yellows on
    digitalWrite(green1, LOW);
    digitalWrite(yellow1, HIGH);
    digitalWrite(yellow2, HIGH);
    delay(5000);

    // turn both yellows off, and opposite green and red
    digitalWrite(yellow1, LOW);
    digitalWrite(red1, HIGH);
    digitalWrite(yellow2, LOW);
    digitalWrite(red2, LOW);
    digitalWrite(green2, HIGH);
    delay(5000);

    // both yellows on again
    digitalWrite(yellow1, HIGH);
    digitalWrite(yellow2, HIGH);
    digitalWrite(green2, LOW);
    delay(3000);

    // turn both yellows off, and opposite green and red
    digitalWrite(green1, HIGH);
    digitalWrite(yellow1, LOW);
    digitalWrite(red1, LOW);
    digitalWrite(yellow2, LOW);
    digitalWrite(red2, HIGH);
    delay(5000);
}

Here’s what that looks like (sped up):

Arduino traffic light with junction in action

Arduino Traffic Light Next Steps

That’s all for today. Your new understanding of Arduino LEDs and buttons applies to all kinds of different projects. If you want to expand these traffic lights, why not build a four-way (or more) junction, complete with many pedestrian crossings, and pedestrian traffic lights?

Or why not expand your new skills with a bigger project such as this DIY MIDI controller How to Make a MIDI Controller with an Arduino How to Make a MIDI Controller with an Arduino As a musician who has amassed a collection of musical instruments and noise boxes, the humble Arduino is the perfect tool to create a custom MIDI controller. Read More ?

Image Credit: androsvector/Shutterstock

Explore more about: Arduino, DIY Project Tutorials, Programming.

Enjoyed this article? Stay informed by joining our newsletter!

Enter your Email

Leave a Reply

Your email address will not be published. Required fields are marked *

  1. Ken Scott
    May 2, 2019 at 1:14 pm

    I added a flashing yellow after red and yellow as this is how pedestrian crossings work in UK

    int red = 10;
    int yellow = 9;
    int green = 8;
    int button = 12; // switch is on pin 12

    void setup(){
    pinMode(red, OUTPUT);
    pinMode(yellow, OUTPUT);
    pinMode(green, OUTPUT);
    pinMode(button, INPUT);
    digitalWrite(green, HIGH);
    }

    void loop() {
    if (digitalRead(button) == HIGH){
    delay(15); // software debounce
    if (digitalRead(button) == HIGH) {
    // if the switch is HIGH, ie. pushed down - change the lights!
    changeLights();
    delay(15000); // wait for 15 seconds
    }
    }
    }

    void changeLights(){
    // green off, yellow on for 3 seconds
    digitalWrite(green, LOW);
    digitalWrite(yellow, HIGH);
    delay(3000);

    // turn off yellow, then turn red on for 5 seconds
    digitalWrite(yellow, LOW);
    digitalWrite(red, HIGH);
    delay(5000);

    // red and yellow on for 2 seconds (red is already on though)
    digitalWrite(yellow, HIGH);
    delay(2000);

    // flashing yellow
    digitalWrite(red,LOW);
    delay(1000);
    for(int flash = 0; flash <= 6; flash++) {
    digitalWrite(yellow, LOW);
    delay(200);
    digitalWrite(yellow, HIGH);
    delay(200);
    };

    // turn off red and yellow, then turn on green
    digitalWrite(yellow, LOW);
    digitalWrite(red, LOW);
    digitalWrite(green, HIGH);
    delay(3000);
    }

  2. Brindall
    April 13, 2019 at 7:49 pm

    Once you get the lights working, try this:

    I added a buzzer to simulate a car honking its horn. It beeps at the end of every loop. While the buzzer doesn't sound much like a car horn, it was fun and easy to write that part myself using the same functions learned in the rest of this program.

    (Now to simulate the flashing lights and siren of the police car and ambulance about to arrive after the crash!)

  3. Noha
    November 28, 2018 at 9:36 am

    What if I wanna implement a complete 4-way intersection traffic signal with pedestrians crossing in all directions. How will be the idea of it ?

  4. Noha
    November 28, 2018 at 9:35 am

    What if I wanna implement a complete 4-way intersection traffic signal with pedestrians crossing in all directions. How will the idea look like ??

  5. yoyo
    January 30, 2018 at 2:13 pm

    this does not help me3

  6. Oscar
    November 11, 2017 at 12:03 pm

    Could you give me a download link to the Fritzing file, please? I want to take a look at it.

  7. Daniel
    October 27, 2017 at 3:55 am

    This might be a dumb question but why is the point of the wire going from the Vcc node into the breadboard? it doesnt feed anything to the rest of the circuit and everything performs the same way without it present.

  8. Arya
    October 12, 2017 at 5:39 pm

    hi, i did everything correctly and the green light for the lights 2 wont turn on, do you know how to fix this? thanks

    • gu65ni88
      January 17, 2018 at 9:30 am

      Maybe the light is busted?

    • Joe
      January 6, 2019 at 3:59 am

      Is the led in the right polarity? Is the negative connected to the negative side of the board and the positive side connected to the pin output? Sometimes people put the wrong side pin on the output pin of the arduino. Like the positive side of the led should be on the arduino pin. This can be a very commom mistake. If not then maybe the led is burned out, or just defective. Put in another good led in its place.

  9. Joan
    September 3, 2017 at 3:22 pm

    Thank you very much for this tutorial!! A great way to start tinkering with the components and getting things done!

  10. Alex
    July 23, 2017 at 4:51 pm

    I have a question about the logic of the traffic light circuit. Why would the yellow and red lights ever need to be on at the same time? Apart from the half second transition between a yellow light and a red light?

    • steve
      August 2, 2017 at 7:31 pm

      In the UK, and perhaps other countries too, there is a phase of combined red/yellow. This is set at 2 seconds, and is used as "prepare to go" rather than the 2 second yellow only phase that is a precursor to stop.

  11. Ron Tseytlin
    July 5, 2017 at 6:55 pm

    Thank you for the tutorial! Everything worked for me. But I have a question: What is the use of the red wire on the board's right? It doesn't seem to be connected to anything in any of the examples, and when I removed it everything was still the same.

  12. BharathiKumar
    May 4, 2017 at 2:27 pm

    Ya nice,I will do many times,super but i will lean more ideas in this little....tell me more instruction to do in this projects....

  13. Markus
    April 27, 2017 at 10:04 am

    I did everything like the instructions said and inserted the code but nothing happens could it be that something is broken on my bord

    • Willie
      May 22, 2017 at 11:59 am

      did you fix it? I have this exact problem right now :/

      • Osman
        August 18, 2017 at 11:29 pm

        I had the same problem, I felt a bit stupid but let me share anyway. I put the wires exactly as the picture. But my breadboard is longer an actually consists of two halves.. so by putting the wire on the far right like the picture, it was not connected to the setup on the left half of my board..

  14. Heithem
    April 25, 2017 at 2:22 pm

    what if we add a pedestrian button to push to cross
    how will the code be

  15. Giovanni Edrose
    March 27, 2017 at 2:16 pm

    can we program our arduino with our smartphones?How?

  16. Danny DelBalzo
    March 17, 2017 at 7:16 pm

    I'm following your basic code and continue to get this error message:

    'changeLights' was not declared in this scope

    Do you have any suggestions?

    • Kyriakos
      March 20, 2017 at 12:20 pm

      same problem here.

      • Joe Coburn
        March 20, 2017 at 5:46 pm

        All fixed, sorry! :)

        • lUZ
          December 24, 2017 at 12:27 am

          HI,I want that the code continue to loop if I do not press the button for 15 seconds,what is the code for that,thanks!

    • Aidan R.
      July 15, 2017 at 11:24 pm

      This happened to me. If you just copy and paste the code it will work though not sure why.

  17. mohamed
    February 15, 2017 at 1:44 am

    what if you have a four-way intersection with four crossing? how do you modify that

  18. T o connor
    February 5, 2017 at 10:00 pm

    For the first example ,[ the single traffic light set]
    the ""delay(15000);"" part of the
    void loop(){
    changeLights();
    delay(15000);
    is adding 15secs to the turn on time of the green LED.
    If this line is removed the green led will run on for the 3 sec as written in the code.

  19. bilal
    February 3, 2017 at 5:04 pm

    there is problem while runnig the code
    traffic for signal 1 is working but for signal 2 its not working plz guide

    • Joe Coburn
      March 20, 2017 at 5:47 pm

      I've updated a typo, thanks for stopping by.

      • Francis Heron
        June 3, 2017 at 5:20 pm

        can you please advise where the corrected code appears or what it is as I cant find it

  20. troy
    February 1, 2017 at 2:21 am

    What is the correct code for the pedestrian crossing traffic light.

    • Joe Coburn
      March 20, 2017 at 5:47 pm

      All fixed now, checkout the updated code!

  21. melvin B
    January 26, 2017 at 8:57 am

    The Arduino gives a message while compiling: 'changelights' was not declared. This refers to the line directly after the "void loop(){"
    Should it be declared in de void setup() or before that?

    • Nahuel
      February 16, 2017 at 3:10 am

      Just move the declaration of changeLights() before loop()

      void changeLights() {
      ...
      }

      void setup() {
      ...
      }

      void loop() {
      ...
      }

  22. Aakash Choudhry
    January 11, 2017 at 7:45 pm

    Did this code work for anyone??

    • Brian Graham
      January 29, 2017 at 12:59 pm

      // light one
      int red1 = 10;
      int yellow1 = 9;
      int green1 = 8;

      // light two
      int red2 = 13;
      int yellow2 = 12;
      int green2 = 11;

      void setup(){
      Serial.println("Welcome");
      // light one
      pinMode(red1, OUTPUT);
      pinMode(yellow1, OUTPUT);
      pinMode(green1, OUTPUT);

      // light two
      pinMode(red2, OUTPUT);
      pinMode(yellow2, OUTPUT);
      pinMode(green2, OUTPUT);
      }

      void loop(){
      changeLights();
      delay(15000);
      }

      void changeLights(){
      // turn both yellows on
      Serial.println("Hello world");
      digitalWrite(green1, LOW);
      digitalWrite(yellow1, HIGH);
      digitalWrite(yellow2, HIGH);
      delay(5000);

      // turn both yellows off, and opposite green and red
      digitalWrite(yellow1, LOW);
      digitalWrite(red1, HIGH);
      digitalWrite(yellow2, LOW);
      digitalWrite(red2, LOW);
      digitalWrite(green2, HIGH);
      delay(5000);

      // both yellows on again
      digitalWrite(yellow1, HIGH);
      digitalWrite(yellow2, HIGH);
      digitalWrite(green2, LOW);
      delay(3000);

      // turn both yellows off, and opposite green and red
      digitalWrite(green1, HIGH);
      digitalWrite(yellow1, LOW);
      digitalWrite(red1, LOW);
      digitalWrite(yellow2, LOW);
      digitalWrite(red2, HIGH);
      delay(5000);

      }

      • Steven Jurick
        February 10, 2017 at 1:45 pm

        Why do you turn both yellows on?

    • ledpup
      February 3, 2017 at 5:03 am

      The first changeLights function is missing an open curly brace {

      void changeLights()
      // green off, yellow on for 3 seconds
      digitalWrite(green, LOW);
      etc.

      Should be:

      void changeLights() *{*
      // green off, yellow on for 3 seconds
      digitalWrite(green, LOW);
      etc.

  23. saleem
    January 10, 2017 at 1:45 am

    Easy to understand arduino function

    • Steven Jurick
      February 10, 2017 at 1:44 pm

      Realistically, in a 4-way intersection, both Red Lights are lit for about 1/2 sec before the Red turns to Green.

      How would you implement the additional 500ms for the Red light that's about to turn green? Since using delay is linear (code executes down line by line), I can't get it to work without the yellow also pausing for 500ms along with the Red before both turning off.

      Ex:
      North-South light is RED
      East-West light is GREEN
      EW Green turns YELLOW
      EW Yellow turns RED
      NS RED should stay on for .5 sec, then turn Green

      Perhaps using millis() or even a state machine is required for this? If you can do it with delay please let me know.

      Below is my code for a 4-way intersection without the needed .5 red delay:

      // Environment
      int ledRedNS = 11;
      int ledYelNS = 10;
      int ledGrnNS = 9;
      int ledRedEW = 8;
      int ledYelEW = 7;
      int ledGrnEW = 6;
      int rgDelay = (6000); //Red and Green on duration
      int yDelay = (4000); //Yellow on duration

      void setup() {
      // Initialize digital pins as an output
      pinMode(ledRedNS, OUTPUT);
      pinMode(ledYelNS, OUTPUT);
      pinMode(ledGrnNS, OUTPUT);
      pinMode(ledRedEW, OUTPUT);
      pinMode(ledYelEW, OUTPUT);
      pinMode(ledGrnEW, OUTPUT);

      // Set initial light state (RED NS ON; GRN EW ON for rgDelay)
      digitalWrite(ledRedNS, HIGH);
      digitalWrite(ledGrnEW, HIGH);
      delay(rgDelay);
      }

      void loop() {
      //YEL EW ON; GRN EW OFF for yDelay
      digitalWrite(ledYelEW, HIGH);
      digitalWrite(ledGrnEW, LOW);
      delay(yDelay);

      //RED EW ON; RED NS OFF; GRN NS ON for rgDelay
      digitalWrite(ledRedEW, HIGH);
      digitalWrite(ledRedNS, LOW); //Needs to pause 500ms before turning LOW
      digitalWrite(ledGrnNS, HIGH);
      digitalWrite(ledYelEW, LOW);
      delay(rgDelay);

      //YEL NS ON; GRN NS OFF for yDelay
      digitalWrite(ledYelNS, HIGH);
      digitalWrite(ledGrnNS, LOW);
      delay(yDelay);

      //RED NS ON; RED EW OFF; GRN EW OFF; YEL NS OFF for rgDelay
      digitalWrite(ledRedNS, HIGH);
      digitalWrite(ledRedEW, LOW); //Needs to pause 500ms before turning LOW
      digitalWrite(ledGrnEW, HIGH);
      digitalWrite(ledYelNS, LOW);
      delay(rgDelay);
      }

      • Joe Coburn
        February 10, 2017 at 2:22 pm

        Yep, state machine is required - check out our guide below!

        //www.makeuseof.com/tag/arduino-delay-function-shouldnt-use/

        • Steven Jurick
          February 11, 2017 at 1:51 am

          OK, so I've rebuilt my sketch using millis(); instead of delay. I setup a large if statement in loop() and I can alternate RED/GRN LEDs at a given interval, but I'm really lost on how to introduce the YEL on each side, which will obviously cancel it's respective GRN, then when the YEL turns to RED, leaving the other RED on for 500ms, then turn it GRN and start the whole cycle over again.

          I guess there needs to be a way to check how long each individual LED has been on? Is that correct thinking?