// Ejemplo de generación de una señal PWM - de 2 kHz y duty_cycle configurable entre 0 y 30 %
//https://wokwi.com/projects/411624405871589377
// the number of the LED pin
#define LED_PIN 23 // GPIO23
#define PULS_PIN 22 // GPIO pulsador - pin interrupcion
// setting Timer y PWM properties
hw_timer_t * timer = NULL; // estructura de datos del timer
const int timer_tics = 10e6; // tics/seg valor del contador del timer - cada 0.1 microsegundos
const float freqPWM = 1000; // un ciclo equivale a 1/freqPWM sec => 1/1000 = 1 ms
const int resolucionPWM = 100; // el duty_cycle se controla con una resolución de 1 a 100
const float ticsPWM = timer_tics/(resolucionPWM*freqPWM); // configurado en alarma -> cuenta 0.1 useg, ticksPWM=100 y salta alarma cada 10 useg.
volatile int antirebote; // variable para eliminar rebotes del pulsador
#define seg_anti_rebote 0.3 // en segundos
const int nticks_anti_rebote = 0.3*1e5; // equivale a 10 useg, /(10e-6)
volatile unsigned int dutyCycle; // variable que va de 1 a 100, es el valor del duty_cycle
volatile unsigned int PWM; // valor 0 a 100 que controla la luminosidad
// ISR finTimer
void IRAM_ATTR finTimer() { // no incluir delay o while(condicion)
dutyCycle=dutyCycle+1;
if(dutyCycle>=100) dutyCycle=0; // va de 1 a 100
// set LED on / off
if(dutyCycle<PWM) digitalWrite(LED_PIN, HIGH); //encendido;
else digitalWrite(LED_PIN, LOW); //apagado;
if(antirebote>0) antirebote=antirebote-1; // elimina posibles rebotes hasta de duracion XX ticks
}
void IRAM_ATTR ISR_pulsador(){
if(antirebote==0){
antirebote=nticks_anti_rebote; // duración máxima de los rebotes eliminados (en ticks del timer)
PWM=PWM+1; // saltos de PWM desde 0 al 30% -> "iluminación" LED 0 a 100 pues no es lineal
if(PWM>30) PWM=0;
}
}
void setup(){
Serial.begin(115200);
Serial.printf("\n\n Ejemplo PWM - control luminosidad de un LED\n");
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, HIGH); //encendido;
delay(1000);
digitalWrite(LED_PIN, LOW); //apagado;
delay(1000);
pinMode(PULS_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(PULS_PIN), ISR_pulsador, FALLING);
// mode: LOW / HIGH / CHANGE / FALLING / RISING
antirebote=0;
// configurar timer a esta frecuencia => p.e. a 10 MHz
timer = timerBegin(timer_tics); // how quickly the timer counter is “ticking”.
timerAttachInterrupt(timer, &finTimer);
// Set alarm to call finTimer function - each XX ticks
// Repeat the alarm (third parameter) with unlimited count = 0 (fourth parameter).
timerAlarm(timer, ticsPWM, true, 0); // se solicita ISR cada 10 microseg
PWM=10; // inicialmente PWM al 10%
timerRestart(timer);
Serial.printf("\nTimer configurado con %d ticks / seg\n", timer_tics);
Serial.printf("Frecuencia del PWM: %.0f Hz - periodo: %.0f useg\n", freqPWM, 1.0e6/freqPWM);
Serial.printf("Resolucion del PWM: %d pasos - incremento paso: %.0f useg\n", resolucionPWM, 1.0e6/ (timer_tics/(resolucionPWM*freqPWM)));
}
void loop(){
Serial.printf("Valor PWM: %d \n", PWM);
// Serial.printf("antirebote: %d \n", antirebote);
delay(1000); // cada 2 segundos indica el valor configurado
}