#define RR 12
#define RY 11
#define RG 10
#define CWR 9
#define CWG 8
#define CWO 7
volatile bool cw_go = false;
#define ROAD_YELLOW_TIME 500
#define ROAD_MIN_GREEN_TIME 3000
#define CW_GREEN_TIME 2000
#define CW_GREEN_BLINKS 5
#define CW_GREEN_BLINK_TIME 100
#define BUFFER_TIME 1000
#define DELAY_LOOP 1000
#define BUTTON 2
volatile bool button_pressed = false;
// These constants should match the photoresistor's "gamma" and "rl10" attributes
#define GAMMA 0.7f
#define RL10 50.0f
#define DAY_THRESHOLD 1000.0f
volatile bool day = true;
bool is_day()
{
// Convert the analog value into lux value:
int analogValue = analogRead(A0);
float voltage = analogValue / 1024. * 5;
float resistance = 2000 * voltage / (1 - voltage / 5);
float lux = pow(RL10 * 1e3 * pow(10, GAMMA) / resistance, (1 / GAMMA));
return lux > DAY_THRESHOLD;
}
void clear_leds()
{
for (int i = 7; i <= 12; i++)
{
digitalWrite(i, LOW);
}
}
void on_button_pressed()
{
if (day && !cw_go)
{
button_pressed = true;
digitalWrite(CWO, HIGH);
}
}
void setup()
{
pinMode(BUTTON, INPUT);
attachInterrupt(digitalPinToInterrupt(BUTTON), on_button_pressed, RISING);
Serial.begin(115200);
for (int i = 7; i <= 12; i++)
{
pinMode(i, OUTPUT);
}
goto_state_init();
}
void goto_state_init()
{
clear_leds();
digitalWrite(RG, HIGH);
digitalWrite(CWR, HIGH);
}
void road_goto_state_stop() {
// Yellow
digitalWrite(RG, LOW);
digitalWrite(RY, HIGH);
delay(ROAD_YELLOW_TIME);
// Red
digitalWrite(RY, LOW);
digitalWrite(RR, HIGH);
}
void road_goto_state_go() {
// Red yellow
digitalWrite(RY, HIGH);
delay(ROAD_YELLOW_TIME);
// Green
digitalWrite(RY, LOW);
digitalWrite(RR, LOW);
digitalWrite(RG, HIGH);
}
void cw_goto_state_go() {
cw_go = true;
digitalWrite(CWR, LOW);
digitalWrite(CWG, HIGH);
}
void cw_goto_state_stop() {
for (int i = 0; i < CW_GREEN_BLINKS; i++)
{
digitalWrite(CWG, LOW);
delay(CW_GREEN_BLINK_TIME);
digitalWrite(CWG, HIGH);
delay(CW_GREEN_BLINK_TIME);
}
// CW Stop
cw_go = false;
digitalWrite(CWR, HIGH);
digitalWrite(CWG, LOW);
}
void loop()
{
if (!is_day())
{
if (day)
{
day = false;
clear_leds();
}
digitalWrite(RY, HIGH);
delay(CW_GREEN_BLINK_TIME);
digitalWrite(RY, LOW);
delay(CW_GREEN_BLINK_TIME);
}
else
{
if (!day)
{
day = true;
goto_state_init();
}
if (button_pressed)
{
button_pressed = false;
road_goto_state_stop();
delay(BUFFER_TIME);
digitalWrite(CWO, LOW);
cw_goto_state_go();
delay(CW_GREEN_TIME);
cw_goto_state_stop();
delay(BUFFER_TIME);
road_goto_state_go();
delay(ROAD_MIN_GREEN_TIME);
}
else
{
delay(DELAY_LOOP);
}
}
}