Ir ao conteúdo
  • Comunicados

    • Gabriel Torres

      Seja um moderador do Clube do Hardware!   12-02-2016

      Prezados membros do Clube do Hardware, Está aberto o processo de seleção de novos moderadores para diversos setores ou áreas do Clube do Hardware. Os requisitos são:   Pelo menos 500 posts e um ano de cadastro; Boa frequência de participação; Ser respeitoso, cordial e educado com os demais membros; Ter bom nível de português; Ter razoável conhecimento da área em que pretende atuar; Saber trabalhar em equipe (com os moderadores, coordenadores e administradores).   Os interessados deverão enviar uma mensagem privada para o usuário @Equipe Clube do Hardware com o título "Candidato a moderador". A mensagem deverá conter respostas às perguntas abaixo:   Qual o seu nome completo? Qual sua data de nascimento? Qual sua formação/profissão? Já atuou como moderador em algo outro fórum, se sim, qual? De forma sucinta, explique o porquê de querer ser moderador do fórum e conte-nos um pouco sobre você.   OBS: Não se trata de função remunerada. Todos que fazem parte do staff são voluntários.
    • DiF

      Poste seus códigos corretamente!   21-05-2016

      Prezados membros do Fórum do Clube do Hardware, O Fórum oferece um recurso chamado CODE, onde o ícone no painel do editor é  <>     O uso deste recurso é  imprescindível para uma melhor leitura, manter a organização, diferenciar de texto comum e principalmente evitar que os compiladores e IDEs acusem erro ao colar um código copiado daqui. Portanto convido-lhes para ler as instruções de como usar este recurso CODE neste tópico:  
José Caetano

Dúvida em melhorar PWM

Recommended Posts

Boa noite pessoal! Certo, vou direto ao assunto. Meu problema é o seguinte: Preciso controlar um motor por pwm para variar a velocidade dele de 10% em 10%, 0 ele fica desligado e em 100% em rotação máxima. Fiz um código tirando como base alguns exemplos que encontrei na net, porém quando eu coloca o duty em 10% por exemplo o motor só vibrava e não rodava, só com duty acima dos 40% que ele começava a girar. Ai li que eu preciso usar o duty da metade do valor pra cima para o motor funcionar desde o início. Ok, fiz isso e realmente funcionou, agora ele gira mesmo com 10% de duty, porém agora ele não altera muito a velocidade com duty em 10% ou 90% por exemplo, ou seja, a velocidade não varia muito. Como posso resolver isso? Segue trechos do código de como configurei no pic:

 

   setup_timer_2(T2_DIV_BY_16, 155, 1);
   setup_ccp1(CCP_PWM);
   setup_ccp2(CCP_PWM);
   set_pwm1_duty(0);
 
duty=431; 
 
testa_botoes()
{
   if((!input(aumenta))&&(duty<659))  //Teste se foi pressionado o botão de aumentar duty.
   {
      delay_ms(10);
      if(input(aumenta))  //Debouce
      {
         duty=duty+38;
         toca_buzzer();
      }
   }
   if((!input(diminui)&&(duty>279)))  //Testa se foi pressionado o botão de diminuir duty.
   {
      delay_ms(10);
      if(input(diminui))  //Debouce
      {
         duty=duty-38;
         toca_buzzer();
      }
   }
   

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

@Jose Caetano

 

Poste o código completo. Pois não sei qual PIC você está usando e nem o cristal.

 

Falou

Compartilhar este post


Link para o post
Compartilhar em outros sites
  • Autor do tópico


  • #include "main.h"


    unsigned int8 zero = 0b1000000;
    unsigned int8 um = 0b1001111;
    unsigned int8 dois = 0b0100100;
    unsigned int8 tres = 0b0110000;
    unsigned int8 quatro = 0b0011001;
    unsigned int8 cinco = 0b0010010;
    unsigned int8 seis = 0b0000010;
    unsigned int8 sete = 0b1111000;
    unsigned int8 oito = 0b0000000;
    unsigned int8 nove = 0b0010000;
    int8 motor1 = 0;
    int8 motor2 = 0;
    long duty = 0;
    int1 sel_motor = 0;  //Variável de seleção do motor-0 para motor01 e 1 para motor02
    int1 var_motores = 0;
    int1 motores_rodando = 0;


    #define buzzer          PIN_D7  // Buzzer
    #define bt_motor01      PIN_E0  //Botoes de selecionar o motor
    #define bt_motor02      PIN_E1  //Botoes de selecionar o motor
    #define diminui         PIN_C4  //Botoes de alterar o duty
    #define aumenta         PIN_C5  //Botoes de alterar o duty
    #define led_motor01e02  PIN_C6  // Led do motor 01
    #define led_debug       PIN_C7  // Led do motor 02
    #define led_motores     PIN_B7  // Led dos motores
    #define bt_motores      PIN_C0  // Led da chave geral dos motores.
    #define motores         PIN_C3 // Saida geral dos motores.
    #define motor01         PIN_C4 // Saida do Motor 01.
    #define motor02         PIN_C5 // Saida do Motor 02.


    testa_duty();
    testa_botoes();
    toca_buzzer();










    void main (void)
     { 
       setup_adc_ports(NO_ANALOGS);
       setup_psp(PSP_DISABLED);
       setup_spi(SPI_SS_DISABLED);
       setup_timer_2(T2_DIV_BY_16, 155, 1);
       setup_ccp1(CCP_PWM);
       setup_ccp2(CCP_PWM);
       set_pwm1_duty(0);
       set_pwm2_duty(0);
       setup_comparator(NC_NC_NC_NC);
       setup_vref(FALSE);
       
       
       output_high(led_debug);
       delay_ms(50);
       output_low(led_debug);
       delay_ms(100);
       output_high(led_debug);
       delay_ms(50);
       output_low(led_debug);
       delay_ms(100);
       output_high(led_debug); 
         
       duty=431; 


       while (1)
       {   
          testa_duty();
          testa_botoes();
          if((duty!=279)&&(motores_rodando==1))
          {
             if(sel_motor==0)
                {
                set_pwm1_duty(duty);
                set_pwm2_duty(0);
                output_low(led_motor01e02);
                }
                else
                {
                set_pwm1_duty(0);
                set_pwm2_duty(duty);
                output_high(led_motor01e02);
             }
          }
          if(motores_rodando==0)
             {
             set_pwm1_duty(0);
             set_pwm2_duty(0);
             }
           
           if(sel_motor==0)
             {
             output_low(led_motor01e02);
             }
           else
             {
             output_high(led_motor01e02);
             }  
       }


    }


    testa_botoes()
    {
       if((!input(aumenta))&&(duty<659))  //Teste se foi pressionado o botão de aumentar duty.
       {
          delay_ms(10);
          if(input(aumenta))  //Debouce
          {
             duty=duty+38;
             toca_buzzer();
          }
       }
       if((!input(diminui)&&(duty>279)))  //Testa se foi pressionado o botão de diminuir duty.
       {
          delay_ms(10);
          if(input(diminui))  //Debouce
          {
             duty=duty-38;
             toca_buzzer();
          }
       }
       if(!input(bt_motores))  //Teste se foi pressionado o botão da chave geral dos motores.
       {
          delay_ms(10);
          if(input(bt_motores))  //Debouce
          {
             if(var_motores==0)
                {
                var_motores=1;
                toca_buzzer();
                }
             else
                {
                var_motores=0;
                toca_buzzer();
                }
          }
       }
       if(var_motores==0)
          {
             motores_rodando=0;
             output_low(led_motores);
          }
       else
          {
             output_high(led_motores);
             motores_rodando=1;
          }


     //Testa botoes de seleção dos motores.
     if(!input(bt_motor01))  //Teste se foi pressionado o botão do motor 01.
       {
          delay_ms(50);
          if(input(bt_motor01))  //Debouce
          {
             sel_motor=0;  // 0 para motor 1.
             toca_buzzer();
          }
       }
       if(!input(bt_motor02))  //Teste se foi pressionado o botão do motor 02.
       {
          delay_ms(50);
          if(input(bt_motor02))  //Debouce
          {
             sel_motor=1;  // 1 para motor 2.
             toca_buzzer();
          }
       }
       
       
    }


    testa_duty()
    {
       if(duty==279)
       {
          set_pwm1_duty(0);
          set_pwm2_duty(0);
          output_a(zero);
          output_b(zero);
          output_d(zero);
       }
       else if(duty==317)
       {
          output_a(zero);
          output_b(um);
          output_d(zero);
       }
       else if(duty==355)
       {
          output_a(zero);
          output_b(dois);
          output_d(zero);
       }
       else if(duty==393)
       {
          output_a(zero);
          output_b(tres);
          output_d(zero);
       }
       else if(duty==431)
       {
          output_a(zero);
          output_b(quatro);
          output_d(zero);
       }
       else if(duty==469)
       {
          output_a(zero);
          output_b(cinco);
          output_d(zero);
       }
       else if(duty==507)
       {
          output_a(zero);
          output_b(seis);
          output_d(zero);
       }
       else if(duty==545)
       {
          output_a(zero);
          output_b(sete);
          output_d(zero);
       }
       else if(duty==583)
       {
          output_a(zero);
          output_b(oito);
          output_d(zero);
       }
       else if(duty==621)
       {
          output_a(zero);
          output_b(nove);
          output_d(zero);
       }
       else if(duty==659)
       {
          output_a(um);
          output_b(zero);
          output_d(zero);
       }
    }


    toca_buzzer()
    {
       output_high(buzzer);
       delay_ms(50);
       output_low(buzzer);
    }

    Compartilhar este post


    Link para o post
    Compartilhar em outros sites

    @Jose Caetano

     

    Já é um começo. Mas faltou o conteúdo do arquivo main.h. Dentro desse arquivo consta o PIC, o cristal, os fuses utilizados....

     

    Falou

    Editado por MatheusLPS

    Compartilhar este post


    Link para o post
    Compartilhar em outros sites
  • Autor do tópico
  • Ah é mesmo, desculpe! Segue:

    #include <16F877A.h>
    #device adc=8
     
    #FUSES NOWDT                    //No Watch Dog Timer
    #FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
    #FUSES PUT                      //Power Up Timer
    #FUSES NOPROTECT                //Code not protected from reading
    #FUSES NODEBUG                  //No Debug mode for ICD
    #FUSES NOBROWNOUT               //No brownout reset
    #FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
    #FUSES NOCPD                    //No EE protection
    #FUSES NOWRT                    //Program memory not write protected
    #FUSES RESERVED                 //Used to set the reserved FUSE bits
     
    #use delay(clock=10000000)

    Compartilhar este post


    Link para o post
    Compartilhar em outros sites

    @Jose Caetano

     

    Estou dando uma olhada no seu código nesse momento, debugando ele no Proteus.

     

    Mas estou com uma dúvida. Você usou lógica inversa, if((!input(aumenta))&&(duty<659)), para testar se o botão está pressionado. Nessa caso, você usou resistor de PULL-UP?

     

    Posta o circuito como ele está montado no momento para que eu possa executar a mesma coisa que você.

     

    Falou

    Compartilhar este post


    Link para o post
    Compartilhar em outros sites

    @Jose Caetano

     

    Só uma print do circuito ajuda.

     

    Parei de usar o Proteus 8. Voltei para o confiável Proteus 7.10

     

    Falou

    Compartilhar este post


    Link para o post
    Compartilhar em outros sites

     

    Fiz alguns testes aqui. Minhas observações.

     

    aVtRFVN.png

     

    Esse é um típico caso onde a simulação não dá conta de correr em tempo real. Isso ocorre por causa do chaveamento dos 2 transistores. Só de iniciar a animação sem sinal nenhum nos CCPs, a simulação já vai em 55%.

     

    Nesse caso específico seu, onde precisamos verificar se o sinal PWM está variando com o tempo, podemos usar o osciloscópio do Proteus. Não gosto dele pois ele exige muito processamento. Mas nesse caso, não tem outra forma.

     

    Fiz isso então, tirei os cabos dos 2 TIPs e joguei no osciloscópio.

     

    1 - Dei play na animação e não acontece nada com o sinal como esperado.

     

    2- Se aperto o botão de ativação dos motores (PINO C0), o PWM1 começa a aparecer normalmente. 

     

    3 - Se nesse momento, aperto o botão de incrementar ou decrementar o PWM, o sinal se comporta a contento. Ele sobe e desce.

     

    4 - Se eu agora, apertar o botão de ativar o motor 2, o sinal do PWM 1 pára e o PWM 2 inicia como esperado. PWM para cima e par baixo OK.

     

    Não vi problema com o seu circuito e nem com o código. 

     

    Percebi que você declarou a variável duty como long. Correto.....

     

    Mas vi uma coisa estranha. Logo de início você declara o duty cicle em 441. Era se esperar algo em torno de 50%, próximo a isso. mas pela simulação está na casa dos 80%.......

     

    Fiz um teste simples:

     

    #include <16f877a.h>
     
    #FUSES NOWDT                    //No Watch Dog Timer
    #FUSES hs                       //Crystal osc <= 4mhz
    #FUSES PUT                      //Power Up Timer
    #FUSES NOPROTECT                //Code not protected from reading
    #FUSES NODEBUG                  //No Debug mode for ICD
    #FUSES BROWNOUT                 //Reset when brownout detected
    #FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
    #FUSES NOCPD                    //No EE protection
     
    #use delay(clock=10000000)
     
    int main() 
    {
       setup_timer_2(T2_DIV_BY_16, 155, 1);
       setup_ccp1(CCP_PWM);
       set_pwm1_duty(0);
       
       while (TRUE) 
       {            
             set_pwm1_duty(512L);
       }
    }      

     

    E mesmo assim, o duty não está correto! Que loucura.

     

    Se eu não usar o setup_timer_2(T2_DIV_BY_16, 155, 1); Mas usar o divisor 4, algo como setup_timer_2(T2_DIV_BY_4, 249, 1); Tudo funciona perfeitamente. Exceto que a frequencia não é mais de 1Khz e sim de 2.5Khz.

     

    Terei que investigar isso. Pode ser bug do Proteus, do CCS (última versão) ou não sei...

     

    Sugiro usar os 2.5Khz. Testei e seu código parece OK agora a questão do duty cicle. 

     

    Será que o CCS tá bugado no divisor por 16?

     

    Vou buscar no forum deles...

     

    Falou

    Editado por MatheusLPS

    Compartilhar este post


    Link para o post
    Compartilhar em outros sites
  • Autor do tópico
  • Olha quanto ao bug não sei te dizer mas minha dúvida na verdade é como faço pra ter um controle mais preciso do motor, ou seja conseguir fazer ele girar em baixas velocidades sem vibrar e aos poucos ir aumentando. Desse jeito que eu fiz ai até funcionou porém a velocidade não varia tanto.

    Compartilhar este post


    Link para o post
    Compartilhar em outros sites

    Experimente só trocar a configuração do Timer 2 e me diz se faz diferença. Como eu citei ali em cima.

     

    Falou

    Compartilhar este post


    Link para o post
    Compartilhar em outros sites

    OLA! não sou intrometido mas ,estou na mesma duvida , mesma duvida que nada comparado com a de vocês Da de LAPADA NA MINHA! 

    que é simples #include <16f877a.h>

     

     

     #FUSES NOWDT                    //No Watch Dog Timer#FUSES hs                       //Crystal osc <= 4mhz#FUSES PUT                      //Power Up Timer#FUSES NOPROTECT                //Code not protected from reading#FUSES NODEBUG                  //No Debug mode for ICD#FUSES BROWNOUT                 //Reset when brownout detected#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O#FUSES NOCPD                    //No EE protection #use delay(clock=10000000) int main() {   setup_timer_2(T2_DIV_BY_16, 155, 1);   setup_ccp1(CCP_PWM);   set_pwm1_duty(0);      while (TRUE)    {                     set_pwm1_duty(512L);   }}  

     

    a questão é tem como acender três leds como se fosse um RGB , variando sua luminosidade ?   

    Compartilhar este post


    Link para o post
    Compartilhar em outros sites
  • Autor do tópico
  • Experimente só trocar a configuração do Timer 2 e me diz se faz diferença. Como eu citei ali em cima.

     

    Falou

    Vou fazer os testes na placa mesmo com o motor e te digo. Obrigado até agora.

    Compartilhar este post


    Link para o post
    Compartilhar em outros sites

    Crie uma conta ou entre para comentar

    Você precisar ser um membro para fazer um comentário






    Sobre o Clube do Hardware

    No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas publicações 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

    ×