segunda-feira, 19 de agosto de 2013

Trena ultrassônica com PIC - MBLAB XC8



/*
 *                              detector ultrasonico MPlab XC8
 *
 * Compilador : MPlabXC8
 * Microcontrolador: 16F648A
 * Autor: aguivone
 * Versão: 1
 * descrição:trena ultrassônica
 * Data :  19 de agosto de 2013
 */
#include <stdio.h>
#include <string.h> //para usar funçoes de string deve se adicionar este header
#include <stdlib.h>
#define _XTAL_FREQ 16000000    // use este cristal pois a variavel de centimetros é do tipo inteiro 16 bits
#include <xc.h>
#include <delays.h>


/////////////////////////////////////////////////////////configuraçôes//////////////////////////////////////////////////
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator: High-speed crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF       // Power-up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = OFF      // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD)
#pragma config BOREN = OFF      // Brown-out Detect Enable bit (BOD disabled)
#pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EE Memory Code Protection bit (Data memory code protection off)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

#define LED     PORTBbits.RB4  //pisca a cada aquisição
#define TRIGGER PORTBbits.RB5  //pino de saida de pulso
#define ECO     PORTBbits.RB6  //pino de retorno(eco do som) 

//variaveis usadas/////////////////////////////////////////////////////
 unsigned long distancia_cm= 0;
 unsigned char caracter;
 bit flag_interrupcao = 0;

///////////////////////////////////////////////////interrupção//////////////////////////////////////////////////////////////
void interrupt RS232(void)//vetor de interrupção
 {
     caracter = RCREG;
     flag_interrupcao = 1;
     RCIF = 0;//  limpa flag de interrupção de recepção
 }

/////////////////////////////////funçoes usadas pela uart //////////////////////////////////////////////////////
void inicializa_RS232(long velocidade,int modo)
{////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(modo == 1)
        {//modo = 1 ,modo alta velocidade
         TXSTA = 0X24;//modo assincrono,trasmissao 8 bits.
         valor =(int)(((_XTAL_FREQ/velocidade)-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/velocidade)-64)/64);//calculo do valor do gerador de baud rate
        }
    SPBRG = valor;
    RCIE = 1;//habilita interrupção de recepção
    TXIE = 0;//deixa interrupção de transmissão desligado(pois corre se o risco de ter uma interrupção escrita e leitura ao mesmo tempo)
}
void escreve(char valor)
{
    TXIF = 0;//limpa flag que sinaliza envio completo.
    TXREG = valor;
    while(TXIF ==0);//espera enviar caracter
}
void imprime(const char frase[])
{
     char indice = 0;
     char tamanho = strlen(frase);
      while(indice < tamanho ) ///veja que o programa pode travar se aqui não tiver as duas aspas
       {
           escreve(frase[indice]);
           indice++;
       }
}
void int_to_char(unsigned long  quant)
{
    char convert_char1='0';
    char convert_char2='0';
        char convert_char3='0';
        char convert_char4='0';
        if(quant > 400)//maior que o range maximo
        {
          //  imprime("fora do range! \n\r");
            //faz nada!
        }
        else
        {
       while(quant>=1000)
        {
         quant=quant-1000;
         convert_char1++;
         }
       while(quant>=100)
        {
         quant=quant-100;
         convert_char2++;
         }
       while(quant>=10)
        {
         quant=quant-10;
        convert_char3++;
         }
       while(quant>=1)
        {
           quant=quant-1;
         convert_char4++;
         }
          escreve(convert_char1);
          escreve(convert_char2);
          escreve(convert_char3);
          escreve(convert_char4);
          imprime("- \n\r");
        }

}

void main(void)
{
    TRISB = 0X42;   //configura pino b1 e b6 como entrada(RX) e o resto como saida
    PORTB = 0;  // limpar as portas que estão configuradas como saidas
    CMCON = 0x07;        // Comparadores desligados.
    OPTION_REG = 0X80;//desabilita pull ups
    inicializa_RS232(9600,1);//modo de alta velocidade
    PEIE = 1;//habilita interrupção de perifericos do pic
    GIE = 0; //GIE: Global Interrupt Enable bit - neste caso não vou precisar das interrupções
    imprime("Trena ultrassônica! \n\r");
    for(;;)
    {

                          LED = 1;
              TRIGGER = 1;
                          __delay_us(20);
              TRIGGER = 0;
              while(!ECO);//espera o pino ir para nivel alto
                          distancia_cm=0;
              while(ECO)//espera o pino ir para nivel baixo
              {
                              distancia_cm++;
                          }
              //de forma empirica verifiquei que 1cm = 30unidades de contagem(aproximadamente)
                          distancia_cm = distancia_cm/ 11;//valor empirico aproximado!
                  int_to_char(distancia_cm);///envia valor para porta serial
              LED = 0;
                          __delay_ms(500);//espera 1s para ler novo valor
              //(no datasheet eles alertam que este tempo não pode ser menor que 60ms para não pegar ecos falsos)
    }//fim do for


}

terça-feira, 13 de agosto de 2013

Trena ultrassônica com HC - SR04 (ATMEGA328):


/*
 *                         usando o sensor ultrassônico HC-SR04
 *   Version    : 1
 *   microcontrolador : AVR ATMega328
 *   descrição  : medir distancia com o modulo HC-SRO4
 *   criado: 13/08/2013
 *   autor: aguivone moretti fogia
 */
/////////////////////////////////////////////////////////////////////////
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#define F_CPU 16000000UL  // 16MHz deve vir antes da funcão de delay
#include <util/delay.h>
#include <string.h>
#include <avr/eeprom.h>//usado para acessar memoria
////////////////////////////parametros///////////////////////////////////
//funçoes basicas dos pinos
 #define alterna_pino(x,y) x ^= _BV(y)   
 #define liga_pino(x,y) x |= _BV(y)
 #define desliga_pino(x,y) x &= ~(_BV(y))
 #define estado_pino(x,y) ((x & _BV(y)) == _BV(y)) //o pino deve estar como entrada ,testa se está em nivel logico 1

//configurando os pinos/////////////////////////////////////////////////

 #define TRIGGER    PB2  //no rele de discagem deve ser colocado um resistor de 470R para não curto circuitar a linha telefonica 
 #define LED        PB3

 //variaveis usadas/////////////////////////////////////////////////////
 long distancia_cm= 0;

 ///////////////////////////funçoes auxiliares//////////////////////////
void delay_ms(long conta)
{
  long valor=0;
  while(valor<conta)
  {
    _delay_us(999);// 1ms
    valor++;
  }
}

void RS232_inicializa(unsigned int BAUD)
{
   unsigned int velocidade = F_CPU/16/BAUD-1;
   // veja que na simulação do proteus dá erros nas velocidade diferentes de 9600 mas na pratica funciona.
    UCSR0A = 0X20;
    UBRR0H = (unsigned char)(velocidade>>8);
    UBRR0L = (unsigned char)velocidade;
    UCSR0B = 0X18;//não vou habilitar nenhuma interrupção da porta serial
    /* 8 bits , 1 stop bit, assincrono , sem paridade,modo nornal */
    UCSR0C = (1<<USBS0)|(3<<UCSZ00);
}

void escreve_caracter(unsigned char carac)
{  
            _delay_loop_1(1);//tempo para estabilizar tensão            
            while ( !( UCSR0A & (1<<UDRE0)) ); //espera transmitir para enviar um novo
            UDR0 = carac;    
            while ( !( UCSR0A & (1<<UDRE0)) ); //espera transmitir desabilita a transmissão
            _delay_loop_1(1);//tempo para garantir o envio
}

void impri_serial(const char frase[20])
{
      unsigned int indice=0;
      unsigned int tamanho = strlen(frase);    
       while(indice<=tamanho)///veja que o programa pode travar se aqui não tiver as duas aspas
       {
            escreve_caracter(frase[indice]);
            indice++;
       }
}

void int_to_char(long quant)
{


       char convert_char1='0';
       char convert_char2='0';
       char convert_char3='0';
       char convert_char4='0';


       while(quant>=1000)
        {
         quant=quant-1000;
         convert_char1++;
         }
       while(quant>=100)
        {
         quant=quant-100;
         convert_char2++;
         }
       while(quant>=10)
        {
         quant=quant-10;
        convert_char3++;
         }
       while(quant>=1)
        {
           quant=quant-1;
         convert_char4++;
         }
          escreve_caracter(convert_char1);
          escreve_caracter(convert_char2);
          escreve_caracter(convert_char3);
          escreve_caracter(convert_char4);
          impri_serial("- \n\r");

} 


int main(void)
{
           DDRB = 0XFE;  //inicializa portC,como saida exceto B0  - usado para icp1
           DDRC = 0X00;  //inicializa portC,como entrada
           DDRD = 0XF6;  //inicializa portD como Saida exceto pd0 e d3;      
           liga_pino(PORTB,TRIGGER);
           RS232_inicializa(9600);
           impri_serial("Sensor de distancia ultrassonica! \n\r");
           sei();
           long tempo;
      for(;;)
            { 
              desliga_pino(PORTB,LED);
              tempo = 0;
              desliga_pino(PORTB,TRIGGER);
              _delay_us(20);//20us necessario para gerar os pulsos
              liga_pino(PORTB,TRIGGER);
              while(estado_pino(PINB,PB0)==0);//espera o pino ir para nivel alto
              while(estado_pino(PINB,PB0)==1)//espera o pino ir para nivel baixo
              {distancia_cm++;}    
              //de forma empirica verifiquei que 1cm = 30unidades de contagem(aproximadamente)
              distancia_cm = distancia_cm/30;
              int_to_char(distancia_cm);///envia valor para porta serial
              desliga_pino(PORTB,LED);
              delay_ms(1000);//espera 1s para ler novo valor
              //(no datasheet eles alertam que este tempo não pode ser menor que 60ms para não pegar ecos falsos)
             }//fim do for
}//fim do main