sexta-feira, 15 de julho de 2016

Brincando com leds - detector de cores

       Olá, hoje vou compartilhar algo simples mas que nem sempre pensamos, eu já havia visto pessoas usando led para gerar tensão e como sensor de luz, então resolvi  mostrar como montar um circuito que detecta cor.
       O circuito basicamente é um amplificador de diferenças(veja a figura abaixo),uma pequena tensão gerada pelo led é amplificada(chegando perto de 500mv) e logo depois é amplificado novamente para ter tensão e corrente suficiente para acender um led.

         Para detectar a cor vermelha por exemplo basta usar um led vermelho e para outras cores usar a mesma cor de led. Dependendo da cor do led ele pode acender para duas ou mais cores, por exemplo se usar um led verde ele ira detectar o verde e amarelo(veja o vídeo de demonstração abaixo) pois no amarelo existe componentes de luz verde. Para separar as cores basta usar três leds com as cores primarias verde, vermelho e azul veja a ilustração a seguir.

        No dia do teste eu não tinha nenhum led azul, usei o amarelo mesmo sabendo que ele não seria o indicado mas apenas para mostrar que o circuito funciona com qualquer led. Veja o vídeo :



        O principio de funcionamento é similar ao do fotodiodo,uma dica para saber mais de fotodiodo é acessar o link  http://www.newtoncbraga.com.br/index.php/como-funciona/4715-art1181.É logico que usar um fotodiodo ou qualquer outro dispositivo especifico para receber a luz e converter em variações elétricas dão  maior sensibilidade e a filtragem da cor pode ser por meio de filmes colorido(um modo simples é usa papel celofane), mas aqui o intuito é meramente didático e informativo.
        OBS: os resultados foram melhores com leds de 5mm, já os de 3mm e smd não tem a mesma eficiência(geram um nível de tensão menor, as vezes insuficientes), outro detalhe é que os de alto brilho tem resposta melhor do que os foscos.

segunda-feira, 11 de julho de 2016

Usando 2 portas seriais no mesmo microcontrolador - 16F1947

         Olá, as vezes queremos usar 2 portas seriais ao mesmo tempo a melhor forma de se fazer isso e usar um microcontrolador que possua 2 portas UART(COM) em seu hardware, graças a compatibilidade entre os microcontroladores e com poucas alterações e possível fazer com que um mesmo código execute as configurações da serial e imprima nas duas portas sem grandes dificuldades.
          Neste exemplo tudo que é digitado em qualquer uma das portas é retornado na mesma porta. Veja o código fonte do aquivo "Main.c" e do "serial16F1947.c". A simulação do código é vista na figura a seguir, veja que neste exemplo na serial 1 pressionei F e na serial 2 pressionei H e então recebi o mesmo carácter de volta ficando FF e HH.


O código fonte:


/*
 *               testando hardware do microcontrolador - 2 serial        
 *
 * Compilador : MPlabXC8
 * Microcontrolador: 16F1947
 * Autor: aguivone
 * Versão: 1
 * Data :  11/07/2016*/
#include <xc.h>
#include <stdio.h>
#include "serial16F1947.c"

#define _XTAL_FREQ 16000000//usado para rotinas de  delays
#define LED               LATDbits.LATD4
#define LER_LED           PORTDbits.RD4

//
///////////configuração dos fuses bits/////////////////////////////////////////////
// CONFIG1
#pragma config FOSC = HS        // Oscillator Selection (HS Oscillator, High-speed crystal/resonator connected between OSC1 and OSC2 pins)
#pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = ON       // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Memory Code Protection (Data 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)
#pragma config IESO = ON        // Internal/External Switchover (Internal/External Switchover mode is enabled)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)

// CONFIG2
#pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
#pragma config VCAPEN = OFF     // Voltage Regulator Capacitor Enable (VCAP pin functionality is disabled)
#pragma config PLLEN = OFF      // PLL Enable (4x PLL disabled)
#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 LVP = OFF        // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)
//////////////////////////////////////////////////////////////////////////////////

//************************************************************************************/
//VARIAVEIS GLOBAIS
//************************************************************************************/

////variaveis da porta serial
char   gcCaracter;
//*******************************************************************************/
//===================================================================================
//Função:    _interrupcoes
//Descrição: usada para tratar as interrupções geradas pelo microcontrolador.
//===================================================================================
void interrupt interrupcoes(void)//vetor de interrupção
 {
      if(RC1IF)//verifica interrupção da serial na COM1
    {//interrupção da serial
        gcCaracter = RC1REG;   
        escreve_RS232(gcCaracter,0);//finaliza string
        RC1IF = 0;//  limpa flag de interrupção de recepção
    }
    if(RC2IF)//verifica interrupção da serial na COM2
    {//interrupção da serial
        gcCaracter = RC2REG;
        escreve_RS232(gcCaracter,1);//finaliza string
        RC2IF = 0;//  limpa flag de interrupção de recepção
    }
}

//===================================================================================
//Função:    _config_CPU
//Parâmetros: não tem
//Retorno:   não tem retorno.
//Descrição: inicializa os registradores do microcontrolador.
//===================================================================================
void config_CPU()
{
    //configura portas logicas
    TRISA = 0X00;
    TRISB = 0X00;
    TRISC = 0x80;
    TRISD = 0x00;
    TRISE = 0x00;
    TRISF = 0x00;//todos entrada e ainda são as entrasas analogicas
    TRISG = 0x04;
    // inicializa portas logicas configuradas como saida para 0
    LATA = 0;
    LATB = 0;
    LATC = 0;
    LATD = 0;
    LATE = 0;
    LATF = 0;
    LATG = 0;
    inicializa_RS232(9600,1,0);//modo de alta velocidade inicializa COM1
    inicializa_RS232(9600,1,1);//modo de alta velocidade inicializa COM2
    PEIE = 1;//habilita interrupção de perifericos do pic
    GIE = 1; //GIE: Global Interrupt Enable bit  
    __delay_ms(100);
    
}
void main(void) 
{
    config_CPU(); 
    imprime_RS232("Imprimindo: COM 1!\r\n",0); 
    imprime_RS232("Digite um caracter:\r\n",0); 
    imprime_RS232("Imprimindo: COM 2!\r\n",1);  
    imprime_RS232("Digite um caracter:\r\n",1);
    for(;;)
    { 
       //faz nada          
    }
}

O código do arquivo "serial16F1947.c"

/*
 *                          FUNÇOES USADAS NA SERIAL
 *
 * Compilador :      MPlabXC8
 * Microcontrolador: 16F1947
 * Autor:            Aguivone
 * Versão:           1
 * Data de criação:  11 de julho de 2016.
 */

#include <xc.h>
#include <stdio.h>
#include <string.h> //para usar funçoes de string deve se adicionar este header
#define _XTAL_FREQ 16000000//usado para rotinas de  delays

//===================================================================================
//Função:    _inicializa_RS232
//Parâmetros: unsigned long ulVelocidade
//          : unsigned int uiModo
//          : porta serial(1 ou 0) 
//Retorno:   não tem retorno.
//Descrição: usada para iniciar a porta serial.
//===================================================================================
void inicializa_RS232(unsigned long ulVelocidade,unsigned int uiModo,int porta)
{//// por padrão é usado o modo 8 bits e sem paridade, mas se necessario ajuste aqui a configuração desejada.
    // verifique datasheet para ver a porcentagem de erro e se a velocidade é possivel para o cristal utilizado.
    unsigned long valor;
    if(porta == 0)
    {
        RC1STA = 0X90;//habilita porta serial,recepção de 8 bit em modo continuo,assincrono.        
            if(uiModo == 1)
            {//modo = 1 ,modo alta velocidade
             TX1STA = 0X24;//modo assincrono,trasmissao 8 bits.
             valor =(((_XTAL_FREQ/ulVelocidade)-16)/16);//calculo do valor do gerador de baud rate
            }
            else
            {//modo = 0 ,modo baixa velocidade
             TX1STA = 0X20;//modo assincrono,trasmissao 8 bits.
             valor =(((_XTAL_FREQ/ulVelocidade)-64)/64);//calculo do valor do gerador de baud rate
            }
        SP1BRG = valor;
        RC1IE = 1;//habilita interrupção de recepção
        TX1IE = 0;//deixa interrupção de transmissão desligado(pois corre se o risco de ter uma interrupção escrita e leitura ao mesmo tempo)

    }
    else
    {
       RC2STA = 0X90;//habilita porta serial,recepção de 8 bit em modo continuo,assincrono.
        if(uiModo == 1)
        {//modo = 1 ,modo alta velocidade
         TX2STA = 0X24;//modo assincrono,trasmissao 8 bits.
         valor =(((_XTAL_FREQ/ulVelocidade)-16)/16);//calculo do valor do gerador de baud rate
        }
        else
        {//modo = 0 ,modo baixa velocidade
         TX2STA = 0X20;//modo assincrono,trasmissao 8 bits.
         valor =(((_XTAL_FREQ/ulVelocidade)-64)/64);//calculo do valor do gerador de baud rate
        }
    SP2BRGL = valor;
    SP2BRGH = valor<<8;
    RC2IE = 1;//habilita interrupção de recepção
    TX2IE = 0;//deixa interrupção de transmissão desligado(pois corre se o risco de ter uma interrupção escrita e leitura ao mesmo tempo)
    }
    
}
//===================================================================================
//Função:    _escreve1_RS232
//Parâmetros: char cValor, int porta
//Retorno:   não tem retorno.
//Descrição: usada para escrever 1 caracter.
//===================================================================================
 void escreve_RS232(char cValor,int porta)
{
     if(porta == 0)
    {
        TX1IF = 0;//limpa flag que sinaliza envio completo.
        TX1REG = cValor;
        while(TX1IF ==0);//espera enviar caracter
    }
    else
    {
        TX2IF = 0;//limpa flag que sinaliza envio completo.
        TX2REG = cValor;
        while(TX2IF ==0);//espera enviar caracter
    }
     __delay_us(10);//só pra garantir
}
 
//===================================================================================
//Função:    _imprime_RS232
//Parâmetros: const char ccFrase[], int porta
//Retorno:   não tem retorno.
//Descrição: usada para escrever uma string(vetor de caracteres).
//===================================================================================
 void imprime_RS232(const char ccFrase[],int porta)
{
     unsigned char indice = 0;
     unsigned char tamanho = strlen(ccFrase);     
      while(indice < tamanho ) ///veja que o programa pode travar se aqui não tiver as duas aspas
       {
           escreve_RS232(ccFrase[indice],porta);
           indice++;
       }
}


Controlando PWM conforme a variação de temperatura(sensor LM35).

         Olá, pessoal hoje vou deixar um exemplo de como alterar a largura de pulso de um sinal(PWM) conforme varia a temperatura.Para fazer este controle simples  criei 2 variáveis que define a partir de quando se deve reduzir ou aumentar a largura do pulso, ficando ainda uma região em que não aumenta e nem diminuí(zona de operação).veja afigura a seguir:



        Com a ideia deste exemplo é possível  controlar uma resistência elétrica,ventilador (ou cooler), células peltier, motores,transformadores e uma infinidades de circuitos que precisem de usar PWM para seu controle e que dependam da temperatura, neste exemplo foi usado o sensor de temperatura LM35. na imagem abaixo é visualizado a simulação no Proteus:



O Código Fonte:

/*
 *                 Fazendo um controle sim-ples de temperatura X PWM
 *
 * Compilador :      MPlabXC8
 * Microcontrolador: 18F13K22
 * Autor:            Aguivone
 * Versão:           1
 * Data de criação:  11/07/2016.
 * Exemplo de como fazer um controle simples de PWM com o LM35 
 */

#include <string.h> //para usar funçoes de string 
#include <xc.h>
#define led               LATBbits.LATB4
#define ler_led           PORTBbits.RB4
#define _XTAL_FREQ        16000000//usado para rotinas de  delays

//************************************************************************************/
//VARIAVEIS GLOBAIS
//************************************************************************************/
char   gcCaracter;
long   glTemperatura = 0;// em °C
long   glTemp_min = 18;// menor temperatura em °C 
long   glTemp_max = 20;// maior temperatura em °C
long   glCorrente = 0;// em A
//pwm
long    uiMax_passos = 0;//frequencia em khz
int    uiDuty = 30;//25% da largura de pulso
int    uiTempo = 0;

//serial 
unsigned char gucBufferSerial[5];     // Buffer da serial
volatile unsigned int  guiTamBuffer;        // Usado para contar o tamanho do buffer de recepção.
volatile unsigned char gucRecBufferStatus = 'S';

/*******************************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)

//todas as interrupções são tratadas aqui
void interrupt interrupcoes(void)//vetor de interrupção
 {
    if(ADIF)
    {//se interrupção do modulo analogico!
        ADIF = 0;//limpa flag
    }
   /*
    * interrupções que não serão usada,mas fica aqui para caso alguém precise usar
    * 
    *  if(RCIF )
    {//interrupção da serial
      RCIF = 0;//  limpa flag de interrupção de recepção 
    }  
    if(TMR2IF)
    {//interrupção do timer2
      TMR2IF = 0;//não será usado      
    }
    if(CCP1IF)
    {//interrupção do ccp1
      CCP1IF = 0;//não será usado
    }   */  
 }
//inicializa a serial 
void inicializa_RS232(unsigned long ulVelocidade,unsigned int uiModo)
{//// por padrão é usado o modo 8 bits e sem paridade, mas se necessario ajuste aqui a configuração desejada.
    // verifique datasheet para ver a porcentagem de erro e se a velocidade é possivel para o cristal utilizado.
    RCSTA = 0X90;//habilita porta serial,recepção de 8 bit em modo continuo,assincrono.
    int valor;
        if(uiModo == 1)
        {//modo = 1 ,modo alta velocidade
         TXSTA = 0X24;//modo assincrono,trasmissao 8 bits.
         valor =(int)(((_XTAL_FREQ/ulVelocidade)-16)/16);//calculo do valor do gerador de baud rate
        }
        else
        {//modo = 0 ,modo baixa velocidade
         TXSTA = 0X20;//modo assincrono,trasmissao 8 bits.
         valor =(int)(((_XTAL_FREQ/ulVelocidade)-64)/64);//calculo do valor do gerador de baud rate
        }
    SPBRG = valor;
   // RCIE = 1;//habilita interrupção de recepção
    RCIE = 0;//desabilita interrupção de recepção - neste exemplo não vamos receber nada
    TXIE = 0;//deixa interrupção de transmissão desligado(pois corre o risco de ter uma interrupção escrita e leitura ao mesmo tempo)
}
//cria função pra enviar 1 caracter
 void escreve_RS232(char cValor)
{
    TXIF = 0;//limpa flag que sinaliza envio completo.
    TXREG = cValor;
    while(TXIF ==0);//espera enviar caracter
    __delay_ms(1);
}
 //cria a funcão semelhante ao "print"(pois a funcão nativa não funciona tão bem)  
 void imprime_RS232(const char ccFrase[])
{
     unsigned char indice = 0;
     unsigned char tamanho = strlen(ccFrase);
      while(indice < tamanho ) ///veja que o programa pode travar se aqui não tiver as duas aspas
       {
           escreve_RS232(ccFrase[indice]);
           indice++;
       }
}
 //convete um numero para uma string de numeros, com escolha de quantos digitos será usado
void long_to_char_RS232(unsigned long  ulQuant,int iTam)
{
        char cTexto[7];
        int  iValor = 0;
        while(iValor < 6 )
        {
             cTexto[iValor]='0';
             iValor++;
        }
         while(ulQuant>=10000)
            {
             ulQuant=ulQuant-10000;
             cTexto[6]++;
             }
         while(ulQuant>=10000)
            {
             ulQuant=ulQuant-10000;
             cTexto[5]++;
             }
         while(ulQuant>=1000)
            {
             ulQuant=ulQuant-1000;
             cTexto[4]++;
             }
          while(ulQuant>=100)
            {
             ulQuant=ulQuant-100;
             cTexto[3]++;
             }
           while(ulQuant>=10)
            {
             ulQuant=ulQuant-10;
             cTexto[2]++;
             }
           while(ulQuant>=1)
            {
             ulQuant=ulQuant-1;
             cTexto[1]++;
             }
        iValor = iTam ;
          while(iValor != 0 )
           {
              escreve_RS232(cTexto[iValor]);              
              iValor--;
           }
}
//usado para ler o LM35
unsigned long ler_adc_un(void)
{
    unsigned long ultensao;
    ADCON0bits.GO = 1; //inicia conversão
    while (ADCON0bits.GO_DONE == 1); //espera finalizar leitura
    ultensao = ADRES;//(ADRESH << 8) | ADRESL;
    return(ultensao);
}
//usado para deixar as amostras mais confiaveis
void ler_ADC(int giMedia)//numero de amostras
{
      int iMedia=0;      
      glTemperatura = 0;
      while(iMedia < giMedia)
      {
        glTemperatura = glTemperatura +  ler_adc_un();
        __delay_us(2);//tempo minino para aquisições
        iMedia++;
      } 
      glTemperatura = glTemperatura/giMedia;
      if(glTemperatura <= 1)
        {
        glTemperatura = 0;   
        }
        else
        {
          glTemperatura = glTemperatura/2 ;
          //agora é só corrigir a não linearidade do sensor
          if(glTemperatura>24)
          {
           glTemperatura--;
          }
           if(glTemperatura>64)
          {
            glTemperatura--;
          }
          if(glTemperatura>103)
          {
             glTemperatura = 100;//valor maximo aceitavel
          }
        }
}
//configura o pwm
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 2
    PR2 = pr2;
    CCP1CON = 0X0F;//habilita pwm
   // desabilita interupções de ccp e timer 2
    CCP1IE = 0;//habilita modulo ccp1
    TMR2IE = 0; //habilita desliga interrupcçaõde  timer 2
}

//copnfigurações iniciais
void inicializa_cpu(void)
{
    TRISC = 0xDF;
    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
    inicializa_RS232(9600,1);//modo de alta velocidade
    ADCON0 = 0X21;//liga modulo analogico digital e configura   entrada de sinal para o pino RA2(AN2)
    ADCON1 = 0X00;// Vref- seta ao Vss e  Vref+ ao Vdd
    ADCON2 = 0b10111110;// justificado a direita// tempo de aquisição 20TAD // clk Fosc/64    
    ANSEL = 0x00;//desabilita portas analogicas(para não atrapalhar recepção no pino)/hab ra2
    ANSELH = 0x01;//em alguns casos não funciona nem a interrupção de recepção.
    imprime_RS232("Controlador LM35 X PWM. \n\r");
    imprime_RS232("Temperatura :\n\r");
    inicializa_PWM1(1,40,1); //100khz veja no comentario abaixo "SUGESTÃO DE DEFINES :"    
    CCPR1 = uiDuty;
    PEIE = 1;//habilita interrupção de perifericos do pic
    GIE = 1; //GIE: Global Interrupt Enable bit
}
//*******************************Rotina principal*********************************************/
void main(void)
{
  inicializa_cpu();
  for(;;)
    {
       if(uiTempo == 0)
       {
           long_to_char_RS232(glTemperatura,3); 
           imprime_RS232("\n\r");
           ler_ADC(6);//pega 6 amostras para tirar media  
           if(glTemperatura > glTemp_max)
           {
                if(uiDuty > 25)
                        {// limita um valor maximo para variar, mas se quiser pode por até 0;
                           uiDuty --;//decrementa variavel  
                        }
                        CCPR1 = uiDuty;
           }           
           if(glTemperatura < glTemp_min)
           {
              if(uiDuty < 40)//o max é 40 passos nessa frequencia
               {
                  uiDuty++;//incrementa variavel
               } 
               CCPR1 = uiDuty;  
           }              
           led = ~ler_led;
           uiTempo = 50;//seta tempo           
       }
       else
       {
          uiTempo--; 
       } 
       __delay_ms(1);
    }//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
 *
//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)   //
*/