Autor Tema: Control de Fase con Interupciones  (Leído 18291 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Control de Fase con Interupciones
« 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.

Código: [Seleccionar]
#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
El papel lo aguanta todo

Desconectado firepic

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1130
    • JC Servicios
Re: Control de Fase con Interupciones
« Respuesta #1 en: 04 de Mayo de 2008, 03:13:01 »
Saludos MLO! Oye muy bueno!  :-/ Gracias por el aporte!
Aquí ya somos unos cuantos que estamos engomados  :D
Ok nos leemos!  :mrgreen:
"Por la presunción solo se ocasiona una lucha, pero con los que consultan juntos hay sabiduría" (Proverbios 13:10).
Visita Mi Sitio Web

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2568
Re: Control de Fase con Interupciones
« Respuesta #2 en: 04 de Mayo de 2008, 05:10:43 »
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

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: Control de Fase con Interupciones
« Respuesta #3 en: 05 de Mayo de 2008, 01:12:53 »
Hola Pocher.

No se si te entendi bien ... espero que si ... me avisas si era otra cosa  :mrgreen:

Código: [Seleccionar]
#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.
El papel lo aguanta todo

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2568
Re: Control de Fase con Interupciones
« Respuesta #4 en: 05 de Mayo de 2008, 02:10:57 »
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.


Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: Control de Fase con Interupciones
« Respuesta #5 en: 05 de Mayo de 2008, 02:44:45 »
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.
El papel lo aguanta todo

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2568
Re: Control de Fase con Interupciones
« Respuesta #6 en: 05 de Mayo de 2008, 15:44:02 »
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

Desconectado firepic

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1130
    • JC Servicios
Re: Control de Fase con Interupciones
« Respuesta #7 en: 05 de Mayo de 2008, 15:48:36 »
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:
"Por la presunción solo se ocasiona una lucha, pero con los que consultan juntos hay sabiduría" (Proverbios 13:10).
Visita Mi Sitio Web

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: Control de Fase con Interupciones
« Respuesta #8 en: 05 de Mayo de 2008, 16:09:49 »
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.
El papel lo aguanta todo

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2568
Re: Control de Fase con Interupciones
« Respuesta #9 en: 06 de Mayo de 2008, 01:58:08 »
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

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: Control de Fase con Interupciones
« Respuesta #10 en: 06 de Mayo de 2008, 12:48:09 »
Ok!!!

Esas cosas pasan .... y muy a menudo. Me alegra que solucionaras el problema.

Saludos
El papel lo aguanta todo

Desconectado MexaTronko

  • PIC10
  • *
  • Mensajes: 38
Re: Control de Fase con Interupciones
« Respuesta #11 en: 16 de Julio de 2011, 03:51:33 »
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 )
         {
         }
   }

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: Control de Fase con Interupciones
« Respuesta #12 en: 17 de Julio de 2011, 00:06:57 »
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
El papel lo aguanta todo

Desconectado MexaTronko

  • PIC10
  • *
  • Mensajes: 38
Re: Control de Fase con Interupciones
« Respuesta #13 en: 18 de Julio de 2011, 00:16:42 »
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 );
               }
         }
   }

Desconectado MexaTronko

  • PIC10
  • *
  • Mensajes: 38
Re: Control de Fase con Interupciones
« Respuesta #14 en: 18 de Julio de 2011, 04:58:52 »
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 )
         {
         }
   }