#include <Arduino.h>
//pines
const int pin_salida = 32; //salida de la señal PWM
const int pin_entrada = 33; //pin de entrada de la señal PWM
const int boton_frecuencia = 34; //boton para cambiar frecuencia de LEDs
const int boton_ciclo = 35; //boton para cambiar ciclo de trabajo de LEDs
const int ledPins[] = {23, 22, 21, 19, 18};
//frecuencias y ciclos de trabajo (PL = 7)
int frecuencias[] = {8, 22, 37, 157, 307};
int ciclosTrabajo[] = {6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90, 96};
volatile int frecuenciaIndex = 2; //indice inicial de frecuencia de LEDs
volatile int cicloTrabajoIndex = 7; //indice inicial de ciclo de trabajo de LEDs
//variables para medición de señal PWM
volatile unsigned long inicioPulso = 0; //inicio del pulso (millis)
volatile unsigned long tiempoAlto = 0; //duración del estado HIGH (ms)
volatile unsigned long tiempoBajo = 0; //duración del estado LOW (ms)
//temporizadores para LEDs
unsigned long ultimoCambioLED = 0; //ultimo cambio de estado de LEDs
unsigned long periodoLED = 1000 / frecuencias[frecuenciaIndex] ; //periodo inicial de LEDs
int ledActual = 0; //led actualmente encendido
//variables para impresión
unsigned long ultimaImpresion = 0;
const unsigned long intervaloImpresion = 2000;
//interrupción para medir señal PWM
void IRAM_ATTR medirSenalPWM() {
unsigned long tiempoActual = millis();
if (digitalRead(pin_entrada) == HIGH) {
//flanco ascendente
tiempoBajo = tiempoActual - inicioPulso; //calcular tiempo en LOW
} else {
//flanco descendente
tiempoAlto = tiempoActual - inicioPulso; //calcular tiempo en HIGH
}
inicioPulso = tiempoActual; //actualizar inicio del pulso
}
//interrupción para cambiar frecuencia de leds
void IRAM_ATTR cambiarFrecuencia() {
static unsigned long ultimaPulsacion = 0;
unsigned long tiempoActual = millis();
if (tiempoActual - ultimaPulsacion > 50) { //debounce
frecuenciaIndex = (frecuenciaIndex + 1) % 5; //avanzar en la tabla de frecuencias
periodoLED = 1000 / frecuencias[frecuenciaIndex]; //actualizar periodo de LEDs
Serial.print("Nueva frecuencia de LEDs: ");
Serial.println(frecuencias[frecuenciaIndex]);
ultimaPulsacion = tiempoActual;
}
}
//interrupción para cambiar ciclo de trabajo de LEDs
void IRAM_ATTR cambiarCiclo() {
static unsigned long ultimaPulsacion = 0;
unsigned long tiempoActual = millis();
if (tiempoActual - ultimaPulsacion > 50) { //debounce
cicloTrabajoIndex = (cicloTrabajoIndex + 1) % 16; //avanzar en la tabla de ciclos
Serial.print("Nuevo ciclo de trabajo de LEDs: ");
Serial.println(ciclosTrabajo[cicloTrabajoIndex]);
ultimaPulsacion = tiempoActual;
}
}
//secuencia de LEDs
void manejarLEDs() {
unsigned long tiempoActual = millis();
if (tiempoActual - ultimoCambioLED >= periodoLED) {
ultimoCambioLED = tiempoActual;
//apagar el LED anterior
digitalWrite(ledPins[ledActual], LOW);
//avanzar al siguiente LED
ledActual = (ledActual + 1) % 5;
//encender el LED actual
digitalWrite(ledPins[ledActual], HIGH);
}
}
//generación de señal PWM
void generarPWM() {
static unsigned long inicioCiclo = 0;
static bool estadoPWM = false;
unsigned long tiempoActual = millis();
unsigned long periodoTotal = 1000 / frecuencias[frecuenciaIndex];
unsigned long tiempoAltoPWM = (periodoTotal * ciclosTrabajo[cicloTrabajoIndex]) / 100;
if (estadoPWM && tiempoActual - inicioCiclo >= tiempoAltoPWM) {
estadoPWM = false;
inicioCiclo = tiempoActual;
digitalWrite(pin_salida, LOW);
} else if (!estadoPWM && tiempoActual - inicioCiclo >= (periodoTotal - tiempoAltoPWM)) {
estadoPWM = true;
inicioCiclo = tiempoActual;
digitalWrite(pin_salida, HIGH);
}
}
void setup() {
//configurar pines
pinMode(pin_salida, OUTPUT);
pinMode(pin_entrada, INPUT);
pinMode(boton_frecuencia, INPUT);
pinMode(boton_ciclo, INPUT);
for (int i = 0; i < 5; i++) {
pinMode(ledPins[i], OUTPUT);
}
//configuración de interrupciones
attachInterrupt(digitalPinToInterrupt(pin_entrada), medirSenalPWM, CHANGE); //señal PWM
attachInterrupt(digitalPinToInterrupt(boton_frecuencia), cambiarFrecuencia, FALLING); //frecuencia
attachInterrupt(digitalPinToInterrupt(boton_ciclo), cambiarCiclo, FALLING); //ciclo de trabajo
Serial.begin(115200);
}
void loop() {
generarPWM(); //generar señal PWM
manejarLEDs(); //manejar secuencia de LEDs
//imprimir valores periódicamente
unsigned long tiempoActual = millis();
if (tiempoActual - ultimaImpresion >= intervaloImpresion) {
ultimaImpresion = tiempoActual;
//imprimir frecuencia y ciclo de trabajo de PWM
if (tiempoAlto + tiempoBajo > 0) {
float frecuenciaPWM = 1000.0 / (tiempoAlto + tiempoBajo);
float cicloTrabajoPWM = (float)tiempoAlto / (tiempoAlto + tiempoBajo) * 100;
Serial.print("Frecuencia PWM generada: ");
Serial.print(frecuenciaPWM, 2);
Serial.println(" Hz");
Serial.print("Ciclo de trabajo PWM: ");
Serial.print(cicloTrabajoPWM, 2);
Serial.println(" %");
}
//imprimir configuración actual de LEDs
Serial.print("Frecuencia de LEDs: ");
Serial.print(frecuencias[frecuenciaIndex]);
Serial.println(" Hz");
Serial.print("Ciclo de trabajo de LEDs: ");
Serial.print(ciclosTrabajo[cicloTrabajoIndex]);
Serial.println(" % \n");
}
}