Vous êtes sur la page 1sur 33

ADVERTENCIA: Algunas personas intentan construir esto con un optoacoplador con zerocrossing porque

"es mejor", ¿verdad? Algunos incluso se les dice en las tiendas de electrónica que es mejor usar un
optoacoplador de este tipo. INCORRECTO. Esto solo funcionará con un optoacoplador de disparo aleatorio:
NO encender el zerocross es el principio de este atenuador.

Cambiar una carga de CA con un Arduino es bastante simple: un relé mecánico o un relé de estado sólido con
un Triac aislado ópticamente. (Yo digo Arduino, pero si usas un microcontrolador 8051 o PIC16F877A,
también hay cosas para ti aquí).

Se vuelve un poco más complicado si uno quiere atenuar una lámpara de CA con un arduino: simplemente
limitando la corriente a través de, por ejemplo. un transistor no es realmente posible debido a la gran potencia
que el transistor necesitará para disiparse, lo que genera mucho calor y tampoco es eficiente desde el punto de
vista del uso de energía.

Corte de fase
Una forma de hacerlo es a través del control de fase con un Triac: el Triac está completamente abierto, pero
solo durante una parte de la onda AC sinusal. Esto se llama corte de borde de ataque.
Uno podría permitir que un Arduino simplemente abra el Triac durante varios microsegundos, pero eso tiene
el problema de que es impredecible durante qué parte de la onda sinusal se abre el triac y, por lo tanto, el nivel
de atenuación es impredecible. Uno necesita un punto de referencia en la onda sinusal.
Para eso es necesario un detector de cruce por cero. Este es un circuito que le dice al Arduino (u otro
microcontrolador) cuando la onda sinusal pasa por cero y, por lo tanto, da un punto definido en esa onda
sinusal.
Al abrir el Triac después de una demora de varios microsegundos a partir del cruce por cero, se obtiene un
nivel predecible de atenuación.

Modulación de salto de pulso


Otra forma de hacerlo es mediante la modulación por omisión de pulsos. Con PSM, uno o más ciclos
completos (sinuswaves) se transfieren a la carga y luego uno o más ciclos no se transfieren. Aunque es
efectivo, no es una buena manera de atenuar las luces, ya que existe la posibilidad de que parpadee. Aunque
podría ser tentador, en PSM siempre se debe permitir que se pase una onda sinusal completa a la carga, no la
mitad sinusal, ya que en ese caso la carga se alimentará de DC, lo cual no es bueno para la mayoría de las
cargas de CA. La diferencia entre el corte del borde de ataque y el PSM se encuentra principalmente en el
software: en ambos casos, uno necesitará un circuito que detecte el cruce por cero y que pueda controlar un
triac.

Un circuito que puede hacer esto es fácil de construir: el cruce por cero se deriva directamente de las líneas
rectas de CA rectificadas, por supuesto a través de un optoacoplador, y da una señal cada vez que la onda pasa
por cero. Debido a que la onda sinusoidal primero pasa por una rectificación de doble fase, la señal de cruce
por cero se da independientemente de si la onda sinusal sube de cero o de abajo a cero. Esta señal puede
utilizarse para activar una interrupción en el Arduino.

Atenuación PWM
La atenuación de PWM, como en los LED, no se realiza con frecuencia con cargas de CA por varios motivos.
Aunque es posible. Compruebe este instructivo para ver cómo.

No hace falta decir que tiene que haber una separación galvánica entre el lado de Arduino de las cosas y
cualquier cosa conectada a la red eléctrica. Para aquellos que no entienden la "separación galvánica" significa
"sin conexiones metálicas", por lo tanto ---> optoacopladores. PERO, si no entiendes la "separación
galvánica", quizás no debas construir esto.

El circuito que se muestra aquí hace precisamente eso. La tensión de 220 voltios de la red se realiza a través
de dos resistencias de 30k a un puente rectificador que da una señal rectificada de doble fase a un
optoacoplador 4N25. El LED en este optoacoplador, por lo tanto, baja con una frecuencia de 100Hz y la señal
en el colector de alta frecuencia con una frecuencia de 100Hz, en línea con la onda sinusoidal en la red
eléctrica. La señal del 4N25 se alimenta a un pin de interrupción en el Arduino (u otro microprocesador). La
rutina de interrupción alimenta una señal de una longitud específica a uno de los pinos de E / S. La señal de
pin de E / S regresa a nuestro circuito y abre el LED y un MOC3021, que se dispara brevemente el Opto-
Tiristor. El LED es una serie con el MOC3021. Tenga en cuenta que en la operación de atenuación esa luz no
será muy visible porque dura muy poco. Si se utiliza el interruptor triac para uso continuo, el LED se
iluminará claramente.

Tenga en cuenta que las lámparas incandescentes son normales para la atenuación. También funcionó con una
lámpara halógena, pero acortará la vida útil de la lámpara halógena. No funcionará con ninguna lámpara cfl, a
menos que se especifique específicamente que son adecuados para un regulador de intensidad. Lo mismo
ocurre con las lámparas LED.

¡NO UN! Es posible que el LED que se usa, la señal de la dirección simplemente no la corte y usted puede
terminar con una lámpara que simplemente parpadea en el lugar de ser regulada sin problemas. Reemplazar el
LED con un puente de alambre curará eso. El LED no es realmente necesario. aumentar la resistencia de 220
ohmios a 470 luego

DETENER: Este circuito está conectado a un voltaje de 110-220. Esto no es seguro. Desenchúfelo antes de
acercarse incluso a la PCB. La placa de refrigeración del Triac está unida a la red eléctrica. No lo toques
mientras esté en funcionamiento. Póngalo en un recinto / contenedor adecuado.

ESPERE: Permítame agregar una advertencia más fuerte aquí: este circuito es seguro si está construido e
implementado solo por personas que saben lo que están haciendo. Si no tiene idea o si está dudando de lo que
está haciendo, es probable que esté MUERTO. NO TOQUE CUANDO ESTÉ CONECTADO A LA RED

Materiales
No hay paso
4N25 € 0.25 o H11AA1 o IL250, IL251, IL252, LTV814 (ver texto en el siguiente paso)
Resistor 10k € 0.10
puente rectificador 400 voltios € 0.30
Resistencia de 2x 30 k 1/2 vatio (las resistencias probablemente disiparán 400mW máximo cada 0,30 €
1 conector 0,20 €
Zenerdiode de 5.1 voltios (opcional)

Conductor de la lámpara
LED (Nota: puede reemplazar el LED con un puente de alambre ya que el LED a veces puede hacer que la
lámpara parpadee en lugar de regularse suavemente)
MOC3021 Si eligió otro tipo, asegúrese de que NO tenga detección de cruce por cero, no puedo enfatizar esto
lo suficiente, NO lo use, por ejemplo. un MOC3042
Resistor 220 Ohm € 0,10 (en realidad usé un 330 Ohm y funcionó bien)
Resistor 470 Ohm-1k (terminé usando un 560 Ohm y funcionó bien)
TRIAC TIC206 € 1,20 o BR136 € 0,50
1 conector 0,20 €

Otro
Pieza de PCB 6x3cm
cableado eléctrico

Eso es alrededor de 3 € en partes

Encontrará dos imágenes para el PCB: mi primera, que dejo aquí para fines de documentación y una nueva
ligeramente modificada. La diferencia es que omití el zenerdiode ya que no es realmente necesario y le di al
LED su propia resistencia (1k): ya no está en serie con el optoacoplador, que ahora tiene una resistencia de
470 Ohm. Hice la PCB mediante transferencia directa de tóner y luego la grabé en un baño de ácido
clorhídrico / peróxido de hidrógeno. Hay muchos instructables que dicen cómo hacerlo. Puede utilizar el
diseño de impresión adjunto para hacer lo mismo. Rellenar la impresión es bastante sencillo. Usé pies IC para
los optoacopladores y el puente rectificador.
Descarga la impresión aquí.
Nota: Necesitas Fritzing para esto. Para la transferencia directa de tóner, el lado impreso del archivo pdf
impreso va directamente contra la capa de cobre para la transferencia. Una vez que se transfiere, mirarás la
tinta desde el otro lado y verás el texto normal nuevamente. Hice pequeñas alteraciones en el PCB: eliminé el
zenerdiode y el LED ya no está en serie con el optoacoplador.

Utilicé un TIC206. Eso puede entregar 4 amperios. Tenga en cuenta que las pistas de cobre de la PCB no
podrán soportar 4 amperios. Para cualquier carga seria, suelde un trozo de cable de instalación de cobre en las
pistas que van del TRIAC a los conectores y en la pista entre los dos conectores.

En caso de que no esté claro cuáles son las entradas: de arriba a abajo en la segunda imagen:
+ 5Volts
Señal de interrupción (va a D2 en arduino)
Señal triac (proveniente de D3 en Arduino)
Suelo

NOTA:
Si tiene un optoacoplador H11AA1 o IL 250, 251 o 252, no necesita el puente rectificador. Estos tienen dos
diodos antiparellel y por lo tanto pueden manejar CA. Es compatible con pin con el 4N25, simplemente
introdúzcalo y suelde 2 puentes entre R5 y + y R7 y -. El LTV814 no es compatible.
El circuito presentado es adecuado para cargas resistivas puras, como las lámparas incandescentes.
Si desea usarlo para cargas inductivas, entonces es necesario un circuito de amortiguación. La figura muestra
las modificaciones para su uso con cargas inductivas. Eso sí, esto no es algo que intenté, ya que solo quería
atenuar las lámparas, pero se basa en ejemplos y teorías disponibles en Internet. Tendrías que adaptar el PCB
proporcionado.
La figura superior muestra el circuito tal como está, para atenuar una lámpara. Es en toda su simplicidad solo
una resistencia para activar la puerta a través del diac en el optoacoplador. El valor de 1k puede cambiarse
como se explicó en el texto anterior.
La figura inferior da un circuito omnipresente para uso en cargas inductivas.

Se compone de una resistencia adicional y un condensador. La corriente de la compuerta es inferior a 15 mA.


Si está utilizando un triac menos sensible para controlar la carga inductiva, reduzca la resistencia de 2.4kΩ a
1.2kΩ, proporcionando más corriente para impulsar el triac y aumente el condensador a 200nF. Este circuito
de amortiguación está ahí para proteger el triac del alto voltaje generado por una carga inductiva. La
retroalimentación puede causar algún problema para la carga no inductiva. La pequeña fuga puede ser lo
suficientemente significativa como para encender una carga pequeña (por ejemplo, una lámpara).

Hay otros circuitos de amortiguamiento, por ej. Una resistencia y un condensador en serie directamente sobre
la carga.
Si no le importa la teoría, pero solo desea el software, vaya al siguiente paso

La forma de usar un atenuador / atenuador de CA es bastante simple una vez que entienda lo básico:

En AC, la potencia suministrada a la lámpara está directamente relacionada con la superficie total de la onda
sinusal, la lámpara se puede regular permitiendo solo que una parte predecible de esa onda sinusal fluya a
través de la lámpara.

Como tal, necesitamos un punto de referencia en ese seno desde donde calculamos cuándo se debe encender
la lámpara.

El punto de referencia más fácil de usar es el llamado 'cruce por cero': el momento en que la luz pasa por cero.
Después de cada cruce por cero, hay una mitad completa de la onda sinusal disponible para enviar a través de
la lámpara.

Entonces, lo que el software debe hacer es detectar el zerocross y luego esperar un tiempo determinado en esa
sinuswave para encender el TRIAC.

Hay 2 frecuencias de red principales

en el mundo: 50 Hz en Europa y la mayor parte de Asia y África y 60 Hz en América (y partes del Caribe).
Hay 2 voltajes principales en el mundo: 110-120V y 220-240V pero no son importantes para las matemáticas
aquí

Para facilitar su uso, tomaré la frecuencia de 50Hz como ejemplo:


50Hz es 50 ondas por segundo.
Cada sinuswave por lo tanto toma 1000 ms / 50 = 20 ms (milisegundos)
Como hay 2 sinuspeaks en una onda, eso significa que después de cada detección de cero hay un período de
10 ms que podemos regular.
Si encendemos la lámpara directamente al comienzo de ese período, la lámpara recibirá toda la potencia, si lo
hacemos al final de ese período de 10 ms, la lámpara no recibirá energía y si la hacemos a la mitad, la lámpara
recibirá la mitad de la potencia. .
Como estamos usando TRIAC, lo que el software debe hacer es esperar el punto cero en la sinuscurva, tomar
nota de eso y luego esperar un tiempo específico dentro de ese período de 10 ms para enviar un pulso al
TRIAC.
Si envía ese pulso a 5 ms, la lámpara solo se quemará a media potencia.

En el circuito, la detección de cero se realiza mediante el optoacoplador bifase y está disponible como la señal
X en la placa.
Hay básicamente 2 formas para que un microcontrolador detecte esa señal:
1-un 'sondeo' continuo del pasador de cruce por cero
2: usar una interrupción para indicar al programa que hubo un cruce por cero
La principal diferencia entre los dos es que en el 'sondeo' cada vez que la computadora pasa por su bucle
principal, necesita verificar el pin. Si su programa está ocupado haciendo muchas otras cosas, puede ser
demasiado tarde para verificar el pin de cruce cero, mientras que al usar una interrupción, no importa con qué
esté ocupado el programa. La interrupción es una especie de "tapping en el hombro" que dice "Oye mira,
surgió algo que debes atender AHORA".

Después de detectar el cruce por cero, el programa debe esperar un tiempo específico y luego encender el
TRIAC.
También aquí, esa espera se puede hacer de dos maneras diferentes.
1- emitiendo una orden de 'espera'
2-mediante el uso de una interrupción de temporizador

Nuevamente, ambos métodos tienen sus pro y sus contras. El comando 'esperar' ('retraso' en lenguaje
Arduino) literalmente deja que la computadora espere el tiempo requerido y no puede hacer nada más
mientras tanto. si la lámpara se está quemando a baja potencia al dejar que la computadora espere, digamos 9
ms, eso significa que a cada 10 ms se le pide a la computadora que espere 9 ms: ergo estará inactiva el 90%
del tiempo. Eso está bien si su controlador solo se usa para controlar la lámpara, pero si necesita hacer otras
cosas, queda poco tiempo.
Usando una interrupción de temporizador resuelve eso. Básicamente, lo que hace es que el programa le dice al
temporizador: "Oye, acabo de escuchar que tenemos un cruce por cero, tengo que hacer otra cosa, pero solo
esperas 4,5 ms y luego enciendes el Triac" Así que el programa continúa. de manera alegre y 4,5 ms (como
ejemplo) después de que se notificara que había un cruce de 0, el temporizador enciende el TRIAC.

Sondeo: (note que este es un ejemplo aproximado para ilustrar el sondeo, obviamente necesita alguna mejora)

int AC_LOAD=3; // We use pin 3 to ignite the TRIAC

int state; // integer to store the status of the zero crossing

void setup()

pinMode(AC_LOAD, OUTPUT);// Set AC Load pin as output

}
void loop()

state=digitalRead(AC_LOAD);

if (state=1) {

delayMicroseconds(5000); // =5 ms=half power

digitalWrite(AC_LOAD, HIGH); // triac firing

Impulsado por interrupción: Para usar una interrupción, primero debemos configurar eso.
En el Arduino que es como sigue:

void setup()

pinMode(AC_LOAD, OUTPUT);// Set AC Load pin as output

attachInterrupt(0, zero_crosss_int, RISING); // Choose the zero cross interru


pt # from the table above

Lo que esto dice es que la interrupción está asociada a la interrupción 0, va a una función llamada
"zero_crosss_int" y reacciona a un flanco ascendente en el pin.

En la función Zero_cross_int a la que el programa salta después de la interrupción, determinamos el tiempo


que debemos esperar antes de disparar el TRIAC. También añadiremos un poco de funcionalidad. No solo
queremos un conjunto de niveles en el que la lámpara se encienda, vamos a agregar algunas funciones para
regular el nivel de luz en pasos.
Para eso he elegido la cantidad totalmente arbitraria de 128 pasos. Eso significa que cada paso es 10ms / 128
= 10000us / 128 = 75us (de hecho es 78, pero llego a eso más adelante). El tiempo total de atenuación
entonces se calcula de 75x (1 a 128). El número entre 1-128, que determina nuestro nivel de atenuación, lo
asignamos a la variable entero 'atenuación'

void zero_crosss_int() // function to be fired at the zero crossing to dim the


light

int dimtime = (75*dimming); // For 60Hz =>65

delayMicroseconds(dimtime); // Off cycle


digitalWrite(AC_LOAD, HIGH); // triac firing

delayMicroseconds(10); // triac On propagation delay (for 60Hz use 8.3


3)

digitalWrite(AC_LOAD, LOW); // triac Off

Lo que sucede aquí es que el programa primero calcula el tiempo de inactividad (= tiempo para esperar antes
de que se dispare el triac)
Luego espera esa cantidad de tiempo, posteriormente espera esa cantidad de tiempo y dispara el Triac. El
Triac se apagará nuevamente en el siguiente cruce por cero, pero ya vamos a escribir un punto bajo en el pin
TRIAC para evitar un encendido accidental en el próximo ciclo. Sin embargo, debemos esperar un poco para
saber con seguridad si el TRIAC está encendido, por lo que esperamos 10us. Ahora (10000-10) / 128 todavía
es 78, pero encontré que 75 funciona bien. Siéntase libre de usar 78 aunque.

Lo único que queda por hacer en el programa principal es establecer el nivel en el que queremos que la
lámpara se encienda:

void loop() {

for (int i=5; i <= 128; i++){

dimming=i;

delay(10);

Lo que sucede aquí es un simple bucle que regula la lámpara en 128 pasos. He elegido no comenzar en 1 sino
en 5 porque a ese nivel podría haber algunos problemas de tiempo que podrían hacer que la lámpara parpadee.

El programa anterior es solo un ejemplo de cómo controlar la lámpara. Obviamente, desea agregar alguna otra
funcionalidad en lugar de simplemente hacer que una lámpara suba y baje de brillo.

Utilizando un temporizador:
Si desea que su programa sea eficiente en el tiempo, necesitará usar una interrupción para la detección de
cruce por cero y un temporizador para determinar el tiempo de espera.
Aproximadamente un programa se vería de la siguiente manera:

Inicializar
Configure las diversas constantes y variables que necesita e incluya las bibliotecas utilizadas (como la
biblioteca de TimerOne)

Preparar
Poner las patillas y las 2 interrupciones.
La interrupción de cruce de cero apunta a una función y también lo hace la interrupción del temporizador

Funcionalidad Cero-Cruz
Establecer un valor booleano que indica si se ha producido un cruce de cero
Función de temporizador
Si volvemos a regular el brillo en 128 pasos, entonces la función del temporizador está configurada para ser
llamada siempre que haya pasado el tiempo de un paso (por ejemplo, 75us) y luego verifica si el número de
pasos aprobados es igual al número de pasos establecido. Si ese es el caso, el triac está encendido

Step 4: Arduino Controlled Light Dimmer: the


Software

Como se discutió en la página teórica anterior, el software es bastante fácil.


Si desea desarrollar su propio software, todo lo que necesita hacer es:
Espera al zerocross
Espere un tiempo específico entre 0 y 9090 microsegundos (9090 = 10.000-10)
enciende tu TRIAC
Espere aproximadamente 10 us (ese es el tiempo que necesita para asegurarse de que el TRIAC esté
encendido)
desactiva el TRIAC del año (de hecho, solo eliminas la señal de activación del TRIAC, el TRIAC
permanecerá encendido hasta el próximo zerocross)

Solo esbozo brevemente el flujo del programa que utilicé:

(asegúrese de leer la 'NOTA' a continuación)

La señal cero de X genera una interrupción.


A 50Hz esa interrupción es cada 10 ms o 10.000 uS
A 60 Hz, la interrupción es cada 8.333 ms o 8333 uS.
La rutina de interrupción luego enciende el Triac después de un tiempo específico. Ese tiempo se establece en
el ciclo principal del programa.
A medida que el programa varía la atenuación de Completo a Desactivado en 128 pasos (eso es solo una
elección que se hizo, podría ser de 100 pasos también), a 50 Hz necesitamos que los pasos sean de 75 uS y a
60 Hz que deben ser 65 nosotros

Funciona de la siguiente manera:


La función de interrupción "zero_crosss_int" se llama cada vez que se detecta un cruce por cero, que es de
100 veces por segundo. La única función es establecer el tiempo en que el Triac se enciende al valor de la
variable 'atenuación'
En el bucle principal del programa, se establece el valor real de esa variable.

/*

AC Voltage dimmer with Zero cross detection

Author: Charith Fernanado Adapted by DIY_bloke

License: Creative Commons Attribution Share-Alike 3.0 License.

Attach the Zero cross pin of the module to Arduino External Interrupt pin

Select the correct Interrupt # from the below table

(the Pin numbers are digital pins, NOT physical pins:

digital pin 2 [INT0]=physical pin 4 and digital pin 3 [INT1]= physical pin 5)

check: <a href="http://arduino.cc/en/Reference/attachInterrupt">interrupts</a>

Pin | Interrrupt # | Arduino Platform

---------------------------------------

2 | 0 | All -But it is INT1 on the Leonardo

3 | 1 | All -But it is INT0 on the Leonardo

18 | 5 | Arduino Mega Only

19 | 4 | Arduino Mega Only

20 | 3 | Arduino Mega Only

21 | 2 | Arduino Mega Only

0 | 0 | Leonardo

1 | 3 | Leonardo

7 | 4 | Leonardo
The Arduino Due has no standard interrupt pins as an iterrupt can be attached to
almosty any pin.

In the program pin 2 is chosen

*/

int AC_LOAD = 3; // Output to Opto Triac pin

int dimming = 128; // Dimming level (0-128) 0 = ON, 128 = OFF

void setup()

pinMode(AC_LOAD, OUTPUT);// Set AC Load pin as output

attachInterrupt(0, zero_crosss_int, RISING); // Choose the zero cross interru


pt # from the table above

//the interrupt function must take no parameters and return nothing

void zero_crosss_int() //function to be fired at the zero crossing to dim the l


ight

// Firing angle calculation : 1 full 50Hz wave =1/50=20ms

// Every zerocrossing thus: (50Hz)-> 10ms (1/2 Cycle)

// For 60Hz => 8.33ms (10.000/120)

// 10ms=10000us

// (10000us - 10us) / 128 = 75 (Approx) For 60Hz =>65

int dimtime = (75*dimming); // For 60Hz =>65

delayMicroseconds(dimtime); // Wait till firing the TRIAC

digitalWrite(AC_LOAD, HIGH); // Fire the TRIAC

delayMicroseconds(10); // triac On propogation delay


// (for 60Hz use 8.33) Some Triacs need a long
er period

digitalWrite(AC_LOAD, LOW); // No longer trigger the TRIAC (the next zero c


rossing will swith it off) TRIAC

void loop() {

for (int i=5; i <= 128; i++){

dimming=i;

delay(10);

Acerca del software: en teoría, en el bucle se podría permitir que la variable 'i' comience desde '0'. Sin
embargo, dado que la sincronización en la interrupción es un poco de una aproximación, usar '0' (totalmente
activado) podría arruinar la sincronización un poco. lo mismo ocurre con 128 (Full off), aunque eso parece ser
menos crítico. Si '5' o quizás '1' es el límite para su configuración, es cuestión de intentarlo, su rango puede ir
desde, por ejemplo, 2 a 126 en lugar de 0-128. Si alguien tiene una forma más precisa de configurar el tiempo
en la interrupción, me encantaría escucharlo.
Por supuesto no es necesario trabajar con interrupciones. También es posible seguir sondeando el pin de cruce
por cero para ir a 0.

Aunque el software funciona con una interrupción para determinar el momento de cruce de cero, aún no es tan
eficiente porque el tiempo (tiempo de inactividad) que debemos esperar después del cruce de cero antes de
que se dispare el triac se gasta literalmente "esperando" en el cruce de cero función de interrupción.

Sería más eficiente programar una interrupción del temporizador para que se dispare en el momento adecuado
para que, mientras tanto, el arduino pueda hacer otra cosa. Tal programa se puede encontrar en el paso 6

NOTA

Permítanme reiterar la declaración anterior: este programa es una demostración de cómo puede controlar el
atenuador. No es un programa eficiente, ya que pasa la mayor parte del tiempo esperando. Por lo tanto, NO es
el más adecuado para combinar con otras tareas del procesador. Si necesita un programa más eficiente, use un
temporizador en lugar de un retraso

Paso 5: Arduino Controlado Lightdimmer: el Software II


Encontré otra pieza de software que permite controlar la lámpara a través del puerto serie. Se dispara en el
borde descendente de la señal de cruce por cero, por lo que el tiempo es un poco diferente.

Todavía no lo he probado, pero veo razones por las que no debería funcionar: por lo que puedo ver, no recibe
el número escrito en el puerto serie, pero recibe el valor ASCII de cada dígito que se escribe, por lo que 0 'se
verá como 48
int AC_pin = 3;//Pin to OptoTriac

byte dim = 0; //Initial brightness level from 0 to 255, change as you like!

void setup() {

Serial.begin(9600);

pinMode(AC_pin, OUTPUT);

attachInterrupt(0, light, FALLING);//When arduino Pin 2 is FALLING from HIGH t


o LOW, run light procedure!

void light() {

if (Serial.available()) {

dim = Serial.read();

if (dim < 1) {

//Turn TRIAC completely OFF if dim is 0

digitalWrite(AC_pin, LOW);

if (dim > 254) { //Turn TRIAC completely ON if dim is 255

digitalWrite(AC_pin, HIGH);

if (dim > 0 && dim < 255) {

//Dimming part, if dim is not 0 and not 255

delayMicroseconds(34*(255-dim));

digitalWrite(AC_pin, HIGH);

delayMicroseconds(500);

digitalWrite(AC_pin, LOW);
}

void loop() {

Solo una nota: El software anterior no es mío. Creo que es mejor mantener la verificación del puerto serie
fuera de la interrupción. Además, el retraso de 500uS antes de que se apague el TRIAC es quizás un poco
largo.

El código siguiente utiliza la función del temporizador en lugar de un retraso y se ha confirmado que funciona
en el Leonardo también
/*AC Light Control

Updated by Robert Twomey

Changed zero-crossing detection to look for RISING edge rather


than falling. (originally it was only chopping the negative half
of the AC wave form).

Also changed the dim_check() to turn on the Triac, leaving it on


until the zero_cross_detect() turn's it off.

Adapted from sketch by Ryan McLaughlin


http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1230333861/30

*/
#include <TimerOne.h> // Avaiable from http://www.arduino.cc/playground/Code/Timer1
volatile int i=0; // Variable to use as a counter volatile as it is in an interrupt
volatile boolean zero_cross=0; // Boolean to store a "switch" to tell us if we have crossed zero
int AC_pin = 11; // Output to Opto Triac
int dim = 0; // Dimming level (0-128) 0 = on, 128 = 0ff
int inc=1; // counting up or down, 1=up, -1=down

int freqStep = 75; // This is the delay-per-brightness step in microseconds.


// For 60 Hz it should be 65
// It is calculated based on the frequency of your voltage supply (50Hz or 60Hz)
// and the number of brightness steps you want.
//
// Realize that there are 2 zerocrossing per cycle. This means
// zero crossing happens at 120Hz for a 60Hz supply or 100Hz for a 50Hz supply.

// To calculate freqStep divide the length of one full half-wave of the power
// cycle (in microseconds) by the number of brightness steps.
//
// (120 Hz=8333uS) / 128 brightness steps = 65 uS / brightness step
// (100Hz=10000uS) / 128 steps = 75uS/step

void setup() { // Begin setup


pinMode(AC_pin, OUTPUT); // Set the Triac pin as output
attachInterrupt(0, zero_cross_detect, RISING); // Attach an Interupt to Pin 2 (interupt 0) for Zero Cross
Detection
Timer1.initialize(freqStep); // Initialize TimerOne library for the freq we need
Timer1.attachInterrupt(dim_check, freqStep);
// Use the TimerOne Library to attach an interrupt
// to the function we use to check to see if it is
// the right time to fire the triac. This function
// will now run every freqStep in microseconds.
}

void zero_cross_detect() {
zero_cross = true; // set the boolean to true to tell our dimming function that a zero cross has
occured
i=0;
digitalWrite(AC_pin, LOW); // turn off TRIAC (and AC)
}

// Turn on the TRIAC at the appropriate time


void dim_check() {
if(zero_cross == true) {
if(i>=dim) {
digitalWrite(AC_pin, HIGH); // turn on light
i=0; // reset time step counter
zero_cross = false; //reset zero cross detection
}
else {
i++; // increment time step counter
}
}
}

void loop() {
dim+=inc;
if((dim>=128) || (dim<=0))
inc*=-1;
delay(18);
}
Step 7: MQTT Your Dimmer

Es posible usar MQTT para controlar su atenuador, siempre que tenga una conexión WLAN. En este ejemplo
estoy usando un Arduino UNO con Ethernetshield.
El tema es "home / br / sb" con una carga útil de 0-100 para establecer el nivel de atenuación

#include <Ethernet.h> // Ethernet.h

#include <PubSubClient.h> // PubSubClient.h

#include <TimerOne.h> //TimerOne.h

#define CLIENT_ID "Dimmer"

#define PUBLISH_DELAY 3000

String ip = "";

bool startsend = HIGH;

uint8_t mac[6] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x07};

volatile int i=0; // Variable to use as a counter volatile as it i


s in an interrupt

volatile boolean zero_cross=0; // Boolean to store a "switch" to tell us if we


have crossed zero

int AC_pin1 = 4;// Output to Opto Triac

int dim1 = 0;// Dimming level (0-100) 0 = on, 100 = 0ff


int inc=1; // counting up or down, 1=up, -1=down

int freqStep = 100;

EthernetClient ethClient;

PubSubClient mqttClient;

long previousMillis;

void zero_cross_detect() {

zero_cross = true; // set the boolean to true to tell our dimmin


g function that a zero cross has occured

i=0;

digitalWrite(AC_pin1, LOW); // turn off TRIAC (and AC)

// Turn on the TRIAC at the appropriate time

void dim_check() {

if(zero_cross == true) {

if(i>=dim1) {

digitalWrite(AC_pin1, HIGH); // turn on light

i=0; // reset time step counter

zero_cross = false; //reset zero cross detection

else {

i++; // increment time step counter

void setup() {
attachInterrupt(0, zero_cross_detect, RISING); // Attach an Interupt to Pin
2 (interupt 0) for Zero Cross Detection

Timer1.initialize(freqStep); // Initialize TimerOne libra


ry for the freq we need

Timer1.attachInterrupt(dim_check, freqStep);

pinMode(4, OUTPUT);

// setup serial communication

Serial.begin(9600);

while (!Serial) {};

Serial.println(F("dimmer"));

Serial.println();

// setup ethernet communication using DHCP

if (Ethernet.begin(mac) == 0) {

Serial.println(F("Unable to configure Ethernet using DHCP"));

for (;;);

Serial.println(F("Ethernet configured via DHCP"));

Serial.print("IP address: ");

Serial.println(Ethernet.localIP());

Serial.println();

ip = String (Ethernet.localIP()[0]);

ip = ip + ".";

ip = ip + String (Ethernet.localIP()[1]);
ip = ip + ".";

ip = ip + String (Ethernet.localIP()[2]);

ip = ip + ".";

ip = ip + String (Ethernet.localIP()[3]);

//Serial.println(ip);

// setup mqtt client

mqttClient.setClient(ethClient);

mqttClient.setServer( "192.168.1.103", 1883); // <= put here the address of YO


UR MQTT server

//Serial.println(F("MQTT client configured"));

mqttClient.setCallback(callback);

Serial.println();

Serial.println(F("Ready to send data"));

previousMillis = millis();

mqttClient.publish("home/br/nb/ip", ip.c_str());

void loop() {

// it's time to send new data?

if (millis() - previousMillis > PUBLISH_DELAY) {

sendData();

previousMillis = millis();

mqttClient.loop();

Serial.print("dim1 = ");

Serial.println(dim1);

}
void sendData() {

char msgBuffer[20];

if (mqttClient.connect(CLIENT_ID)) {

mqttClient.subscribe("home/br/sb");

if (startsend) {

mqttClient.publish("home/br/nb/ip", ip.c_str());

startsend = LOW;

void callback(char* topic, byte* payload, unsigned int length) {

char msgBuffer[20];

payload[length] = '\0'; // terminate string with '0'

String strPayload = String((char*)payload); // convert to string

Serial.print("strPayload = ");

Serial.println(strPayload); //can use this if using longer southbound topics

Serial.print("Message arrived [");

Serial.print(topic);

Serial.print("] ");//MQTT_BROKER

for (int i = 0; i < length; i++) {

Serial.print((char)payload[i]);

Serial.println();

Serial.println(payload[0]);

dim1=strPayload.toInt();
}

Paso 8: Software para establecer el nivel usando los botones arriba y abajo
Debajo de un código para establecer el nivel de luz con los botones arriba y abajo. Utiliza un temporizador
que comprueba el tiempo necesario para activar el TRIAC, en lugar de esperar en un bucle de retardo

/*

AC Light Control

Uses up and down buttons to set levels

makes use of a timer interrupt to set the level of dimming

*/

#include <TimerOne.h> // Avaiable from http://www.arduino.cc/playgroun


d/Code/Timer1

volatile int i=0; // Variable to use as a counter of dimming steps


. It is volatile since it is passed between interrupts

volatile boolean zero_cross=0; // Flag to indicate we have crossed zero

int AC_pin = 3; // Output to Opto Triac

int buton1 = 4; // first button at pin 4

int buton2 = 5; // second button at pin 5

int dim2 = 0; // led control

int dim = 128; // Dimming level (0-128) 0 = on, 128 = 0ff

int pas = 8; // step for count;

int freqStep = 75; // This is the delay-per-brightness step in micr


oseconds. It allows for 128 steps

// If using 60 Hz grid frequency set this to 65

void setup() { // Begin setup

Serial.begin(9600);

pinMode(buton1, INPUT); // set buton1 pin as input


pinMode(buton2, INPUT); // set buton1 pin as input

pinMode(AC_pin, OUTPUT); // Set the Triac pin as outp


ut

attachInterrupt(0, zero_cross_detect, RISING); // Attach an Interupt to Pin


2 (interupt 0) for Zero Cross Detection

Timer1.initialize(freqStep); // Initialize TimerOne libra


ry for the freq we need

Timer1.attachInterrupt(dim_check, freqStep); // Go to dim_check procedure


every 75 uS (50Hz) or 65 uS (60Hz)

// Use the TimerOne Library to attach an interrupt

void zero_cross_detect() {

zero_cross = true; // set flag for dim_check function that a zer


o cross has occured

i=0; // stepcounter to 0.... as we start a new cyc


le

digitalWrite(AC_pin, LOW);

// Turn on the TRIAC at the appropriate time

// We arrive here every 75 (65) uS

// First check if a flag has been set

// Then check if the counter 'i' has reached the dimming level

// if so.... switch on the TRIAC and reset the counter

void dim_check() {

if(zero_cross == true) {

if(i>=dim) {

digitalWrite(AC_pin, HIGH); // turn on light


i=0; // reset time step counter

zero_cross=false; // reset zero cross detection flag

else {

i++; // increment time step counter

void loop() {

digitalWrite(buton1, HIGH);

digitalWrite(buton2, HIGH);

if (digitalRead(buton1) == LOW)

if (dim<127)

dim = dim + pas;

if (dim>127)

dim=128;

if (digitalRead(buton2) == LOW)

if (dim>5)

{
dim = dim - pas;

if (dim<0)

dim=0;

while (digitalRead(buton1) == LOW) { }

delay(10); // waiting little bit...

while (digitalRead(buton2) == LOW) { }

delay(10); // waiting little bit...

dim2 = 255-2*dim;

if (dim2<0)

dim2 = 0;

Serial.print("dim=");

Serial.print(dim);

Serial.print(" dim2=");

Serial.print(dim2);

Serial.print(" dim1=");

Serial.print(2*dim);

Serial.print('\n');

delay (100);
}

Step 9: More Interrupt Driven Software

// AC dimmer

// The hardware timer runs at 16MHz. Using a

// divide by 256 on the counter each count is

// 16 microseconds. 1/2 wave of a 60Hz AC signal

// is about 520 counts (8,333 miliseconds).

// 1/2 wave of a 50 Hz signal is 625 counts

/*

Pin | Interrrupt # | Arduino Platform

---------------------------------------

2 | 0 | All -But it is INT1 on the Leonardo

3 | 1 | All -But it is INT0 on the Leonardo

18 | 5 | Arduino Mega Only

19 | 4 | Arduino Mega Only

20 | 3 | Arduino Mega Only

21 | 2 | Arduino Mega Only

0 | 0 | Leonardo

1 | 3 | Leonardo

7 | 4 | Leonardo

The Arduino Due has no standard interrupt pins as an iterrupt can be attached to almosty any pin.

In the program pin 2 is chosen

*/
#include <avr/io.h>

#include <avr/interrupt.h>

#define ZEROCROSS 2 //zero cross detect

#define TRIAC 3 //triac gate

#define PULSE 4 //trigger pulse width (counts)

int dim=483;

void setup(){

// set up pins

pinMode(ZEROCROSS, INPUT); // zero cross detect

digitalWrite(ZEROCROSS, HIGH); // enable pull-up resistor

pinMode(TRIAC, OUTPUT); // triac gate control

// set up Timer1

//(see ATMEGA 328 data sheet pg 134

OCR1A = 100; // initialize the comparator compared with TCNT1

TIMSK1 = 0x03; // enable comparator A and overflow interrupts

// 0x03=0b11 =OCIE1A and TOIE1

// OCIE1A Timer/Counter1 Output Compare A Match


interrupt enable. Interrupt set

// TOIE1 Timer/Counter1 Overflow interrupt is enabled.

TCCR1A = 0x00; // timer control registers set for

TCCR1B = 0x00; // normal operation, timer disabled

// set up zero crossing interrupt


attachInterrupt(0,zeroCrossingInterrupt, RISING);

//Interrupt Service Routines

void zeroCrossingInterrupt(){ //zero cross detect

TCCR1B=0x04; //start timer with divide by 256 input 16us tics 4=0b100 =CS12:1, CS11:0, CS10:0
table 16.5

TCNT1 = 0; //reset timer - count from zero

ISR(TIMER1_COMPA_vect){ // comparator match. overflow werd bereikt als de


waarde van 'i' wordt gematched

digitalWrite(TRIAC,HIGH); // Triac will be set high

TCNT1 = 65536-PULSE; // trigger pulse width telt 4 periodes van 16uS

ISR(TIMER1_OVF_vect){ // timer1 overflow wordt bereikt na 4x16us

digitalWrite(TRIAC,LOW); // turn off triac gate

TCCR1B = 0x00; // disable timer stopd unintended triggers

void loop(){ // sample code to exercise the circuit

dim--;

OCR1A = i; //set the compare register brightness desired. delay to on value

if (dim<65){dim=483;} // 1 msec tot 7.726 msec

delay(15);

}
3 canales
Este circuito también se puede utilizar para un mezclador RGB, aunque necesita dos circuitos TRIAC
adicionales. Puede usar este circuito + PCB en modo doble, pero asegúrese de usar un opto-coupler de ciclo
aleatorio como el MOC3021. No utilice un optoacoplador de zerocross como el MOC3041.
Ahora hice un Ibble de 3 canales.

Por supuesto, el circuito de cruce por cero solo se necesita una vez.
Quizás esto todavía sea algo para la tradición (llámelo anticuado): luces de árbol de Navidad que funcionan
directamente con 220 (o 110) voltios. Cuelgue 3 cadenas de lámparas de diferentes colores en el árbol y
regúlelas con este circuito expandido con dos circuitos TRIAC

Frecuencia
Dependiendo de la frecuencia de la red (ya sea 50 o 60), los valores de pasos diferentes deben configurarse
manualmente. Sin embargo, es posible dejar que el software determine la frecuencia en una rutina de
configuración, por ejemplo. midiendo el tiempo entre dos cruces por cero o cuente el número de
zerocriossings dentro de un tiempo establecido.

Obviamente, uno puede usar la serie de microcontroladores 8051 también para controlar el atenuador.
Como ya no tengo un sistema de desarrollo 8051, no puedo probar ningún código, pero si desea desarrollarlo
para un 8051, el siguiente ejemplo puede ser de ayuda:

//

//Controlling AC with a 8051

//Untested Code

//Compiles with MicroC Pro for 8051

int dimming;

int x;

int i;

void ex0_isr(void) iv IVT_ADDR_EX0 ilevel 0 ics ICS_AUTO {

/*===================================================*/

int dimtime=(75*dimming);

//delay_us(dimtime);

P0=0xFF; // sets entire PORT 0 high, can also use e.g. P0_1 =1 ;

delay_us(10); //propagationdelay

P0=0x00;
}

void delay(int maal){

for (x=1; x< maal; x++) {

delay_us(75); // 65 for 60Hz

/*===================================================*/

void main()

/*------------------------

Configure INT0 (external interrupt 0) to generate

an interrupt on the falling-edge of /INT0 (P3.2).

Enable the EX0 interrupt and then enable the

global interrupt flag.

------------------------------------------------*/

IT0_bit =1; // Configure interrupt 0 for falling edge on /INT0 (P3.2)

EX0_bit = 1; // Enable EX0 Interrupt

EA_bit = 1; // Enable Global Interrupt Flag

P0 = 0x00; //all pin of PORT0 declared as output

while (1)

for(i=5;i<128;i++){

dimming=i;

delay(10);//arbitrary delay between steps


}

,.,.,
Paso 15: Oscurecimiento: un poco de teoría
Solo como fondo de este instructable: hay varios tipos de atenuadores. Lo que se presenta aquí es un
regulador TRIAC de borde delantero (también conocido como "fase delantera") con control de fase (también
conocido como "corte de fase").

Dimmers de vanguardia
En este tipo, el atenuador en realidad corta partes del comienzo de la onda sinusoidal. Este es el tipo de
regulador más utilizado, ya que es adecuado para TRIACs. Después de todo, un Triac es fácil de encender y
se apagará solo una vez que haya un cruce por cero porque la corriente cae por debajo de la corriente de
retención de la puerta

Atenuadores del borde de salida


También conocidos como reguladores de 'control de fase inversa'. Un regulador de borde de salida es un
circuito considerablemente más complejo. Los circuitos simples que son comunes con los tipos de borde de
vanguardia ya no se pueden usar, porque la mayoría de los TRIAC no se pueden desactivar. Los TRIAC de
desactivación de la puerta (GTO) existen, pero son mucho más caros y menos comunes en los tamaños
relativamente pequeños necesarios para la iluminación. Para poder implementar un atenuador de borde
trasero, el dispositivo de conmutación debe encenderse a medida que la forma de onda de CA pasa a través de
cero, utilizando un circuito llamado detector de cruce por cero. Después de un tiempo predeterminado
establecido por el control, el dispositivo de conmutación se apaga y la carga no utiliza la parte restante de la
forma de onda.

Los atenuadores de borde de salida generalmente usan un MOSFET, ya que estos casi no requieren corriente
de control y son resistentes y confiables. También son relativamente baratos y están disponibles a niveles de
voltaje adecuados para el funcionamiento de la red. Otra opción es usar un IGBT (transistor bipolar de puerta
aislada), que combina las ventajas de MOSFET y el transistor bipolar. Estos son generalmente más caros que
los MOSFETs. Nuevamente, la forma de onda es ideal, y es obvio, a partir de la forma de onda real que se
muestra en la Figura 9, que existe una desviación significativa, especialmente a plena potencia. Esto se debe a
que parte del voltaje aplicado siempre se perderá debido a que la electrónica compleja requiere algo de voltaje
para funcionar.

La mayoría de los atenuadores de borde trasero tienen otra función útil, al menos cuando se usan con
lámparas incandescentes. El circuito está diseñado para proporcionar un 'arranque suave', aumentando la
tensión a la lámpara de forma relativamente lenta. Con las lámparas incandescentes, esto casi elimina el
'choque térmico', ese breve período de encendido en el que la lámpara consume aproximadamente 10 veces la
corriente de funcionamiento normal. El choque térmico es el responsable de la mayoría de los fallos iniciales
de la lámpara: es raro que alguna lámpara incandescente falle mientras está encendida. La falla es casi
siempre en el momento en que se enciende el interruptor. Al incluir la característica de arranque suave, la vida
útil de la lámpara aumenta.

Step 16: Zero Crossing: a Bit of Theory


Aunque ya describí el zerocross, pasaré algunas palabras más en él.
Con el circuito 'puente y optoacoplador' que usé en este proyecto, el principio es muy claro: una tensión de
CA de la red pasa a través de 2 resistencias de 33 ky se rectifica con el puente de diodos.
Esta rectificación da como resultado un voltaje de CC pulsante que mantiene el optoacoplador abierto,
manteniendo la señal de zerocross BAJA hasta que el voltaje cae a 'cero' en qué punto el optoacoplador ya no
estará en conducción y la señal del zerocross se eleva, hasta que el voltaje aumenta. de nuevo, lo suficiente
como para enviar de nuevo el optoacoplador a la conducción, lo que hace que el pin de zerocross salga BAJO.
La 'calidad' de ese pulso de zerocross depende, por supuesto, de una serie de factores, pero principalmente de
la velocidad del optoacoplador, el valor de la resistencia de colector, pero no el valor de las dos resistencias en
la línea de red.

Si ese valor es demasiado bajo, su optoacoplador se quemará, pero si es demasiado alto, la tensión a la que
todavía hay suficiente corriente que atraviesa el optoacoplador para mantener la conducción aumenta cada vez
más. Eso significa que si el valor de la resistencia es demasiado alto, la conmutación del optoacoplador
ocurrirá más arriba en el flanco ascendente y descendente de la onda sin, lo que dará como resultado una señal
de zerocross amplia, que comienza mucho antes del zerocross real hasta mucho después del zerocross.
Ergo: El valor de la resistencia debe ser lo más bajo posible. Sin embargo, en la práctica, encontré que 2x 33k
es un buen valor, lo que lleva a un pulso que comienza a 200uS antes del zerocross real. Eso es muy
aceptable. La corriente a través del 4N25 es de aproximadamente 3.33 mA. Seguramente podríamos subir eso
un poco, pero no es necesario. Con estos valores, el uso ocioso de este circuito es de aproximadamente 0,7
vatios.

Lo mismo ocurre con el circuito con el H11AA1. La ventaja del H11AA1 es que no se necesita un puente de
diodos, ya que tiene dos diodos antiparalelos. Lo mismo ocurre con la serie IL250 o la LTV814.
Uno puede alcanzar el mismo efecto con dos optoacopladores regulares como el 4N25, como muestra la
figura o con un optoacoplador dual.

También proporcioné un circuito en el que se puede regular el ancho del pulso de zerocross.
Como se dijo antes, el ancho de la señal de Zerocrossing determina cuán lejos antes de que se genere el
zerocrossing real de la interrupción. Idealmente, si sabe qué tan amplia es su señal de zerocross, podría
tenerlo en cuenta en el software. Supongamos que su señal es 600uS de ancho y supongamos que se trata de
un tiempo dividido en partes iguales. Entonces sabrá que su interrupción se genera unos 300uS antes del
Zerocrossing real. Puede esperar ese período después de cada interrupción para obtener un manejo más
preciso del zerocross

Vous aimerez peut-être aussi