Traffic Control System – Code

The entire traffic system is composed of three subsystems. The first subsystem controls the traffic lights. This system has a default state and an alternative state. The default state of the intersection is for the east -west road to have green lights, while the north- south are red. The alternative state is for the north -south lights to be green and the east -west to be red. There are two ways to swap from the default state to the alternative state. The first way is for a car to pull up to the south side of t he intersection and trigger the IR sensor. After a few seconds of delay, the state swap is initiated. The east -west lights go from green to yellow for one second and then change to red for the duration of the alternative state. After another delay, the north-south lights go from red to green. They stay green for 10 seconds before the reverse swap occurs. The reverse swap switches the alternative state back to the default state.

The second way to change the default state of the intersection is handled by the second subsystem. The second subsystem handles the crosswalk, and has a direct influence over the operation of the first subsystem. The second subsystems first function is triggered by any of the 4 blue buttons. If a blue button is pressed, this tells the controller that a pedestrian wants to cross the east -west road using either of the two crosswalks. After a short delay, the intersection switches to what is called the “alternative plus” state. This state is the same as the alternative state with addition of counting down the 7- segment displays. In this state, drivers coming from the south would have to yield to pedestrians crossing the street before turning. The second function this subsystem handles is the crosswalk for the north- south road. This function doesn’t interfere with the default operation of the intersection. It simply verifies that the north -south lights are red, then starts the countdown on the corresponding 7- segment displays.

The third subsystem operates independently from the first two. It controls the flashing lights over the train track and the servo motors that bring the arms down. To mimic an oncoming train, a red push button is located to the south east of the train track. Once this button is pushed, a 3 second delay is initiated and followed by the servo motor arms moving across each side of the road to block oncoming traffic and pedestrians from crossing the track while the train is passing.

These systems are controlled by two ATmega328Ps. The main board controls the railroad and traffic light functions while a second board controls the seven segment displays that are the crosswalk count downs. The two board system was chosen because the ATmega328P did not have enough ports to control all of these functions. For a schematic for this code, go to https://www.ece.louisville.edu/courses/ece412/?p=2351.

Main Code Segment

#define F_CPU 8000000UL
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>

#define G1 PD0 //setting lights up with ports
#define Y1 PD1
#define R1 PD2
#define G2 PD3
#define Y2 PD4
#define R2 PD5

#define Servo PB1

#define B1 PC5
#define B2 PC4
#define B3 PC3

int main(void)
{
DDRB=0xff;
DDRD=0xff;
DDRC=0x00;
PORTB=0x00;
PORTC=0x00;
PORTD=0x00;
DDRC|=0<<DDC0; //setting PC0 to be an input 0x01
PORTC|=(1<<PORTC0); //setting PC0 to have pull-up resistor as long as 
//pin is setup as input
DDRC|=0<<DDC1;//setting PC1 to be an input 0x02
PORTC|=(1<<PORTC1);//setting PC1 to have pull-up resistor as long as 
//pin is setup as input
DDRC|=0<<DDC2;//setting PC2 to be an input 0x04
PORTC|=(1<<PORTC2);//setting PC2 to have pull-up resistor as long as 
//pin is setup as input
DDRC|=0<<DDC3;//setting PC3 to be an input 0x08

PORTC|=(1<<PORTC3);//setting PC3 to have pull-up resistor as long as 
//pin is setup as input
DDRC|=0<<DDC4;//setting PC4 to be an input 0x10
PORTC|=(1<<PORTC4);//setting PC3 to have pull-up resistor as long as 
//pin is setup as input
DDRC|=0<<DDC5;//setting PC5 to be an input 0x20
PORTC|=(1<<PORTC5);//setting PC3 to have pull-up resistor as long as 
//pin is setup as input
DDRD|=0xFF;
TCCR1A|=1<<WGM11|1<<COM1A1|1<<COM1A0;//setup compare match
TCCR1B|=1<<WGM13|1<<WGM12|1<<CS11|1<<CS10;//Setting Clock Pre-scaler 
//to /64
ICR1=2499;//value calculated for frequency to be 50hz for the 
//Servo motors
while(1)
if(!(PINC&(1<<B1)))//Setting up buttons if pushed crosswalks 
{
_delay_ms(6000);
PORTD=0x00;
PORTD|=(1<<G1);
PORTD|=(1<<R2);
_delay_ms(5000);
PORTB=0x00;
}
else if(!(PINC&(1<<B2)))// NO ! PC4 Power is low, ! before 
{
//parenthesisis if high, both work
_delay_ms(8000);
PORTD=0x00;
PORTD|=(1<<Y1);
PORTD|=(1<<R2);
_delay_ms(3000);
PORTD=0x00;
PORTD|=(1<<R1);
PORTD|=(1<<R2);
_delay_ms(3000);
PORTD=0x00;
PORTD|=(1<<G2);
PORTD|=(1<<R1);
_delay_ms(23000);
PORTD=0x00;
}
else if(!(PINC&0x01)==0x01)//if PC0 Power is low, Beam broken
{
_delay_ms(8000);
PORTD=0x00;
PORTD|=(1<<Y1);
PORTD|=(1<<R2);
_delay_ms(5000);
PORTD=0x00;
PORTD|=(1<<R1);
PORTD|=(1<<R2);
_delay_ms(3000);
PORTD=0x00;
PORTD|=(1<<R1);
PORTD|=(1<<G2);
_delay_ms(8000);
PORTD=0x00;
PORTD|=(1<<Y2);
PORTD|=(1<<R1);
_delay_ms(6000);
PORTD=0x00;
PORTD|=(1<<R1);
PORTD|=(1<<R2);
_delay_ms(3000);
PORTD=0x00;
PORTD|=(1<<G1);
PORTD|=(1<<R2);
_delay_ms(5000);
}
else if(!(PINC&(1<<B3)))//Servo Motor
{
_delay_ms(4000);
OCR1A=ICR1-365;//up to neutral position(-365)
_delay_ms(1000);//delay
OCR1A=ICR1-545;//down right position (-155), (-550) for other way
_delay_ms(10000);
OCR1A=ICR1-365;//up to neutral position(-365)
_delay_ms(500);//delay
}
else
{
PORTD=0x00;
PORTD|=(1<<G1);
PORTD|=(1<<R2);
}
}

Slave Code Segment

#define F_CPU 8000000UL
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>

#define Direction PC0 //inputs
#define StartPC1//inputs
#define SSD1A PD0
#define SSD1B PD1
#define SSD1C PD2
#define SSD1D PD3
#define SSD2A PD4
#define SSD2B PD5
#define SSD2C PD6
#define SSD2D PD7
#define Blank PB0
#define B1 PC5
#define B2 PC4

int main(void)
{
DDRD=0xff;
DDRC=0x00;
DDRB=0xff;
PORTB=0x00;
PORTC=0x00;
PORTD=0x00;

DDRC|=0<<DDC0;//setting PC0 to be an input 0x01
PORTC|=(1<<PORTC0);//setting PC0 to have pull-up resistor as long as 
//pin is setup as input
DDRC|=0<<DDC1;//setting PC1 to be an input 0x02
PORTC|=(1<<PORTC1);//setting PC1 to have pull-up resistor as long as 
//pin is setup as input
DDRC|=0<<DDC2;//setting PC2 to be an input 0x01
PORTC|=(1<<PORTC2);//setting PC2 to have pull-up resistor as long as 
//pin is setup as input
DDRC|=0<<DDC4;//setting PC4 to be an input 0x01
PORTC|=(1<<PORTC4);//setting PC4 to have pull-up resistor as long as 
//pin is setup as input
DDRC|=0<<DDC5;//setting PC5 to be an input 0x01
PORTC|=(1<<PORTC5);//setting PC5 to have pull-up resistor as long as 
//pin is setup as input

while(1)
{
if(!(PINC&(1<<B1)))
{
_delay_ms(7000);
PORTB=0x00;
PORTB|=(1<<Blank);
PORTD=0x00;
PORTD|=(1<<SSD1C);
PORTD|=(0<<SSD1B);
PORTD|=(1<<SSD1A);
_delay_ms(2000);
PORTD=0x00;
PORTD|=(1<<SSD1C);
PORTD|=(0<<SSD1B);
PORTD|=(0<<SSD1A);
_delay_ms(2000);
PORTD=0x00;
PORTD|=(0<<SSD1C);
PORTD|=(1<<SSD1B);
PORTD|=(1<<SSD1A);
_delay_ms(2000);
PORTD=0x00;
PORTD|=(0<<SSD1C);
PORTD|=(1<<SSD1B);
PORTD|=(0<<SSD1A);
_delay_ms(2000);
PORTD=0x00;
PORTD|=(0<<SSD1C);
PORTD|=(0<<SSD1B);
PORTD|=(1<<SSD1A);
_delay_ms(2000);
PORTD=0x00;
PORTD|=(0<<SSD1C);
PORTD|=(0<<SSD1B);
PORTD|=(0<<SSD1A);
_delay_ms(2000);
PORTB=0x00;
PORTB|=(0<<Blank);
}
else if(!(PINC&(1<<B2)))
{
_delay_ms(7000);
PORTB=0x00;
PORTB|=(1<<Blank);
PORTD=0x00;
PORTD|=(1<<SSD2C);
PORTD|=(0<<SSD2B);
PORTD|=(1<<SSD2A);
_delay_ms(2000);
PORTD=0x00;
PORTD|=(1<<SSD2C);
PORTD|=(0<<SSD2B);
PORTD |= (0<<SSD2A);
_delay_ms(2000);
PORTD = 0x00;
PORTD |= (0<<SSD2C);
PORTD |= (1<<SSD2B);
PORTD |= (1<<SSD2A);
_delay_ms(2000);
PORTD = 0x00;
PORTD |= (0<<SSD2C);
PORTD |= (1<<SSD2B);
PORTD |= (0<<SSD2A);
_delay_ms(2000);
PORTD = 0x00;
PORTD |= (0<<SSD2C);
PORTD |= (0<<SSD2B);
PORTD |= (1<<SSD2A);
_delay_ms(2000);
PORTD = 0x00;
PORTD |= (0<<SSD2C);
PORTD |= (0<<SSD2B);
PORTD |= (0<<SSD2A);
_delay_ms(2000);
PORTB = 0x00;
PORTB |= (0<<Blank);
}
}
}