Ir ao conteúdo

Posts recomendados

Postado

Boa noite!

Eu estou programando o meu PIC para ele acionar o motor DC para a direita e para a esquerda somente com PWM. Porém estou com muita dificuldade na parte do código e no uso do TIMER. Por isso não sei qual timer tenho que usar, se é o TIMER0, TIMER1 ou TIMER2. Também estou com muita dificuldade na parte lógica do programa e nas configurações. Alguém pode por favor me ajudar, eu tenho que fazer esse código até essa semana. Desde já agradeço.

Segue abaixo o meu circuito no proteus:

image.png.2078c91ad397db9ac1d0e8652163fb95.png

Postado
23 horas atrás, aphawk disse:

@Alexsander Lima ,

 

O Pic do seu trabalho tem 4 PWMs , tem várias maneiras de fazer isso !

 

Paulo

Sim eu estava observando isso também. Mas como é a minha primeira vez estou tendo muita dificuldade com os cálculos. Estou tentando usar o TIMER1, porém não sei nem por onde começo. A finalidade do meu projeto é fazer com que a onda PWM fique no mínimo 1 us em nível lógico alto e no máximo 2us, em um período total de 20us. Só que como disse não faço ideia de como fazer, pois tenho que usar 4 saídas PWM para controlar o meu motor, e quero poder controlar o sentido, uma coisa que tenho mais propriedade pois é só mudar as combinações do MOSFET's de acordo com o valor do ADRES, que é o valor traduzido do conversor ADC, mas também quero controlar a velocidade. Porém estou com dificuldade nessa última parte. Se puder me ajudar eu ficaria muito agradecido

16 minutos atrás, Alexsander Lima disse:

Sim eu estava observando isso também. Mas como é a minha primeira vez estou tendo muita dificuldade com os cálculos. Estou tentando usar o TIMER1, porém não sei nem por onde começo. A finalidade do meu projeto é fazer com que a onda PWM fique no mínimo 1 us em nível lógico alto e no máximo 2us, em um período total de 20us. Só que como disse não faço ideia de como fazer, pois tenho que usar 4 saídas PWM para controlar o meu motor, e quero poder controlar o sentido, uma coisa que tenho mais propriedade pois é só mudar as combinações do MOSFET's de acordo com o valor do ADRES, que é o valor traduzido do conversor ADC, mas também quero controlar a velocidade. Porém estou com dificuldade nessa última parte. Se puder me ajudar eu ficaria muito agradecido

E aqui esta o circuito pronto. Coloquei um optoacoplador 4N25 pra proteção do circuito porque não tinha drivers.image.png.5029330ede5b559e9264fa4ab43b5c84.png

Postado

Gente eu consegui desenvolver o código só que ele não está compilando e não funciona no proteus. Eu optei por utilizar o timer 0, se alguém ver algo de errado me avisa por favor para eu poder corrigir.

Citação

 

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//DEFINES
#define flagTIMER INTCONbits.TMR0IF //FLAG DO TIMER0
#define flagAD PIR1bits.ADIF        //FLAG DO SENSOR A/D
#define Q1 LATBbits.LATA2   // Define o sinal que vai entrar no optoacoplador do Q1 (Pino RA2)
#define Q2 LATBbits.LATA0   // Define o sinal que vai entrar no optoacoplador do Q2 (Pino RA0)          
#define Q3 LATBbits.LATA4   // Define o sinal que vai entrar no optoacoplador do Q3 (Pino RA4)
#define Q4 LATBbits.LATA5   // Define o sinal que vai entrar no optoacoplador do Q4 (Pino RA5)
#define Sentido_Frente()
#define Sentido_Tras()
#define Sentido_Parado()
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//DECLARAÇÃO DE VARIÁVEIS
unsigned char duty = 0;     //Variável que recebe o valor do duty cycle
int x = 0;                  //Variável que recebe o valor do ADRES
int y = 0;
char direcao = 0;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*CÁLCULO DO ESTOURO
 * Clock = 16MHz
 * ESTOURO = TIMER0 * Prescaler * 250ns 
 * ESTOURO = 256*256*250*10E-9
 * ESTOURO = 16ms --> mais ou menos 20ms*/

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void config() {
  //ENTRADA
    TRISAbits.TRISA1 = 1;    //Define RA3 como entrada (Nível lógico alto)
    
  //SAÍDA
    TRISAbits.TRISA0 = 0;    //Define RA0 como saída (Nível lógico baixo)
    TRISAbits.TRISA2 = 0;    //Define RA2 como saída (Nível lógico baixo)
    TRISAbits.TRISA4 = 0;    //Define RA4 como saída (Nível lógico baixo)
    TRISAbits.TRISA5 = 0;    //Define RA5 como saída (Nível lógico baixo)
            
//---------------------------------------------------------------------------------------------------------------------------------------------------
   //CONFIGURAÇÕES DO TIMER0
    OPTION_REGbits.PS2 = 1;    //DEFINE UM PRESCALER DE 256
    OPTION_REGbits.PS1 = 1;
    OPTION_REGbits.PS0 = 1

 //----------------------------------------------------------------------------------------------------------------------------------------------------
   //SELEÇÃO DO CANAL ANALÓGICO
    ANSELAbits.ANSA4 = 0;
    ANSELAbits.ANSA2 = 0;   
    ANSELAbits.ANSA1 = 1;   //Define o canal AN1 como entrada analógica
    ANSELAbits.ANSA0 = 0;
    
 //----------------------------------------------------------------------------------------------------------------------------------------------------    
    //CONFIGURAÇÕES DO CONVERSOR ADC
    //ADCON0
    ADCON0bits.CHS4 = 0;
    ADCON0bits.CHS3 = 0;     
    ADCON0bits.CHS2 = 0;    //Seleciona o canal analógico AN3 para a conversão
    ADCON0bits.CHS1 = 0;
    ADCON0bits.CHS0 = 1;
    
    ADCON0bits.GO = 1;   //Define o status da conversão
            /*When ADON = 1:
        1 = A/D conversion in progress (Conversão em andamento)
        0 = A/D Idle  (Conversão inativa)*/
    
    ADCON0bits.ADON = 1;    //Habilita o conversor A/D
   /*1 = A/D Converter module is enabled (Conversor Habilitado)
    0 = A/D Converter module is disabled (Conversor desabilitado)*/

    //ADCON1
    ADCON1bits.ADFM = 1;    //Define o formato do resultado da conversão A/D
    /* 1 = Right justified (Justificado à direita)
    0 = Left justified  (Justificado à esquerda)*/
    
    ADCON1bits.ADCS = 100;
 //-----------------------------------------------------------------------------------------------------------------------------------------------
    //Valor inicial do duty cycle
    
    duty = 16;   //Duty inicializada
 /*----------------------------------------------------------------------------------------------------------------------------------------------*/   
    //INTERRUPÇÕES 
    INTCONbits.GIE = 1;     //HABILITA AS INTERRUPÇÕES GLOBAIS
    
    //INTERRUPÇÃO DO TIMER 0
       INTCONbits.TMR0IE =1;  // HABILITA A INTERRUPÇÃO DO TIMER0
    
    //INTERRUPÇÃO DO SENSOR ADC
     PIE1bits.ADIE = 1;      //HABILITA A INTERRUPÇÃO DO SENSOR A/D
    /*1 = Enables the A/D interrupt (Ativa a interrupção do Sensor)
    0 = Disables the A/D interrupt  (Desativa a interrupção)*/
     
      PIR1bits.ADIF = 0;      //SINALIZA (FLAG) A INTERRUPÇÃO DO CONVERSOR A/D
    /*1 = An A/D conversion completed (Conversão concluída)
    0 = The A/D conversion is not complete  (Conversão não concluída)*/
      
 /*------------------------------------------------------------------------------------------------------------------------------------------------*/   

}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void __interrupt() interrupcao() {
    
    if(flagAD == 1) {  //Acontece caso uma interrupção AD aconteça
    flagAD = 0;        // Zera a flag do Sensor (Sinaliza a interrupção do sensor)
    
        switch (direcao) {
 //--------------------------------------------------------------------------------------------------------------------------------           
    //CASE0: Pra frente
            case 0: 
                if (Q1 ==1 && Q4 == 1)
                    TMR0 = duty;
                Q1 = 0 && Q4 = 0;
        }
        else {
            TMR0 = 255 - duty;
            Q1 = 0 && Q4 = 1;
        }
        break; 
//----------------------------------------------------------------------------------------------------------------------------------     
   //CASE1: Pra Trás 
        case 1: 
                if (Q2 ==1 && Q3 == 1)
                    TMR0 = duty;
                Q2 = 0 && Q3 = 0;
  
            else {
            TMR0 = 255 - duty;
            Q2 = 0 && Q3 = 1;
        }
                break;
    }
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void main (void) {
    config();
    while (1) {
         x = ADRES/64;          // ADRES = Resultado da conversão de acordo com a tensão (5V = 1024)
         duty = x + 16;
         y = ADRES/4;
         if (y > 133 ) {     
             Q1 = 1;
             Q2 = 0;
             Q3 = 0;
             Q4 = 1;
    }
    if (y <123) {    //Motor pra esquerda
             Q1 = 1;
             Q2 = 0;
             Q3 = 0;
             Q4 = 1;
    }
    else ( 133 >= y >= 123){
             Q1 = 0;
             Q2 = 0;
             Q3 = 0;
             Q4 = 0;;
    }
    return;
}
}

 

 

  • Membro VIP
Postado
11 horas atrás, Alexsander Lima disse:

o código só que ele não está compilando e não funciona no proteus.

São duas coisas distintas. Foque em uma de cada vez. Sobre não compilar - a 1ª coisa - , geralmente o compilador mostra qual linha está o problema.

Acho que estás queimando etapas: faça primeiro um led piscar. E tem +: a escolha do timer não é opção. Você deve usar aquele que foi projetado para o controle da largura do sinal em determinado pino. Vai ter que dar uma olhadela no datasheet do seu mc. E por fim: não reinvente a roda: pesquise e ache programas prontos na net. Claro não vai achar um com seu nome e sobrenome mas com certeza um que se relaciona com motor, seu mc e pwm. Algo como pwm motor control using pic using pic microcontroller c code

 

Ah.. e seu circuito...

image.png

não deve funcionar a contento pois a tensão no gate dos de cima está baixa: eles não conduziriam. Pra corrigir aplique uns 20V nos optos de cima.

Postado

Galera boa noite. Eu não tive êxito no meu código e tive que refazer, estou totalmente perdido. Eu estou pensando em fazer uma interrupção externa com o TIMER2 para controlar 4 saídas PWM do PIC12F1501. Eu não entendi como relaciona o pwm com o tempo e nem com o valor traduzido da potência regulada pelo potenciômetro. Eu preciso entregar isso amanhã, então por favor estou precisando muito de ajuda.

Segue a tentativa de código:

Citação


#include <xc.h>
#include <htc.h>
#define _XTAL_FREQ 8000000

#pragma config FOSC = INTOSC    // Oscillator Selection Bits (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = OFF      // MCLR Pin Function Select (MCLR/VPP pin function is digital input)
#pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable (Brown-out Reset disabled)
#pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)

// CONFIG2
#pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
#pragma config STVREN = OFF     // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will not cause a Reset)
#pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LPBOR = OFF      // Low-Power Brown Out Reset (Low-Power BOR is disabled)
#pragma config LVP = OFF        // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//DEFINES
#define IN1 LATA4
#define IN2 LATA5
#define IN1_HIGH PWM3DCH
#define IN1_LOW PWM3DCL
#define IN2_HIGH PWM4DCH
#define IN2_LOW PWM4DCL
#define TEMPO_RAMPA 10    //tempo delay inversao de sentido pwm
#define Sentido_Frente 1
#define Sentido_Tras 2
#define Sentido_Parado 0
#define flagTIMER PIR1bits.TMR2IF //FLAG DO TIMER2
#define flagAD PIR1bits.ADIF        //FLAG DO SENSOR A/D
#define Q1 LATBbits.LATA2   // Define o sinal que vai entrar no optoacoplador do Q1 (Pino RA2)
#define Q2 LATBbits.LATA0   // Define o sinal que vai entrar no optoacoplador do Q2 (Pino RA0)          
#define Q3 LATBbits.LATA4   // Define o sinal que vai entrar no optoacoplador do Q3 (Pino RA4)
#define Q4 LATBbits.LATA5   // Define o sinal que vai entrar no optoacoplador do Q4 (Pino RA5)
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* O que eu quero que o meu código faça?
 * Eu quero que ele transforme uma grandeza analógica em uma grandeza digital, através do PWM e de um potênciometro, 
 * para movimentar o meu Motor DC. 
 * No programa, eu vou usar o timer 2, que é um contador de 8 bits e vai realizar as interrupções do código.
 
 * --> Passos:
 * 1° - Eu preciso configurar as entradas e saídas do meu PIC
 * 2° - Configurar o meu sensor A/C e o meu timer 2 consultando o datasheet
 * 3° - Preciso configurar as saídas PWM e as interrupções do meu PIC
 * 4° - Tenho que pensar na lógica (void main)
  
 * Minha lógica:
 * ---> De acordo com o tempo em que a minha onda PWM estiver em nível lógico alto (1) e em nível lógico baixo(0), a velocidade do motor irá se alterar.
 * - Ou seja, quando o meu pulso estiver em alta durante 1 ms, ele vai ir para trás (antihorário) e quando menor a tensão mais rápido ele vai para trás.
 * - Já para ficar parado a onda precisa ficar em alta durante 1,5 ms, e para frente a onda vai no máximo até 2ms.
 * - É importante ressaltar que o período máximo do estouro do TIMER 2 é 20ms.
 * - O ADRES (1024) é o valor máximo traduzido pelo CONVERSOR do PIC, e que deve ser relacionada com o TIMER2 (256),de tal forma que 
 * quando o ADRES assumir um valor menor que a sua metade, o motor irá girar para trás, já se ele assumir a metade ele vai estar em 1,5 ms, ou seja,
 * vai estar parado, agora se for maior, ele vai pra frente.
 * - O que eu tenho que fazer é relacionar o ADRES com o TIMER2 e essa variação de tensão com o sentido e a velocidade do motor.
 */
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void config (){
//ENTRADA
    TRISAbits.TRISA1 = 1;    //Define RA3 como entrada (Nível lógico alto)
    
  //SAÍDA
    TRISAbits.TRISA0 = 0;    //Define RA0 como saída (Nível lógico baixo)
    TRISAbits.TRISA2 = 0;    //Define RA2 como saída (Nível lógico baixo)
    TRISAbits.TRISA4 = 0;    //Define RA4 como saída (Nível lógico baixo)
    TRISAbits.TRISA5 = 0;    //Define RA5 como saída (Nível lógico baixo)
            
//---------------------------------------------------------------------------------------------------------------------------------------------------
//TIMER 2
    T2CONbits.TMR2ON = 1;           //ATIVA O TIMER2
    T2CONbits.T2OUTPS = 0b1001;     //POSTSCALER 1:10
    T2CONbits.T2CKPS = 0b10;        //PRESCALER 1:16
    OSCCONbits.IRCF = 0b1110;       //FREQUÊNCIA DO OSCILATOR INTERNO DE 8MHz
//------------------------------------------------------------------------------------------------------------------------------------------------
//PWM


//-------------------------------------------------------------------------------------------------------------------------------------------------
//CONVERSOR A/D    
    ADCON0bits.CHS4 = 0;
    ADCON0bits.CHS3 = 0;     
    ADCON0bits.CHS2 = 0;    //Seleciona o canal analógico AN3 para a conversão
    ADCON0bits.CHS1 = 0;
    ADCON0bits.CHS0 = 1;
    ADCON0bits.GO = 1;      //Define o status da conversão
    ADCON0bits.ADON = 1;    //Habilita o conversor A/D
    ADCON1bits.ADFM = 1;    //Define o formato do resultado da conversão A/D
//------------------------------------------------------------------------------------------------------------------------------------------------    
        //INTERRUPÇÕES 
    
      INTCONbits.GIE = 1;     //HABILITA AS INTERRUPÇÕES GLOBAIS
      PIE1bits.TMR2IE =1;     //HABILITA A INTERRUPÇÃO DO TIMER2
      PIE1bits.ADIE = 1;      //HABILITA A INTERRUPÇÃO DO SENSOR A/D
      PIR1bits.ADIF = 0;      //SINALIZA (FLAG) A INTERRUPÇÃO DO CONVERSOR A/D
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void __interrupt () interrupcao () {
    if(flagTIMER == 1)      //Caso a flag do TIMER2 ative (ocorra o estouro)
        flagTIMER = 0;      //Zera a flag do TIMER2
    
}

void main(void) {
   
    return;
}
 

 

  • Membro VIP
Postado

Google pic12f1501 pwm example.

Dica: use o mesmo compilador do exemplo que achar. P.ex. mikroc é bom. Sua versão de degustação atende seu requisito

https://www.mikroe.com/mikroc-pic

https://forum.mikroe.com/viewtopic.php?f=88&t=57641

 

E também tem mplab xpress

https://www.microchip.com/en-us/development-tools-tools-and-software/mplab-xpress

https://circuitdigest.com/microcontroller-projects/pic-microcontroller-pic16f877a-pwm-tutorial

 

+1 dica: você não precisa de 4 canais pwm um pra cada mosfet. Basta-lhe 1 apenas. Aplique-o p.ex. nos mosfets de baixo e os de cima aplique um simples sinal liga desliga. Use portas and ou outro pino do mc. Sorry... sem desenho...

 

Você tem o dia todo pela frente. 😁.

Tenha um super bom dia... extensivo aos amigos leitores 😉

 

Postado

@.if Eu nem sei como te agradecer pela ajuda. Eu vou tentar até o último instante aqui e se eu espero que dê certo. Muito obrigado. Mas eu não entendi como colocar o pwm para os optoacopladores de baixo e liga/desliga para os de cima. Porque pelo o que eu vi eu preciso para aplicar pwm nos de baixo pelo menos duas saídas PWM (PWM1 e PMW2). 

Por exemplo, no meu circuito, os Mosfets Q3 e Q4 estão ligados respectivamente às saídas RA4 e RA5.

  • Membro VIP
Postado

ok... Olha isso

ponte_hbrida_162.jpg

Perceba que pra controlar a velocidade do motor basta controlar o pwm na base de Q1 ou seja um (01) canal apenas. Já o sentido de rotação você controla nos relés. Ou seja 2 sinais: 1 pra sentido e 1 pwm que também serve como liga desliga. Se preferir (ou seu professor exigir) mantenha os mosfets no lugar dos relés.

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

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...

LANÇAMENTO!

eletronica2025-popup.jpg


CLIQUE AQUI E BAIXE AGORA MESMO!