//OBS: en la simulación, la frecuencia de oscilación es diferente a la del modelo real, por lo que al poner
//run simulation, cambia el parpadeo del led cada 8s
/*
Curso: PIT12 IOT con ESP 32 - A
Estudiante: Eduardo Dante Cáceres Bottoni
Tarea: Tarea periféricos ESP32
Enunciado:
Realizar un programa que simule un semáforo con las siguientes carácterísticas:
1. Para el control del tiempo de encendido y apagado utilizar el periférico timer.
2. El cambio de colores del semáforo será cada 4 segundos.
3. La simulación de los colores se hará por medio de leds, rojo, verde, amarillo
4. Se imprimirá por el monitor el estado(color) del semáforo.
5. Para el control de intensidad de los leds se utilizará el periférico pwm a la mitad del ciclo de trabajo.
Ayuda: Los leds se conectaran a los pines que dispongan de pwm.
Link de la simulación: https://wokwi.com/projects/341706005389771346
Solución:
*/
//definimos las variables para el PWM
#define frecuencia 1000
#define Resolucion 10
#define dutycycle 512
//Valores iniciales del semáforo
const int luces[] = {15,2,4};
//15: verde
//2: amarillo
//4: rojo
const String Nombres[] = {"Verde","Amarillo","Rojo"};
const int CanalesPWM [] = {0,1,2};
//Cambiador de estado
volatile byte estado = 0;
//Variable auxiliar que detecta el cambio de estado
byte aux=estado;
//timer
hw_timer_t *timer = NULL;
//Declaración de la función de interrupción y de imprimir estado, respectivamente
void IRAM_ATTR cambioEstado();
void ImprimirEstado();
void setup() {
// Inicializar transmisión serial
Serial.begin(9600);
//Inicializar los pines y los canales PWM
for(byte i=0;i<3;i++){
pinMode(luces[i],OUTPUT);
ledcSetup(CanalesPWM[i], frecuencia, Resolucion);
}
//Asignar los canales PWM a las entradas
for(byte i=0;i<3;i++){
ledcAttachPin(luces[i], CanalesPWM[i]);
}
//Inicializamos con el valor Verde (estado=0), con la mitad del dutycyle
ledcWrite(CanalesPWM[estado], dutycycle);
//Imprimimos el valor Del color
Serial.println(Nombres[estado]);
//Inicializamos el TIMER (Preescaler 80)
timer = timerBegin(0, 80, true);
//
timerAttachInterrupt(timer, &cambioEstado, true);
//Establecemos el tiempo: como preescaler 80, T=1us, entonces 4s/1us=4 000 000
timerAlarmWrite(timer, 4000000, true);
//Activamos las interrupciones por timer
timerAlarmEnable(timer);
}
void loop() {
// variable auxiliar (aux) siempre será igual a estado, hasta que estado entre en la interrupción
if(aux!=estado){
ledcWrite(CanalesPWM[estado],dutycycle); //Encender el nuevo LED de estado
Serial.println(Nombres[estado]); //Imprimir el valor del color
aux=estado; //igualar el valor de aux para que no vuelva a entrar en el if hasta la proxima interrupcion
}
}
void IRAM_ATTR cambioEstado() {
ledcWrite(CanalesPWM[estado],0); //Apagamos el led inicial
estado=estado==2?0:estado+1; //Hacemos cambio del valor de estado
}