[Aporte] Control de fase (Dimmer) con Arduino

Scooter

Cascarrabias crónico
Acabo de realizar el control de fase de uun tirac por software con un arduino.
Por si a alguien le puede interesar, publico el código fuente y un video del funcionamiento, el esquema lo publicaré en cuanto lo haga.

Código:
int cuenta = 0;
int segundo = 0;
int tarda =1;
boolean cero = false;
int espera ;

#include <FlexiTimer2.h>

void interrupcion(){
  cero = true;
  FlexiTimer2::set(espera, 1.0/10000, timer); // call every 500 1ms "ticks"
  FlexiTimer2::start();

}

void timer(){
static boolean output = HIGH;
if (cero){
  digitalWrite(8,HIGH);
  cero = false;
  FlexiTimer2::set(1, 1.0/10000, timer); // call every 500 1ms "ticks"
  FlexiTimer2::start();
  }
else{
  digitalWrite(8,LOW);
  FlexiTimer2::stop();
}
}




void setup() {
  // put your setup code here, to run once:
pinMode (7,INPUT_PULLUP);
pinMode (8,OUTPUT);
attachInterrupt(digitalPinToInterrupt(7), interrupcion, RISING);
Serial.begin(9600);
digitalWrite(8,LOW);



}

void loop() {
  // put your main code here, to run repeatedly:
 espera = map(analogRead(0),0,1023,0,100);

}

 
Aclarando el funcionamiento usa una interrupción externa para detectar el paso por cero en el pin7.
Eso puede cambiar según que Arduino se use, ya que no todos disponen de los mismos pines para activar interrupciones externas.
Una vez recibida la interrupción se lanza el timer2 configurado a 0,1ms con una parte proporcional a la lectura del potenciómetro. Cuando el timer2 desborda se activa el pin 8 que es donde está conectado el optotriac y se lanza de nuevo el timer2 0,1ms más para desactivar el pin. En ese punto se para el timer2.

Como se puede ver el main loop está prácticamente vacío, allí se puede hacer lo que se crea conveniente, basta con dar un valor entre 0 y 100 a la variable tarda y la lámpara ya va sola con ese porcentaje. Va al revés, 100 es apagada y 0 encendida a tope.

Esto es para 50Hz, para 60Hz, estará totalmente apagada con tarda por encima de tarda = 83. Y no tengo claro que pasaría, creo que funcionará.
 
Como lo prometido es duda, aporto el esquema y el código editado algo mas limpio.

1559233991756.png
C:
/*
 *  Dimmer por interrupciones
 * 
 *  Programado para Arduino Leonardo, micro, promicro o semejante, pero adpatable a acasi cualquier otro
 * 
 *  (CC) con mención del autor Por Félix Díaz 2019
 * 
 *  Está pensado para sistemas de 50Hz en los que un semiperiodo dura 10ms y por ello se permiten cien fracciones a 100us cada una
 *  Para 60Hz al llegar a 83 el triac estará totalemte apagado, habrá que reconfigurar los timers si se quiere un ajuste de 0~100
 *  No lo he probado a 60Hz porque no dispongo de una red eléctrica para poder hacerlo
 * 
 */

// Definición de variables
boolean cero = false;   //Flag para saber en que paso estamos ya que se llama dos veces a la misma interrupción
int espera ;            // Tiempo de espera en 0,1ms desde el paso por cero hasta el disparo del triac

#define interrup 7    //Pin en el que entran las interrupciones del detector de paso por cero, dependerá del arduino que usemos
#define triac 8       //Pin en el que se conecta el triac, el que nosotros queramos

#include <FlexiTimer2.h>      //Librería para el uso del Timer2

// Interrupción por paso por cero en la red, es necesario un optoacoplador de alterna o uno de continua con un puente
void interrupcion(){
  cero = true;
  FlexiTimer2::set(espera, 1.0/10000, timer); // se programa el timer con el número de 100 us que se desee
  FlexiTimer2::start();
}

// Interrupción por desbordamiento del timer2
/*
 * Esta interrupción se llama dos veces, para disparar el triac con el retardo deseado y 100us después para cortar el pulso de disparo, por eso hay un flag,
 * para diferenciar en cual de esas dos ocasiones estamos.
 *
 */
void timer(){
static boolean output = HIGH;
if (cero){    // Es la primera vez, activamos el triac y lanzamos una nueva interrupción para dentro de 100us
  digitalWrite(triac,HIGH);
  cero = false;
  FlexiTimer2::set(1, 1.0/10000, timer); // Se espera 1 100us
  FlexiTimer2::start();
  }
else{       // es la segunda vez, cortamos el pulso de disparo y paramos el timer
  digitalWrite(triac,LOW);
  FlexiTimer2::stop();
}
}


void setup() {
  // Inicialización los pines etcput your setup code here, to run once:
pinMode (interrup,INPUT_PULLUP);      //Activamos internal pullup para ahorrar una resistencia
pinMode (triac,OUTPUT);               // Pin de control de triac como salida
attachInterrupt(digitalPinToInterrupt(interrup), interrupcion, RISING);  //interrupción, pin, función
digitalWrite(triac,LOW);              // Apagamos el triac por si acaso, debería de estar (apagado sin hacer nada)
}

void loop() {
  // Aquí iría el código correspondiente, en este caso se lee un potenciometro y ya está
 espera = map(analogRead(0),0,1023,0,100);

}
 
Atrás
Arriba