O "coração do circuito" é basicamente oc componentes L1,C1 e D1 além do componente de chaveamento que pode ser transistor(aquece mais) ou mosfet. Veja a figura a seguir para melhor compreensão:
O circuito é bem simples de se implementar, provavelmente o mais trabalhoso será encontrar o indutor, dai se tem 3 escolhas : arrancar um indutor de uma fonte chaveada usada(sucata), este indutor pode ser feito com fios de cobre esmaltado, a bitola do fio vai depender da corrente a ser manuseada pelo circuito , e por ultimo ainda encontrar um indutor comercial que se aproxime do indutor desejado.Não vou entrar em muitos detalhes de dimensionamento do circuito pois isso foge da proposta do blog que é apenas montar o código-fonte.
No microcontrolador PIC18F13K22 o pinos usado foram pino 5 (usado para pwm), pino 8(ref_tensão), pino 15 (para led que indica falha) e pino16 (indica o status, fica piscando).Este código pode ser transferido para qualquer outro modelo de microcontrolador que tenha PWM.
Vamos então agora para o código fonte :
Código-fonte principal :
/* * Conversor DC/DC * * Compilador : MPlabXC8 * Microcontrolador: 18F13K22 * Autor: Aguivone * Versão: 1 * Data de criação: 19/05/2015. * Retomada do projeto: 30/11/2016 * Primeira versão estavel: 06/11/2016 */ #include <stdio.h> #include <stdlib.h> #include <string.h> //para usar funçoes de string deve se adicionar este header #include <xc.h> #include "config_cpu.h" #include "conv_adc.h" // configuração de frequencia de PWM #define PWM_20KHZ_CLK16 inicializa_PWM1(1, 200, 1) #define _XTAL_FREQ 16000000//usado para rotinas de delays #define VAL_MAX_PWM 70 // valor max de pwm pra não sobreaquecer demais a bobina #define VAL_MIN_PWM 5 // valor minimo de pwm #define MAX_CORRENTE 1024//só pra ignorar por enquanto // em unidades do conversor //para calcular a tensão faça : (tensão desejada)/0,05371 ; // o valor deve ser inteiro(sem virgula) por exemplo; //para 12V temos : 12/0,05371 = 223,4 então será 223 ou 224. #define DDP_TRAB 450// para 24V (depende do divisor resistivo) #define LED_STATUS LATCbits.LATC0 #define LED_FALHA LATCbits.LATC1 //************************************************************************************/ //VARIAVEIS GLOBAIS //************************************************************************************/ //parametros de tensão/corrente long glTensao = 0;// em V long glCorrente = 0;// em A int uiStatus = 0; //indica o modo como está o estado das tensões //pwm long uiMax_passos = 0;//frequencia em khz int uiDuty_cycle = 1; //variaveis de uso geral long glTempo_led=0; int uiAlterna_leds=0; //=================================================================================== //Função: _interrupcoes //Parâmetro: não tem. //Retorno: não tem. //Descrição: usada para tratar as interrupções geradas pelo microcontrolador. //=================================================================================== void interrupt interrupcoes(void)//vetor de interrupção { if(ADIF) {//se interrupção do modulo analogico! ADIF = 0;//limpa flag } if(TMR2IF) {//interrupção do timer2 TMR2IF = 0;//não será usado } if(CCP1IF) {//interrupção do ccp1 CCP1IF = 0;//não será usado } } //=================================================================================== //Função: _delay_ms //Parâmetros: long delay, essa função cobre uma falha nas rotinas de tempo para o pic da serie 18F //Retorno: não tem retorno. //Descrição: faz microcontrolador perder tempo. //=================================================================================== void delay_ms(long delay) { while(delay > 0) { __delay_ms(1); delay--; } } //=================================================================================== //Função: _liga_leitura_0 //Parâmetro: não tem. //Retorno: não tem. //Descrição: liga entrada de sinal analogico na porta 0. //=================================================================================== void liga_leitura_0(void) { ADCON0 = 0X21; } //=================================================================================== //Função: _liga_leitura_1 //Parâmetro: não tem. //Retorno: não tem. //Descrição: liga entrada de sinal analogico na porta 1. //=================================================================================== void liga_leitura_1(void) { ADCON0 = 0X25; } void ler_ADC(int giMedia)//numero de amostras { int iMedia=0; glTensao = 0; glCorrente = 0; while(iMedia < giMedia) { glTensao = glTensao + ler_adc_un(); __delay_us(2);//tempo minino para aquisições iMedia++; } liga_leitura_1();//agora lê a corrente __delay_us(2);//tempo minino para aquisições iMedia=0; while(iMedia < giMedia) { glCorrente = glCorrente + ler_adc_un(); __delay_us(2);//tempo minino para aquisições iMedia++; } liga_leitura_0();//volta a ler tensão glTensao = glTensao/giMedia; glCorrente = glCorrente/giMedia; } void inicializa_PWM1(char prescaler,char pr2,char postcaler)//prescaler / PR2 / postcaler { uiMax_passos =(int) pr2; switch(prescaler) { case 1: { prescaler = 0; }break; case 4: { prescaler = 1; }break; case 16: { prescaler = 3; }break; } T2CON = (postcaler - 1)<<3; T2CON = T2CON + 4 + prescaler;//o 4 é para habilitar o timer PR2 = pr2; CCP1CON = 0X0F;//habilita pwm CCP1IE = 1;//desabilita interrupção pois não vamos precisar dela, modulo ccp1 TMR2IE = 0; //desabilita interrupção pois pode até travar processamento(não vamos usar tambem); timer 2 } void duty_cicle(long valor) { CCPR1 = valor; } //=================================================================================== //Função: _inicializa_cpu //Parâmetros: não tem //Retorno: não tem retorno. //Descrição: inicializa os registradores do microcontrolador. //=================================================================================== void inicializa_cpu(void) { TRISC = 0xC0;//habilita 6 e 7 com entrada analogica TRISA = 0XFF;//configura portA como entrada TRISB = 0X20;//configura portB B5 (pino RX) como entrada PORTB = 0; // limpar as portas que estão configuradas como saidas ADCON0 = 0X21;//liga modulo analogico digital e configura entrada de sinal para o pino RC6(AN8) ADCON1 = 0X00;// Vref- seta ao Vss e Vref+ ao Vdd ADCON2 = 0b10111110;// justificado a direita// tempo de aquisição 20TAD // clk Fosc/64 PEIE = 1;//habilita interrupção de perifericos do pic GIE = 1; //GIE: Global Interrupt Enable bit ANSEL = 0x00;//desabilita portas analogicas(para não atrapalhar recepção no pino) ANSELH = 0x03;//em alguns casos não funciona nem a interrupção de recepção. habilita somente os pinos que vão funcionar como AD PWM_20KHZ_CLK16;//100khz veja no comentario abaixo "SUGESTÃO DE DEFINES :" duty_cicle(1);//inicia com valor minimo uiDuty_cycle = 1; } // //*******************************Rotina principal*********************************************/ void main(void) { inicializa_cpu(); for(;;) { glTempo_led++; if(glTempo_led > 100) { if(uiAlterna_leds == 0) { LED_STATUS = 1; uiAlterna_leds=1; ;//pisca led } else { LED_STATUS = 0; uiAlterna_leds = 0; ;//pisca led } if(uiStatus > 0) { LED_FALHA = 1; } else { LED_FALHA = 0; } glTempo_led=0; } ///processamento das tensões ler_ADC(4);//pega pelo menos 5 amostras para tirar media /// /verifica tensão if(glTensao > DDP_TRAB )//flutuação máxima {//tensão superior a permitida if(uiDuty_cycle < VAL_MIN_PWM) { //não consegue mais compensar chegou ao limite uiStatus = 2;//sobretensão } else { //tenta compensar valor uiDuty_cycle--;//a duty_cicle(uiDuty_cycle); uiStatus = 0;//tudo ok } } else { if(glTensao < DDP_TRAB )//flutuação máxima { //tensão inferior a permitida if(uiDuty_cycle > VAL_MAX_PWM) { //não consegue mais compensar chegou ao limite uiStatus = 3;//subtensão } else { //tenta compensar valor uiDuty_cycle++;//lembre que a saida é invertida duty_cicle(uiDuty_cycle); uiStatus = 0;//tudo ok } }//fim de tensão fora do range } //////////////// }//loop infinito } /*calculos para pwm * * periodo do pwm * * Tpwm = [PR2+1]*4*Tosc*prescaler(do timer2) * * duty cycle * <bits 5e4> * D = (CCPR1L + CCP1CON) * Tosc * prescaler (do timer2) * * numero de passos do pwm * * N = (Fosc/(Fpwm * 4 * prescaler)) */ /* SUGESTÃO DE DEFINES : * use estes valores como referencia * Note que os valores do meio são o numero de passos do pwm(quanto mais passos mais preciso será) * //clock de 4mhz #define PWM_250HZ_CLK4 inicializa_PWM1(16, 250, 1) // #define PWM_500HZ_CLK4 inicializa_PWM1(16, 125, 1) // #define PWM_1KHZ_CLK4 inicializa_PWM1(4, 250, 1) // #define PWM_1K25HZ_CLK4 inicializa_PWM1(16, 50, 1) // #define PWM_2KHZ_CLK4 inicializa_PWM1(4, 125, 1) // #define PWM_2K5HZ_CLK4 inicializa_PWM1(4, 100, 1) // #define PWM_4KHZ_CLK4 inicializa_PWM1(1, 250, 1) // #define PWM_5KHZ_CLK4 inicializa_PWM1(1, 200, 1) // #define PWM_8KHZ_CLK4 inicializa_PWM1(1, 125, 1) // #define PWM_10KHZ_CLK4 inicializa_PWM1(1, 100, 1) // #define PWM_20KHZ_CLK4 inicializa_PWM1(1, 50, 1) // #define PWM_25KHZ_CLK4 inicializa_PWM1(1, 40, 1) // #define PWM_100KHZ_CLK4 inicializa_PWM1(1, 10, 1) // //clock de 8mhz #define PWM_500HZ_CLK8 inicializa_PWM1(16, 250, 1) // #define PWM_1KHZ_CLK8 inicializa_PWM1(16, 125, 1) // #define PWM_2KHZ_CLK8 inicializa_PWM1(4, 250, 1) // #define PWM_2K5HZ_CLK8 inicializa_PWM1(16, 50, 1) // #define PWM_4KHZ_CLK8 inicializa_PWM1(4, 125, 1) // #define PWM_5KHZ_CLK8 inicializa_PWM1(4, 100, 1) // #define PWM_8KHZ_CLK8 inicializa_PWM1(1, 250, 1) // #define PWM_10KHZ_CLK8 inicializa_PWM1(1, 200, 1) // #define PWM_16KHZ_CLK8 inicializa_PWM1(1, 125, 1) // #define PWM_20KHZ_CLK8 inicializa_PWM1(1, 100, 1) // #define PWM_40KHZ_CLK8 inicializa_PWM1(1, 50, 1) // #define PWM_50KHZ_CLK8 inicializa_PWM1(1, 40, 1) // #define PWM_200KHZ_CLK8 inicializa_PWM1(1, 10, 1) // //clock de 16mhz #define PWM_1KHZ_CLK16 inicializa_PWM1(16, 250, 1) // #define PWM_2KHZ_CLK16 inicializa_PWM1(16, 125, 1) // #define PWM_4KHZ_CLK16 inicializa_PWM1(4, 250, 1) // #define PWM_5KHZ_CLK16 inicializa_PWM1(16, 50, 1) // #define PWM_8KHZ_CLK16 inicializa_PWM1(4, 125, 1) // #define PWM_10KHZ_CLK16 inicializa_PWM1(4, 100, 1) // #define PWM_16KHZ_CLK16 inicializa_PWM1(1, 250, 1) // #define PWM_20KHZ_CLK16 inicializa_PWM1(1, 200, 1) // #define PWM_32KHZ_CLK16 inicializa_PWM1(1, 125, 1) // #define PWM_40KHZ_CLK16 inicializa_PWM1(1, 100, 1) // #define PWM_80KHZ_CLK16 inicializa_PWM1(1, 50, 1) // #define PWM_100KHZ_CLK16 inicializa_PWM1(1, 40, 1) // #define PWM_400KHZ_CLK16 inicializa_PWM1(1, 10, 1) //
/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////
*/
Código-fonte "config_cpu.h" :/* * File: config_cpu.h * Author: aguivone * * Created on 25 de Agosto de 2014, 16:24 */ #ifndef CONFIG_CPU_H #define CONFIG_CPU_H /*******************************configuraçôes do pic ****************************************************/ // CONFIG1H #pragma config FOSC = HS // Oscillator Selection bits (HS oscillator) #pragma config PLLEN = OFF // 4 X PLL Enable bit (PLL is under software control) #pragma config PCLKEN = ON // Primary Clock Enable bit (Primary clock enabled) #pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor disabled) #pragma config IESO = OFF // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled) // CONFIG2L #pragma config PWRTEN = OFF // Power-up Timer Enable bit (PWRT disabled) #pragma config BOREN = OFF // Brown-out Reset Enable bits (Brown-out Reset disabled in hardware and software) #pragma config BORV = 19 // Brown Out Reset Voltage bits (VBOR set to 1.9 V nominal) // CONFIG2H #pragma config WDTEN = OFF // Watchdog Timer Enable bit (WDT is controlled by SWDTEN bit of the WDTCON register) #pragma config WDTPS = 32768 // Watchdog Timer Postscale Select bits (1:32768) // CONFIG3H #pragma config HFOFST = ON // HFINTOSC Fast Start-up bit (HFINTOSC starts clocking the CPU without waiting for the oscillator to stablize.) #pragma config MCLRE = OFF // MCLR Pin Enable bit (RA3 input pin enabled; MCLR disabled) // CONFIG4L #pragma config STVREN = ON // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset) #pragma config LVP = OFF // Single-Supply ICSP Enable bit (Single-Supply ICSP enabled) desliga programação em baixa voltage #pragma config BBSIZ = OFF // Boot Block Size Select bit (512W boot block size) #pragma config XINST = OFF // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode)) // CONFIG5L #pragma config CP0 = OFF // Code Protection bit (Block 0 not code-protected) #pragma config CP1 = OFF // Code Protection bit (Block 1 not code-protected) // CONFIG5H #pragma config CPB = OFF // Boot Block Code Protection bit (Boot block not code-protected) #pragma config CPD = OFF // Data EEPROM Code Protection bit (Data EEPROM not code-protected) // CONFIG6L #pragma config WRT0 = OFF // Write Protection bit (Block 0 not write-protected) #pragma config WRT1 = OFF // Write Protection bit (Block 1 not write-protected) // CONFIG6H #pragma config WRTC = OFF // Configuration Register Write Protection bit (Configuration registers not write-protected) #pragma config WRTB = OFF // Boot Block Write Protection bit (Boot block not write-protected) #pragma config WRTD = OFF // Data EEPROM Write Protection bit (Data EEPROM not write-protected) // CONFIG7L #pragma config EBTR0 = OFF // Table Read Protection bit (Block 0 not protected from table reads executed in other blocks) #pragma config EBTR1 = OFF // Table Read Protection bit (Block 1 not protected from table reads executed in other blocks) // CONFIG7H #pragma config EBTRB = OFF // Boot Block Table Read Protection bit (Boot block not protected from table reads executed in other blocks) #endif /* CONFIG_CPU_H */
//////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
Código-fonte "conv_adc.h" :
/* * FUNÇOES USADAS NA CONVERSAO ANALOGICO/DIGITAL * * Compilador : MPlabXC8 * Microcontrolador: 18F13K22 * Autor: Aguivone * Versão: 1 * Data de criação: 21 de agosto de 2014. */ #include <xc.h> // =================================================================================== // Função: _ler_adc_un // Parâmetros: não tem. // Retorno : unsigned long ultensao. // Descrição : retorna o valor lido em unidades de medidas. // =================================================================================== unsigned long ler_adc_un(void) { unsigned long ultensao; ADCON0bits.GO = 1; //inicia conversão while (ADCON0bits.GO_DONE == 1); //espera finalizar leitura ultensao = (ADRESH << 8) | ADRESL; return(ultensao); } // =================================================================================== // Função: _ler_adc_mv // Parâmetros: não tem. // Retorno : unsigned long ultensao. // Descrição : retorna o valor lido em milivolts. // =================================================================================== unsigned long ler_adc_mv(void) { unsigned long ultensao; ultensao =((ler_adc_un() * 5000)/1023); //Vref está em milliVolts return(ultensao); }
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Exemplo do protótipo funcionando :
Conclusões do projeto:
O circuito funcionou de forma satisfatória, conseguiu compensar a queda de tensão para uma carga de 300mA(com uma queda de tensão de saída de 0,3V), além de regular a tensão na saída mesmo que a entrada de tensão do circuito variasse. Como todos os outros exemplos postados aqui no blog este projeto é apenas didático podendo ser melhorado para uso comercial.
A tensão minima de trabalho ficou em 11V e a máxima é até 23V (geralmente até 1 ou 2 volta da tensão de saída), para mudar o valor da tensão de saída basta mudar o valor da variável "DDP_TRAB", não recomendo colocar um valor menor do que a entrada pois o circuito apenas eleva(conversor boost) a tensão.
Uma ultima dica é usar um dissipador de calor no mosfet de chaveamento.
Lembrando que para acompanhar as postagens basta entrar na página do facebook e curtir.
https://www.facebook.com/Microcontroladores-C-576463872371829 ou procurando por microcontroladores-c no face.
Parabéns pelo Projeto, muitoooo bacana. Eu estou realizando um projeto bem parecido, o meu é de (tensao de entrada) Vi= 24v para (tensao de saida) Vo=32v, porém essa tensão de 24v oscila entre 24 e 27v. Eu agradeceria muitooooo se você me desse dicas de como fazer, eu ja tem mto coisa pronta, o q eu nao tenho é esse controle de tensão Vo se manter estável, alterando a tensao de entrada. Meu e-mail é : dr.rirotho@gmail.com
ResponderExcluir