Controlo de Fase

Software e Hardware para uC PIC

Moderadores: andre_luis, 51, guest2003, Renie

Controlo de Fase

Mensagempor Adrian Lemos » 12 Set 2012 08:29

Bom dia pessoal do forum.

Estou desenvolvendo um circuito para controlar várias cargas resistivas por PWM com o pic16f876A, (projetinho de semestre da faculdade) a idéia é colocar o máximo de canais possíveis e os testes inicias foram com 8 porem estou com o seguinte problema.

O circuito detector de Zero está ok a cada cruzamento tenho um pulso perfeito de + - 200us, faço a leitura da borda de subida e aciono um led "tudo perfeito apenas para teste", porém quando faço o acionamento do optoacoplador, colocando o canal 1 do osciloscopio no detector de zero e o canal 2 na porta do pino do moc, o tempo de acionamento fica variando em relacao ao zero e por consequência a lâmpada fica com a intensidade variando. Ja fiz algumas tentativas de ligar e deligar o timer e a int 0 em pontos diferentes mas sem sucesso.

A idéia do software é a cada cruzamento por zero, ele liga o timer e a cada 200us ele faz um incremento, sendo assim ele permanece em zero ou liga o pino do moc, dividindo os 8.33ms por 200us eu teria aproximadamente 41 niveis, porém não inicializo do zero e vou até +-90% da potencia máxima.

A solução é conseguir ligar o pino da porta do moc sempre na mesma base de tempo, pois como está variando o triac é acionado em pontos difentes, eu não sei o que está gerando essa variação dentro do software, pois a rotina é praticamente travada, os botões estão no main principal.

Grato;

O código está meio poluido devido aos testes, e nesta versão acabei bagunçando algumas temporizações.... mas o que eu preciso entender é lógica de como posicionar melhor a hora de ligar e desligar as interrupções de forma geral.

Segue o código.


Código: Selecionar todos
// Pic16f876 Controle de fase
// Cristal 20MHZ
//

#include <pic.h>
#include <stdlib.h>
#include <stdio.h>

#define   RELOAD_TMR0() { TMR0 -= 6; } // 6

#define REF_FASE                     PB0
//#define BOTAO_1                 PB5
//#define BOTAO_2                      PB4
//#define BOTAO_3                      PB3
//#define BOTAO_4                      PB2

#define TRIAC_1                 RC6 //6  //1
#define TRIAC_2                      RC7 //7  //2
//#define TRIAC_0                      RC0
#define TRIAC_3                      RC3
#define TRIAC_4                      RC4
#define TRIAC_5                      RC5
#define TRIAC_6                      RC6
#define TRIAC_7                      RC7
#define BT_INC                   RB5//RD1
#define BT_DEC                   RB4//RD0
   
#define LEDC0                   RC0
#define LEDC1                   RC1
#define LEDC2                   RC2

 unsigned int tempo,tempo2,conta_tempo;
 unsigned int Bounce;
 unsigned char varredura,potencia_1,potencia_2;
 unsigned char x,y;
 unsigned char TimerContador;

__CONFIG( HS & WDTDIS & PWRTEN & UNPROTECT & BOREN & LVPDIS  & DEBUGEN );

delay_ms (unsigned int tempo);
//escreve_adc(void);
unsigned int le_ad (unsigned char Canal_Adc); // Rotina Leitura Conversor A/D.

void main ()
{   
  //-----GERAL-----
  //OPTION = 0b001000100;       // 
 
  OPTION = 0b11000010;       // 001 6 -> 200us.   010 6 --> 400us.
  INTCON = 0b11110000;       // habilita int global e perifericos .
  //INTCON = 0b11111010;       // habilita int global e perifericos .
 
  //------I/O---------
  TRISA  = 0b11111111;       // Configura  1 in /  0 out
  TRISB  = 0b11111111;          // 18f877 00110001;     
  TRISC  = 0b00000000;
//  TRISD  = 0b11111111;
 
  PORTA  = 0b00000000;
  PORTB  = 0b11111110;        // 18f877 00000010;
  PORTC  = 0b00000000;
  //PORTD  = 0b01111111;
   
  //-----SERIAL------        //8 bits / Baud
  PIE1 = 0b00100000;         // bit 5 = 1 serial modo de interrupcao
  PIR1 = 0b00000000;
 
 //   x = 5;
//   y = 5;
    //TMR0IE = 0; 
               
   for(;;)
   {      
      if(BT_INC == 0)
      {
         //TRIAC_0 = 1;
         LEDC0 = 1;
         Bounce = 500;
            while( Bounce-- );
            while( BT_INC == 0 );
         x = x + 1;
         if (x > 18) //26
         {
            x = 18;
         }
         LEDC0 = 0;
      }
      
      if(BT_DEC == 0)
      {         
         //   TRIAC_0 = 1;
         LEDC1 = 1;
         Bounce = 500;
            while( Bounce-- );
            while( BT_DEC == 0 );
         x = x - 1;
         if (x < 2 )
         {
            x = 2;
         }
         //TRIAC_0 = 0;
         LEDC1 = 0;
      }
      
      /*while( BT_INC == 1 );
      if(BT_INC == 1)
      {
         if (x == 0)
         {
            x = 12;
         }
         TRIAC_0 = 0;
      }
      */
      
               
   }
}      
   
interrupt void ISR ( void ) // Rotina Timer 0.
{
  if( TMR0IF && TMR0IE ) 
  {
     TMR0IF = 0;          // limpa Flag do timer 0
      RELOAD_TMR0();       // Faz recarga do Timer0.
      // TRIAC_0 = 1;
     //TRIAC_0 = 0;
   
     if (TimerContador > 4)
     {
           
        if(TimerContador == x)
       {
          TRIAC_1 = 1;
       }
      /* if(TimerContador == x)
       {
          TRIAC_2 = 1;
       }   
      
      //if(TimerContador == 3)
      //{
      //   TRIAC_0 = 1;
      //}
      
       if(TimerContador == 1)
       {
          TRIAC_3 = 0;
       }
       if(TimerContador == 1)
       {
          TRIAC_4 = 0;
       }
       if(TimerContador == 1)
       {
          TRIAC_5 = 0;
       }   
       if(TimerContador == 1)
       {
          TRIAC_6 = 0;
       }   
       if(TimerContador == 1)
       {
          TRIAC_7 = 1;
       }*/
    }
   
    if(TimerContador > 15) 
     {
        TMR0IE = 0;
        TRIAC_2 = 0;
        TRIAC_1 = 0;
      
        //TRIAC_0 = 0;
        
        //TRIAC_3 = 0;
        //TRIAC_4 = 0;
        //TRIAC_5 = 0;
        //TRIAC_6 = 0;
        //TRIAC_7 = 0;
        
        TimerContador = 0;
        //INTF = 0;       
    }
   
    TimerContador++;
   
     if(conta_tempo)
     conta_tempo--;
  }
 
  if(INTE && INTF)
  {
     TMR0IE = 1;
     INTF = 0;    
     LEDC2 = 1;
     LEDC2 = 0;
    
     //TRIAC_0 = 1;
     //TRIAC_0 = 0;    
 
  }         
   
}
/*
delay_ms (unsigned int tempo)
{
  conta_tempo = tempo + 1;
  while( conta_tempo );
} */
Ainda não sei, mas uma hora vou saber...
Adrian Lemos
Bit
 
Mensagens: 7
Registrado em: 09 Jul 2010 21:26
Localização: Campinas - SP

Mensagempor ze » 12 Set 2012 13:03

se não se importa vou dar um baita chute. sua entrada de ref de fase não é do tipo smicth trigger portanto o momento da transição não é muito definido. Use uma entrada que tenha tal característica ou coloque uma porta sm.tg. externa. doeu?
Outra coisa eu prefiro fazer if (x>=y)... do que (x==y) pois esta última pode não ocorrer caso x++ seja feito 2x antes de avaliar. (nem sei se me eu mesmo me autoentendi....confuso...)
sucessos
Avatar do usuário
ze
Dword
 
Mensagens: 1655
Registrado em: 05 Jun 2007 14:32

Mensagempor Adrian Lemos » 12 Set 2012 14:44

Lellis boa tarde;

Em relação a Refêrencia de fase olhando no osciloscópio ela está Ok, até modifiquei a rotina acinando um led e o pulso fica cravado, porém entendi seu ponto de vista.

Em relação ao if(X>=y) também modifiquei e a oscilação do pino de saída que aciona o moc em relação a referencia de fase melhorou uns 80% mas aleatóriamente acontece pequenas variações dando a impressão de que hora a int do timer tem um tamanho, hora tem outro dentro de um ciclo.

Fiz alguns testes modificando a hora de trocar o estado da flag da int0 e a int do timer mas mesmo assim sem novidades :(

Sigo nos testes....
Ainda não sei, mas uma hora vou saber...
Adrian Lemos
Bit
 
Mensagens: 7
Registrado em: 09 Jul 2010 21:26
Localização: Campinas - SP

Mensagempor ze » 12 Set 2012 16:26

permita-me mais chutes... A cada ocorrencia do if o tamanho fica diferente mesmo. Tente trocar "if (...)" por "switch...case...break" pra ver se sincroniza melhor. Talvez não. Mas vais notar que vai ocupar um pouco mais de espaço.
Também, se souber quando e onde ocorrem, tente compensar as diferenças com asm NOP´s
Ah esta última dica vai resolver: não desista!
boa sorte
Avatar do usuário
ze
Dword
 
Mensagens: 1655
Registrado em: 05 Jun 2007 14:32

Mensagempor Adrian Lemos » 12 Set 2012 17:18

Estou re-pensando a rotina, ela ficou com muitos if´s.... "case" ainda não consegui visualizar uma saída... depois de dimerizar eu ainda pretendo alterar os canais via algum protocolo de rede.

Estou analisando a possibilidade de otmizar a rotinha trabalhando com pulso do moc invertido, onde é 1 vira 0 e vice versa... ou mesmo colocar um shift register além de servir de buffer para o uC...
Ainda não sei, mas uma hora vou saber...
Adrian Lemos
Bit
 
Mensagens: 7
Registrado em: 09 Jul 2010 21:26
Localização: Campinas - SP

Mensagempor vtrx » 12 Set 2012 19:15

Voce deve ter uma rotina de interrupção externa a cada passagem por zero,e manter o triac disparado por X tempo logo que a interrupção externa for disparda.
Avatar do usuário
vtrx
Dword
 
Mensagens: 2239
Registrado em: 20 Abr 2008 21:01

Mensagempor Adrian Lemos » 13 Set 2012 08:26

Sim VTRX ja está assim.

1 -A int externa apenas liga o timer.
2- O timer0 interrompe a cada 200us para gerar os niveis, dentro de 8.33ms / 0.2ms me da condições de ter aproximadamente 40 níveis de tensão. Após isso eu zero os contadores, zero as respectivas flag´s.

Porém a porta (meu software) que aciona o moc está gerando uma latência quando eu faço o trigger pelo osciloscópio no cruzamento por zero, vejo que o pino nunca está acionando na mesma base de tempo, ele apresenta uma variação de +-300us o que significa uma variação de +- 7 volts em cima da lampanda causando oscilação visual.
Ainda não sei, mas uma hora vou saber...
Adrian Lemos
Bit
 
Mensagens: 7
Registrado em: 09 Jul 2010 21:26
Localização: Campinas - SP

Mensagempor J » 13 Set 2012 08:57

O Lellis chutou em cheio ...

Já precisei usar isso e a solução foi utilizar um Schmitt trigger ...

Dependendo de como foi projetado o circuito de detecção do zero ele erra sempre ... e o pior é que o erro não é constante ...

Eu utilizei um Timer a 100us, mas a leitura fazia a cada 200us ...

tratei os valores em porcentagem para poder acionar a saída com controle PID.

Dividí cada semiciclo em 32 partes dando ênfase para a máxima potência (ou seja, começava já com um "recorte da senóide" com uma área um pouco maior)

Funcionou muito bem ... (usei isso no meu TCC)
J
Nibble
 
Mensagens: 74
Registrado em: 13 Jan 2009 02:49

Mensagempor Adrian Lemos » 13 Set 2012 09:34

Eu também desconfiei do circuito de Detector de zero, mas eu fiz o sequinte teste.

Mudei o codigo para ligar um led auxiliar assim que ele entra-se na int do timer 0 após uma passagem por Zero e ai ficou ok (visualizando no osciloscopio), porém quando a rotina se extende um pouco mais o problema aparece, onde é a parte que eu testo os níveis dos demais canais. Simplificando o código para 1 ou 2 canais o problema aparece lembrando que a idéia inicial seriam de pelo menos 8 canais.
Ainda não sei, mas uma hora vou saber...
Adrian Lemos
Bit
 
Mensagens: 7
Registrado em: 09 Jul 2010 21:26
Localização: Campinas - SP

Mensagempor vtrx » 13 Set 2012 18:48

Sim VTRX ja está assim.

+-,faça um teste.
Interrupção externa é dispara e neste evento voce dispara o Triac,aguarda um tempo fixo e corta o Triac.
Verifique se fica estável.
Claro que as outras rotinas não podem demorar mais tempo que o tempo mínimo de disparo do Triac para 'efeito' de 'desligado'.
Quando voce cita que 'testou com Leds',voce quer dizer algo parecido com o do link?
http://www.youtube.com/watch?v=lsGNHgkuT_0
Avatar do usuário
vtrx
Dword
 
Mensagens: 2239
Registrado em: 20 Abr 2008 21:01

Mensagempor Adrian Lemos » 14 Set 2012 14:17

Agora azedou a boca da égua !

Modifiquei o código isolando as int´s deixando apenas o timer0 rodando a 200us ligando e desligando a porta e a surpresa, algo está errado pois os valores medidos não bate com o calculado..... eu ja tinha conferido isso e estava ok :(

De volta ao Zero... :)
Ainda não sei, mas uma hora vou saber...
Adrian Lemos
Bit
 
Mensagens: 7
Registrado em: 09 Jul 2010 21:26
Localização: Campinas - SP

Mensagempor ze » 14 Set 2012 16:03

pode ser problema com o compilador. Deixe todas as otimizações desligadas e depois ligadas (não necessariamente nesta ordem). Reinsta-le, re-formate, re-encarne, re-sefôda...

Se um ou dois ciclos perdidos não fizerem muita falta, uma maneira teórica maluca de controlar varios canais pwm um pouco + otimizada
Código: Selecionar todos
#define triacx RBx //entendeu né?

void interrup(void){
...
if (dc0<dt) triac0=0; else triac0=1;
if (dc1<dt) triac1=0; else triac1=1;
if (dc2<dt) triac2=0; else triac2=1;
if (dc3<dt) triac3=0; else triac3=1;
if (dc4<dt) triac4=0; else triac4=1;
if (dc5<dt) triac5=0; else triac5=1;
if (dc6<dt) triac6=0; else triac6=1;
if (dc7<dt) triac7=0; else triac7=1;

dt++;
...
}

e no main() voce controla os dutty cicle. faça por brincadeira pra ver que merdadá:
Código: Selecionar todos
for(;;)
{
while(_zerocross);while(!_zerocross);//sincronizado com a rede
dc0=64; //p.ex.
dc1=a++;//p.ex.
}

si mula, com proteus.
ou dá uma olhada no espelho pra ver se não acha o problema. rs.
bfds!
Avatar do usuário
ze
Dword
 
Mensagens: 1655
Registrado em: 05 Jun 2007 14:32

Mensagempor vtrx » 15 Set 2012 00:32

Ja que voce esta usando C18,de uma 'apelada' para saber se o compilador não está pensando muito 'por conta própria'.
Declare as variáveis como volatile.

Código: Selecionar todos
volatile unsigned int tempo,tempo2,conta_tempo;
volatile unsigned int Bounce;
volatile unsigned char varredura,potencia_1,potencia_2;
volatile unsigned char x,y;
volatile unsigned char TimerContador;
Avatar do usuário
vtrx
Dword
 
Mensagens: 2239
Registrado em: 20 Abr 2008 21:01

Mensagempor Eliomarjj » 26 Set 2012 12:47

Experimenta compensar com hardware, coloque alguns capacitores de filtro. :idea: :shock:
Eliomarjj
Bit
 
Mensagens: 23
Registrado em: 27 Jan 2010 12:01

Mensagempor Adrian Lemos » 27 Set 2012 17:02

Desculpe pela ausencia estou em semana de provas!

fiz algumas modificações no software, mudei o momento de resetar o timer0 e etc...mas não obtive sucesso.

resolvi fazer um video do problema que esta acontecendo segue anexo o link para visualização.

http://youtu.be/3NOTe_YhvQU

o canal amarelo indica os pulsos da refência de fase - Ok
o canal azul significa o disparo de um canal do Dimmer, é nitida a variação do pulso de disparo.

Eliomarjj, em que local do circuito ligar os capacitores e quais os valores para testes?

fico no aguardo
Ainda não sei, mas uma hora vou saber...
Adrian Lemos
Bit
 
Mensagens: 7
Registrado em: 09 Jul 2010 21:26
Localização: Campinas - SP


Voltar para PIC

Quem está online

Usuários navegando neste fórum: Nenhum usuário registrado e 1 visitante

cron

x