TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: kaki en 18 de Mayo de 2011, 00:43:24
-
Hola estoy intentando hacer un cruce por 0. este el codigo que manejo en la INT0 del puerto B-
//DETECTO PASO POR 0
#INT_EXT
void CrucePor0()
{
Tiempo = 0;
if (j==0){
enable_interrupts(INT_TIMER0);//Habilito Timer0
j=1;
salida1_off;
ext_int_edge(H_TO_L); // Cambio la detección del flanco, para que la proxima sea de bajada
PIN1_ON;
PIN2_OFF;
}
else {
enable_interrupts(INT_TIMER0);//Habilito Timer0
j=0;
salida1_off;
ext_int_edge(L_TO_H); // La próxima interrupción será de subida
PIN1_OFF;
PIN2_ON;
}
}
En cuanto a la parte de HADWARE lo que ago es transformar de 220v a 10V luego le pongo una resistencia de 100K ... Lo que quiero saber si esta bien lo que ago. Ya que me parece que la Frecuciancia se altera.. o los Siclos del transformado estan defasados con respecto al de la linea 220. Todo va mas rapido o tengo mal calculado el tiempo en TIMER 0
-
Podes poner directamente la tensión de red a un optoacoplador optico, con sus respectivas resistencias, por supuesto.
Saludos!
-
Para detectar el cruce por cero solo necesitas poner una resistencia que te limite la corriente que entra al pic, generalmente es del orden de 5 a 10 Megas, y con eso metes la linea de AC directamente al pic.
una duda, que es lo que quieres hacer con el timer0,no entiendo para que lo habilitas
-
Lo habilito para que empiese a desbordar... Yo Capto el cruce por cero, Activo el retardo q va a estar apagado antes de enceder el triac.. y despues lo desabilito... y comiensa el ciclo de nuevo pero en el otro franco.
Como calculo ra resistencia q va en el OPTOCOPLADOR??? y se la vancara a frecuencia de 50 hz?? digamos si tendra reaccion para apagar y prender cada 10ms??
-
Como calculo ra resistencia q va en el OPTOCOPLADOR??? y se la vancara a frecuencia de 50 hz?? digamos si tendra reaccion para apagar y prender cada 10ms??
R= 220V*1.4142/10mA. Yo lo probé para control por triac, y funciona ;-)
Si usas rivale, mucho cuidado, dado que no esta aislado.
Saludos!
-
Si usas rivale, mucho cuidado, dado que no esta aislado.
como comenta suky, si lo haces como te dije hay que tener cuidado, la ventaja es que usas menos componentes, por eso la resistencia debe ser de 10M aprox para que la corriente que entra al pic sea poca y puedas detectar el cruce por cero, lo he probado y funciona!!
veo que estas habilitando la interrupcion por timer 0 pero que haces cuando esta ocurre, supongo que le das el pulso al triac para que se encienda, el pulso yo lo he hecho de 100us y es suficiente para activar el triac.
recuerda que tu timer debe durar maximo 10 ms, dependiendo de cuanta potencia quieres que deje pasar
-
ah que llaman rivale??
el Timer lo tengo cunfigurado a con un cristal de 20 mhz y un prescaler de 4... despues el set_timer0(207); y esto me da 39.20us q multiplicado por 255 me da 10 ms...
haci tengo 255 puntos para controlar la intencidad...
esta bien calculado el tiempo??
-
ah que llaman rivale??
suky se refiere a que si hacias lo que yo te decia de poner una resistencia para conectar tu señal de alterna directamente al tu pic(yo soy rivale)
me parece que estas configurando mal tu timer, cuando le pones "set_timer0(207)" , significa que tu timer empezara a contar a partir del 207, y solo llega hasta 255.
lo que puedes hacer es ponerle un preescaler de 256, de esta manera el tiempo maximo de tu timer seria
4*256/20000000= 0.0512 ms, si multiplicas esto por 256, entonces te da un tiempo de 13.1072ms, no es exacto pero es cercano a los 10ms que necesitas.
con esto tu timer lo debes iniciar en 60 para que llegue a desbordarse(255) en 10 ms, y asi tienes 256-60=195 diferentes intensidades de luz
-
no seria mas lindo 3 x 256 = 0.0384 x 256 = 9.8304 eso es mas cera todabia!!
-
no seria mas lindo 3 x 256 = 0.0384 x 256 = 9.8304 eso es mas cera todabia!!
pero de donde sacas el 3?, recuerda que el incremento del timer0 esta dado por la frecuencia de tu oscilador, el tiempo maximo esta dado por:
4*PRE*256/OSC
tu oscilador es de 20M, el preescalador es el unico que puedes variar, entonces el mas cercano es si le pones 256
-
y el 4 que es entonceS??? 256 es el prescaler??
-
Ha, lo puedes ver en la hoja de especificaciones para mas detalle, pero te comento, cada instruccion del pic tarda 4 veces el periodo del oscilador, entonces cada incremento del timer es 4/osc
el preescalador de multiplica el tiempo de cada incremento: entonces es 4*PRE/osc
con esto sabes cada cuanto tiempo se incrementa en 1 el timer0, pero como es de 8 bits, se incrementa 256 veces
entonces queda:
4*PRE*256/osc; el PRE que te recomende es de 256, pero no tiene nada que ver con el 256 que es el tamaño del timer0.
-
entonces el set_timer0(256 - ALGUNVALOR); y ahi es la de donde arranca el para llegar adesvoerdar.. mientra mas grande la variable mas tiempo va a tardar en desbordar?? o nada q ver??
-
y el 4 que es entonceS??? 256 es el prescaler??
Amigo, hay que estudiar un pocos mas el datasheet, sino estas inventando cosas. Busca en el foro, hay informacion igual, porque sino parece un chiste.
Saludos
-
el set_timer0 te sirve para darle un valor inicial al timer, al contrario de lo que dices, entre mayor sea el valor, mas rapido se desborda el timer
por ejemplo, si le das el valor de cero, al timer le quedan 255-0 incrementos para desbordarse
si le das valor de 100, al timer le quedan 255-100=155 incrementos para que se desborde y genere la interrupcion.
si quieres calcular el tiempo que el falta al timer para desbordarse usa esta ec
tiempo= 4*PRE*(256-X)/20000000
donde X es el valor que le diste en set_timer0(X)
-
Muchas gracias ya entendi a la perfeccion gracias a rivale por las formulas y esplicaciones y Suky por el consejo de buscar en el foro.. buscando encontre una explicacion...
Cualquier cosa los vuelvo a moslestar saludos...
-
Por nada, que bueno que te sirvio.
y como dice suky trata de leer las hojas de especificaciones, ya si algo no entiendes se te ayuda en el foro ya con preguntas mas concretas o de aplicacion
-
Bueno en base a todo lo que aprendi quice hacer el dimmer.. pero no tuve exito. El problema es que no se seba nunca el Triac.
aca dejo el codigo a ver que ven anormal ustedes que yo no veo:
para variar la intencidad, vario una variable que se llama Intencidad. el ADC no lo uso por ahora solo para pueva, no lo miren...
#include <18f2550.h>
#device adc=8
//FUSES Y OCILADOR
#fuses HS,NOWDT,NOPROTECT,NOLVP,NODEBUG
#use delay(oscillator=20M)
//DEFINO PARA EL LCD
#define LCD_DB4 PIN_B4
#define LCD_DB5 PIN_B5
#define LCD_DB6 PIN_B6
#define LCD_DB7 PIN_B7
#define LCD_RS PIN_B1
#define LCD_E PIN_B2
#define triac_on output_high(pin_a1)
#define triac_off output_low(pin_a1)
#define PIN1_ON output_high(pin_c0)
#define PIN1_OFF output_low(pin_c0)
#define PIN2_ON output_high(pin_c1)
#define PIN2_OFF output_low(pin_c1)
//CONSTANTE
//const int TotalTiempo=255; //Tiempo total q demora cada medio ciclo
//VARIABLES
int PasosDimer; // se incrementa en 1 cada X vueltas del timer, coincidendo con la captura de bits del mando
int Intencidad; //Variable de
int j=0; // Identifica Cruce por 0 si es alto o bajo
//INCLUDE LIBRERIAS
#include <LCD.lib>
//TIEMPO
#INT_TIMER0
void Desbordamiento()
{
set_timer0(255);//51.2us
PasosDimer++;
if (PasosDimer == Intencidad ){ //Si Tiempo es igual a Pote disparo Trian
triac_on;
}
triac_off;
}
//DETECTO PASO POR 0
#INT_EXT
void CrucePor0()
{
Intencidad = 100;//Regulo la intencidad manual mente por ahora variando esta variable y compilando (de 1 a 195)
PasosDimer=0;
if (j==0){
j=1;
PIN1_ON;
PIN2_OFF;
ext_int_edge(H_TO_L); // Cambio la detección del flanco, para que la proxima sea de bajada
}
else {
j=0;
PIN1_OFF;
PIN2_ON;
ext_int_edge(L_TO_H); // La próxima interrupción será de subida
}
}
//LECTURA ANALOGICA(NO LA USO POR AHORA)
#INT_AD
void leer()
{
// Intencidad = read_adc();
}
//MAIN
void main(void){
//INICIALIZO LCD
lcd_init();
//ADC
setup_adc(ADC_CLOCK_INTERNAL);
setup_adc(AN0_ANALOG);
enable_interrupts(INT_AD);
//TIMER
setup_timer_0(RTCC_INTERNAL | RTCC_DIV_256);
//disable_interrupts(INT_TIMER0);
enable_interrupts(INT_TIMER0);
set_timer0(255);
//INTERUPCION
ext_int_edge(L_TO_H);
enable_interrupts(INT_EXT);
//GLOBAL
enable_interrupts(GLOBAL);
//SETEO CANCAR DE ADC
set_adc_channel(0);
//TIEMPO PARA Q TOME CONFIGURACIONES ADC
delay_ms(10);
for(;;){
//Muestro la variable PASOSDIMER
lcd_gotoxy(1,1);
printf(lcd_putc,"Timer: ");
lcd_gotoxy(8,1);
printf(lcd_putc,"%u",PasosDimer);
//Muestro la variable Intencidad
lcd_gotoxy(1,2);
printf(lcd_putc,"Intencidad: ");
lcd_gotoxy(12,2);
printf(lcd_putc," %u", Intencidad);
//Empieso Lectura
read_ADC(ADC_START_ONLY);
}
}
Saludos..
-
Utiliza el buscador, hay varios códigos de dimmers, como para que veas y leas las experiencias que han tenido otros. Fíjate cual opto-triac es el adecuado para esta aplicación.
Saludos!
-
ya me lei 50 post y no se cual es mi error... hay codigos que son similar al mio y no me anda igual... El optotriac es el adecuado el MOC3021... solo hechale una leida y ve que ves anormal... te lo agradeceria...
-
Hola.
Bueno, el error es que no sebas bien el TRIAC ... lee la hoja técnica del TRIAC en cuestión y verifica que el tiempo en el que esta el GATE es el suficiente. Mira aqui (http://www.todopic.com.ar/foros/index.php?topic=21584.0)
Saludos
-
creo que tienes mal tu algoritmo, estas poniendo el set_timer0 dentro de la interrupcion del timer, pero lo debes de poner en cuanto detectes el cruce por cero, porque a partir de ese momento empiezas c contar para prender el triac, ademas, dentro de tu interrupcion del timer prendes y apagas el triac muy rapido, despues de que lo prendes pon un delay de 100 us y despues lo apagas. checa si eso funciona
-
Encontre el problema. La interrusion se cumple mucho mas rapido que si cumpla la condicion dentro del TIMER0. Lo que no se si el error lo tengo en los timpo de desbor o en la Interrupsion. Saludos
-
entonces me parece que el tiempo de tu timer es mayor que el periodo de la linea de AC, checa que si este bien el tiempo de desboradmiento
-
TIMER0:
Cristal -> 20Mhz
Prescaler -> 256
Ser_Timer0 (255)
-------------------
Tiempo 51.20 us
Divido el Tiempo del siclo para ver la intencidad maxima y minimo(osea desde donde
parte y hasta donde llega para que la lampara esta la maximo o minimo).
10000 / 51.20 = 195
Bueno lo que pasa es que el timer0 solo desborda 2 veces. Osea el paso por 0 va mas
rapido que el Timer0.
¿Cual puede ser el problema?
-
El problema que veo es que el tiempo que permanece el GATE en alto es muy poco. Mirando tu último código, en la parte de la interrupción, validas con un if para encender el GATE, pero inmediatamente lo vuelves a apagar. Si revisaste el link que te postee? ahí esta un código (probado) de lo que necesitas
-
Lo que pasa que ese codigo que me pasaste usa el CCP y no entiendo mucho... quiero hacer que yo entienda para poder aprender... Ya corregi lo del Tiempo de cebado del triac.. El problema que tengo ahora es otro!! saludos..
-
cual es tu problema actual?
para encender el triac yo lo he hecho con 100 us
-
El problema es qeu el Timer0 va mas lento que la interutsion.. y se resetea antes que lo deberia...
mira:
TIMER0:
Cristal -> 20Mhz
Prescaler -> 256
Ser_Timer0 (255)
-------------------
Tiempo 51.20 us
Divido el Tiempo del siclo para ver la intencidad maxima y minimo(osea desde donde
parte y hasta donde llega para que la lampara esta la maximo o minimo).
10000 / 51.20 = 195
Bueno lo que pasa es que el timer0 solo desborda 2 veces. Osea el paso por 0 va mas
rapido que el Timer0.
¿Cual puede ser el problema?
entra solo 2 veces con ese tiempo... y chau pone el contador en 0..
-
si tu cristal es de 20 MHz, esta bien tu presscales de 256, pero entonces tu tiempo maximo de desbordamiento es de 13.107 ms, lo cual es mayor que el periodo de la senoidal
si tu señal de alterna es de 60 Hz entonces cada semiciclo de la senoidal dura 8 ms aprox.
tu timer porque lo cargas con 255? con eso se desbordaria inmediatamente.
si despues de detectar el cruce por cero le pones un valor de: set_timer0(99), entonces van a pasar 8 ms y te genera la interrupcion, en este caso coincidira con tu ciclo de la senoidal
si le pones set_timer0(180) el timer se desbordara 3.8 ms despues del cruce, lo cual solo dejaria pasar aprox la mitad del ciclo y tendrias un valor de intensidad media
-
lo trabajo a 50 hz!!
si yo uso un prescaler de 256, Cristal de 20 Mhz y cargo el timer en 255 entonces tengo 52.20 microsegundos...
El siclo teoricamente tiene q volver a pasar por 0 una ves que el timer 197 ... variando el 197 es la intencidad de la luz.. a mas chico ese numero mayor intencidad por q va a estar mas tiempo sebado el triac...
Entiendes??
-
entre mayor sea el numero que le cargues al timer va a tardar menos en prenderse, por lo tanto es mayor la intensidad de luz
-
No no estamos entendiendo.. hablamos de cosas distintas... ahi te doy un ejemplo con codigo.
#INT_TIMER0
void Desbordamiento()
{
set_timer0(Periodo); //51.2us --> esta siempre en 255 no cambia
PasosDimer++; // Incrementa la veces q pasa el contador
Intencidad = 5;
if (PasosDimer == Intencidad){ //Si las veces q desbordo el Timer es igual a la q setien en la Variable INTENCIDAD prende el tric(Mas grande la bariable menos intencidad)
triac_on; //Enciendo Triac
LED3_ON; //Enciendo Led de estado .. al pedo
}
if (PasosDimer == Intencidad + 2 ){ //pasan 100Us para que alcanse a sevar el triac
triac_off;//Apago Trian
LED3_OFF;// Apago led de estado
}
}
Bueno el problema es que no prende nunca el Triac o LED solo prende cuando intencidad es 2 o 1... la Variable PasosDimer vuelve a 0 antes de lo normal.
Este es el codigo para detectar paso por 0
#INT_EXT
void CrucePor0()
{
//Regulo la intencidad manual mente por ahora variando esta variable y compilando (de 1 a 195)
PasosDimer=0;
if (j==0){
j=1;
LED1_OFF;
LED2_OFF;
ext_int_edge(H_TO_L); // Cambio la detección del flanco, para que la proxima sea de bajada
} else {
j=0;
LED2_ON;
LED1_ON;
ext_int_edge(L_TO_H); // La próxima interrupción será de subida
}
}
-
dentro de tu interrupcion externa es donde debes darle el valor al timer0, ya que a partir de ese momento empezaras a contar el tiempo para encender el triac
-
Y en el MAIN no es lo mismo que ponerlo en la Interupsion Externa?? Si o si tiene q ir ahi??
-
no es lo mismo, lo que pasa es que cuando detectas el cruce, es donde debes empezar a contar para activar el triac. si lo haces en el main, como sabes que empieza a contar al mismo tiempo que el el cruce por cero.
mi idea es asi:
#int_ext
void ext()
{
///detectas el cruce y haces el cambio de flanco
set_timer0(xx)
}
#int_timer0
void int_t0()
{
//aca es cuando ya paso tu tiempo de espera para prender el triac
prendes el triac
retardo de 100 us aprox
apagas el triac
}
con esto prendes el triac, y se quedara prendido hasta el proximo cruce por cero, entonces vuelves a empezar a contar con tu timer para volverlo a prender
-
okey voy a probar
-
Bueno probe toda la noche y estoy 100% seguro que el codigo esta bien!!! no se por que no me nada....
Code:
Timer0:
#INT_TIMER0
void Desbordamiento()
{
PasosDimer++;
if (PasosDimer == Intencidad){ //Ensiende el Trian
triac_on;
LED3_ON;
}
if (PasosDimer == Intencidad + 2 ){ //Espera 100 Us para apagar el Triac
triac_off;
LED3_OFF;
}
}
Interrupcion:
#INT_EXT
void CrucePor0()
{
set_timer0(Periodo);
PasosDimer=0;
Intencidad = 197; //Regulo la intencidad manual mente por ahora variando esta variable y compilando (de 1 a 195)
if (j==0){
j=1;
LED1_OFF;
LED2_OFF;
ext_int_edge(H_TO_L); // Cambio la detección del flanco, para que la proxima sea de bajada
} else {
j=0;
LED2_ON;
LED1_ON;
ext_int_edge(L_TO_H); // La próxima interrupción será de subida
}
}
Variables y Definiciones:
#define triac_on OUTPUT_BIT(pin_a1,1)
#define triac_off OUTPUT_BIT(pin_a1,0)
#define LED1_ON OUTPUT_BIT(pin_c0,1)
#define LED1_OFF OUTPUT_BIT(pin_c0,0)
#define LED2_ON OUTPUT_BIT(pin_c1,1)
#define LED2_OFF OUTPUT_BIT(pin_C1,0)
#define LED3_ON OUTPUT_BIT(pin_c2,1)
#define LED3_OFF OUTPUT_BIT(pin_c2,0)
//CONSTANTE
const int Periodo=255; //255; //Tiempo total q demora cada medio ciclo
//VARIABLES
int PasosDimer; // se incrementa en 1 cada X vueltas del timer, coincidendo con la captura de bits del mando
int Intencidad; //Variable de
int j=0; // Identifica Cruce por 0 si es alto o bajo
No se fijate que el codigo hace lo correcto pero el pic no entra nunca al maldito IF q prende el Triac
-
tu variable paso_dimer la haces 0 en esta parte, aunque la incrementes en la int_timer0 nunca va a llegar al valor que quieres para entrar en el if
set_timer0(Periodo);
PasosDimer=0;
Intencidad = 197; //Regulo la intencidad manual mente por ahora variando esta variable y compilando (de 1 a 195)
-
y entonces donde va "PasosDimer=0;" ??? en todos los codigo que vi esta ahi.. y es logico!!
-
el paso_dimer lo haces igual a cero pero despues de que entre a la condicion del if
es decir, primero deja que se incremente, y cuando sea igual a "intensidad" entonces lo borras
-
no tiene logica lo q dices!! entonces la INT_EXT esta al pedo!! para que lo sincronisamos con 0 si ago 0 la variable en el IF del Timer0!!
-
Hola.
Has cero la variable de conteo después de apagar el TRIAC, pero en la rutina del Timer0, no en la rutina de detección del cruce por cero y des-habilita el timer mejor; es mejor que inicie a contar desde que detecta el cruce por cero y se desactive después de apagar el TRIAC.
Saludos
-
No anda Probe desactivando el Timer poniendolo como dicen ustedes y no anda... Saludos