Ir ao conteúdo
  • Cadastre-se
Visitante

PIC mplab xc8 - pic18f4550 - adc/pwm- eletronica

Recommended Posts

Visitante

Olá preciso variar o duty cycle do pwm, de acordo com uma entrada ADC via potenciometro, o problema é que preciso variar a escala do potenciometro e de acordo com a tensão o pwm varia. Por exemplo de 0 á 1,25v do ADC(pot) duty cycle vai de 0 á 77%, de 1,26 a 2.25v, duty cycle varia de 77 a 35%. Me ajudem se puder, segue código fonte.
 

#include "config.h" // Inclui o arquivo config.h
#include "delay_pic18.h" // Inclui o arquivi delay_pic18.h
#include "LCD4b.h" // Inclui o arquivo LCD4b.h
#include <xc.h> // Inclui o arquivo header xc.h
#include <stdio.h> // Inclui o arquivo stdio.h
#include <pic18f4550.h> // Inclui biblioteca do PIC18F4550.

int adc = 0; // Variável de armazenamento da conversão ADC
float resultado, conversao; // Váriaveis de casa decimais para conversão do ADC 0 Á 1023 P/ 0 Á 5V
float tensão, calculo; // Váriaveis de casa decimais para conversão do PWM 0 Á 255 P/ 0 Á 5V
int porcentagem; // Váriaveis de casa decimais para valores em porcentagem (%) de 0 á 100% do resultado do PWM

void main(void) { // Função Principal
    //------------------------------------------------------------------------------------------------------------------//
    //Definição dos I/O's (Input/Output)
    ADCON1 = 0x0F; // Desabilita todos os canais A/D
    TRISB = 0b00000000; // Define todo o PORTB como sáida
    TRISBbits.TRISB3 = 0; // CCPR2L (saida para led)
    TRISAbits.RA0 = 1; // Define a PORTAN0 como entrada analógica
    PORTBbits.RB3 = 0; // Começa desligado a saida
    PORTB = 0b00000000; // Começa desligado todas as saídas dos pinos do PORTB

    //------------------------------------------------------------------------------------------------------------------// 
    //Registradores configurados da entrada ADC-AN0(via/Potenciomêtro)
    ADCON0 = 0b00000001; /* Bit´s 7 e 6 = 0 -Não utilizados
                          * CHS<3:0> = 0001 - Seleçção do canal analógico AN0
                          * GO/DONE = 0 -Conversão A/D não iniciada
                          * ADCON = 1 -Módulo A/D habilitado
                          */
    ADCON2 = 0b10000111; /*ADFM = 1 -Resultado da conversão justificada á direita.
                          * Bit 6 - Não utilizado
                          * ACQT<2:0> = 0 - 0 TAD
                          * ADCS<2:0> = 111 - Oscilador Interno para A/D
                          */
    //------------------------------------------------------------------------------------------------------------------//
    //Registradores configurados para uso do PWM via TIMER2 pela saída CCPR2L = PORTB.RB3
    CCP2CON = 0b00001100; // Modo PWM
    PR2 = 255; // Frequência 250Hz > entre 0 e 255
    T2CONbits.T2CKPS = 0b10; // Prescaler do timer 2 em 1:16
    T2CONbits.TMR2ON = 1; // Incia o PWM

    CCPR2L = 0; // inicia em 0 duty cycle
    //------------------------------------------------------------------------------------------------------------------//
    //Texto de apresentação do Projeto
    lcd_ini(); // Inicializa o Display LCD 16X2
    lcd_envia_byte(0, 0x81); // Posiciona o cursor na coluna 1 da linha 1
    printf("SIST.ROBOTICOS"); // Escreve no display LCD
    lcd_envia_byte(0, 0xC0); // Posiciona o cursor na coluna 0 da linha 2
    printf("MECATRONICA-2018"); // Escreve no display LCD
    __delay_ms(2000); // Aguarda 2 segundos
    lcd_envia_byte(0, 0x01); // Limpa o dispaly LCD
    __delay_ms(20); // Aguarda 20 milisegundos
    lcd_envia_byte(0, 0x80); // Posiciona o cursor na coluna 0 da linha 1
    printf("DUTY-CYCLE:"); // Escreve no dispaly LCD
    lcd_envia_byte(0, 0x8B); // Posiciona o cursor na coluna 11 da linha 1
    printf(" 000"); // Escreve no display LCD
    lcd_envia_byte(0, 0xC0); // Posiciona o cursor na coluna 0 da linha 2
    printf("ADC(V):"); // Escreve no display LCD
    lcd_envia_byte(0, 0xCB); // Posiciona  o cursor na coluna 11 da linha 2
    printf("0000"); // Escreve no display LCD
    __delay_ms(2000); // Aguarda 2 segundos

    //------------------------------------------------------------------------------------------------------------------//
    //Entrada do loop infinito
    while (1) { // loop infinito
        __delay_ms(50);
        //------------------------------------------------------------------------------------------------------------------//
        //Conversão de 0 á 5V do ADC
        ADCON0bits.GO = 1; // Inicia a conversão A/D
        while (ADCON0bits.GO); // Aguarda a finalização da conversão
        adc = ADRESH; // Armazena a parte alta do resultado em ADC
        adc = (adc << 8 + ADRESL; /* Desloca 8 bit's á esquerda e soma com a 
                                    * parte baixa do resultado da conversão A/D.
                                    */
        //------------------------------------------------------------------------------------------------------------------//
        //ADC
        resultado = conversao * 1; // Multiplica o resultado da variável anterior para obter as casa decimais desejadas.
        conversao = adc * 5.0 / 1023; // Converte de 0 a 1023, para valores de Tensão(V) 0 á 5V (Potenciometro)
        //------------------------------------------------------------------------------------------------------------------//
        //PWM
        calculo = CCPR2L * 5.0 / 255; // Converte de 0 a 255, para valores de Tensão (V) 0 á 5V (PWM TIMER2)
        tensão = calculo * 1; // Ajusta as casas decimais da conversão
        //------------------------------------------------------------------------------------------------------------------//
        //PWM(%)
        porcentagem = calculo * 100 / 5.0; // Converte os valores de tensão para valores em porcentagem (%) de 0 á 100%
        //------------------------------------------------------------------------------------------------------------------//
        // Atualização do display LCD com os valores da conversão do PWM/ADC
        lcd_envia_byte(0, 0x80); // Posiciona o cursor na coluna 0 da linha 1
        printf("DUTY-CYCLE: %03d", porcentagem); // Escreve no display LCD
        lcd_envia_byte(0, 0x8f); // Posiciona o cursor na coluna 0 da linha 1
        printf("%c", 37); // Escreve no display LCD % de acordo com a tabela ASC||
        lcd_envia_byte(0, 0xC0); // Posiciona o cursor na coluna 0 da linha 2
        printf("ADC-AN0(V): %04.2f", conversao); // Escreve no display LCD
        //------------------------------------------------------------------------------------------------------------------//
        CCPR2L = adc;
        
        /*
        if(CCPR2L > 255){CCPR2L = 0x00;}
        if(CCPR2L <   0){CCPR2L = 255;}
         
        if ((conversao >= 0.0) && (conversao <= 1.25));
        {
            CCPR2L = 196;
        }
        if ((conversao >= 1.26) && (conversao <= 2.5));
        {
            CCPR2L = 81;
        }
        if ((conversao >= 2.51) && (conversao <= 3.75));
        {
            CCPR2L = 109;
        }
        if ((conversao >= 3.76) && (conversao <= 5));
        {
            CCPR2L = 229;
        }
        */
    }
}

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Amigo tipo assim... se adc 10bits vai de 0 a 1023, faça a proporção e compute diretamente o valor do ad

Algo como se 2.25V=>1023 ... 1.25V=>568

aí divida em "duas águas"

float adc;//int bastaria mas pra missão atual, deve ser fracionário
if (adc<568) setdutcycle(adc*1.39);//788 máximo ou 77% do dutty 10bits
else setdutcycle((788-adc*1.39)-358));//máximo com mínimo 35% do dutty 10bits

Ou seja, o mc não precisa converter em % pra computar. Faça isso previamente

A rotina setdutcycle(x) basta dar uma olhadela no d.s. e posicionar corretamente os bits com o argumento x

 

Tenta aí algo do gênero pois nem sei se a matemática e algoritmo estão certos. Digitei online e nem sei se me autoentendi direito kk. Confere ae...

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

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

×