Continuamos con el proyecto del Dimmer programable que me permita utilizar todos los excedentes de mis placas fotovoltaicas.
En el capítulo de hoy unimos lo aprendido en vídeos anteriores y fabricaremos un dimmer que ya permite regular la potencia a su salida.
Además, vamos a hacer una versión que nos permitirá seleccionar con el teclado cuánta potencia suministrar.
No te pierdas la animación en la que explicamos el funcionamiento del programa del microcontrolador a lo largo de una semionda de alterna, es muy ilustrativa.
Enlaces de compra a los materiales del vídeo:
Aquí el código del primer programa que vemos en el vídeo:
#include <Arduino.h>
const int pinSalida = 32; // Pin GPIO35 que excitará al Triac
const int pinEntrada = 34; // Pin GPIO34 para detectar los cruces por 0
hw_timer_t *timer = NULL; // Declaración de la variable timer
volatile int contadorPulsos = 0; // cuenta las veces que cambia el pin de entrada
// Interrupción externa. Se lanza cada vez que se detecta una señal de subida en el pin de entrada
void IRAM_ATTR deteccion0() {
// Lo único que hacemos al detectar un cruce por 0 es reiniciar el contador de pulsos
contadorPulsos=0;
detachInterrupt(digitalPinToInterrupt(pinEntrada));
timerAlarmEnable(timer); // Habilita la alarma del temporizador
}
// La interrupción del Timer se ejecutará cada 100 microsegundos
// Como un segundo tiene 100 seminodas, cada una de ellas dura 10.000 microsegundos
// En cada semionda ejecutaremos esta función 100 veces
void reloj100us() {
contadorPulsos++; // cada vez que entramos incrementamos el contador de pulsos
if (contadorPulsos==70) // llegados al punto de la onda en que queremos encender ...
digitalWrite(pinSalida, false); // ... activa la salida del Triac (lógica inversa)
if (contadorPulsos==71) { // y un ciclo del reloj más tarde ...
digitalWrite(pinSalida, true); // ... desactiva la salida del Triac (lógica inversa);
timerAlarmDisable(timer); // ya podemos parar el reloj hasta el próximo cruce por 0
// para detectar el próximo cruce por 0 es necesario activar la interrupción externa
attachInterrupt(digitalPinToInterrupt(pinEntrada), deteccion0, RISING);
}
}
// Configuración
void setup() {
pinMode(pinEntrada, INPUT); // Definimos el pin de entrada para la detección de cruces por 0
// Asignamos la función "deteccion0" a la interrupción por un flanco de subida en la entrada
attachInterrupt(digitalPinToInterrupt(pinEntrada), deteccion0, RISING);
pinMode(pinSalida, OUTPUT);
// Configura un temporizador para llamar a una función cada 100us (0.0001 segundos)
timer = timerBegin(0, 80, true); // Usamos el grupo de temporizadores 0 y la escala de prescaler 80
timerAttachInterrupt(timer, &reloj100us, true); // Adjunta la función reloj100us como interrupción
timerAlarmWrite(timer, 100, true); // Establece el período del temporizador (100 microsegundos)
}
void loop() {
}
Y a continuación el código del segundo programa:
#include <Arduino.h>
const int pinSalida = 32; // Pin GPIO35 que excitará al Triac
const int pinEntrada = 34; // Pin GPIO34 para detectar los cruces por 0
hw_timer_t *timer = NULL; // Declaración de la variable timer
volatile int contadorPulsos = 0; // cuenta las veces que cambia el pin de entrada
int CicloDimmer=50; // valor inicial
// Interrupción externa. Se lanza cada vez que se detecta una señal de subida en el pin de entrada
void IRAM_ATTR deteccion0() {
contadorPulsos=0; // Al detectar un cruce por 0 reiniciamos el contador de pulsos
detachInterrupt(digitalPinToInterrupt(pinEntrada)); // y desactivamos la interrupción externa para evitar ruidos
timerAlarmEnable(timer); // Habilita la alarma del temporizador
}
// La interrupción del Timer se ejecutará cada 100 microsegundos
// Como un segundo tiene 100 seminodas, cada una de ellas dura 10.000 microsegundos
// En cada semionda ejecutaremos esta función 100 veces
void reloj100us() {
contadorPulsos++; // cada vez que entramos incrementamos el contador de pulsos
if (contadorPulsos==CicloDimmer) // llegados al punto de la onda en que queremos encender ...
digitalWrite(pinSalida, false); // ... activa la salida del Triac (lógica inversa)
if (contadorPulsos==CicloDimmer+1) { // y un ciclo del reloj más tarde ...
digitalWrite(pinSalida, true); // ... desactiva la salida del Triac (lógica inversa);
// para detectar el próximo cruce por 0 es necesario activar la interrupción externa
attachInterrupt(digitalPinToInterrupt(pinEntrada), deteccion0, RISING);
}
}
// Configuración
void setup() {
pinMode(pinEntrada, INPUT); // Definimos el pin de entrada para la detección de cruces por 0
// Asignamos la función "deteccion0" a la interrupción por un flanco de subida en la entrada
attachInterrupt(digitalPinToInterrupt(pinEntrada), deteccion0, RISING);
pinMode(pinSalida, OUTPUT); // Definimos el pin de salida que excitará al Triac
// Configura un temporizador para llamar a una función cada 100us (0.0001 segundos)
timer = timerBegin(0, 80, true); // Usamos el grupo de temporizadores 0 y la escala de prescaler 80
timerAttachInterrupt(timer, &reloj100us, true); // Adjunta la función reloj100us como interrupción
timerAlarmWrite(timer, 100, true); // Establece el período del temporizador (100 microsegundos)
Serial.begin(115200); // Activamos puerto serie
// Y solicitamos al usuario un valor para la regulación del Dimmer
Serial.println("Ingrese un valor entre 1 y 99:");
}
void loop() {
int valorIngresado;
if (Serial.available() ) { // si hemos recibido algo nuevo del usuario
valorIngresado = Serial.parseInt(); // lo convertimos en número entero
if (valorIngresado >= 1 && valorIngresado <= 99) { // se valida que el número está entre 1 y 99
Serial.print("Dimmer establecido en: "); // mostramos el valor leído al usuario
Serial.println(valorIngresado);
CicloDimmer = valorIngresado; // establecemos la nueva regulación del dimmer
// y activamos la interrupción externa por si ha pillado durante el ciclo que estuviera desactivada
attachInterrupt(digitalPinToInterrupt(pinEntrada), deteccion0, RISING);
} else {
// si el usuario no ha ingresado un número correcto se lo pedimos de nuevo
Serial.println("Valor fuera de rango. Debe estar entre 1 y 99.");
}
while (Serial.available() ) { // si se ha recibido más información, no la necesitamos
Serial.read(); // Limpia el búfer de entrada
}
}
}

