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);
}
}
}

Crosswalk Simulator/Stoplight: The Big Picture

The fundamental goal of this project was to recreate the same type of crosswalk that could be found at the intersection of Eastern Parkway and Speed School. The scope of the project contained two stop lights (6 LEDs Total), walk/don’t walk graphics, battery powered crosswalk button, a sounding buzzer for echolocation,  and a “time remaining” indicator.

The A3BU board worked well for all functions that we needed to complete this project. The board provided us with enough GPIO pins to provide power control for 6 of the 3V LED’s, as well as frequency pulse with modulation to control the buzzer. An analog -to-digital converter (ADC) pin was also utilized to detect digital-hi’s when the crosswalk button was pressed. The battery provided a voltage that would then be tested against a certain range, and if the value was in that range, the crosswalk logic would trigger.

LED Layout with A3BU, buzzer, and button.

Final Project pic 2

The LCD display served a large purpose as it displayed all of our crosswalk functions. When the crosswalk button was pressed and the light turns red, a ASCII graphic of a “walkman” appears letting you know its safe to cross. A incremented bar also appears, gradually growing larger allowing the walker to see how much time they have left to cross. Once this timer ends, an ASCII “stop-hand” appears, letting the user know it’s no longer safe to cross.

 

LCD displaying the ‘walkman’ and the timer bar at the top

Final Project pic 1

The buzzer was turned off and on by varying the duty cycle on the GPIO output, while the pitched was changed by editing the frequency of the pulses. Here is a video displaying all the functions.