1 de abr. de 2012

Sensor Ultra-Sônico


Sensores de ultra som são componentes muito úteis no desenvolvimento de projetos microcontrolados por serem fáceis de implementar e ter uma resposta linear diretamente proporcional a distância em que se encontra de um determinado objeto.
Veremos agora como funciona o sensor de ultrasom DYP-ME007 que pode  ser adquirido diretamente da China através do site www.goodluckbuy.com

Sensor ultra1

O Sensor de ultrasom pode detectar objetos a distâncias que variam entre 2 e 350cm de distância com uma precisão de 3mm, sendo que o modelo testado retornou uma precisão de 2mm.
A detecção de distância é feita através do disparo de um pulso de nível alto com duração de 10us no pino de Trigger do sensor, assim que ele detectar este sinal, emite uma sequencia de 8 pulsos na frequência de 40KHz, frequência esta que define o termo Ultra-sônico utilizado na nomenclatura. Após este som emitido “Bater” em algum objeto, retorna e é capturado pelo microfone do sensor para processamento das informações.

Sensor

A distância “D” corresponde a real distância do objeto, como o sensor recebe a informação de distância de emissão e recepção, obtêm duas vezes a distância real, como a velocidade do som no ar a temperatura média de 25°C é de 340m/s, facilmente se obtém a relação de distância em milímetros através da equação:
Distância = Velocidade * Tempo
2 * Distância = 340 * Tempo
Distância = 170 * Tempo
 
Todos estes cálculos são efetuados diretamente pelo sensor DYP-ME007 que ao final entrega no pino Echo um pulso ativo correspondente a distância real do objeto como mostra a figura abaixo:
 
Temporização
 
Para se transformar o tempo (us) retornado pelo sensor  em distância(mm), basta dividir valor do tempo por 58.
Este valor é obtido da seguinte relação:
Um metro corresponte a um pulso de aproximadamente 5764us, transformando em cm temos 57,64cm que arredondamos para 58 para facilitar os cálculos no microcontrolador.

Teste de funcionamento.

Este sensor possui quatro pinos de conexão sendo:
VCC – Alimentação de 5V (Consumo médio de 20ma)
GND – Alimentação GND
Trigger- Pino para disparo de leitura (10ms)
Echo – Pino de retorno de informações referente a distância medida
Out – Este pino NÃO deverá ser conectado

Podemos detectar a largura de pulso do sensor de várias maneiras, porém a maneira mais elegante de se fazer isto com microcontroladores PIC, é utilizando o módulo CCP na função CAPTURE.
Para isto temos que conhecer um pouco mais sobre este módulo interno do microcontrolador.
O módulo CCP utiliza os Timers internos do microcontrolador como base de tempo, neste caso específico do modo CCP que é o CAPTURE, é utilizado o TIMER1 incrementando a cada us.
Desta forma quando o módulo CCP detecta a borda alta correspondente ao pino ECHO do sensor, ativa a contagem do TIMER,(incrementeado a cada us) e muda a configuração da borda de sensibilidade para baixa, aguardando assim o término do pulso referente a distância, com isto conseguimos saber qual o período do pulso entrege pelo sensor em já em us.
Após esta informação ser processada temos que alterar novamente a borda de sensibilidade para alta afin de estarmos prontos para uma nova informação proveniente so sensor.
Através do uso deste módulo, trabalhamos apenas com interrupções liberando o microcontrolador para outras tarefas tornando o programa mais eficiente.


Abaixo segue o programa exemplo da placa PK2Lab para uso com estes sensores.
/******************************************************************************
                      JL Audio Manutenção Eletrônica
Data: 01/2012
Autor: Jean Carlos
Projeto: Sensor de distância DYP-ME007
Microprocessador: PIC18F4550
Clock do processador: 8MHz
Estação de desenvolvimento: PK2Lab V 1.1
Compilador: MikroC PRO V 4.60.0.0
Versão atual:
Descrição:

          Este projeto demonstra o uso do sensor de distancia DYP-DM007
          Com a placa PK2Lab, o valor referente a distância entre o
          objeto e o sensor é exibido no display LCD.

          Trigger -> RC0
          Echo    -> RC2 -> Entrada do módulo CCP1

          O resultado da captura é salvo em CCPR1H e CCPR1L
          Para efetuar este projeto, iremos configurar o TMR1 como contador
          sincrono,para ser incrementado pela fonte de clock externo que é
          o cristal de 8MHz conectado a placa PK2Lab(Sem PLL).

          8MHz -> (Fosc/4)2MHz -> Prescaler 2:1 -> 1MHz (1uS)
          Para calcular a distancia em centimetros, usamos a formula abaixo:


*******************************************************************************/
// Configuração do LCD da placa PK2Lab V.1.1

sbit LCD_RS at RB2_bit;
sbit LCD_EN at RB3_bit;
sbit LCD_D4 at RB4_bit;
sbit LCD_D5 at RB5_bit;
sbit LCD_D6 at RB6_bit;
sbit LCD_D7 at RB7_bit;

sbit LCD_RS_Direction at TRISB2_bit;
sbit LCD_EN_Direction at TRISB3_bit;
sbit LCD_D4_Direction at TRISB4_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D7_Direction at TRISB7_bit;


//******************************************************************************
// Definições e  Variáveis Globais

#define Trigger RC0_bit
char txt[4];                  // Usado para conversão de dados em string
char Tempo_H, Tempo_L, Distancia_cm;
unsigned int Periodo;         // Variável que armazena o período do Pulso ECHO

//******************************************************************************
// Funções Auxiliares

void interrupt()
{
if(CCP1IF_bit && CCP1CON.B0)  // Captura por CCP1 e borda configurada como subida...
{
  CCP1IF_bit  = 0;            // Limpa a flag para nova captura
  CCP1IE_bit  = 0;            // Desabilita interrupção por periféricos(CCP1)
  CCP1CON     = 4;          // Configura a borda de captura para DESCIDA. (ESTE EVENTO CAUSARIA INTERRUPÇÃO ERRÔNEA)
  CCP1IE_bit  = 1;            // Habilita interrupção por periféricos(CCP1)
  TMR1H       = 0;             // Zera registradores do TMR1 para contagem de tempo
  TMR1L       = 0;
  TMR1ON_bit  = 1;          // Habilita contagem de tempo.
}

else if(CCP1IF_bit)
      {
       CCP1IF_bit  = 0;        // Limpa a flag para nova captura
       TMR1ON_bit  = 0;      // Desabilita contagem de tempo.
       CCP1IE_bit  = 0;        // Desabilita interrupção por periféricos(CCP1)
       CCP1CON     = 5;      // Configura a borda de captura para SUBIDA. (ESTE EVENTO CAUSARIA INTERRUPÇÃO ERRÔNEA)
       CCP1IE_bit  = 1;       // Habilita interrupção por periféricos(CCP1)
       Tempo_H     = CCPR1H;  // Carrega valores de tempo capturado(Neste caso em us)
       Tempo_L     = CCPR1L;
      }

}
Pulso()                       // Gera o Pulso de trigger para o sensor ultra som.
{
Trigger = 1;
Delay_us(10);
Trigger = 0;
}

//******************************************************************************
//Rotina Principal

void main()
{
TRISC  = 0b00000100;         // Entrada CCP1
PORTC  = 0b00000000;
INTCON = 0b11000000;         // Liga interruptores GIE e PEIE
TMR1IE_bit = 0;              // Desabilita interrpções de TMR1
CCP1IE_Bit = 1;              // Habilita interrupções por CAPTURA(CCP1)
CCP1CON    = 5;              // Configura módulo CCP1 para CAPTURA e borda de SUBIDA.

T1CKPS1_bit = 0;             // Prescaller TMR1 2:1
T1CKPS0_bit = 1;
TMR1CS_bit  = 0;             // Clock selecionado -> OSC/4
TMR1ON_bit  = 0;             // Timer -> 1 = Habilita contagem

Lcd_Init();
Lcd_Cmd(_Lcd_Cursor_Off);
Lcd_Cmd(_LCD_CLEAR);
Lcd_Out(1,1,"***  PK2Lab  ***");
Lcd_Out(2,1,"Distancia:    cm");
Delay_ms(100);

while(1)
{
Pulso();                                 // Dispara leitura de distância.
Delay_ms(100);                     // Intervalo entre leituras.
Periodo = (Tempo_H<<8)+ Tempo_L;   // Obtenção do período relativo ao ECHO
Distancia_cm = Periodo/58;    // Conversão da distância informada para cm

                  //------------------------------------------------------------------------------------//
                  // Um Pulso de 58us corresponde a uma distância de 1cm  //
                  //------------------------------------------------------------------------------------//


// Distância MINIMA 3cm e MAXIMA 3m

if((Distancia_cm < 3)||Distancia_cm >300) Lcd_Out(2,12,"---");
else
    {
    byteToStr(Distancia_cm, txt);   // Converte texto para impressão
    Lcd_Out(2,12,txt);                   // Imprime valores no display
    }
}
}

5 comentários:

  1. Olá Jean, parabéns pelo projeto!, pergunta: quando entra na interrupção, não fica desativado outra interrupção? é necessário desativar a interrupção? vou olhar o código novamente para ver prioridade de interrupção, valeu! Paulo Roquetti

    ResponderExcluir
    Respostas
    1. Olá Paulo, eu desativo as interrupções por periféricos para poder mudar a borda de sensibilidade da interrupção, o que ocorre é que sempre que se altera essa borda é gerado errôneamente pelo microcontrolador um evento de interrupção, por isto temos que desabilitar no momento que alteramos essa configuração e logo após podemos reabilitar as interrupções sem que este erro ocorra.

      Excluir
  2. Excelente post, Parabéns! Será muito útil.

    ResponderExcluir
  3. Olá...

    Como faço para realizar a leitura com um oscilador de 20mhz??

    Obrigado desde já

    ResponderExcluir
  4. Olá Bruno, você terá que trabalhar com os ajustes de prescaler para garantir 1MHz para o contador, isto pode ser feito inclusive utilizando o oscilador interno dos PICs, dependendo do modelo já temos inclusive 8MHz interno. Grande abraço!

    ResponderExcluir