|
Fig8. Circuito de Control con TRIAC
|
Desde un punto de referencia en el bloque DC, la señal para indicar el cruce por cero, es generado por la polarización de los diodos que posee el opto-acoplador U1 en ambos ciclos, donde la corriente AC que circula se reduce al orden de los miliamperios debido a las resistencias R1 y R2. Cuando la onda sinusoidal pasa por el punto cero, ninguno de los diodos de U1 esta polarizado y por lo tanto el colector y emisor del transistor quedara abierto, conforme la onda pase el punto cero y vaya incrementándose, el voltaje aplicado a los diodos se incrementara hasta que uno de ellos se polarice haciendo que el transistor se cierre; Considerando esto podemos deducir que el nivel logico en el colector de U1, sera 1 solo cuando la señal AC cruce por cero y el resto de tiempo permanecerá con valor 0, esto se representa con el pulso ZCD de la figura 6.
Para controlar la puerta (G) del TRIAC, y mantener aislado el bloque AC del circuito, se utiliza un opto-acoplador tipo triac U2, con esto la activación dependerá de la polarización del diodo en U2, en la figura 6 este evento se representa con la señal TDT. Finalmente el Microcontrolador utilizara como entrada la señal ZCD para detectar el instante donde se produce el cruce por cero y la salida TDT para disparar el TRIAC.
Lista de componentes que muestra el circuito de la figura 8, es la siguiente:
- Fusible F1 0.5A / 220V
- Resistencia R1,R2 100kΩ / 1.0W
- Resistencia R3 220Ω / 0.5W
- Resistencia R4 10kΩ / 0.25W
- Resistencia R5 1kΩ / 0.25W
- Triac T1 BT-136 600V
- Opto-Acoplador U1 PC-814
- Opto-Acoplador U2 MOC-3022
En el lado del Microcontrolador, emplearemos un circuito bastante simple utilizando el PIC16F887, observe la figura 9. La señal de entrada ZCD que proviene del circuito de control se conectara al pin de interrupción externa INT, y la señal de salida TDT al circuito de control sera el pin RB1, además se utilizara una resistencia variable para dividir la tensión y hacer lectura de su valor analógico en el pin AN0, finalmente un diodo conectado al pin RE2 indicar con un destello que el programa del PIC esta en funcionamiento.
|
Fig9. Circuito PIC16F887
|
Programación del PIC
Ya en esta sección trataremos la programación del microcontrolador PIC, como sabrán no es sencillo describir el funcionamiento de un programa en pocas palabras y que sea fácil de entender, me disculpo si no he sido claro en alguna parte, por eso para ir entrando en contexto, la figura 10 ilustra el flujo que sigue el programa principal y también la rutina de servicio a la interrupción.
|
Fig10. Flujo-grama Programa principal e ISR
|
Programa Principal: Posterior a la configuracion de los puertos, el modulo ADC, el temporizador y las interrupciones, el programa principal ingresa en un bucle continuo para ejecutar tres tareas cada milisegundo, estas tres tareas son: destellar el LED, hacer lectura del canal analógico ADC y ajustar el tiempo de disparo. Cabe resaltar que ninguna de estas tareas representa un proceso bloqueante, la codificación utiliza una técnica de programación por estados, si quieres conocer mas detalles al respecto puedes revisar la siguiente publicación. <Programación por estados con Temporizador>Rutina de Servicio a la Interrupción ISR: El código de esta rutina atiende a dos eventos, la interrupción del temporizador T0IF que permite ejecutar las tareas del programa principal cada milisegundo, y la interrupción externa INT que indica el cruce por cero ZCD, con la que sincronizara el tiempo de disparo TDT basado en un contador. Este contador se incrementa con cada interrupción del temporizador.
Si bien los comentarios en la codificación del programa describen el propósito de cada linea, se ha establecido la configuracion de variables considerando lo siguiente:
- La interrupción del temporizador se ajusto a 0.0002 segundos, con este tiempo para cada semi-ciclo de onda, la rutina ISR atiende hasta 50 interrupciones T0IF (0.010 / 0.0002 = 50). Un registro contador CNT se inicia en 0 cada vez que ocurre la interrupción externa INT(Cruce por cero) y se incrementa con cada interrupción T0IF, el control del disparo se da cuando el contador CNT alcanza el valor del tiempo TDT (Pulso de disparo).
- El valor para el tiempo TDT estará en función de la lectura ADC al canal AN0, cuya voltaje analógico es ajustable por un potenciómetro, entonces para que el resultado de la conversion de 10-bit, permanezca en el rango 0 a 49, se divide entre 21, y con ello se actualiza al valor del tiempo TDT.
A continuación se muestra el código del programa para el PIC16F887, considerando que la frecuencia del oscilador es Fosc=8MHz.
#include <xc.h>
#include <stdio.h>
#define ZCDpin PORTBbits.RB0 //Entrada para indicar Cruce por cero
#define TDTpin PORTBbits.RB1 //Salida para el pulso de disparo TRIAC
#define LEDpin PORTEbits.RE2 //Salida para destellar el LED
volatile uint8_t tick1ms = 0;
volatile uint8_t TDTval = 0; //Variable de control para disparo 0-49
void setupMCU(void);
void taskLED(void);
void taskADC(void);
void main(void)
{
setupMCU(); //Configuración
while(1)
{
if(tick1ms) //Valida en cada milisegundo
{
tick1ms = 0; //Limpia bandera
taskLED(); //Tarea para destello
taskADC(); //Tarea de lectura ADC
}
}
}
void __interrupt() isr(void) //Rutina ISR
{
static uint8_t cnt0, cnt1, toffset;
if(INTCONbits.INTF) //pulso ZCD
{
INTCONbits.INTF = 0;
toffset = 0; //Reinicia corrección del contador
}
if(INTCONbits.T0IF) //Activa cada 0.0002s
{
INTCONbits.T0IF = 0; //Limpia bandera
TMR0 += 156; //Reinicia contador T0
if(cnt0++ > 4) //Valida 5 x 0.0002 = 0.001s
{
tick1ms = 1; //Activa cada 0.001s
cnt0 = 0;
}
if(toffset == 6) //Valida corrección ZCD
{
cnt1 = 0; //Reinicia contador TDT
toffset++;
}
if(toffset < 6) toffset++;
if(cnt1 == TDTval) TDTpin = 1; //Valida y activa disparo
else TDTpin = 0;
if(cnt1 < 50) cnt1++; //t=50*0.2m = 10m
}
}
void setupMCU(void)
{
OSCCONbits.IRCF = 0b111; //Ajusta Fosc=8MHz, Tcy=0.5u
while(OSCCONbits.HTS == 0) {}
/* CONFIGURACION PUERTOS*/
ANSEL = 0;
ANSELH = 0;
TRISEbits.TRISE2 = 0; //Salida LED
TRISBbits.TRISB1 = 0; //Salida control TDT
LEDpin = 0; //Apaga el LED
TDTpin = 0; //Nivel bajo en pulso TDT
TRISBbits.TRISB0 = 1; //Entrada ZCD
OPTION_REGbits.nRBPU = 0; //Pull-up en ZCD
OPTION_REGbits.INTEDG = 1; //Flanco Ascendente
INTCONbits.INTF = 0; //Limpia bandera INT
INTCONbits.INTE = 1; //Activa interrupcion externa
/* CONFIGURACION TIMER0 0.2MS */
OPTION_REGbits.T0CS = 0;//Modo Termporizador
OPTION_REGbits.PSA = 0; //Con prescala
OPTION_REGbits.PS = 0b001; //Prescala 1:4
TMR0 = 156; //256-[(time*Fosc)/(pre*4)] time=0.0002 seg
INTCONbits.T0IF = 0; //Limpia bandera
INTCONbits.T0IE = 1; //Activa interrupcion del TMR0
/* CONFIGURACION ADC-10 Canal0*/
ANSELbits.ANS0 = 1; //Activa canal AN0
ADCON0bits.ADCS = 0b10; //TAD=4us > 1.6us (8MHz/32)
ADCON0bits.CHS = 0; //Selecciona Canal 0
ADCON0bits.ADON = 0; //Desactiva el modulo ADC
INTCONbits.GIE = 1; //Habilita las interrupciones
}
void taskADC(void) //Ciclo 1ms, Lectura ADC de 10Hz
{
static uint8_t state = 0, cnt = 0;
static uint16_t adcraw;
cnt++;
switch(state)
{
case 0: //Activa ADC para captura
ADCON0bits.ADON = 1;
cnt = 0;
state = 1;
break;
case 1: //Inicia conversion AN0
ADCON0bits.GO = 1;
state = 2;
break;
case 2://Espera fin de conversion AN0
if(ADCON0bits.GO == 0)
{
adcraw = ADRESL; //ADRESL First
adcraw |= (uint16_t) (ADRESH << 8);
adcraw >>= 6; //Corrige alineacion de ADH:ADL
ADCON0bits.ADON = 0;
state = 3;
}
break;
case 3: //Espera fin de ciclo
if(cnt++ > 99) //valida 100 x 1ms = 100ms
{
TDTval = (uint8_t) (adcraw / 22U); //Ajusta a TDT
state = 0;
}
}
}
void taskLED(void) //Destella led ciclo 1ms
{
static uint16_t tcnt = 0;
if(tcnt++ > 999)
{
tcnt = 0;
LEDpin = 1;
}
if(tcnt == 200) LEDpin = 0;
}
Pruebas de Funcionamiento
Se ensayo el código inicial en el microcontrolador para llevar a cabo las pruebas de funcionamiento utilice una placa de control TRIAC que disponía de un proyecto anterior, en esta placa de cuatro salidas, solo se utilizo uno de los canales.
|
Fig11. Circuito de control y PIC
|
No hay comentarios.:
Publicar un comentario