// Shing Yan (sy228@cornell.edu)
// Raymond Siow (rs234@cornell.edu)
//
// ECE 476
// Final Project
- Traffic control
// Section:
Mondays
// Last Updated:
#include <Mega32.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <delay.h>
// other
constants
#define T0reload 256-250
#define maxkeys 16
#define NOBUTTON 99
// traffic light
FSM states
#define B_GOES_A_WALK 1
#define A_DONT_WALK 2
#define B_YELLOW 3
#define B_RED 4
#define A_GREEN 5
#define B_WALK 6
#define A_GOES_B_WALK 7
#define B_DONT_WALK 8
#define A_YELLOW 9
#define A_RED 10
#define B_GREEN 11
#define A_WALK 12
// sensor states
#define NO_CAR 31
#define IS_CAR 32
// traffic
condition constants
#define LO 13
#define MI 14
#define HI 16
// traffic
sensor condition
#define READY_TO_ADJ 17
#define RECENTLY_ADJ 18
// time
constants used
#define TEN_MS 10
#define HUNDRED_MS 100
#define HALF_SEC 500
#define FIVE_MIN 300000
#define L_CYCLE_LO 60*2
#define L_CYCLE_NM 90*2 //Normal
#define L_CYCLE_HI 120*2
#define LT_A_FLASH 15*2
#define LT_B_FLASH 15*2
// timer
variables
int half_sec;
int traf_t;
int peds_t;
// traffic light
related variables
int lightState;
int lgt_t_a;
int lgt_t_b;
int lgt_t_a_dw;
int lgt_t_b_dw;
int lgt_t_a_reload;
int lgt_t_b_reload;
// traffic
condition
int traf_cond_a;
int traf_cond_b;
// sensors
related variables
int sensorState_a1;
int sensorState_a2;
int car_q_time_a1;
int car_q_time_a2;
int sensorState_b1;
int sensorState_b2;
int car_q_time_b1;
int car_q_time_b2;
int car_q_time_a;
int car_cnt_a;
int time_base_a;
int car_q_time_b;
int car_cnt_b;
int time_base_b;
// some other constants
int hi = L_CYCLE_HI >> 1;
int mi = L_CYCLE_NM >> 1;
int lo = L_CYCLE_LO >> 1;
void light_fsm(void);
void traffic_fsm(void);
void adjust_traf(void);
void pedestrian_fsm(void);
void initalize(void);
void main(void);
// timer0
overflow ISR
interrupt [TIM0_OVF] void timer0_overflow(void)
{
// reload to force 1 mSec overflow
TCNT0 = T0reload;
// Decrement the three times if they
are not already zero
if (half_sec > 0) half_sec--;
if (traf_t > 0) --traf_t;
if (peds_t > 0) --peds_t;
}
// When magnetic
field -> 1
// No field
-> 0
// light_fsm is a function that implements the state machine
used
// to control
switching of the traffic lights
void light_fsm(void) {
half_sec = HALF_SEC;
/***********************************
PORT A - DIRECTION A
.0 - RED
.1 - YELLOW
.2 - GREEN
.3 - WALK
.4 - DON'T WALK
PORT B - DIRECTION B
.0 - RED
.1 - YELLOW
.2 - GREEN
.3 - WALK
.4 - DON'T WALK
***********************************/
switch
(lightState) {
case
B_GOES_A_WALK:
// decrement b's counter
if
(lgt_t_b > 0) --lgt_t_b;
// if counter reaches
don't walk... switch to a's don't walk state
if
(lgt_t_b < lgt_t_b_dw) lightState = A_DONT_WALK;
// set a's timer
break;
case
A_DONT_WALK:
// set walk off on a
PORTA.3 = 1;
// toggle don't walk
light while decrementing b's counter
PORTA.4 = ~PORTA.4;
// if reaches 5 sec
before the end of don't walk state... go to next state
if
(lgt_t_b > 0) --lgt_t_b;
if
((lgt_t_b >> 1) < 5) lightState
= B_YELLOW;
break;
case
B_YELLOW:
// set traffic light to
yellow on b
PORTB.2 = 1;
PORTB.1 = 0;
// 2 sec before going to
state
if
(lgt_t_b > 0) --lgt_t_b;
if
((lgt_t_b >> 1) < 3) lightState
= B_RED;
// set don't walk light
on a if not already
PORTA.4 = 0;
break;
case
B_RED:
// set traffic light to
red on b
PORTB.1 = 1;
PORTB.0 = 0;
// 1 sec before going to
next state
if
(lgt_t_b > 0) --lgt_t_b;
if
((lgt_t_b >> 1) < 2) lightState
= A_GREEN;
break;
case
A_GREEN:
// set traffic light to
green on a
PORTA.0 = 1;
PORTA.2 = 0;
// 1 sec before going to
next state
if
(lgt_t_b > 0) --lgt_t_b;
if
((lgt_t_b >> 1) < 1) lightState
= B_WALK;
break;
case
B_WALK:
// set don't walk off and set walk on on
b
PORTB.4 = 1;
PORTB.3 = 0;
// 1 sec befire going to next state
if
(lgt_t_b > 0) --lgt_t_b;
lightState
= A_GOES_B_WALK;
break;
case
A_GOES_B_WALK:
// decrement a's counter
if
(lgt_t_a > 0) --lgt_t_a;
// if counter reaches
don't walk... switch to b's don't walk state
if
(lgt_t_a < lgt_t_a_dw) lightState = B_DONT_WALK;
// set a's timer
break;
case
B_DONT_WALK:
// set walk off on b
PORTB.3 = 1;
// toggle don't walk
light while decrementing a's counter
PORTB.4 = ~PORTB.4;
// if reaches 5 sec
before the end of don't walk state... go to next state
if
(lgt_t_a > 0) --lgt_t_a;
if
((lgt_t_a >> 1) < 5) lightState
= A_YELLOW;
break;
case
A_YELLOW:
// set traffic light to
yellow on a
PORTA.2 = 1;
PORTA.1 = 0;
// 2 sec before going to
state
if
(lgt_t_a > 0) --lgt_t_a;
if
((lgt_t_a >> 1) < 3) lightState
= A_RED;
// set don't walk light
on b if not already
PORTB.4 = 0;
break;
case
A_RED:
// set traffic light to
red on a
PORTA.1 = 1;
PORTA.0 = 0;
// 1 sec before going to
next state
if
(lgt_t_a > 0) --lgt_t_a;
if
((lgt_t_a >> 1) < 2) lightState
= B_GREEN;
break;
case
B_GREEN:
// set traffic light to
green on b
PORTB.0 = 1;
PORTB.2 = 0;
// 1 sec before going to
next state
if
(lgt_t_a > 0) --lgt_t_a;
if
((lgt_t_a >> 1) < 1) lightState
= A_WALK;
break;
case
A_WALK:
// set don't walk off and
set walk on on a
PORTA.4 = 1;
PORTA.3 = 0;
// 1 sec befire going to next state
if
(lgt_t_a > 0) --lgt_t_a;
lightState
= B_GOES_A_WALK;
adjust_traf();
break;
}
}
// This task checks the road condition every 10ms and adjust
the variables
// of the
traffic lights if necessary.
void traffic_fsm(void) {
/***********************************
PORT A - DIRECTION A
.6 - SENSOR IN A1
.7 - SENSOR IN A2
PORT B - DIRECTION B
.6 - SENSOR IN B1
.7 - SENSOR IN B2
***********************************/
//update the traffic condition every
10ms
traf_t = TEN_MS;
// state machine for traffic light a1
switch
(sensorState_a1) {
case
NO_CAR:
PORTC.3 = 1;
car_q_time_a1 = 0;
if
(PINA.6 == 0){
sensorState_a1 = IS_CAR;
}
break;
case
IS_CAR:
if
(PINA.6 == 1) {
sensorState_a1 = NO_CAR;
car_cnt_a++;
} else {
// increment waiting time
car_q_time_a1++;
}
break;
}
// if waiting time at the sensor >
1 sec, we assume that it's stopped
// this is when the wait time is
incremented
if
(car_q_time_a1 > 100) {
car_q_time_a1-=100;
car_q_time_a+=2;
PORTC.3 = ~PORTC.3;
}
// state machine for traffic light a2
switch
(sensorState_a2) {
case
NO_CAR:
PORTC.3 = 1;
car_q_time_a2 = 0;
if
(PINA.7 == 0) {
sensorState_a2 = IS_CAR;
}
break;
case
IS_CAR:
if
(PINA.7 == 1){
sensorState_a2 = NO_CAR;
car_cnt_a++;
} else {
// increment waiting time
car_q_time_a2++;
}
break;
}
// if waiting time at the sensor >
1 sec, we assume that it's stopped
// this is when the wait time is
incremented
if
(car_q_time_a2 > 100) {
car_q_time_a2-=100;
car_q_time_a+=2;
PORTC.3 = ~PORTC.3;
}
// state machine for traffic light b1
switch
(sensorState_b1) {
case
NO_CAR:
PORTC.7 = 1;
car_q_time_b1 = 0;
if
(PINB.6 == 0){
sensorState_b1 = IS_CAR;
}
break;
case
IS_CAR:
if
(PINB.6 == 1) {
sensorState_b1 = NO_CAR;
car_cnt_b++;
} else {
// increment waiting time
car_q_time_b1++;
}
break;
}
// if waiting time at the sensor >
1 sec, we assume that it's stopped
// this is when the wait time is
incremented
if
(car_q_time_b1 > 100) {
car_q_time_b1-=100;
car_q_time_b+=2;
PORTC.7 = ~PORTC.7;
}
// state machine for traffic light a2
switch
(sensorState_b2) {
case
NO_CAR:
PORTC.7 = 1;
car_q_time_b2 = 0;
if
(PINB.7 == 0){
sensorState_b2 = IS_CAR;
}
break;
case
IS_CAR:
if
(PINB.7 == 1){
sensorState_b2 = NO_CAR;
car_cnt_b++;
} else {
// increment waiting time
car_q_time_b2++;
}
break;
}
// if waiting time at the sensor >
1 sec, we assume that it's stopped
// this is when the wait time is
incremented
if
(car_q_time_b2 > 100) {
car_q_time_b2-=100;
car_q_time_b+=2;
PORTC.7 = ~PORTC.7;
}
}
void adjust_traf(void) {
int
wait_a, rate_a, traf_a;
int
wait_b, rate_b, traf_b;
int
time_base;
time_base = time_base_a
+ time_base_b;
// set wait time for a1 and a2
if (car_q_time_a > (time_base_b*3/4))
{
wait_a = HI;
} else if
(car_q_time_a < (time_base_b/4)) {
wait_a = LO;
} else {
wait_a = MI;
}
// set rate for a1 and a2
if (((float)time_base_a)/car_cnt_a < 4) {
rate_a = HI;
} else if
(((float)time_base_a*2)/car_cnt_a > 10) {
rate_a = LO;
} else {
rate_a = MI;
}
traf_a = wait_a
+ rate_a;
// determine the traffic in road a
if (traf_a < MI*2) {
traf_cond_a = LO;
PORTC.0 = 0;
PORTC.1 = 1;
PORTC.2 = 1;
} else if
(traf_a < HI*2) {
traf_cond_a = MI;
PORTC.0 = 1;
PORTC.1 = 0;
PORTC.2 = 1;
} else {
traf_cond_a = HI;
PORTC.0 = 1;
PORTC.1 = 1;
PORTC.2 = 0;
}
// set wait time for b1 and b2
if (car_q_time_b > (time_base_a*3/4))
{
wait_b = HI;
} else if
(car_q_time_b < (time_base_a/4)) {
wait_b = LO;
} else {
wait_b = MI;
}
// set rate for b1 and b2
if (((float)time_base_b)/car_cnt_b < 2) {
rate_b = HI;
} else if
(((float)time_base_b)/car_cnt_b > 6) {
rate_b = LO;
} else {
rate_b = MI;
}
traf_b = wait_b
+ rate_b;
// determine the traffic in road b
if (traf_b < MI*2) {
traf_cond_b = LO;
PORTC.4 = 0;
PORTC.5 = 1;
PORTC.6 = 1;
} else if
(traf_b < HI*2) {
traf_cond_b = MI;
PORTC.4 = 1;
PORTC.5 = 0;
PORTC.6 = 1;
} else {
traf_cond_b = HI;
PORTC.4 = 1;
PORTC.5 = 1;
PORTC.6 = 0;
}
// reset variables for road a