The traffic light is a fun little project, that can be completed in under an hour. Learn how to build your own – using an Arduino – and how to modify the circuit for an advanced model.
Don’t worry if you’ve never used an Arduino before, we have a beginners guide Getting Started With Arduino: A Beginner's Guide Getting Started With Arduino: A Beginner's Guide Arduino is an open-source electronics prototyping platform based on flexible, easy-to use hardware and software. It's intended for artists, designers, hobbyists, and anyone interested in creating interactive objects or environments. Read More .
Note: This is the latest in a series of beginner level tutorials for Arduino, the open source electronics prototyping platform. Here’s a list of the previous articles in the series:
- What Is Arduino & What Can You Do With It What Is Arduino & What Can You Do With It? What Is Arduino & What Can You Do With It? The Arduino is a remarkable little electronics device, but if you've never used one before, just what exactly are they, and what can you do with one? Read More
- What Is An Arduino Starter Kit & What Does It Contain? What’s Included In An Arduino Starter Kit? [MakeUseOf Explains] What’s Included In An Arduino Starter Kit? [MakeUseOf Explains] I have previously introduced the Arduino open-source hardware here on MakeUseOf, but you’re going need more than just the actual Arduino to build something out of it and actually get started. Arduino "starter kits" are... Read More
- More Cool Components To Buy With Your Starter Kit 8 More Cool Components For Your Arduino Projects 8 More Cool Components For Your Arduino Projects So, you're thinking about getting an Arduino starter kit, but wondering if some basic LEDs and resistors is going to be enough to keep you busy for the weekend? Probably not. Here are another 8... Read More
- Getting Started With Your Arduino Starter Kit – Installing Drivers & Setting Up The Board & Port Getting Started With Your Arduino Starter Kit - Installing Drivers & Setting Up The Board & Port Getting Started With Your Arduino Starter Kit - Installing Drivers & Setting Up The Board & Port So, you’ve bought yourself an Arduino starter kit, and possibly some other random cool components - now what? How do you actually get started with programming this Arduino thing? How do you set it up... Read More
- A Closer Look At The Structure Of An Arduino App & The Example Blink Program
What You Need
Apart from the basic Arduino, you’ll need:
- Red, yellow and green LEDs.
- A breadboard.
- 6 x 220 ? resistors.
- Connecting wires.
- 1 x pushbutton switch.
- 1 x 10k ? resistor
Almost any Arduino will be suitable, providing it has enough pins. Make sure you read our 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 probably have these parts in your 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 already.
A Simple Example
Let’s start small. A basic, single traffic light is a good place to start. Here’s the circuit:
Connect the anode (long leg) of each LED to digital pins eight, nine, and ten (via a 220? resistor). Connect the cathodes (short leg) to Arduino ground.
I used Fritzing to draw these diagrams. Not only is it easy to use, it’s free!
The Code
Start by defining variables so that we 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’ll we 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);
}
That was easy. Now for the difficult part -– the actual logic of a traffic light. Create a separate function for changing the lights (you’ll see why later).
When you first begin programming, the code itself is very rudimentary – it’s figuring out the minute logic details that presents the biggest problem. The key to being a good programmer is to be able to look at any process, and break it down into its fundamental steps. Here’s the rest of the code:
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);
}
Done! Now, upload and run (make sure to select the correct board and port from the Tools > Port and Tools > Board menus). You should have a working traffic light that changes every 15 seconds, like this (sped up):
A 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:
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? resistor attached to it, and you may be wondering why. This is called a pull-down resistor. It’s a difficult concept to grasp at first, but bear with me.
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 being pushed would be defined as being in a low state, but in fact it’s said to be ‘floating’, because no current is being 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 state reading. A pull down resistor keeps a small amount of current flowing when the switch is closed, thereby ensuring an accurate low state reading. In other logic circuits, you may find a pull-up resistor instead – 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, we’re going to read the state of the pushbutton switch instead, and only change the lights when it’s activated.
The Code
Start by adding a new variable to the start of the program:
int button = 12; // switch is on pin 12
Now, in the setup function, add a new line to declare the switch as an input. I’ve also added a single line to start the traffic lights in the green stage. Without this initial setting, they would be turned off, until the first time a changeLights() was initiated using a function.
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 is checked twice (digitalRead(button)), separated by a small delay. This is called debouncing. Much like the pull down resistor was needed for the button, this simple check stops the code detecting minor interference as a button press. You don’t have to do this (and it would probably work just fine without it), but it’s good practice.
By waiting inside the if statement for 15 seconds, the traffic lights can’t change for at least that duration. Once 15 seconds is up, the loop restarts. Each restart of the loop, read the state of the button again, but if it isn’t pressed, the if statement never activates, the lights never change, and it simply restarts again.
Here’s how this looks (sped up):
A Junction
Let’s try a more advanced model. Instead of a pedestrian crossing, modify your circuit to have two traffic lights:
Connect the second traffic light to digital pins 11, 12, and 13.
The Code
First, assign your new traffic light pins to variables, and configure them as outputs, just 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 being 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 will be 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):
That’s it for this time, so I hope you learnt lots and had fun writing from scratch. You got your hands dirty with a few LEDs and resistors, as well as adding a switch with a pull down resistor – hopefully you understood why we need one. Play around with the code, adjust it, and most importantly have fun. If you make any additions or changes, why not let us know about it in the comments?
Image Credit: androsvector via Shutterstock.com
this does not help me3
Could you give me a download link to the Fritzing file, please? I want to take a look at it.
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.
hi, i did everything correctly and the green light for the lights 2 wont turn on, do you know how to fix this? thanks
Maybe the light is busted?
Thank you very much for this tutorial!! A great way to start tinkering with the components and getting things done!
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?
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.
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.
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....
I did everything like the instructions said and inserted the code but nothing happens could it be that something is broken on my bord
did you fix it? I have this exact problem right now :/
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..
what if we add a pedestrian button to push to cross
how will the code be
can we program our arduino with our smartphones?How?
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?
same problem here.
All fixed, sorry! :)
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!
This happened to me. If you just copy and paste the code it will work though not sure why.
what if you have a four-way intersection with four crossing? how do you modify that
That gets more complex...You will need to start implementing non blocking code, so take a look at this:
http://www.makeuseof.com/tag/arduino-delay-function-shouldnt-use/
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.
there is problem while runnig the code
traffic for signal 1 is working but for signal 2 its not working plz guide
I've updated a typo, thanks for stopping by.
can you please advise where the corrected code appears or what it is as I cant find it
What is the correct code for the pedestrian crossing traffic light.
All fixed now, checkout the updated code!
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?
Just move the declaration of changeLights() before loop()
void changeLights() {
...
}
void setup() {
...
}
void loop() {
...
}
Did this code work for anyone??
// 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);
}
Why do you turn both yellows on?
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.
Easy to understand arduino function
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);
}
Yep, state machine is required - check out our guide below!
http://www.makeuseof.com/tag/arduino-delay-function-shouldnt-use/
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?