Ir ao conteúdo
  • Cadastre-se

Dúvida em melhorar PWM


Posts recomendados

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();
      }
   }
   

 

Link para o comentário
Compartilhar em outros sites



#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);
}

Link para o comentário
Compartilhar em outros sites

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)
Link para o comentário
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

Link para o comentário
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

Link para o comentário
Compartilhar em outros sites

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.

Link para o comentário
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 ?   

Link para o comentário
Compartilhar em outros sites

Visitante
Este tópico está impedido de receber 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...