Arduino Tutorial: Interactive traffic lights
You will start your first interactive Arduino project with the arduino starter kit in this lesson by making button-controlled traffic lights. When the button is pressed, the lights will change for pedestrians to pass by.
Required Components:
Resistor 220R *6
Push Button *1
5MM LED *2 red
5MM LED *2 green
5MM LED *2 yellow
*Why are there 5 LEDs with 6 resistors?
The extra resistor is a pull-down resistor for the button.
*After this, we won t list the Arduino, Breadboard, Prototype Shield or Jumpers in the component list any more as they will be necessary for every arduino project.
Circuit
Follow the wiring diagram below to build your circuit.
Please note that the green lines represent socket connections and do not represent the color of wire you must use.
Only use the provided USB cable to power the Arduino after you build the circuit. This cable provides a steady 5V to the Arduino. If you use another power source, there is a chance the voltage might be too high, which might overload the components.
Code
The sketch is originally from “Beginning Arduino”
Sample code 3-1:
/*
Traffic Light
This code copied from the book Beginning-Arduino.
*/
int carRed = 12; //assign the car lights
int carYellow = 11;
int carGreen = 10;
int button = 9; //button pin
int pedRed = 8; //assign the pedestrian lights
int pedGreen = 7;
int crossTime =5000; //time for pedestrian to cross
unsigned long changeTime;//time since button pressed
void setup() {
pinMode(carRed, OUTPUT);
pinMode(carYellow, OUTPUT);
pinMode(carGreen, OUTPUT);
pinMode(pedRed, OUTPUT);
pinMode(pedGreen, OUTPUT);
pinMode(button, INPUT);
digitalWrite(carGreen, HIGH); //turn on the green lights
digitalWrite(pedRed, HIGH);
}
void loop() {
int state = digitalRead(button);
//check if button is pressed and it is over 5 seconds since last button press
if(state == HIGH && (millis() - changeTime)> 5000){
//call the function to change the lights
changeLights();
}
}
void changeLights() {
digitalWrite(carGreen, LOW); //green off
digitalWrite(carYellow, HIGH); //yellow on
delay(2000); //wait 2 seconds
digitalWrite(carYellow, LOW); //yellow off
digitalWrite(carRed, HIGH); //red on
delay(1000); //wait 1 second till its safe
digitalWrite(pedRed, LOW); //ped red off
digitalWrite(pedGreen, HIGH); //ped green on
delay(crossTime); //wait for preset time period
//flash the ped green
for (int x=0; x<10; x++) {
digitalWrite(pedGreen, HIGH);
delay(250);
digitalWrite(pedGreen, LOW);
delay(250);
}
digitalWrite(pedRed, HIGH);//turn ped red on
delay(500);
digitalWrite(carRed, LOW); //red off
digitalWrite(carYellow, HIGH); //yellow on
delay(1000);
digitalWrite(carYellow, LOW); //yellow off
digitalWrite(carGreen, HIGH);
changeTime = millis(); //record the time since last change of lights
//then return to the main program loop
}
After uploading the sketch, take a look at how LED changes. First, the green traffic light is on and the red pedestrian light is on to allow cars to pass.
Once you press the button, the pedestrian light changes from red to green and the traffic light changes from just green to green and red. There is then a delay allowing time for pedestrians to cross the street.
When the delay comes to the end, the green pedestrian light blinks to notify pedestrians.
When this finishes, the lights change back to the initial state with the green traffic light on and red pedestrian light on.
The above codes do look complex, but actually, it is not that difficult to understand the ideas in practice.
If you find it is difficult for you to follow, try to draw a diagram like the one in the homework of arduino Project 2. This will help you to comprehend the codes a little better. Good luck!
Code
Based on the previous 2 projects, most of the codes should make sense for you. The codes start from a set of variable declarations, but we have used a new term. It is explained below:
unsigned long changeTime;
Before we use int to store integers from -32768 to 32767. The long command we use in this project can store integers from -2147483648 to 2147483647. Unsigned long cannot store negative numbers. So it stores integers from 0 to 4294967295.
If we use int, we might go over the limit of 32 seconds (32768ml sec) and risk having errors in running the sketch.As a result, we need another command to store integers and exclude negative numbers, such as unsigned long whose limit is 49 days.
Then we enter the setup() function to configure the LED and button.
pinMode(button, INPUT);
We have been quite familiar with pinMode() function introduced in Project 1. Its difference with LED project lies in that the button should be set as INPUT.
In setup() function, please initialize the pedestrian and traffic light:
digitalWrite(carGreen, HIGH); //initializing green traffic light on
digitalWrite(pedRed, LOW); //pedestrian red light on
The first line of the main sketch is to test the state of button in pin9.
int state = digitalRead(button);
Can the box of variable be infinite big?
Why can some variables store large amounts of data while some can't? It depends on storage space of the variable, a bit like a box. For example, the storage capacity of int is much smaller than ”unsigned long” .
Just like a computer has a limited storage space, a micro-controller, like your Arduino, is the same. The maximum storage space of Arduino UNO’s main chip (Atmega328 is 32k, so if we can save some storage space, we should definitely do that.
Some common variables you will come across:
There are various type of variables. Int and long are for integers, char is for characters, float and double are for variables with decimal point.
In the setup() function, there is a new command digitalRead() !
This command is used to read the digital pin’s state, whether high (1) or low (0).The command has one parameter: pin number .
This command passes the signal read to the variable state for further judgment.
When state value is HIGH or 1, it means that the push button has been pressed.
When state value is LOW or 0, it means that the push button hasn't been pressed.
We can check the value of state to test if the button is pressed.
if(state == HIGH && (millis() changeTime)> 5000) { //carry out light-changing command changeLights(); }
Here we use the if() command to test conditions.
if(condition){
Statement;
}
If the condition specified in the parenthesis is satisfied, it carries out the statement. If not, the program skips over the code.
In other words, if the if expression returns TRUE, the statement is run. If it returns FALSE, the statement is skipped.
In the above codes, the first condition is whether variable state is HIGH (or on). When the push button is pressed, the state turns HIGH. The second condition is that value returns for millis() minus that for change Time is more than 5000.
We u s e "&&" to connect the two conditions. This is a logical operator, showing that we want the above two conditions met at the same time.
"millis()" is a command that returns the number of milliseconds since the Arduino board began running the current program. This number will overflow (go back to zero), after approximately 50 days.
Here we use it to calculate if there is a break of more than 5 seconds when pressing button more than once. If shorter than 5 seconds, it skips over the code to avoid errors caused by accidentally pressing the button.
This is a command inside the if() command.
changeLights();
This is a function created outside of loop() function. When we want to use it, we just need to cite the name of the function. It has not returned a value and does not need to pass parameters so it is a void function. When it is used, the program will run the function and go back to the main code afterwards. Beware not to miss the parenthesis when using this function as otherwise it will not be recognised.
Logical Operators
Some other common boolean operators:
&& ——logic and (True only if both conditions are true)
|| —— logic or (True if either condition is true)
!—— logic not (True if the condition is false)
Components
Push Button
The push button we used has 4 pins. When you press a button or flip a lever, they connect two pins together so that electricity can flow through them. Actually, there are only really two electrical connections; inside the switch package pins 1 and 4 are connected together, as are 2 and 3. The little tactile switches that are used in this lesson have four connections.You might have one with 2 pins, but it works the same way.
A push button can switch on and switch off the electricity flowing through the circuit. In the project, when it is pressed, D9 pin detects HIGH (on), otherwise it remains LOW (off).
What is pull-down resistor?
Pull-down resistors are used in electronic logic circuits to ensure that inputs to the arduino settle at expected logic levels if external devices are disconnected. A pull-down resistor weakly "pulls" the voltage of the wire it is connected to to ground when the other components on the line are inactive.
When the switch on the line is open, it has high impedance and acts like it is disconnected. Since the other components act as though they are disconnected, the circuit acts as though it is disconnected, and the pull-up resistor brings the wire up to the HIGH logic level. When another component on the line goes active, it will override the HIGH logic level set by the pull-up resistor. The pull-up resistor assures that the wire is at a defined logic level even if no active devices are connected to it.
Homework After Class
1. Choose 6 LEDs of any color and achieve the LED lights display.
2. When you are done, try to light up the column of LEDs in the middle and have them pass the light towards either edge.
3 or light the column from left to right.