Ir ao conteúdo
  • Cadastre-se

Controle de resistencia com PWM


rodrigocirilo

Posts recomendados

@vtrx ah então é mais ou menos o que eu estou tentando, veja o que fiz..

#int_ext void zero_ISR()  {enable_interrupts(INT_TIMER0); enable_interrupts(INT_TIMER1);/*  //    clear_interrupt(INT_RB);       delay_us(brilho);      output_b(0b0000010);          #asm nop #endasm        output_b(0b0000000);     /*    delay_us(brilho1);      output_b(0b0001000);      #asm nop #endasm      output_B(0b0000000);*/      }   #INT_TIMER0void TIMER0 (void){               delay_us(brilho);       output_b(0b0000010);          #asm nop #endasm         output_b(0b0000000);       disable_interrupts(INT_TIMER0);        set_timer0(254);} #INT_TIMER1 //Diretiva de identificação da interrupção do Timer 1  void TIMER1 (void){                  delay_us(brilho1);      output_b(0b0001000);          #asm nop #endasm        output_b(0b0000000);        disable_interrupts(INT_TIMER1);        set_timer1(65534);    }

pelo exemplo no proteus vi que cada int_ext ocorre a cada 5ms, então tenho que calcular os timers dentro desse tempo??

 

Tranquilo amigo você ja está ajudando  muito...

 

Acho que estou no caminho certo, retirei o comando delay_us e ao invés de utilizar este tempo pra variar o instante do pulso eu usei a varivel dentro da sintaxe:

SET_TIMER0(variavel)

SET_TIMER1(variavel)

 

com isso eu retardo o estouro dos timers certo?

 

Editando:

 

Achei o valor certo dos set_timers...

 

e mantive a função DELAY_US com valor sendo variáveis, com isso fui alterando os valores das variáveis e o instante dos pulso foram mudando em relação a senoide....creio que agora irá alterar o "brilho" das resistências....

 

agora eu acho que está certo!!!

Link para o comentário
Compartilhar em outros sites

Eu não usaria os Delay,apenas ache o valor correto para cada;

      output_b(0b0001000);          #asm nop #endasm        output_b(0b0000000);

Calcule para cada timer gerar esta subida e decida em todo o range de meia senoide,tente imitar os sinais no Proteus como se estivesse usando o Delay.

Tipo;

#int_ext void zero_ISR()  {   enable_interrupts(INT_TIMER0);   set_timer0(254);              //ENCONTRE OS VALORES PARA A ONDA   enable_interrupts(INT_TIMER1);   set_timer1(65534);            //ENCONTRE OS VALORES PARA A ONDA          }   #INT_TIMER0void TIMER0 (void){        output_b(0b0000010);          #asm nop #endasm         output_b(0b0000000);        disable_interrupts(INT_TIMER0);} #INT_TIMER1 //Diretiva de identificação da interrupção do Timer 1  void TIMER1 (void){                 output_b(0b0001000);          #asm nop #endasm        output_b(0b0000000);       disable_interrupts(INT_TIMER1);  }

Simule no Proteus e lembre-se que se voce setar os TIMERs com um tempo muito longo,o sinal no osciloscópio do Proteus vai desincronisar(vai ficar girando),deste modo saberá que esta fora do range do detetor zero-cross.

Link para o comentário
Compartilhar em outros sites

Caro amigo @vtrx, eu fiz com os delay mesmo vou postar o codigo abaixo, conforme eu incremento ou decremento  o valor das variaveis (dos delay_us) a posição do pulso muda em relação a senoide.

 

o unico erro que está ocorrendo agora é o seguinte...

 

Linha VERDE do osciloscópio você usou  para o sinal do codigo que você me passou certo?, então conforme você vai incrementando o valor da variavel "brilho" o pulso vai andando para frente( ele está sendo atrasado em relação ao zero-cross) até ai ok

 

dai eu usei a linha vermelha do osciloscopio para o outro canal de PWM usei o port RB3, bem para este usei o timer1 no primeiro o timer0, ok está os dois sincronizados com a senoide...  

 

Mas quando eu vario a variavel que controla a "linha vermelha" RB3 ela é atrasada em relação a senoide, MAS isso afeta o timer0 que também tem seu pulso no caso RB1 atrasado, ele anda junto com a linha vermelha..

 

E como disse o verde não, quando vario a variavel dele, somente ela que muda de posição!!

 

coloquei um LCD para ver os valores das variaveis..

long brilho = 0;long brilho1=0; //-------------------------------------------------#int_ext void zero_ISR()  { //clear_interrupt(INT_RB);   //retirei e não afetou o funcionamento ( também não entendi porque INT_RB, se não estamos usando interrupção do b4~b7 enable_interrupts(INT_TIMER1); enable_interrupts(INT_TIMER0);       /*      delay_us(brilho);      output_b(0b0000010);          #asm nop #endasm        output_b(0b0000000);     /*    delay_us(brilho1);      output_b(0b0001000);      #asm nop #endasm      output_B(0b0000000);*/      }   #INT_TIMER0void TIMER0 (void){               delay_us(brilho);       output_b(0b00000010);           #asm nop #endasm         output_b(0b00000000);         disable_interrupts(INT_TIMER0);        set_timer0(245);} #INT_TIMER1  void TIMER1 (void){                  delay_us(brilho1);     output_b(0b00001000);            #asm nop #endasm        output_b(0b00000000);         disable_interrupts(INT_TIMER1);        set_timer1(62900);    } //------------------------------------------------void main()      {      lcd_init();      setup_comparator(NC_NC_NC_NC); //     enable_interrupts(int_rb);   //retirei // não sei o porque estava ativa      output_b(0b00000000);      set_tris_b(0b01110101);           ext_int_edge(L_TO_H);            enable_interrupts(INT_EXT);      disable_interrupts(INT_TIMER1);      disable_interrupts(INT_TIMER0);      enable_interrupts(GLOBAL);            SETUP_TIMER_0(RTCC_INTERNAL | RTCC_DIV_1);      SETUP_TIMER_1(T1_INTERNAL|T1_DIV_BY_1);  set_timer0(245); SET_TIMER1(62900);//------------------------------------------------        while(true)   {      if(input(PIN_B2))      {         brilho=brilho+50;   // incrementa timer0         delay_MS(20);      }      if(input(PIN_B4))      {         brilho=brilho-50;   //decrementa timer0         delay_ms(20);      }      if(input(PIN_B5))      {         brilho1=brilho1+50;  //incrementa timer1         delay_MS(20);      }      if(input(PIN_B6))      {         brilho1=brilho1-50;  //decrementa timer1         delay_ms(20);      }            lcd_gotoxy (1,1);                                    printf (lcd_putc,"%Lu     %Lu",brilho,brilho1);               //  delay_ms(50);    }               }

Aqui os dois PWM sincronizados em relação a senoide:

 

o9tq.png

 

Aqui a variável da "linha verde" incrementada andou para frente, "foi atrasada" e a vermelha ficou parada:

 

mzv5.png

 

 

 

Aqui a variável da "linha vermelha" incrementada andou para frente mas arrastou a verde junto:

 

8ht.png

Link para o comentário
Compartilhar em outros sites

Pelo amor de DEus, fechei o topico com mesmo nome sem querer...

 

amigo @vtrx pode postar aqui ou me encaminhe MP até ser destravado..

 

Att.

 

Rodrigo Cirilo

 

O email [email protected] foi devolvido com a mensagem 

  • Delivery Status Notification (Failure)‏

onde fiz contato para destravar o topico...

Link para o comentário
Compartilhar em outros sites

Algum moderador poderia destravar o topico http://forum.clubedohardware.com.br/forums/topic/1059529-controle-de-resistencia-com-pwm/

 

pois coloquei resolvido sem querer....

 

 

Amigo @vtrx você conseguiu baixar o arquivo do proteus?? tem ideia do que pode causar isso....

Link para o comentário
Compartilhar em outros sites

Ja fiz o código,mas o CCS não está  aceitando usar variáveis para controlar a recarga dos TIMERs.

Ou é BUG da versão que tenho ou é alguma regra que tenho que ler no manual do CCS,mas não vou fazer isto,vou usar uma tabela com os valores pré-gravados.

Só depois do meu almoço eu posto.

Link para o comentário
Compartilhar em outros sites

Ja fiz o código,mas o CCS não está  aceitando usar variáveis para controlar a recarga dos TIMERs.

Ou é BUG da versão que tenho ou é alguma regra que tenho que ler no manual do CCS,mas não vou fazer isto,vou usar uma tabela com os valores pré-gravados.

Só depois do meu almoço eu posto.

Tranquilo, mas está ocorrendo o que postei no outro topico??  de uma canal funcionar corretamento e o outro interfere no primeiro???  estranho...a versão do meu CCS é 4.104..

 

No aguardo..

Link para o comentário
Compartilhar em outros sites

@aphawk nossa cara tá difícil hehehe...  fazer os dois canais via timers, usando o interrupção externa (detectando a passagem por zero)  tá funcionando....

 

...Mas o problema é que um canal varia o pulso certinho em relação a senoide e o outro fica parado quando não atuado.. Mas quando atuo neste ele varia o pulso dele e do outro que nao está sendo atuado...

 

e isso tá difícil...

 

To até pensando em usar 2 pic´s 16F628A um para cada canal, interliga-los via serial para um deles exibir no lcd...

 

o que você acha?  

 

Qual era sua logica??

 

e obrigado por perguntar... :)

 

Editando:

 

Sabem o que eu descobri, que com a interrupção externa habilitando os dois timers o timer que fica em primeiro na sequencia do programa afeta o segundo, o segundo timer na sequencia do programa funciona normalmente.

 

funciona igual se eu colocar os dois pulsos dentro do tratamento da interrupção externa, variando o tempo do primeiro pulso irá afetar o do segundo...variando o tempo somente do segundo pulso o primeiro nao é afetado.

 

 

aqui direto na leitura da passagem por zero (via INT_EXT)

 #int_ext void zero_ISR()  {     delay_us(brilho);            //   <====   variando aqui ele afeta o segundo, pois tem que esperar esse tempo     output_b(0b00001000); // logo o pulso ali embaixo tbm terá de esperar esse tempo, fazendo os pulsos           #asm nop #endasm      //andarem junto na simulação (osciloscopio)      output_b(0b00000000);        delay_us(brilho_1);      //// <====  Mas variando somente esse, o primeiro não é afetado, somente este     output_b(0b00000010);     // pulso que variar o momento do pulso.       #asm nop #endasm        output_b(0b00000000);          } 

 

Aqui a INT_EXT habilita os timer 0 e 1 e no tratamento de suas funções que ocorrem os pulsos.

 

estranho que mesmo sendo timers diferentes ocorre o mesmo que no codigo acima...

 

 #int_ext                            //// habilita a contagem dos timers na passagem por zerovoid zero_ISR()  {  enable_interrupts(INT_TIMER1); enable_interrupts(INT_TIMER0); set_timer0(245); set_timer1(62900);    }   #INT_TIMER0                   void TIMER0 (void){        delay_us(brilho);              //// variando aqui, afeta o timer de baixo no caso o timer1, mesmo sendo     output_b(0b00001000);     /// timers diferentes       #asm nop #endasm        output_b(0b00000000);              disable_interrupts(INT_TIMER0);               set_timer0(245);} #INT_TIMER1  void TIMER1 (void){            delay_us(brilho_1);             ////variando aqui somente esse é atrasado em relação a senoide, o timer0       output_b(0b00000010);     // se mantem igual.       #asm nop #endasm         output_b(0b00000000);         disable_interrupts(INT_TIMER1);              set_timer1(62900);    } 
Link para o comentário
Compartilhar em outros sites

@rodrigocirilo,

 

Claro que pode fazer o PWM ! 

 

Não me lembro mais dos PIC's, mas me parece que por hardware mesmo só tem um canal. Então,, para evitar problemas, faça por software !

 

Se fosse com os Avr's, teria 6 canais kkkkkkk mas vamos em frente.... vamos fazer por software mesmo.

 

Eu usaria uma interrupção do timer como base de tempo. Faria uma conta para que durante o ciclo da senóide minha base de tempo contaria de 0 até 99, assim teria um controle em nível de 1% , mais do que suficiente para muita coisa....., e baseado nessa conta programo o meu Timer para gerar essa frequência. Por exemplo , 100 *60 = 6 Khz . 

 

Criaria dois contadores, um para cada canal PWM, que seriam incrementados automáticamente pela minha rotina de base de tempo.

 

Quando houver a interrupção por cruzamento de zero, eu zero os dois contadores, e permito que a contagem inicie.

 

No meu programa principal, fico comparando os valores dos contadores com os valores desejados, e tomo a ação de mudar o nível da saída correspondente. Então fico parado sem fazer nada, esperando a próxima interrupção para zerar os contadores, e aí vai....

 

Simples , não é ?

 

Paulo

@aphawk Paulo, poderia explicar melhor essa logica, acho que ela seria o caminho, mas ficou um pouco confuso para mim...

 

 

Editando:

 

@aphawk estou seguindo sua logica, mas preciso que alguem me responda por favor os timer 0 e 1 dividem algo dentro do pic, um oscilador por exemplo, pois nem com a logica do Paulo um timer executado primeiro influencia no segundo.. :(

 

 

 

Editando novamente: rsrsrs

 

Aos amigos @aphawk e @vtrx  

 

Bom seguindo a lógica proposta pelo colega Paulo, eu consegui fazer os pulsos (PWM) variarem individualmente.

 

Pergunto:  Após a interrupção externa detectar a passagem por zero, quanto mais rápido eu disparar o TRIAC mais potencia terei certo? e quanto mais eu demorar menos potencia.

 

seguindo essa lógica, na imagem abaixo terei no pulso que está vermelho 50% da potencia e no pulso verde 75% da potencia na saida certo?

 

ahm8.png

Link para o comentário
Compartilhar em outros sites

@rodrigocirilo,

Sim, isso mesmo ! Mas não é tão linear assim. Falando em angulos para você entender melhor :

Suponha que no inicio da subida da senóide o angulo é 0 graus, e no pico superior o angulo é 90 graus, ok ?

Se você disparar assim que cruzar o zero ( 0 graus ) , terá 100% da potencia;

Se disparar em 90 graus, tera 50% ;

Mas, se disparar em 45 graus, não quer dizer que terá 75% , pois a subida não é linear ! Mas pode imaginar que terá algo próximo a esse valor; a conta para calcular a potencia real é bem chatinha, pois é uma integral.

A minha ideia sempre foi os dois canais serem totalmente independentes um do outro, me parece que foi isso que você fez, certo ?

Paulo

Link para o comentário
Compartilhar em outros sites

@aphawk então Paulo pensei que fosse bem linear mesmo... mas digamos que em relação ao brilho da "lampada" ou calor da "resistência" será linear??

 

Bom sábado vou montar na protoboard pra fazer uns testes com lampadas e resistências...

 

O  que eu penei no codigo, foi como citei mais acima... usando o timer0 e o timer1 , totalmente independestes no quesito variáveis, mas mesmo assim a função que estava declarada primeiro no corpo do programa, influenciava a segunda função, e a segunda nada fazia com a primeira, estanho né..

 

Não achei solução e tambem não consegui dicas aqui sobre isso, foi então que resolvi reler sua postagem daquela logica.... e comecei a trabalhar em cima dela....e consegui.. EUREKA, ainda bem que não mosquei em fio!!

 

da uma olhada e vê o que você acha??

 

 #int_ext void zero_ISR()  {  enable_interrupts(INT_TIMER0);   set_timer0(200); }   #INT_TIMER0void TIMER0 (){  temp++;  temp1++;    if(temp==brilho)      {             output_b(0b00100000);            #asm nop #endasm                output_b(0b00000000);               chave1=true;         if(chave==true)            {               disable_interrupts(INT_TIMER0);               temp1=0;               temp=0;                chave=false;                chave1=false;            }      }            if(temp1==brilho_1)     {         output_b(0b01000000);           #asm nop #endasm         output_b(0b00000000);              chave=true;         if(chave1==true)         {          disable_interrupts(INT_TIMER0);            temp1=0;          temp=0;          chave=false;          chave1=false;         }      }               set_timer0(200);} 
Link para o comentário
Compartilhar em outros sites

@rodrigocirilo,

Kkkk certinho, voce não moscou não !!!!!!!

Infelizmente não sei se o código que voce postou acima é em lingua portuguesa ou lingua alienígena ( kkkkk ), não entendo nadinha de C meu amigo, fico te devendo sobre isso.

Mas quanto a potência, acredite, é verdade o que falei... Embora seja fácil controlar o tempo linearmente após o crossover, isso não faz com que o controle da potência seja linear. O problema é que a forma de onda da tensão é senoidal.

Se voce precisa fazer isso de uma maneira linear, eu sugiro que voce crie uma tabela, com a seguinte correspondência : voce entra nela com o percentual que deseja de potência, e ela te retorna o tempo exato que voce precisa para isso.

Desta maneira fica bem rápido o código, basta voce colocar a equação no Excel e fazer os cálculos de 1 em 1 % , indo de 0 até 180 graus.

Vou procurar a equação e posto aqui.

Update : achei a equação.... Espero que seus conhecimentos estejam em dia....

http://www.dsce.fee.unicamp.br/~antenor/pdffiles/eltpot/cap10.pdf

Procure pela página 10-3, equação marcada como (10.3) , ela te informa o valor da tensão eficaz sobre uma carga resistiva ( portanto, a potência seria proporcional ao quadrado deste valor ! ) em função do angulo de disparo e serve para esta sua aplicação .

Paulo

Link para o comentário
Compartilhar em outros sites

@aphawk  para mim Língua alienígena é ASM é simplesmente impossível eu conseguir aprender isso, nunca tentei e acho que nunca tentarei...

 

Nossa quando eu penso que consegui rsrsrsrs.. sempre tem uma equação pra resolver. kkkk impossível de eu conseguir resolver essa conta, mas agradeço ter postado o link....

 

então Paulo, eu percebi que no codigo que fiz,  com a configuração que está o timer0, para disparo imediato do pulso, a variável brilho tem que ter valor minimo no caso 1 e para disparo quase no fim da senoide (antes da proxima passagem por zero) posso chegar no valor maximo de 70.

 

com isso vou fazer alguns testes de bancada, variando de 70 até 1 e ver como a resistencia se comporta... e tirar medições de tensão... com esses dados reais, ai posso fazer o codigo trabalhar para "tentar" a maxima linearidade

 

abrs

Link para o comentário
Compartilhar em outros sites

@rodrigocirilo,

 

Olha, ASM eu tiro de letra.... , isto é, tirava.... mas C , é só para a geração videogame kkkk .

 

Mas hoje só programo em Basic, cansei de sofrer. Tá tudo prontinho prá cada periférico interno, ganho um tempão com isso.

 

Cara, não se assuste com aquela equação, é só montar no excel, e gerar "coeficientes" em função do angulo ! Assim basta voce consultar essa tabela no seu programa, e multiplicar a tensão AC pelo coeficiente, elevar ao quadrado, e dividir pela resistência para obter a potência.

 

Mas se quiser pode levantar essa equivalencia pelo método prático, que é exatamente o que você falou que vai fazer...

 

Paulo

Link para o comentário
Compartilhar em outros sites

Seguinte,ainda não abandonei o código,mas estou programando em uma outra plataforma e pretendo acabar isso primeiro.

Percebí que @rodrigocirilo não conhece programação usando CCS,eu programo,as vezes,com CCS mas sempre que avança alguma rotina mais complexa,ele deixa a desejar.

Não tenho paciencia em ler todo o manual e frequentar os foruns de CCS,por isso só vou postar o resultado final se conseguir tudo funcionando corretamente,e neste momento o CCS não está se comportando como devia(seguindo as intruções),mas acho que chegaremos la´...

 

PS:não tenho nenhum outro compilador C para PIC da familia 16F.

Link para o comentário
Compartilhar em outros sites

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

 

GRÁTIS: ebook Redes Wi-Fi – 2ª Edição

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!