PIC: HC-SR04 - Sensor Ultrassônico
O sensor ultrasônico HC-SR04 funciona como um detector de objetos e permite medir distancias mínimas de 2 centímetros podendo chegar a distancias máximas de até 4 metros com uma precisão de 3 milímetros. Estes sensores emitem um sinal ultrassônico (40 kHz) que ao atingir um objeto, retorna ao sensor. O sinal de retorno é captado, permitindo-se calcular a distância do objeto ao sensor, medindo o tempo de ida e volta do sinal emitido.
Usando a seguinte fórmula, é possível calcular a distância, sendo que v (velocidade do som) é ~350m/s.
d[m] = ( v[m/s] * t[s] ) / 2
Para a contagem do tempo, foi utilizado o Timer1, configurado de modo que incremente a cada 1us.
MikroC PRO PIC
sbit HCSR04_Trigger at RB0_Bit; sbit HCSR04_Echo at RB1_Bit; sbit HCSR04_Trigger_Direction at TRISB0_Bit; sbit HCSR04_Echo_Direction at TRISB1_Bit; //No teste utilizei um cristal de (20MHz + PLL) = 48MHz e configurei //o prescaler do TIMER1 para 1:8 ( mode = 3 ) //fator = 1 / ( ( 4 * Prescaler ) / Clock ) //fator = 1 / ( ( 4 * 8 ) / 48 ) #define fator 1.5 //mode = 0, prescaler 1:1 //mode = 1, prescaler 1:2 //mode = 2, prescaler 1:4 //mode = 3, prescaler 1:8 void HCSR04_Init( char mode ) { HCSR04_Trigger_Direction = 0; HCSR04_Echo_Direction = 1; TMR1L = 0; TMR1H = 0; T1CON = 0b00000000; //Clock 4Mhz / Prescaler 1:1 //T1CON = 0b00010000; //Clock 8 Mhz / Prescaler 1:2 //T1CON = 0b00100000; //Clock 16 Mhz / Prescaler 1:4 //T1CON = 0b01100000; //Clock 32 Mhz / Prescaler 1:8 T1CON.B4 = mode.B0; T1CON.B5 = mode.B1; } unsigned HCSR04_Read() { float distance; unsigned time; unsigned i; HCSR04_Trigger = 0; Delay_us( 2 ); HCSR04_Trigger = 1; Delay_us( 10 ); HCSR04_Trigger = 0; i = 0xFFFF; while( !HCSR04_Echo && i-- ); TMR1H = 0; TMR1L = 0; TMR1ON_Bit = 1; i = 0xFFFF; while( HCSR04_Echo && i-- ); TMR1ON_Bit = 0; time = *(unsigned*)&TMR1L; distance = (0.175 * time / fator); //distancia em mm return (unsigned)distance; }
EXEMPLO:
// LCD module connections sbit LCD_RS at RB6_bit; sbit LCD_EN at RB7_bit; sbit LCD_D4 at RB2_bit; sbit LCD_D5 at RB3_bit; sbit LCD_D6 at RB4_bit; sbit LCD_D7 at RB5_bit; sbit LCD_RS_Direction at TRISB6_bit; sbit LCD_EN_Direction at TRISB7_bit; sbit LCD_D4_Direction at TRISB2_bit; sbit LCD_D5_Direction at TRISB3_bit; sbit LCD_D6_Direction at TRISB4_bit; sbit LCD_D7_Direction at TRISB5_bit; // End LCD module connections //Insira o código da biblioteca aqui!!! char txt[12]; unsigned distancia; void main() { ADCON1 = 0x0F; //Desligar o canal analógico da PORTB HCSR04_Init(3); //Prescaler 1:8 Lcd_Init(); Lcd_Cmd( _LCD_CURSOR_OFF ); while(1) { distancia = HCSR04_Read(); //mm WordToStr(distancia, txt); Lcd_Out(1,1,"Distancia: "); Lcd_Out_CP(txt); Lcd_Out_CP(" mm"); Delay_ms(1000); } }
tem algum link pra baixar assim como nos outros arquivos do blog?
ResponderExcluirComo faço para baixar a biblioteca para o proteus??
ResponderExcluirFIZ O TESTE, E FUNCIONOU MUITO BEM.
ResponderExcluirFIZ UM TESTE, E FUNCIONOU.
ResponderExcluirFIZ ATÉ UM VIDEO.
http://www.youtube.com/watch?v=UR6Q9G8GX9A&feature=youtu.be
Parabéns!!!
ExcluirOla a todos, desde já um muito obrigado pelo post, já agora preciso de uma ajuda só para perceber uma linha do código:
ResponderExcluirdistance = (0.175 * time * fator); //distancia em mm
Como chegaram ao valor 0.175???
Só me falta compreender isso porque o resto percebo.
Obrigado!
Transformando metros pra milimetros e tempo de segundos para microsegundos, e v sendo 350/2 m/s:
Excluira formula fica : 10E+3*v[mm/s] * 10E-6* t[us];
entao = (10E+3 * 10E-6) * 175 * t;
= 10E-3 * 175 * t
= 0.175 * t
considerando o fator
=0.175 * t * fator
Eu pensei nessa fórmula mas por algum motivo dava valores
Excluirdiferentes durante os cálculos mas devia ser distração ( no valor das unidades ) !!!
Muito obrigado pelo esclarecimento e desde já um MUITO OBRIGADO pelo trabalho realizado no blog. Abraço
não consigo ter os valores correctos de medida com o pic 16F877A a 20mhz
Excluirmas a 8mhz tenho tudo certo! seria de esperar que o codigo que usam a 20mhz funcione da mesma forma na pic 16F877A a 20mhz não?
Estou tendo o mesmo problema! copiando o codigo pra 16f877a a 20mhz ele dá errado...
ResponderExcluirno código tinha um pequeno erro, mas já arrumei. Tenta fazer o teste novamente.
Excluirboa noite,
ResponderExcluirTiago, estou tendo o mesmo problema dos colegas acima.
poderia dizer onde encontra a falha do codigo?
obrigado.
Eu ja arrumei o codigo. E tah funcionando perfeitamente. Fiz o teste com o pic rodando a 48MHz.
ExcluirTente ajustar o fator de acordo com o clock desejado.
o que seria o T1CON.B4 = mode.B0; ??????
ResponderExcluirT1CON.B5 = mode.B1;
os bits B4 e B5 do registro T1CON são usados pra configurar o prescaler. No caso estou definindo seus valores com o valor dos bits B0 e B1 da variavel "mode".
ExcluirOlá bacana seu post, eu citei ele, também fiz uma aplicação com o HC e para isso eu emulei o módulo com um PIC12F629. Segue o post, se alguem ta querendo experimentar fazer um code e apenas simular acho que isso pode ajudar: http://robsoneletronico.wordpress.com/2014/05/18/sensor-de-distancia-por-ultrasom-modulo-hc-sr04-emulador-do-modulo/
ResponderExcluirOi,
ResponderExcluirO seu blog é demais... muito tenho aprendido com exemplos práticos do seu blog.
Só que eu queria simular o HC-SR04 como voçê tem na imagem, mas eu não encontro na minha libraria do PROTEUS. Eu tinha a versão 7.8, mas ontem saquei a versão 8.1 do seu blog e algumas livrarias que voçê aqui tem, mas não encontro esta"HC-SR04", não me aparece no PROTEUS.
Pode me arranjar, pondo aqui a libraria do HC-SR04 ou o exemplo deste mesmo projecto????
Desde já muito obrigado pela sua atenção.
O componente que utilizei no Proteus não é simulavel.
ExcluirSe eu usar o Oscilador interno do PIC16F628A, O Fator ficará igual a 1? Mais uma coisa, eu adicionei esse codigo:
ResponderExcluirsbit HCSR04_Saida at RB2_Bit;
sbit HCSR04_Saida2 at TRISB2_Bit;
.
.
HCSR04_Saida2 = 0;
.
.
while(1)
{
distancia = HCSR04_Read(); //mm
if(distancia < 100){
HCSR04_Saida2 = 1;
}
else{
HCSR04_Saida2 = 0;
}
Delay_ms(1000);
}
Para que quando o objeto estiver em uma distancia de até 30cm a saída "HCSR04_Saida2" fique em nível alto. Está certo esse código?
Corrigindo: Distancia de até 10 cm a saída fique em nível alto.
ExcluirArrume isso aqui:
Excluirif(distancia < 100){
HCSR04_Saida2 = 1;
}
else{
HCSR04_Saida2 = 0;
}
Troque HCSR04_Saida2 por HCSR04_Saida
Seria possível usar o PIC 12F675 com clock interno para identificar se a distância estiver menor que 1 metro usando este software?
ResponderExcluirPrecisaria modificar o que?
Obrigado.
Olá, estou projetando um robo que irá utilizar um módulo deste.
ResponderExcluirutilizarei um PIC16F877A.
Seria possível disponibilizar o código para utilizar no source?
A função WordToStr é de que Biblioteca, estou enfrentando muitos problemas para converter Float para Char no compilador XC8 usando a IDE Mplab.
ResponderExcluirConversions.h
ExcluirOlá Thiago,
ResponderExcluirPrimeiramente parabéns pelo site.
Gostaria de saber se no seguidor de linha, posso colocar este sensor, sendo que ao avistar um obstaculo terá que parar por 10 segundo e depois retornar ao percurso normal. Como faço isso.
Preciso de uma força aí.
Obrigado
Carlos
seria possivel ao inves de mostrar a distancia, mostrar litros de agua?
ResponderExcluirBoa noite. Estou com o seguinte problema: Calculei o "factor" para Cristal de 20MHz, configurei o Timer1 para 1us, código exatamente igual ao publicado, apenas essas alterações para ajustar ao meu projeto. Porém, até 2m funciona muito bem. Mais que isso já não dá certo. Achei que pudesse ser o sensor mas já testei dois e estão do mesmo jeito. Alguém sabe o que poderia ser??? Pelo que sei esse sensor mede até 4m certo? Qualquer ajuda é bem vinda... Grato desde já!!!
ResponderExcluirResolvido! Não sei pq mas o problema era com o Clock. Tirei o cristal de 20MHz e rodei com o oscilador interno (4MHz), alterei os valores do "factor" e do Timer1 pra obter 1us e funcionou. Se alguém souber pq não funciona com o Cristal de 20MHz seria uma informação importante... Até mais! Parabéns pelo blog.
ExcluirEste comentário foi removido pelo autor.
ResponderExcluirEstou adaptando ao meu projeto com o 16f887 ja tive resultado positivos mas n consigo compreender essa trecho o que faz ?
ResponderExcluiri = 0xFFFF;
while( !HCSR04_Echo && i-- );
TMR1H = 0;
TMR1L = 0;
TMR1ON_Bit = 1;
i = 0xFFFF;
while( HCSR04_Echo && i-- );
TMR1ON_Bit = 0;
time = *(unsigned*)&TMR1L;
distance = (0.175 * time / fator); //distancia em mm