Go Down

### Topic: Traffic lights - from very simple to "how complicated do you want?" (Read 5854 times)previous topic - next topic

#### Bookworm

##### Feb 15, 2012, 10:21 pm
Hello World!

Well I have recently started learning with the Arduino. I think its brilliant!
I have done the blinking LEDs and other simple examples, which were really useful.
I believe the best way to learn it to experiment.
So here is me learning about going from simple to complex using the example of the humble traffic light.

Version 1 a single set of traffic lights that go.
Red
Red & Amber
Green
Amber
Red

After that I will complicate them by imagining ever more complex road junctions, crossings, car sensors, different sequences for rush hour etc.

Come with me, it should be fun. If I get stuck, or write rubbish sketches, feel free to jump in!

Traffic Lights 1

red LED & Resistor to digital pin 13
amber LED & Resistor to digital pin 12
green LED & Resistor to digital pin 11
Code: [Select]
`/**Do what you like with this code as long as you set *it free and allow others to do the same. i.e. ------------------------------------------------- *This work is licensed under the Creative Commons *Attribution-ShareAlike 3.0 Unported License. *To view a copy of this license, visit *http://creativecommons.org/licenses/by-sa/3.0/ *or send a letter to Creative Commons, 444 Castro Street, *Suite 900, Mountain View, California, 94041, USA. ---------------------------------------- *A set of Traffic Lights. *I am in the UK so it will be a UK set of traffic lights. *Should be easy to customise to any configuration in the world! *Come with me, it should be fun. *I intend to  comment every line to start with *so it should be easy to follow. */int red = 13;   //first of all associate a pin with the red light, in this case 13int amber = 12; // associate pin 12 with the amber lightint green = 11; //and finally the green light with pin 11int maindelay = 1500; //The timings of the lights are based around this number./* *The maindelay is an arbitary delay time, *smaller is faster, larger is slower. *I use it so the proportions stay the same. *i.e. the wait is 4 times longer than the change */void setup() {  pinMode(red,OUTPUT);   //set the red pin as an output  pinMode(amber,OUTPUT); //set the amber pin as an output  pinMode(green,OUTPUT); //set the green pin as an output  digitalWrite(red,HIGH); //Switch the red light on so we have something to start with}void loop(){  digitalWrite(amber,HIGH); //Amber on, get ready to go  delay(maindelay); //Wait   digitalWrite(green,HIGH); //Green on, go  digitalWrite(red,LOW);    //Red off as green is on  digitalWrite(amber,LOW);  //amber off, it's finished with  delay(maindelay*4);       //give traffic time to pass  digitalWrite(amber,HIGH); //amber on, stop if safe to do so  digitalWrite(green,LOW);   //green off, it's finished with  delay(maindelay);          //wait  digitalWrite(amber,LOW);   //amber off  digitalWrite(red,HIGH);    //red on, stop  delay(maindelay*4);        //Time for whatever the traffic has been stopped for to happen.    /*And we are back where we started.    *That's the end of this sequence.    *The light is back at red and the    *sequence can begin again.   */}`

Well. I hope it works for you. I'll be back in a few days with another set of lights.  I am thinking of a crossroads where North-South goes while East-West waits, and vice versa.

See you soon

Bookworm.
Bookworm

#### Bookworm

#1
##### Feb 16, 2012, 01:11 pm
OK.

Part two. I have added a second set of traffic lights. As you might find at a crossroads or where two way traffic has to pass through a single lane (Such as an old hump back bridge).

I have added LEDs and resistors to pins 11(Green), 10(amber) and 9(red).

I have named the signals "north" and "east". I forsee there may be south and west signals at some point.
I have also created functions to turn each signal from red to green and vice versa. that's so the loop can call them as it needs them and I can call upon them in any sequence I need.  They are no longer in a fixed order.

For now the controller starts up with both signals at red.
It then changes the north signal to green, waits a while and turns it  back to red.
Then it does the same with the east signal.
The loop continues.

Code: [Select]
`/* *A set of Traffic Lights. *I am in the UK so it will be a UK set of traffic lights. *Should be easy to customise to any configuration in the world! *Come with me, it should be fun. *I intend to  comment every line to start with *so it should be easy to follow. */int northRed = 13;   //first of all associate a pin number with the  Northern red light, in this case 13int northAmber = 12; // associate pin 12 with the amber lightint northGreen = 11; //and finally the green light with pin 11int eastRed = 8;  //a pin for the east red light, 8int eastAmber = 9;  //a pin for the east amber light , 9int eastGreen = 10;  //a pin for the east green light, 10int maindelay = 1500; //The timings of the lights are based around this number./* *The maindelay is an arbitary delay time, *smaller is faster, larger is slower. *I use it so the proportions stay the same. *i.e. the wait is 4 times longer than the change */void setup() {  pinMode(northRed,OUTPUT);   //set the north red pin as an output  pinMode(northAmber,OUTPUT); //set the north amber pin as an output  pinMode(northGreen,OUTPUT); //set the north green pin as an output  pinMode(eastRed,OUTPUT);   //set the east red pin as an output  pinMode(eastAmber,OUTPUT); //set the east amber pin as an output  pinMode(eastGreen,OUTPUT); //set the east green pin as an output  digitalWrite(northRed,HIGH); //Switch the red light on so we have something to start with  digitalWrite(eastRed,HIGH); //switch the east red light on as well}void loop(){  northtogreen();  //change the north signal to green  delay(maindelay*4);  //wait for the traffic to pass  northtored();  //change the north signal back to red  delay(maindelay/2);  //small delay to allow traffic to clear junction  easttogreen();  //change the east signal to green  delay(maindelay*4);//wait for the traffic to pass  easttored();  //change the east signal back to red  delay(maindelay/2);  //small delay to allow the traffic to clear junction  /*And we are back where we started.    *That's the end of this sequence.    *The light is back at red and the    *sequence can begin again.   */}void northtored(){  //sequence of north lights going to red    digitalWrite(northAmber,HIGH);  //Amber on, prepare to stop  digitalWrite(northGreen,LOW);  //Green off, finished with  delay(maindelay);              //Time for traffic to stop  digitalWrite(northRed,HIGH);  //Red on, stop  digitalWrite(northAmber,LOW);  //Amber off, finished with}void northtogreen(){  //sequence of north lights going to green    digitalWrite(northAmber,HIGH);  //Amber on, prepare to go  delay(maindelay);  //Time for traffic to see amber  digitalWrite(northGreen,HIGH);  //green on, go  digitalWrite(northRed,LOW);  //red off, finished with  digitalWrite(northAmber,LOW);  //amber off, finished with}void easttored(){//sequence of east lights going to red    digitalWrite(eastAmber,HIGH);  //Amber on, prepare to stop  digitalWrite(eastGreen,LOW);  //Green off, finished with  delay(maindelay);              //Time for traffic to stop  digitalWrite(eastRed,HIGH);  //Red on, stop  digitalWrite(eastAmber,LOW);  //Amber off, finished with}void easttogreen(){ //sequence of east lights going to green    digitalWrite(eastAmber,HIGH);  //Amber on, prepare to go  delay(maindelay);  //Time for traffic to see amber  digitalWrite(eastGreen,HIGH);  //green on, go  digitalWrite(eastRed,LOW);  //red off, finished with  digitalWrite(eastAmber,LOW);  //amber off, finished with}/**Version History * * 1.2 Two traffic lights on opposite phases *  -moved licence to bottom of sketch *  -added version history *  -moved code to change lights out of the loop and into their own functions * * 1.1 Single Traffic Light * *Do what you like with this code as long as you set *it free and allow others to do the same. i.e. ------------------------------------------------- *This work is licensed under the Creative Commons *Attribution-ShareAlike 3.0 Unported License. *To view a copy of this license, visit *http://creativecommons.org/licenses/by-sa/3.0/ *or send a letter to Creative Commons, 444 Castro Street, *Suite 900, Mountain View, California, 94041, USA. ---------------------------------------- */`

Now I can see that I have two pairs of functions that are very similar.  Next stage will be to get rid of the duplication.

i.e.
Instead of northtored()  and easttored() it needs a single function changetored() and send it "North" and it will change the north light to red, send it "east" and it will change the east light to red.

Not sure how to do that at the moment.  I have a feeling the individual lights will have to be stored in arrays, each one being a whole set of lights.

Bear with me, or have a go yourself.

See you soon.
Bookworm

#### Bookworm

#2
##### Feb 16, 2012, 06:31 pmLast Edit: Feb 16, 2012, 09:11 pm by Bookworm Reason: 1
Well I'm glad I am doing this while the system is quite simple. Hopefully getting it sorted now will save having to rewrite masses of code.

I have written a small sketch using a 2 Dimentional array (Colours x Signal) to assign each output pin.

Code: [Select]
`/** small sketch to try out 2 dimentional array* in order to address individual signals and their* respective lights.** In this case each signal (Set of red,amber and green lights) is* a row in the array "signal" and each column is either red, amber or green.* I have 2 sets of signals which will be "north"(output pins 13,12 & 11)* and "east" (Output pins 8,9 & 10).*/const int red = 0; //first column in array signal is red const int amber = 1;//second column in array signal is amberconst int green = 2;//third column in array signal is greenconst int totalcolours = 3; //there are red, amber and greenconst int north = 0; //first row in array signal is northconst int east = 1; // second row in array signal is eastconst int totalsignals = 2; //at the moment there are two sets of signalsconst int signal[totalsignals][totalcolours] ={    { 13,12,11  },                                                                {  8, 9,10  }  }; // traffic lights array. //columns are red, amber, green//rows are individual signals.void setup() {  for (int i = 0; i < totalsignals; i++) { //cycle through the signals    for (int j = 0; j < totalcolours; j++) { //cycle through the colours      pinMode(signal[i][j],OUTPUT); //set the pins as outputs    }  }}void loop() {for (int i = 0; i < totalsignals; i++) { //cycle through the signals    for (int j = 0; j < totalcolours; j++) { //cycle through the colours      digitalWrite(signal[i][j],HIGH); //Switch a light on      delay(250); //wait      digitalWrite(signal[i][j],LOW);//switch that light off      delay(100);//wait    }  }}/* *Do what you like with this code as long as you set *it free and allow others to do the same. i.e. ------------------------------------------------- *This work is licensed under the Creative Commons *Attribution-ShareAlike 3.0 Unported License. *To view a copy of this license, visit *http://creativecommons.org/licenses/by-sa/3.0/ *or send a letter to Creative Commons, 444 Castro Street, *Suite 900, Mountain View, California, 94041, USA. ---------------------------------------- */`
The sketch slowly blinks each LED in turn.

Now I can

digitalWrite(signal[signal ID] [colour],HIGH or LOW);

to switch an individual LED on or off.

Next thing to do is to test that out thoroughly and transfer it into the main traffic lights sketch.

As always, bear with me or have a go yourself. If you do, let us know how you are getting on.
Bookworm

#### Bookworm

#3
##### Feb 16, 2012, 09:28 pmLast Edit: Feb 16, 2012, 09:50 pm by Bookworm Reason: 1
It works!!

It turned out easier to copy some of the traffic light sketch into the array sketch. So that's what I did.

It now appears to do exactly the same thing as before, turning north to green, then to red, then east to green and then red.

Code: [Select]
`/* *A set of Traffic Lights. *I am in the UK so it will be a UK set of traffic lights. *Should be easy to customise to any configuration in the world! *Come with me, it should be fun. *I intend to  comment every line to start with *so it should be easy to follow. */const int maindelay = 1000;  //the tempo of the lights are based around //this delay. smaller = faster, larger=slower. The rhythm should  stay the same.const int red = 0; //first column in array signal is red const int amber = 1;//second column in array signal is amberconst int green = 2;//third column in array signal is greenconst int totalcolours = 3; //there are red, amber and greenconst int north = 0; //first row in array signal is northconst int east = 1; // second row in array signal is eastconst int totalsignals = 2; //at the moment there are two sets of signalsconst int signal[totalsignals][totalcolours] ={      {     13,12,11    }  ,  {      8, 9,10    }  }; // traffic lights array. //columns are red, amber, green//rows are individual signals.void setup() {  for (int i = 0; i < totalsignals; i++) { //cycle through the signals    for (int j = 0; j < totalcolours; j++) { //cycle through the colours      pinMode(signal[i][j],OUTPUT); //set the pins as outputs    }  }  for (int i = 0; i < totalsignals; i++) { //cycle through the signals    digitalWrite(signal[i][red],HIGH); //light all the red lights  }}void loop() {  for (int signalID = 0; signalID < totalsignals; signalID++) { //cycle through the signals    settogreen(signalID); //turn the signal called signalID to green    delay(maindelay*2); //wait for traffic to flow    settored(signalID);  //turn the lights back to red    delay(maindelay);    //wait for traffic to clear  }}void settogreen(int i){ //function to set a signal to green   digitalWrite(signal[i][amber],HIGH); //light the amber light  delay(maindelay);//pause  digitalWrite(signal[i][green],HIGH);//light the green light  digitalWrite(signal[i][amber],LOW);//extinguish the amber light  digitalWrite(signal[i][red],LOW);//extingish the red light}void settored(int i){//function to set a signal to red  digitalWrite(signal[i][amber],HIGH);//light the amber light  digitalWrite(signal[i][green],LOW);//extinguish the green light  delay(maindelay);//pause  digitalWrite(signal[i][red],HIGH);//light the red light  digitalWrite(signal[i][amber],LOW);//extinguish the amber light}/**Version History *2.0 Two traffic lights on opposite phases *  - Each light can now be called by it's own address "signal[signalID][colour]" *  - rewrite loop to reflect new addresses *  - deleted duplicated functions * * 1.2 Two traffic lights on opposite phases *  -moved licence to bottom of sketch *  -added version history *  -moved code to change lights out of the loop and into their own functions * * 1.1 Single Traffic Light * *Do what you like with this code as long as you set *it free and allow others to do the same. i.e. ------------------------------------------------- *This work is licensed under the Creative Commons *Attribution-ShareAlike 3.0 Unported License. *To view a copy of this license, visit *http://creativecommons.org/licenses/by-sa/3.0/ *or send a letter to Creative Commons, 444 Castro Street, *Suite 900, Mountain View, California, 94041, USA. ---------------------------------------- */`

It's also smaller (1932 bytes) than the original version of the sketch (2102 bytes).

Adding a new set of lights is as easy as

• adding the pin numbers as an extra row

• declaring a new signal, e.g. south and giving it the value 2

Then the sketch cycles all three sets of signals. You can add as many sets of lights as you like (until you run out of output pins).

I added a new signal "south" to pins 5 (Red), 6(amber) and 7(green).

here are the extra variable declarations and the new line in the array

Code: [Select]
`const int south = 2; //south is the third row in the array.const int totalsignals = 3; //now there are 3 sets of signalsconst int signal[totalsignals][totalcolours] ={      { 13,12,11    },//the output pins for north  {  8, 9,10    },//the output pins for east  {  5, 6, 7    } //the new output pins for south}; // traffic lights array. //columns are red, amber, green//rows are individual signals.`

I don't know why but after adding the third signal the sketch is even smaller(1924 bytes).

Not sure what to try next. maybe a button for pedestrians to request to cross plus the associated red and green man signal.

Bear with, or have a go.  Let me know how you get on.

Bookworm.
Bookworm

#### Bookworm

#4
##### Feb 17, 2012, 11:15 pmLast Edit: Feb 17, 2012, 11:21 pm by Bookworm Reason: 1
Well. I haven't added a button yet.

I had a look at the loop and all I had put in there was a for() loop. It doesn't need that because, well, it is a loop anyway and it makes breaking into the sequence problematical. Any change would have to affect all the signals or wait until a complete cycle had finished.

So I have removed the for() loop.

I think it may be useful to have the arduino report back to the PC what is happening for debugging. So I have opened the serial port and each function sends a line of info when it is called.

Code: [Select]
`/* *A set of Traffic Lights. *I am in the UK so it will be a UK set of traffic lights. *Should be easy to customise to any configuration in the world! *Come with me, it should be fun. *I intend to  comment every line to start with *so it should be easy to follow. */const int maindelay = 1000;  //the tempo of the lights are based around //this delay. smaller = faster, larger=slower. The rhythm should  stay the same.const byte red = 0; //first column in array signal is red const byte amber = 1;//second column in array signal is amberconst byte green = 2;//third column in array signal is greenconst byte totalcolours = 3; //there are red, amber and greenconst byte north = 0; //first row in array signal is northconst byte east = 1; // second row in array signal is eastconst byte totalsignals = 2; //at the moment there are two sets of signalsconst int signal[totalsignals][totalcolours] ={      {     13,12,11      }  ,  {      8, 9,10      }}; // traffic lights array. //columns are red, amber, green//rows are individual signals.byte signalID = 0; // the number of the "active" signalvoid setup() {  Serial.begin(9600); //opens the serial port and sets the baud at 9600  for (byte i = 0; i < totalsignals; i++) { //cycle through the signals    for (byte j = 0; j < totalcolours; j++) { //cycle through the colours      pinMode(signal[i][j],OUTPUT); //set the pins as outputs      Serial.print("setting pin ");      Serial.print( signal[i][j]);      Serial.println(" as output");//tell pc what is happening    }  }  for (byte i = 0; i < totalsignals; i++) { //cycle through the signals    digitalWrite(signal[i][red],HIGH); //light all the red lights    Serial.print("setting signal ");    Serial.print( i);    Serial.println( " to red");// tell pc what is happening  }}void loop() {  if(signalID < totalsignals) {//make sure a valid signal is the active one.    settogreen(signalID); //turn the signal called signalID to green    delay(maindelay*2); //wait for traffic to flow    settored(signalID);  //turn the lights back to red    delay(maindelay);    //wait for traffic to clear    signalID++; //cycle through the signals  }  else  {    signalID=0;//after cycling through all the signals set back to the first  }}void settogreen(byte i){ //function to set a signal to green   Serial.print("Changing signal ");  Serial.print(i);  Serial.println(" to green");//tell pc what is happening  digitalWrite(signal[i][amber],HIGH); //light the amber light  delay(maindelay);//pause  digitalWrite(signal[i][green],HIGH);//light the green light  digitalWrite(signal[i][amber],LOW);//extinguish the amber light  digitalWrite(signal[i][red],LOW);//extingish the red light}void settored(byte i){//function to set a signal to red  Serial.print("Changing signal ");  Serial.print(i);  Serial.println(" to red");//tell pc what is happening  digitalWrite(signal[i][amber],HIGH);//light the amber light  digitalWrite(signal[i][green],LOW);//extinguish the green light  delay(maindelay);//pause  digitalWrite(signal[i][red],HIGH);//light the red light  digitalWrite(signal[i][amber],LOW);//extinguish the amber light}/**Version History * 2.1.1 *  - took redundant for() loop out of void loop() *  - Opened the serial port and added debugging information feed from each function. * 2.1 *  - changed variable type from INT to BYTE where the value will always be in the range 0 - 255 made sketch slightly smaller *2.0 Two traffic lights on opposite phases *  - Each light can now be called by it's own address "signal[signalID][colour]" *  - rewrite loop to reflect new addresses *  - deleted duplicated functions * * 1.2 Two traffic lights on opposite phases *  -moved licence to bottom of sketch *  -added version history *  -moved code to change lights out of the loop and into their own functions * * 1.1 Single Traffic Light * *Do what you like with this code as long as you set *it free and allow others to do the same. i.e. ------------------------------------------------- *This work is licensed under the Creative Commons *Attribution-ShareAlike 3.0 Unported License. *To view a copy of this license, visit *http://creativecommons.org/licenses/by-sa/3.0/ *or send a letter to Creative Commons, 444 Castro Street, *Suite 900, Mountain View, California, 94041, USA. ---------------------------------------- */`

I do intend to add the pedestrian crossing request button next, unless you want to!

Let me know if you are finding this any use at all.  I'll keep on writing and posting so I hope someone is.

Bookworm.
Bookworm

#### Techone

#5
##### Feb 20, 2012, 07:56 am
Great code. I will study your code and adapt the code for a traffic light system in the city I live : Toronto, ON, Canada.

I wonder in the UK it have an advance green ?  for turning left <-- America  ... ops... I mean : turning right <-- UK.

#### tytower

#6
##### Feb 20, 2012, 11:13 am
Now all you need do is add some sensors under each light so that when there is no bloody traffic comming the lights change back . none of this wait for hours shite
Governments should do what they were designed to do only.
Manage the larger issues best done by Government.
My Family and my Property are no

#### sth77

#7
##### Feb 20, 2012, 12:01 pm
My wish for version 3.0:
Mein Arduino-Blog: http://www.sth77.de/ - letzter Eintrag: Diamex-ISP in der aktuellen Arduino-IDE 1.6.4

#### Bookworm

#8
##### Feb 20, 2012, 09:33 pm
I dont know if this works but I have made a stripboard with three sets of lights on and put a video of it on youtube. (Looks like it does in preview, fingers crossed).

Traffic sensing will be added to the sketch.  There is no need to show a direction a green light if there is no traffic waiting after all.
Will have to scan all the signal's sensors each cycle and turn one with waiting traffic to green but without favouring the first signal every time, which I think could happen.

I haven't used millis() yet. Looks to be good as the delay between each light lighting, going out etc. makes the Arduino "Blind" to other events.

Advanced green will have to go in there too. If it's what I think it is we call it a filter arrow, so you will probably see reference to that.

Still haven't done the pedestrian crossing request and lights yet. That will probably be next. I used the time to do the stripboard signals.

Bear with me, or jump in and have a go.

Bookworm.
Bookworm

#### Bookworm

#9
##### Feb 20, 2012, 11:01 pm
Well I added a button to pin 2 (Interrupt 0), a red led to pins 14 & 16 and a green to 15.  That's my pedestrian controller. a button to request a crossing, a WAIT light to acknowledge the button press.
Then, when all the signals are at red the pedestrian gets a green light, crosses, the green flashes 5 times and then the ordinary cycle begins again.

I have added an interrupt for the button press. Pin2 is the input and is set high so the pull up is activated.

When the interrupt happens a function is called that sets a volatile variable (crossRequest) to 1, lights the WAIT light and sends a line to the serial monitor.

Then, when all the signals are at red the variable is tested and, if 1, calls a function to let the pedestrian cross and set the variable back to 0.

Code: [Select]
`/* *A set of Traffic Lights. *I am in the UK so it will be a UK set of traffic lights. *Should be easy to customise to any configuration in the world! *Come with me, it should be fun. *I intend to  comment every line to start with *so it should be easy to follow. *///Global Variables and constantsconst int maindelay = 1000;  //the tempo of the lights are based around this delay. smaller = faster, larger=slower. //The rhythm should  stay the same.//Traffic signal variables and constantsconst byte red = 0; //first column in array signal is red const byte amber = 1;//second column in array signal is amberconst byte green = 2;//third column in array signal is greenconst byte totalcolours = 3; //there are red, amber and greenconst byte north = 0; //first row in array signal is northconst byte east = 1; // second row in array signal is eastconst byte totalsignals = 2; //at the moment there are two sets of signalsconst int signal[totalsignals][totalcolours] ={      { 5, 6, 7},  { 8, 9,10}  }; // traffic lights array. //columns are red, amber, green//rows are individual signals.byte signalID = 0; // the number of the "active" signal//pedestrian variables and constantsvolatile byte crossRequest = 0;// The state of the crossing request button. to begin with it's low as it's not been requested.const byte pedButton = 2;//the pedestrian cross request is on pin 2 (interrupt 0)const byte pedWait = 16;//the pedestrian WAIT signal is on pin 16const byte pedStop = 14;// the pedestrian STOP signal is on pin 14 (DONT WALK)const byte pedGo = 15;// The pedestrian GO signal is on pin 15 (WALK)void setup() {  //set up serial output  Serial.begin(9600); //opens the serial port and sets the baud at 9600    // set up the signals  for (byte i = 0; i < totalsignals; i++) { //cycle through the signals    for (byte j = 0; j < totalcolours; j++) { //cycle through the colours      pinMode(signal[i][j],OUTPUT); //set the pins as outputs      Serial.print("setting pin ");      Serial.print( signal[i][j]);      Serial.println(" as output");//tell pc what is happening    }  }    //set the signals to an initial state  for (byte i = 0; i < totalsignals; i++) { //cycle through the signals    digitalWrite(signal[i][red],HIGH); //light all the red lights    Serial.print("setting signal ");    Serial.print( i);    Serial.println( " to red");// tell pc what is happening  }    //set up the pedestrian button and signal  Serial.println("setting up the pedestrian crossing");  pinMode(pedButton,INPUT); //set the pedestrian button as an input  digitalWrite(pedButton, HIGH); //turn on the pull up resistor on the button to stop it floating  pinMode(pedWait,OUTPUT);// Set the pedestrian WAIT signal as an output  pinMode(pedStop,OUTPUT);//Set the pedestrian STOP signal as an output  pinMode(pedGo,OUTPUT);//Set the pedestrian GO signal as an output  digitalWrite(pedStop, HIGH);// set the pedestrian STOP light to an initial state      attachInterrupt(0, pedestrianButton, CHANGE);// when a pedestrian presses the button,//interrrupt what is happening and run the pedestrianButton function  }void loop() {  if(signalID < totalsignals) {//make sure a valid signal is the active one.    settogreen(signalID); //turn the signal called signalID to green    delay(maindelay*2); //wait for traffic to flow    settored(signalID);  //turn the lights back to red    delay(maindelay);    //wait for traffic to clear    if(crossRequest ==1){//see if the pedestrian button has been pressed  pedcross();//if it has, go to the pedestrian crossing function  }    signalID++; //cycle through the signals  }  else  {    signalID=0;//after cycling through all the signals set back to the first  }}void settogreen(byte i){ //function to set a signal to green   Serial.print("Changing signal ");  Serial.print(i);  Serial.println(" to green");//tell pc what is happening  digitalWrite(signal[i][amber],HIGH); //light the amber light  delay(maindelay);//pause  digitalWrite(signal[i][green],HIGH);//light the green light  digitalWrite(signal[i][amber],LOW);//extinguish the amber light  digitalWrite(signal[i][red],LOW);//extingish the red light}void settored(byte i){//function to set a signal to red  Serial.print("Changing signal ");  Serial.print(i);  Serial.println(" to red");//tell pc what is happening  digitalWrite(signal[i][amber],HIGH);//light the amber light  digitalWrite(signal[i][green],LOW);//extinguish the green light  delay(maindelay);//pause  digitalWrite(signal[i][red],HIGH);//light the red light  digitalWrite(signal[i][amber],LOW);//extinguish the amber light}void pedestrianButton(){//function for when pedestrian button is pressed  crossRequest = 1;// now there is a request to cross   Serial.println( "Pedestrian request to cross received");// tell pc what is happening  digitalWrite(pedWait,HIGH);// light the WAIT to acknowledge the button press. }void pedcross(){// pedestrian crossing function  Serial.println( "Pedestrian crossing start");// tell pc what is happening  delay(maindelay);//pause for traffic to clear  Serial.println( "Pedestrian may cross");// tell pc what is happening  digitalWrite(pedWait, LOW);//switch off the WAIT light  digitalWrite(pedStop, LOW);//switch off the STOP light  digitalWrite(pedGo, HIGH);//Switch on the GO light  delay(maindelay*2);//pause for pedestrians to cross  Serial.println( "Pedestrian time is up, flashing green man");// tell pc what is happening  for (int i=1; i<6; i++){//run the next code 5 times to flash the green man (GO signal)  digitalWrite(pedGo,LOW);//Switch GO light off  delay(200);//Pause  digitalWrite(pedGo,HIGH);//Switch GO light n  delay(200);//Pause}  digitalWrite(pedGo, LOW);//Switch GO light off  digitalWrite(pedStop, HIGH);// Switch WAIT light on  Serial.println( "Pedestrian must stop");// tell pc what is happening  delay(maindelay);// wait for pedestrians to clear crossing  crossRequest = 0;// clear the pedestrian crossing request}/**Version History * 2.1.2 *  - Added an interrupt button to pin 2 (Interrupt 0) as a pedestrian crossing request *  - Added a WAIT signal on pin 16 (pedWait) *  - Added a STOP signal on pin 14 (pedStop) *  - Added a GO signal on pin 15 (pedGo) *  - Added an interrupt to sense a pedestrian requesting to cross. *  - Added a function to allow a pedestrian to cross * 2.1.1 *  - took redundant for() loop out of void loop() *  - Opened the serial port and added debugging information feed from each function. * 2.1 *  - changed variable type from INT to BYTE where the value will always be in the range 0 - 255 made sketch slightly smaller *2.0 Two traffic lights on opposite phases *  - Each light can now be called by it's own address "signal[signalID][colour]" *  - rewrite loop to reflect new addresses *  - deleted duplicated functions * * 1.2 Two traffic lights on opposite phases *  -moved licence to bottom of sketch *  -added version history *  -moved code to change lights out of the loop and into their own functions * * 1.1 Single Traffic Light * *Do what you like with this code as long as you set *it free and allow others to do the same. i.e. ------------------------------------------------- *This work is licensed under the Creative Commons *Attribution-ShareAlike 3.0 Unported License. *To view a copy of this license, visit *http://creativecommons.org/licenses/by-sa/3.0/ *or send a letter to Creative Commons, 444 Castro Street, *Suite 900, Mountain View, California, 94041, USA. ---------------------------------------- */`

I don't know why yet but occasionally a crossing request causes the whole thing to hang. Problem is it's intermittent so I'm having trouble tracking it down. Any Ideas?

I'm still working on it.

Bookworm.
Bookworm

#### Bookworm

#10
##### Feb 21, 2012, 12:42 am
Found on another topic elsewhere.

cut
...if you call Serial.println in you interrupt handler. This may or may not work but often this is a call for doom.
paste

I commented out the Serial.println and recompiled and it runs fine.

Good to know, serial prints put in to aid debugging can be a bug.

Don't know why though. anyone point me at a topic that explains it?

Thanks

Bookworm
Bookworm

#### Kerduino

#11
##### Nov 01, 2016, 03:47 pm
It works!!

It turned out easier to copy some of the traffic light sketch into the array sketch. So that's what I did.

It now appears to do exactly the same thing as before, turning north to green, then to red, then east to green and then red.

Code: [Select]
`/* *A set of Traffic Lights. *I am in the UK so it will be a UK set of traffic lights. *Should be easy to customise to any configuration in the world! *Come with me, it should be fun.  *I intend to  comment every line to start with *so it should be easy to follow.  */const int maindelay = 1000;  //the tempo of the lights are based around //this delay. smaller = faster, larger=slower. The rhythm should  stay the same.const int red = 0; //first column in array signal is red const int amber = 1;//second column in array signal is amberconst int green = 2;//third column in array signal is greenconst int totalcolours = 3; //there are red, amber and greenconst int north = 0; //first row in array signal is northconst int east = 1; // second row in array signal is eastconst int totalsignals = 2; //at the moment there are two sets of signalsconst int signal[totalsignals][totalcolours] ={      {     13,12,11    }  ,  {      8, 9,10    }  }; // traffic lights array. //columns are red, amber, green//rows are individual signals.void setup() {  for (int i = 0; i < totalsignals; i++) { //cycle through the signals    for (int j = 0; j < totalcolours; j++) { //cycle through the colours      pinMode(signal[i][j],OUTPUT); //set the pins as outputs    }  }  for (int i = 0; i < totalsignals; i++) { //cycle through the signals    digitalWrite(signal[i][red],HIGH); //light all the red lights  }}void loop() {  for (int signalID = 0; signalID < totalsignals; signalID++) { //cycle through the signals    settogreen(signalID); //turn the signal called signalID to green    delay(maindelay*2); //wait for traffic to flow    settored(signalID);  //turn the lights back to red    delay(maindelay);    //wait for traffic to clear  }}void settogreen(int i){ //function to set a signal to green   digitalWrite(signal[i][amber],HIGH); //light the amber light  delay(maindelay);//pause  digitalWrite(signal[i][green],HIGH);//light the green light  digitalWrite(signal[i][amber],LOW);//extinguish the amber light  digitalWrite(signal[i][red],LOW);//extingish the red light}void settored(int i){//function to set a signal to red  digitalWrite(signal[i][amber],HIGH);//light the amber light  digitalWrite(signal[i][green],LOW);//extinguish the green light  delay(maindelay);//pause  digitalWrite(signal[i][red],HIGH);//light the red light  digitalWrite(signal[i][amber],LOW);//extinguish the amber light}/**Version History *2.0 Two traffic lights on opposite phases *  - Each light can now be called by it's own address "signal[signalID][colour]" *  - rewrite loop to reflect new addresses *  - deleted duplicated functions * * 1.2 Two traffic lights on opposite phases  *  -moved licence to bottom of sketch  *  -added version history *  -moved code to change lights out of the loop and into their own functions * * 1.1 Single Traffic Light * *Do what you like with this code as long as you set *it free and allow others to do the same. i.e. ------------------------------------------------- *This work is licensed under the Creative Commons  *Attribution-ShareAlike 3.0 Unported License.  *To view a copy of this license, visit *http://creativecommons.org/licenses/by-sa/3.0/  *or send a letter to Creative Commons, 444 Castro Street,  *Suite 900, Mountain View, California, 94041, USA. ---------------------------------------- */`

It's also smaller (1932 bytes) than the original version of the sketch (2102 bytes).

Adding a new set of lights is as easy as
• adding the pin numbers as an extra row
• declaring a new signal, e.g. south and giving it the value 2

Then the sketch cycles all three sets of signals. You can add as many sets of lights as you like (until you run out of output pins).

I added a new signal "south" to pins 5 (Red), 6(amber) and 7(green).

here are the extra variable declarations and the new line in the array

Code: [Select]
`const int south = 2; //south is the third row in the array.const int totalsignals = 3; //now there are 3 sets of signalsconst int signal[totalsignals][totalcolours] ={      { 13,12,11    },//the output pins for north  {  8, 9,10    },//the output pins for east  {  5, 6, 7    } //the new output pins for south}; // traffic lights array. //columns are red, amber, green//rows are individual signals.`

I don't know why but after adding the third signal the sketch is even smaller(1924 bytes).

Not sure what to try next. maybe a button for pedestrians to request to cross plus the associated red and green man signal.

Bear with, or have a go.  Let me know how you get on.

Bookworm.
1. I would like to use an adaption this for a 3-way intersection i'm working on for my dissertation. So is the extra variable declarations and the new line in the array all I need for it to work fine?
2. Does signalID in the code call for a specific value or should just be left as signalID
3. Is it possible to create different sequences for rush hour?

Thanks,
Kay.

#### pert

#12
##### Nov 03, 2016, 08:41 am
2. Does signalID in the code call for a specific value or should just be left as signalID
signalID is passed to the settored/green functions to set the value of the first subscript of the signal array. This means that when signalID is 0 the first traffic light will be controlled(in the example this is north). So the code:
Code: [Select]
`  for (int signalID = 0; signalID < totalsignals; signalID++) { //cycle through the signals    settogreen(signalID); //turn the signal called signalID to green    delay(maindelay*2); //wait for traffic to flow    settored(signalID);  //turn the lights back to red    delay(maindelay);    //wait for traffic to clear  }`
does just what the comment says. It will first set the north traffic light to amber, then green, then amber, then red. Next it will repeat this process with the east traffic light, then the south traffic light, then repeats.

3. Is it possible to create different sequences for rush hour?
Of course, have at it! You can set a different delay between light changes or whatever you like.

Go Up

Please enter a valid email to subscribe