TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: MLO__ en 04 de Mayo de 2008, 00:44:35
-
Hola amigos del foro
He estado trabajando en un programita de control de fase mediante interrupciones (Timer0 y CCPx). Asigno el valor por teclado entre 0.0 y 3.0 (asi lo necesito) .. el punto se escribe solo :mrgreen:
El programa lo que hace es captar la inerrupcion de subida y bajada (FE, RE) y asigna un valor de tiempo de retraso con el timer0. Para cambiar el valor del nivel entre 0 y 3.0 en "caliente" se presiona la tecla "*" y listo.
Adjunto el diagrama en proteus 7.2 SP2.
#include<18F452.h>
#fuses XT, NOWDT
#use delay(clock=4M)
#use rs232(baud=9600, xmit=pin_c6, rcv=pin_c7, bits=8)
#include <LCD.C>
#include <KBD.C>
#define on output_high
#define off output_low
#define zero_cross pin_c0
#define trigger_triac pin_c1
#define subida 0
#define bajada 1
int1 flanco=0;
int8 ints_t0=0, value=0;
#int_CCP1
void ZeroCross_isr(void)
{
if(flanco==subida)
{
enable_interrupts(INT_TIMER0);
setup_ccp1(CCP_CAPTURE_FE);
flanco = bajada;
}
else
{
off(trigger_triac);
setup_ccp1(CCP_CAPTURE_RE);
flanco = subida;
}
}
#int_TIMER0// T_base = 256uS
void pulse_isr(void)// T_flagg = T_base x RTCC_DIV_1 = 256uS
{
++ints_t0;
if(ints_t0>value)
{
on(trigger_triac);
ints_t0 = 0;
disable_interrupts(INT_TIMER0);
}
}
byte get_potencia()//OBTENER NUMERO TECLADO ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
{
char first,second, third;
int8 potencia=0;
primero:
do {first=kbd_getc();} while ((first<'0') || (first>'9'));
printf(lcd_putc, "%c.",first);
first-='0';
segundo:
do {second=kbd_getc();} while (((second<'0') || (second>'9')) && (second != '*') );
if(second == '*')
{lcd_putc('\b'); lcd_putc('\b');lcd_putc(" "); lcd_putc('\b'); lcd_putc('\b'); goto primero;}
lcd_putc(second);
second-='0';
do{third = kbd_getc();} while((third != '#') && (third != '*'));
if(third=='#')
{
potencia = 10*first + second;
potencia = (potencia>28) ? 28 : potencia;
return(potencia);
}
if(third=='*')
{lcd_putc('\b'); lcd_putc(' '); lcd_putc('\b'); goto segundo;}
}
void main(void)
{
char cmd=0;
setup_adc(ADC_OFF);
setup_adc_ports(NO_ANALOGS);
setup_ccp1(CCP_CAPTURE_RE);
setup_timer_0(RTCC_INTERNAL | RTCC_8_BIT | RTCC_DIV_1);
disable_interrupts(INT_TIMER0);
flanco=subida;
lcd_init();
kbd_init();
port_b_pullups(TRUE);
value = 1;
printf(lcd_putc,"\fControl Potencia");
enable_interrupts(INT_CCP1);
enable_interrupts(GLOBAL);
while(true)
{
lcd_putc("\nP?");
value = get_potencia();
do{cmd = kbd_getc();}while(cmd!='*');
printf(lcd_putc, "\fControl Potencia\nP?");
}
}
El valor minimo de delay de disparo que se tiene es de 256uS y el maximo es de 7.17mS (maximo seria 8mS, pero mejor evitar ese valor por los disparos muy cercanos al cruce por cero .... producen trancientes muy fuertes en cargas inductivas). Se puede mejorar el cambio de tiempo asignando un valor con el set_timer0() en la interrupcion.
Lo bueno es que siempre esta haciendo el control de fase, y el valor del delay de disparo se puede asignar cuando sea necesario mediante la variable global ..... estoy "engomado" con los PICS :-/
Espero a alguien le sirva
Chao
-
Saludos MLO! Oye muy bueno! :-/ Gracias por el aporte!
Aquí ya somos unos cuantos que estamos engomados :D
Ok nos leemos! :mrgreen:
-
Podrías poner un ejemplo con números del uso del teclado y del terminal RS232? ... lo he estado probando (jugando) y las pulsaciones del teclado no se muestran en la LCD.
Un saludo
-
Hola Pocher.
No se si te entendi bien ... espero que si ... me avisas si era otra cosa :mrgreen:
#include <18F452.h>
#use delay(clock=4M)
#use rs232(baud=9600, xmit=pin_c6, rcv=pin_c7, bits=8)
#include <lcd.c>
#include <kbd.c>
int8 cmd=0;
void main(void)
{
lcd_init();
kbd_init();
port_b_pullups(TRUE);
lcd_putc("\ft:");
printf("tecla:");
while(TRUE)
{
cmd = kbd_getc();
if(cmd!='\0')
{
printf(lcd_putc, "%c", cmd);
printf("%c", cmd);
}
}
}
Lo que hace el programa es leer la tecla y la despliega en la LCD y en el terminal virtual. Adjunto la simulacion el Proteus 7.2SP2.
-
Sí en este último programa si funciona, pero en el primero cuando pulsas una tecla no aparece nada en la LCD.
Más cosas, la comunicación RS232 no veo que la uses en tu programa y sin embargo sí que has puesto al VTERM.
Es posible que se te hayan traspapeleado los programas y hayas puesto uno de los programas experimentales que hicistes antes de llegar al definitivo.
Con un ejemplo numérico me refería a si no te importa, para un determinado valor del teclado mostrar los resultados numéricos intermedios del control de potencia que hace tu programa.
-
ok .. ya entiendo :lol:
Lo del terminal virtual es porque se me olvido quitarlo :mrgreen:
Con respecto al calculo, yo lo que hago es dar un tiempo de delay despues de detectar el cruce por cero en funcion del valor del numero ingresado y coloco el condicional para que restringir el valor mayor a 28 (que se leeria desde el teclado con 2.8 ) y listo... la verdad el control es simple pero efectivo, ya que puedo cargar el valor de delay con una variable global. La resolucion minima de tiempo entre dos pasos consecutivos de control (por ejemplo, entre 10 y 11, que seria en el teclado 1.0 y 1.1) es de 256uS, un desborde completo del timer0
El teclado a mi si me funciona, no se que sera. Te envio el codigo fuente para que lo compiles alla a ver que pasa.
-
Pués nada que la compilación sobre el fuente .c no funciona: las teclas no se muestran en la LCD.
El archivo .hex que has pasado sí que funciona pero el resultante de la compilación no, y eso que lo he intentado con dos versiones del compilador.
No importa, gracias de todos modos.
Un saludo
-
Ey saludos! :-)
Yo probé lo que mandó el amigo MLO y lo del LCD me funcionó perfecto, se ven los números que uno pulsa con el teclado...
Qué raro que el maestro porcher no pueda verlos.. :?
Ok solo quería decirles eso, que a mi si me funciona... :D
No mas pues, nos leemos! :mrgreen:
-
Hola.
Oye Pocher, no sera de pronto la configuracion de los pines del teclado? A mi una vez me sucedio que el teclado no respondia y era porque lo estaba conectando de la otra manera (blue keypad) y como estoy usando la libreria estandard del kbd.c ... puede darse no?
Por cierto uso la version 4.057 del CCS.
Saludos.
-
Vale ya está.
El fallo que tenía es que en la librería kbd.c puedes usar el puertob ó el puertod y yo lo tenía en el puertod. Este tipo de tonterías son las que muchas veces nos llevan de cabeza.
Un saludo
-
Ok!!!
Esas cosas pasan .... y muy a menudo. Me alegra que solucionaras el problema.
Saludos
-
Hola estoy haciendo un programa para el control de fase para un scr, sincronizado con la linea, pero este programa falla en la sincronia y es que el pulso a mover de la fase no coincide con un cruce por cero ( tiempo en alto de 8.33ms ) que entra a la interrupcion externa , lo que estoy haciendo es mediante la interrupcion externa se detectan flancos de subida ( que porvienen de un cruce por cero de 8.33ms ) y cuando este se presenta se lee el ADC, y lo que hise aqui no se si este bien hise una regla de tres para asignar cada valor del ADC ( 1024 ) un tiempo
8.33ms----->1023
ADCT------->ADC = read_adc();
en esto tengo duda si este correcto, de pues pongo en alto el RB1 a 100useg pero no hay sincronia, dejo mi codigo para ver si me puden ayudar a corregir mi error. GRACIAS.
#include <16F886.H> //Libreria del PIC Implementado.
#device ADC = 10 //Resolucion del ADC.
#fuses HS, NOWDT, NOLVP, PUT, MCLR //Oscilador Externo, Deshabilita el Doggy.
#use delay( clock = 20M ) //Crystal de 20MHz.
#include <LCD_PORTC.C> //Libreria del LCD.
int Cambiar;
int16 ADC, PWML; //Variables.
float ADCT, ADCI, ADCS;
#INT_EXT
void ext_isr( void )
{
ADC = read_adc(); //Lee el ADC.
delay_us( 10 ); //Espera 10useg.
ADCT = ADC * 0.0083 / 1023.0;
printf( lcd_putc, "\fADC = %4ld", ADC );
printf( lcd_putc, "\nPuMo = %4ld", PuMo );
delay_ms( 1000 );
printf( lcd_putc, "\nADCT = %01.7fv", ADCT );
delay_ms( 1000 );
if( Cambiar == 0 )
{
if( ADC == 0 )
{
ADCI = 0;
ADCS = 0.00000814;
printf( lcd_putc, "\fADCI = %01.7fv", ADCI );
printf( lcd_putc, "\nADCS = %01.7fv", ADCS );
delay_ms( 1000 );
output_high( PIN_B1 );
delay_us( 100 );
output_low( PIN_B1 );
delay_ms( 8.23 );
}
else if( ADC > 0 & ADC < 1023 )
{
ADCI = ADCT;
ADCS = ADCT + 0.00000814;
printf( lcd_putc, "\fADCI = %01.7fv", ADCI );
printf( lcd_putc, "\nADCS = %01.7fv", ADCS );
delay_ms( 1000 );
output_high( PIN_B1 );
delay_us( 100 );
output_low( PIN_B1 );
delay_ms( 8.23 );
}
else if( ADC == 1023 )
{
ADCS = ADCT;
ADCI = ADCT - 0.00000814;
printf( lcd_putc, "\fADCI = %01.7fv", ADCI );
printf( lcd_putc, "\nADCS = %01.7fv", ADCS );
delay_ms( 1000 );
output_high( PIN_B1 );
delay_us( 100 );
output_low( PIN_B1 );
delay_Ms( 8.23 );
}
else
{
output_low( PIN_B1 );
}
}
else if( Cambiar == 1 )
{
output_low( PIN_B1 );
ext_int_edge( 0, L_TO_H );
Cambiar = 0;
}
}
void main( void )
{
lcd_init();
setup_adc_ports( SAN0 ); //AN0 como Cana Analogico.
setup_adc( ADC_CLOCK_INTERNAL ); //Oscilador Interno.
set_adc_channel( 0 ); //Habilita el Canal 0.
Cambiar = 0; //Inicializa el Cambio.
ext_int_edge( 0, L_TO_H ); //Inicia con Flanco de Subida.
enable_interrupts( INT_EXT ); //Habilita la Interrupcion Externa.
enable_interrupts( GLOBAL ); //Habilita la Interrupcion Global.
while( 1 )
{
}
}
-
Hola.
Fíjate que en la interrupción tienes delays de 1s y funciones printf(); :shock: por lo tanto vas a perder sincronia con todo!!!! ;-)
Mejor asigna un flag para realizar el proceso en el programa principal para que no te interfiera con el cruce por cero.
Saludos
-
Hola que tal, sigo con el mismo problema de la sincronis, pude modificar lo de los flancos y no hay sincronia, no se si me puedas ayudar a solucionar mi problema y a mejorar mi codigo, dejo lo que pude coregir. GRACIAS.
#fuses HS, NOWDT, NOLVP, PUT //Oscilador Externo, Deshabilita el Doggy.
#use delay( clock = 20M ) //Crystal de 20MHz.
#include <LCD_PORTC.C> //Libreria del LCD.
int Proc, CamFlag;
int16 ADC, PWML, PuMo, ADCI, ADCS; //Variables.
//float ADCT, ADCI, ADCS;
#INT_EXT
void ext_isr( void )
{
if( CamFlag == 0 )
{
Proc = 1;
ext_int_edge( 0, H_TO_L );
CamFlag = 1;
}
else if( CamFlag == 1 )
{
Proc = 0;
ext_int_edge( 0, L_TO_H );
CamFlag = 0;
}
}
void main( void )
{
lcd_init(); //Iniciliza el LCD.
setup_adc_ports( AN0 ); //AN0 como Cana Analogico.
setup_adc( ADC_CLOCK_INTERNAL ); //Oscilador Interno.
set_adc_channel( 0 ); //Habilita el Canal 0.
CamFlag = 0; //Inicializa el Cambio.
ext_int_edge( 0, L_TO_H ); //Inicia con Flanco de Subida.
enable_interrupts( INT_EXT ); //Habilita la Interrupcion Externa.
enable_interrupts( GLOBAL ); //Habilita la Interrupcion Global.
while( 1 )
{
if( Proc == 1 )
{
ADC = read_adc(); //Lee el ADC.
PWML = 1023 - ADC;
PuMo = ADC + 1; //Pulso en Movivmiento.
for( ADCI = 0; ADCI <= ADC; ADCI++ )
{
output_high( PIN_B2 );
}
for( ADCS = 0; ADCS <= PWML; PWML++ )
{
output_low( PIN_B2 );
}
output_high( PIN_B3 );
}
else
{
output_low( PIN_B2 );
output_low( PIN_B3 );
}
}
}
-
Hola que tal, creo que he logrado conseguir la sincronia pero ahora no puedo generar el pulso de 100useg , ya que cuando vario el adc no se logramover el pulso, me podrian ayudar a formarlo, tambien tengo duda sobre el timer no se si esta es la manera correcta de usarlo junto con la interrupcion externa, dejo mi codigo para que lo puedan correigr.GRACIAS.
#include <16F873A.H> //Libreria del PIC Implementado.
#fuses HS, NOWDT, NOLVP, PUT //Osiclador Externo, Deshabilita el Doggy.
#use delay( clock = 20M ) //Crystal de 20MHz.
int CamFlag;
int16 ADC, PWML, PuMo;
float ADCT, ADCS, ADCI;
#INT_EXT
void ext_isr( void )
{
if( CamFlag == 0 )
{
enable_interrupts( INT_TIMER0 );
set_timer0( 131 );
}
else if( CamFlag == 1 )
{
output_low( PIN_B2 );
ext_int_edge( 0, L_TO_H );
CamFlag = 0;
}
}
#INT_TIMER0
void TIMER0_isr( void )
{
ADC = read_adc();
PWML = 1023 - ADC;
ADCT = ADC * 0.00833 / 1023.0;
for( ADC; ADC > 0; ADC-- )
{
output_high( PIN_B2 );
}
for( PWML; PWML > 0; PWML-- )
{
output_low( PIN_B2 );
}
if( ADC == 0 )
{
ADCI = 0;
ADCS = 0.00000814;
output_high( PIN_B1 );
}
else if( ( ADC > 0 ) & ( ADC < 1023 ) )
{
ADCI = ADCT;
ADCS = ADCT + 0.00000814;
output_high( PIN_B1 );
}
else if( ADC == 1023 )
{
ADCS = ADCT;
ADCI = ADCT - 0.00000814;
output_high( PIN_B1 );
}
else
{
output_low( PIN_B1 );
}
CamFlag = 1;
ext_int_edge( 0, H_TO_L );
disable_interrupts( INT_TIMER0 );
}
void main( void )
{
setup_adc_ports( AN0 );
setup_adc( ADC_CLOCK_INTERNAL);
set_adc_channel( 0 );
CamFlag = 0;
setup_timer_0( RTCC_INTERNAL | RTCC_DIV_4 );
ext_int_edge( 0, L_TO_H );
enable_interrupts( INT_EXT );
enable_interrupts( INT_TIMER0 );
enable_interrupts( GLOBAL );
while( 1 )
{
}
}
-
no seria mejor hacer un flag con el timer0 y leer el adc en el bucle principal, asi no ocupas tiempo de interrupcion ya que el ADC tarda "bastante" y te puede colisionar con la interrupcion externa.
Por cierto, ¿que circuito usas de deteccion de cruce por cero? estuve mirando señales a traves de un transformador y en el osciloscopio solo "veo" bien la onda si le pongo una resistencia de carga.
Transformador + puente diodos + diodo = en el anodo del diodo tengo la resistencia de carga y con el osciloscopio veo bien la onda senoidal 100hz, de aqui lo paso a un comparador y tengo el cruce por cero. En el catodo pongo el circuito que hace de fuente de alimentacion de la placa. Si quito la resistencia de carga la señal del osciloscopio es bastante pobre, no se si es que siempre tiene que tener una carga o es que estoy haciendo algo mal.
-
¿Si esta bien la forma de usar la interrupcion externa y la interrupcion del timer0?, Entonces lo primero que tendria que hacer es detectar un flag de subida llamar al timer y saltar al primcipal para hacer el proceso, el pulso lo estoy haciendo con for y una variable auxiliar, no se si es la mejor manera de hacerlo.
ADC = read_adc();
PuMo = ADC + 1;
for( ADCUx = ADC; ADCUx <= PuMo; ADCUx++ )
{
output_high( PIN_B2 );
}
¿esta bien hacerlo asi, y no se si esto me asegura que pueda tener angulos diferentes mientras el ADC va aunmentando?
en cuanto al cruce por cero lo hise con un optoacoplador pero tambien se puede hacer como dices con un comparador o con un transistor.
-
Hola.
Tal como esta, te puede tomar mas tiempo en la interrupción y la idea es demorarse lo menos posible en ellas ... mira el código que usé ... habría que asignar el valor de la conversión a la variable value y eso se puede hacer en el programa principal.
Saludos
-
hola que tal, ya cambie el proceso al principal pero sigue sin formarse el pulso creo que esta mal la forma de usar la interrupcion de timer0, ojala me puedan ayudar a corregir. GRACIAS.
#include <16F886.H>
#device ADC = 10
#fuses HS, NOWDT, NOLVP, PUT, MCLR
#use delay( clock = 20M )
int16 ADC, ADCI, ADCS;
int CamFlag, Pasa;
#INT_EXT
void ext_isr( void )
{
if( CamFlag == 0 )
{
Pasa = 0;
ext_int_edge( 0, H_TO_L );
CamFlag = 1;
}
else if( CamFlag == 1 )
{
Pasa = 1;
ext_int_edge( 0, L_TO_H );
CamFlag = 0;
}
}
#INT_TIMER0
void TIMER0_isr( void )
{
for( ADCI = ADC; ADCI <= ADCS; ADCI++ )
{
output_high( PIN_B2 );
}
disable_interrupts( INT_TIMER0 );
}
void main( void )
{
setup_adc_ports( SAN0 );
setup_adc( ADC_CLOCK_INTERNAL );
set_adc_channel( 0 );
setup_timer_0( RTCC_INTERNAL | RTCC_DIV_4 );
set_timer0( 131 );
while( 1 )
{
ADC = read_adc();
delay_us( 10 );
ADCS = ADC + 1;
if( ADC == 1023 )
{
ADCS = ADC;
ADC = ADC - 1;
}
if( Pasa == 0)
{
enable_interrupts( INT_TIMER0 );
}
else if( Pasa == 1 )
{
output_low( PIN_B2 );
}
}
}
-
Hola.
Mejor quita ese for dentro de la interrupcion del Timer0.
Saludos
-
HOLA que tal MLO, ya hise algo parecido a lo que tu hisite en tu codigo pero sigo sin resultado, ademastengo un problema en la simulacion de proteus me da un errorque dice: ADC conversion started before” wait “time has expired following previous conversion or channel change, no se por que pero creo que algo anda ma por ahi. Denuevodejo mi codigo para que me puedas corregir. GRACIAS.
#include <16F886.H>
#device ADC = 10
#fuses HS, NOWDT, NOLVP, PUT, MCLR
#use delay( clock = 20M )
#include <LCD_PORTC.C>
int16 ADC, ADCI, ADCS;
int CamFlag, Pasa, Cont = 0;
#INT_EXT
void ext_isr( void )
{
if( CamFlag == 0 )
{
Pasa = 0;
ext_int_edge( 0, H_TO_L );
CamFlag = 1;
}
else if( CamFlag == 1 )
{
Pasa = 1;
ext_int_edge( 0, L_TO_H );
CamFlag = 0;
}
}
#INT_TIMER0
void TIMER0_isr( void )
{
/*for( ADCI = ADC; ADCI <= ADCS; ADCI++ )
{
output_high( PIN_B2 );
}*/
Cont++;
if( Cont == ADCS )
{
output_high( PIN_B2 );
}
disable_interrupts( INT_TIMER0 );
}
void main( void )
{
//lcd_init();
setup_adc_ports( SAN0 );
setup_adc( ADC_CLOCK_INTERNAL );
set_adc_channel( 0 );
setup_timer_0( RTCC_INTERNAL | RTCC_DIV_4 );
set_timer0( 131 );
CamFlag = 0;
ext_int_edge( 0, L_TO_H );
enable_interrupts( INT_EXT );
enable_interrupts( GLOBAL );
while( 1 )
{
if( Pasa == 0 )
{
ADC = read_adc();
delay_us( 10 );
ADCS = ADC + 1;
if( ADC == 1023 )
{
ADCS = ADC;
//ADC = ADC - 1;
}
enable_interrupts( INT_TIMER0 );
}
else if( Pasa == 1 )
{
output_low( PIN_B2 );
}
}
}
-
hola gente, disculpen si los molesto este es mi primer post, no puedo crear un tema nuevo porq no tengo nivel suficiente y la mayoria de los temas relacionados no tienen actividad hace meses.
estoy intentado hacer un detector de cruce por cero por medio de la interrupciones por flanco, pero resulta que no me funciona no entra nunca a las interrupcion, los molesto para que me puedan dar una mano.
short band_flanco,band_cruce;
void interrupt() {
if(INTCON.INT0IE){
if (band_flanco==1) //aca me fijo cual semiciclo paso
{
band_flanco=0;
}
else
{
band_flanco=1;
}
band_cruce=1;
INTCON.INT0IE=1;
INTCON.INT0IF=0;
}
}
void main() {
unsigned conver=0,retardo=0;
TRISA=0b00000001;
TRISB=0b00000001;
PORTB=0b00000000;
delay_ms(200); // retardo de 200 ms para esperar a que se estabilize la tension
INTCON.GIE=1; // habilito las interrupciones globales
INTCON.INT0IE=1; // habilito la interrupcion externa RB0
OPTION_REG.INTEDG=1; //interrupcion en flanco positivo
band_flanco=1,band_cruce=0;
while(1){
PORTB.B4=1; // esto lo puse para saber si me entraba a la interrupcion
if (band_cruce) // significa q entro por una vez a la interrupcion
{
PORTB.B4=0;
if (band_flanco==1)
{
INTEDG_bit=1; //NO ESTOY SEGURO QUE SE PUEDA RE-CONFIGURAR LAS INTERRUPCIONES UNA VEZ FUNCIONANDO
PORTB.B1=1; // porq viene de detectar el flanco negativo
}
else
{
INTEDG_bit=0;
PORTB.B2=1; // vengo de detectar el flanco positivo, activo estas salida para saber donde estoy
}
delay_ms(5) ; //lo coloque para probar
PORTB.B3=1; //activo triac
delay_ms(2); // lo mantengo para q se dispare el triac
PORTB.B3=0; // desactivo triac
band_cruce=0;
}
PORTB.B1=0; //reinicio las salidas de indicacion de flanco
PORTB.B2=0;
}
}
utilizo un 16f88, soy nuevo programando no tengo ninguna clase de base, la semana pasada gracias a uds aprendi a usar el converso a/d leyendo temas de diferentes foros, y ahora me puse con esto, segui los registro segun la hoja de dato del pic, pero capaz q me falte algo de experiencia.
saludos, gente y gracias.
-
con que lenguaje trabajas? CCS? C18?
-
disculpa mi ignorancia por lo poco que se, creo q utilizo el C18, porq utilizo el Micro C Pro y creo q fue microchip el q creo el C18.
-
entonces es mikroC lo que usas, el C18 es distinto.
en void interrup tienes que poner if(INTCON.INT0IF) no INT0IE
luego INTCON.INT0IF=0 y nada mas.
-
modifique lo me dijiste, ahora genere el .cof y lo utilizo en el proteus y no me entra nunca a la interrupcion
se queda preguntando se band_cruce es uno, significa q no entra a la interrupcion. que puede ser debere configurar otros registros?
short band_flanco,band_cruce;
void interrupt() {
if(INTCON.INTF){
if (band_flanco==1) //aca me fijo cual semiciclo paso
{
band_flanco=0;
}
else
{
band_flanco=1;
}
band_cruce=1;
INTCON.INTE=1;
INTCON.INTF=0;
}
}
void main() {
unsigned conver=0;
retardo=0;
TRISA=0b00000001;
TRISB=0b00000001;
PORTB=0b00000000;
delay_ms(200); // retardo de 200 ms para esperar a que se estabilize la tension
INTCON.GIE=1; // habilito las interrupciones globales
INTCON.INTE=1; // habilito la interrupcion externa RB0
OPTION_REG.INTEDG=1; //interrupcion en flanco positivo
band_flanco=1;
band_cruce=0;
while(1){
PORTB.B4=1; // esto lo puse para saber si me entraba a la interrupcion
if (band_cruce) <---aca se queda y salta a // significa q entro por una vez a la interrupcion
{
PORTB.B4=0;
if (band_flanco==1)
{
INTEDG_bit=1; //NO ESTOY SEGURO QUE SE PUEDA RE-CONFIGURAR LAS INTERRUPCIONES UNA VEZ FUNCIONANDO
PORTB.B1=1; // porq viene de detectar el flanco negativo
}
else
{
INTEDG_bit=0;
PORTB.B2=1; // vengo de detectar el flanco positivo, activo estas salida para saber donde estoy
}
delay_ms(5) ; //lo coloque para probar
PORTB.B3=1; //activo triac
delay_ms(2); // lo mantengo para q se dispare el triac
PORTB.B3=0; // desactivo triac
band_cruce=0;
}
PORTB.B1=0; <---------aca para luego volver a preguntar por ban_cruce //reinicio las salidas de indicacion de flanco
PORTB.B2=0;
}
}
-
no hay mas registros para INT, como es tu circuito electrico?
-
Mil disculpa eso me pasa por simularlo en el proteus, anda perfecto este detector, lo grabe en el micro y lo puse en la placa. el unico problema es que detecta antes el cruce desde el semiciclo positivo al negativo. Pero sabiendo eso se le coloca un retardo de 2ms y se compensa, yo utilizo un trafo de 220 a 12 vac directo a RB0.
-
12V AC directo a RB0????? Creo que dentro de poco te quedaras sin RB0
-
si funciona bien, solo que le pongo una resistencia de 1 M, para limitar la corriente, pero funciona bien gracias a los diodos de sobretension que tienen los pines del pic, jejeej supongo q tambien se le podia poner directo los 220 vac con una resistencia de 5 M pero preferi aislar alta tension por las dudas.
Muchas Gracias, por contestar mis dudas, es la primera que me manejo en un foro y la verdad q me ayudaron mucho, asi q estoy dispuesta a ayudar en lo que pueda.
Un Abrazo
-
los pics no tienen diodos de proteccion en las entradas, unicamente lo que llevan son Schmitt Trigger buffer y TTL buffer. En caso de que superes el voltaje recomendado en el pin estaras deteriorando el buffer, a la larga probablemente deje de funcionar. Por casualidad has visto que voltaje le llega con la resistencia de 1M? O has hecho el calculo "a vista?"
-
El calculo lo realice para que la resistencia me limite la corriente, y al ser una de 1 M, la Intensidad me da 12 uA. Espero que no se me deteriora nada por ahora.
-
Una pregunta, como puedo realizar un retardo menor a 1 ms, se puede con hacer con NOP?
asm{
nop;
nop;
nop;
nop;
nop;
nop;
.
.
}
si se puede, cuanto se demora cada nop?
muchas gracias, saludos
-
¿No demora un ciclo maquina? = tic de reloj
-
Hola a todos les tengo una pequeña contribución, acabo d eterminar un control de fase preliminar con pic 16f688 pero en realidad puede ser cualquiera con ADC. Funciona muy bien el codigo, presento los mismo problema de falta de sincronia pero logre hacer las correcciones quitando todos los delay_us() de la interrupción. Espero que os ayude, realmente no explio mucho porque el codigo es muy simple. la idea es tener un trimer que me permita variar el angulo de disparo del triac que uso como elemento de suicheo.
Codigo fuente en CCS
#include <16F688.h>
#device adc=10
#use delay(clock=8000000)
#fuses INTRC_IO,PROTECT,NOBROWNOUT,NOMCLR,NOCPD,NOWDT,NOPUT,NOIESO,NOFCMEN,BROWNOUT_NOSL
//********** Definiciones de la Memoria RAM ************************************
int8 Arranque;
int16 Trimer;
int32 Angulo_Disparo;
//********** Registros Especiales del CPU **************************************
#byte PORTA=0x05
#byte PORTC=0x07
//*********** Definiciones de los Pines del PIC16f684 **************************
#define LED PIN_C0 // Led de Encendido/ Apagado
#define FASE PIN_C4 // Salida de PWM
//******************** Funciones de Utilidades Especiales **********************
//******************** Sistema Global de Interrupciones ************************
#INT_EXT
VOID STAR(){
if (Arranque==0){// Cambio para el 2do semi ciclo de Onda
ext_int_edge(H_TO_L);
Arranque=1;
}
else{ // Cambio para el 1er semi ciclo de Onda
ext_int_edge(L_TO_H);
Arranque=0;
}
}
//******************** Funciones de Uso General ********************************
void main(void){
setup_oscillator(OSC_8MHZ);
set_tris_a(0x05); // ´00 0101´ Ceros=Salidas, Unos=Entradas
set_tris_c(0x00); // ´00 0000´ Ceros=Salidas, Unos=Entradas
setup_timer_1(T1_DISABLED);
setup_comparator(NC_NC_NC_NC);
setup_adc_ports(sAN0); //Canal 0 analógico
setup_adc(ADC_CLOCK_INTERNAL); //Fuente de reloj RC
output_low(FASE);// Salida Control de Fase Apagada
output_low(LED);
Arranque=0;
while(true){//bucle infinito
set_adc_channel(0); //Habilitación canal0
delay_us(100); //Retardo para preparar Conversor
Trimer = read_adc(); //Lectura del Potenciometro externo
//Numero que va desde 0 -> 1023
if (Trimer>=30){ // Valor de Offset en 3%
if (Trimer<=850){// Maximo 4Vdc
Angulo_Disparo= (8 * Trimer);//X=1/m * Y, 0->180 Grados
output_high(LED);
ext_int_edge(L_TO_H); // Arranco con el 1er semi ciclo de Onda
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
do{
}while(Arranque==0);
delay_us(Angulo_Disparo);// Angulo 1er semicilo de Onda
output_high(FASE); // Ancho de pulso
delay_us(200);
output_low(FASE);
do{
}while(Arranque==1);
delay_us(Angulo_Disparo+800);// Angulo 2do semiciclo de Onda
output_high(FASE);// Ancho de pulso
delay_us(200);
output_low(FASE);
Arranque=0;
}
else{
disable_interrupts(GLOBAL);
output_low(LED);
}
}
else{
Angulo_Disparo=(8 * 30);
output_high(LED);
ext_int_edge(L_TO_H); // Arranco con el 1er semi ciclo de Onda
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
do{
}while(Arranque==0);
delay_us(Angulo_Disparo);// Angulo 1er semicilo de Onda
output_high(FASE); // Ancho de pulso
delay_us(200);
output_low(FASE);
do{
}while(Arranque==1);
delay_us(Angulo_Disparo);// Angulo 2do semiciclo de Onda
output_high(FASE);// Ancho de pulso
delay_us(200);
output_low(FASE);
Arranque=0;
}
}// While Principal
}//Main