/*
Semáforo inteligente realizado por Juan Manuel Díaz R, Danna Rivera V, Mateo Jaramilo M -->G101
Este semáforo inteligente funciona de la siguiente manera, el semáforo tiene
una secuencia inicial de 20 segundos en verde, luego 2 segundos en amarillo,
luego 15 segundos en rojo, dicha secuencia se puede alterar únicamente
teniendo en cuenta las siguientes distancias de la persona, si la misma está a una
distancia menor a 20 cm y mayor a 10 cm,
el semáforo debe permanecer en amarillo durante 15 segundos,
si después de este tiempo la persona sigue en este rango de distancia
debe permanecer en amarillo durante 10 segundos más, parpadear 2 veces en amarillo
y reanudar la secuencia. Y el otro caso sería cuando el objeto se encuentra a una
distancia menor a 10 cm, en este caso el semáforo pasaría a rojo durante 30 segundos,
si después de este tiempo el objeto sigue en este rango de distancia,
Permanecerá en rojo 10 segundos más, parpadeará 2 veces en amarillo y reanudará
la secuencia. Para ambos casos el semáforo leerá la primera distancia que desencadene
la condición y no interrumpirá las secuencias si dicha distancia sufre alguna variación
mientras se ejecuta la condición.
*/
#define rojo 5
#define amarillo 4
#define verde 3
#define trigPin 7
#define echoPin 6
unsigned long tiempoInicio;
bool objetoEnZona20cm = false;
bool objetoEnZona10cm = false;
bool enCondicionEspecial = false;
unsigned long tiempoUltimaTransicion = 0;
bool parpadeoAmarillo = false;
enum EstadoSemaforo {
VERDE,
AMARILLO,
ROJO
};
EstadoSemaforo estadoActual = VERDE;
unsigned long tiempoVerde = 20000; // 20 segundos
unsigned long tiempoAmarillo = 2000; // 2 segundos
unsigned long tiempoRojo = 15000; // 15 segundos
unsigned long tiempoAmarilloEspecial = 15000; // 15 segundos en condición especial
unsigned long tiempoRojoEspecial = 30000; // 30 segundos en condición especial
unsigned long tiempoParpadeoAmarillo = 1000; // 1 segundo para parpadear en amarillo
void setup() {
pinMode(rojo, OUTPUT);
pinMode(amarillo, OUTPUT);
pinMode(verde, OUTPUT);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
Serial.begin(9600); // Iniciar comunicación serial
delay(1000); // Espera 1 segundo para estabilizar la simulación
tiempoInicio = millis();
// Leer la distancia inicial
long duration, distancia;
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distancia = (duration / 2) / 29.1;
// Verificar la distancia inicial y establecer el estado inicial
if (distancia >= 20) {
objetoEnZona20cm = true;
objetoEnZona10cm = false;
enCondicionEspecial = false;
parpadeoAmarillo = false;
cambiarEstado(VERDE);
} else if (distancia < 20 && distancia >= 10) {
objetoEnZona20cm = false;
objetoEnZona10cm = true;
cambiarEstado(AMARILLO);
} else {
objetoEnZona20cm = false;
objetoEnZona10cm = false;
enCondicionEspecial = true;
parpadeoAmarillo = false;
cambiarEstado(ROJO);
}
}
void loop() {
long duration, distancia;
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distancia = (duration / 2) / 29.1;
Serial.print("Distancia: ");
Serial.print(distancia);
Serial.println(" cm");
unsigned long tiempoActual = millis();
unsigned long tiempoTranscurrido = tiempoActual - tiempoInicio;
// Verificar si la distancia está dentro de los rangos de las condiciones especiales
if (distancia >= 20) {
objetoEnZona20cm = true;
objetoEnZona10cm = false;
if (enCondicionEspecial) {
enCondicionEspecial = false;
parpadeoAmarillo = false;
cambiarEstado(VERDE);
}
} else if (distancia < 20 && distancia >= 10) {
objetoEnZona20cm = false;
objetoEnZona10cm = true;
} else {
objetoEnZona20cm = false;
objetoEnZona10cm = false;
}
if (enCondicionEspecial) {
if (estadoActual == AMARILLO && tiempoTranscurrido >= tiempoAmarilloEspecial) {
if (parpadeoAmarillo) {
cambiarEstado(VERDE);
enCondicionEspecial = false;
parpadeoAmarillo = false;
} else {
parpadearAmarillo();
parpadeoAmarillo = true;
}
} else if (estadoActual == ROJO && tiempoTranscurrido >= tiempoRojoEspecial) {
if (parpadeoAmarillo) {
cambiarEstado(VERDE);
enCondicionEspecial = false;
parpadeoAmarillo = false;
} else {
parpadearAmarillo();
parpadeoAmarillo = true;
}
}
} else if (estadoActual == VERDE) {
if (tiempoTranscurrido >= tiempoVerde) {
cambiarEstado(AMARILLO);
}
} else if (estadoActual == AMARILLO) {
if (tiempoTranscurrido >= tiempoAmarillo) {
if (objetoEnZona10cm) {
enCondicionEspecial = true;
cambiarEstado(AMARILLO);
} else {
cambiarEstado(ROJO);
}
}
} else if (estadoActual == ROJO) {
if (tiempoTranscurrido >= tiempoRojo) {
if (objetoEnZona10cm) {
enCondicionEspecial = true;
cambiarEstado(ROJO);
} else {
cambiarEstado(VERDE);
}
}
}
delay(1000); // retraso de 1 segundos antes de la próxima lectura
}
void cambiarEstado(EstadoSemaforo nuevoEstado) {
if (estadoActual == nuevoEstado) {
return;
}
estadoActual = nuevoEstado;
tiempoInicio = millis(); // Reiniciar el tiempo de inicio
switch (estadoActual) {
case VERDE:
encenderVerde();
break;
case AMARILLO:
encenderAmarillo();
break;
case ROJO:
encenderRojo();
break;
}
}
void encenderRojo() {
digitalWrite(amarillo, LOW);
digitalWrite(verde, LOW);
digitalWrite(rojo, HIGH);
}
void encenderAmarillo() {
digitalWrite(rojo, LOW);
digitalWrite(verde, LOW);
digitalWrite(amarillo, HIGH);
}
void encenderVerde() {
digitalWrite(rojo, LOW);
digitalWrite(amarillo, LOW);
digitalWrite(verde, HIGH);
}
void parpadearAmarillo() {
for (int i = 0; i < 2; i++) {
encenderAmarillo();
delay(tiempoParpadeoAmarillo);
digitalWrite(amarillo, LOW);
delay(tiempoParpadeoAmarillo);
}
}