Dimmer programable. Cap. 4

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
    }
  }
}
Scroll al inicio