Sensor de distancia HC-SR04

Hola a todos. Tengo un problema con la programación de un sensor de distancia por ultrasonidos con un ATmega128 y Mikroc.

Lo que hago es mandar un pulso de 15µs al Trigger y esperar a recibir por el Echo el pulso correspondiente que mas tarde mediré y será lo que me de la distancia.

El VCC del sensor está conectado al puerto PA7 que siempre se mantiene en estado alto para mantener la tensión del sensor.
Código:
 /*Defino donde va a estar conectado el sensor*/

#define ECHO PORTA.B3
#define TRIG PORTA.B5
#define VCC  PORTA.B7
int i,r,distancia;

// Conexiones LCD
sbit LCD_RS at PORTC2_bit;
sbit LCD_EN at PORTC3_bit;
sbit LCD_D4 at PORTC4_bit;
sbit LCD_D5 at PORTC5_bit;
sbit LCD_D6 at PORTC6_bit;
sbit LCD_D7 at PORTC7_bit;

sbit LCD_RS_Direction at DDC2_bit;
sbit LCD_EN_Direction at DDC3_bit;
sbit LCD_D4_Direction at DDC4_bit;
sbit LCD_D5_Direction at DDC5_bit;
sbit LCD_D6_Direction at DDC6_bit;
sbit LCD_D7_Direction at DDC7_bit;
// Fin conexiones LCD

//Función para leer pulso
  int ancho_pulso ()
{
//Espero flanco de subida en ECHO, me mantengo en el bucle hasta que detecte tensión

        for(i=0;i<600000;i++)
          {
          if (!ECHO) continue; else break;
          }
//Si supera esos ciclos es que no hay ningún objeto
          if(i==600000)
          return 0xFFFF;
//Voy a configurar el timer
           TCCR0=0x02; //preescaler 8
           TCNT0=0x00; //empieza a contar
           
                  for(i=0;i<600000;i++)
       {
          if(ECHO)
          {
             if(TCNT0 > 60000) break; else continue;
          }
          else
             break;
       }
       if(i==600000)
          return 0xffff;
          
          distancia=TCNT0;
          
                 if(distancia > 60000)
         return 0xfffe;
       else
          return distancia;
}

void main (){
/*
Configuración previa de los puertos
-Dejo solo como entrada PA3
-Dejo el puerto de VCC como salida para alimentar
-Dejo el trigger a 0 al principio
*/

     DDRA=0xF7;
     PORTA=0xD7;
     delay_ms(1000);

       

 while (1) {
 TRIG=0xFF;
 Delay_ms(15);
 TRIG=0x00;
   
   r=ancho_pulso();
//Inicio LCD
  Lcd_Init();                        // Inicio
  Lcd_Cmd(_LCD_CLEAR);               // Limpio
  Lcd_Cmd(_LCD_CURSOR_OFF);          // Apago cursor
   
   if (r==0xFFF)
   {
    Lcd_Out(1,1,"ERROR");
   }
   else
            {

            int d;

            d=(r/58); //Paso a cm

            LCD_out (1,1,d);

         }
}
}

La verdad es que ando algo perdido espero que alguien pueda orientarme
 
He corregido algo y parece ser que ya manda y recibe a traves de Trigger y Echo respectivamente algo. Pero aun no consigo nada en el LCD...

Código:
 /*Defino donde va a estar conectado el sensor*/

#define ECHO PORTA.B3
#define TRIG PORTA.B5
#define VCC  PORTA.B7
int i,r,distancia;
char texto[7];


// Conexiones LCD
sbit LCD_RS at PORTC2_bit;
sbit LCD_EN at PORTC3_bit;
sbit LCD_D4 at PORTC4_bit;
sbit LCD_D5 at PORTC5_bit;
sbit LCD_D6 at PORTC6_bit;
sbit LCD_D7 at PORTC7_bit;

sbit LCD_RS_Direction at DDC2_bit;
sbit LCD_EN_Direction at DDC3_bit;
sbit LCD_D4_Direction at DDC4_bit;
sbit LCD_D5_Direction at DDC5_bit;
sbit LCD_D6_Direction at DDC6_bit;
sbit LCD_D7_Direction at DDC7_bit;
// Fin conexiones LCD

//Función para leer pulso
  int ancho_pulso ()
{
//Espero flanco de subida en ECHO, me mantengo en el bucle hasta que detecte tensión

        for(i=0;i<600;i++)
          {
          if (!ECHO) continue; else break;
          }
//Si supera esos ciclos es que no hay ningún objeto
          if(i==600)
          return 0xFFFF;
//Voy a configurar el timer
           TCCR0=0x02; //preescaler 8
           TCNT0=0x00; //empieza a contar
           
                  for(i=0;i<600;i++)
       {
          if(ECHO)
          {
             if(TCNT0 > 600) break; else continue;
          }
          else
             break;
       }
       if(i==600)
          return 0xffff;
          
          distancia=TCNT0;
          TCCR1B=0x00;
          
                 if(distancia > 600)
         return 0xfffe;
       else
          return distancia;
}

void main (){
/*
Configuración previa de los puertos
-Dejo solo como entrada PA3
-Dejo el puerto de VCC como salida para alimentar
-Dejo el trigger a 0 al principio
*/

     DDRA=0xF7;
     PORTA=0xD7;
     DDRB=0xFF;
     PORTB=0x00;
     //Inicio LCD
  Lcd_Init();                        // Inicio
  Lcd_Cmd(_LCD_CLEAR);               // Limpio
  Lcd_Cmd(_LCD_CURSOR_OFF);          // Apago cursor
     delay_ms(1000);
  LCD_out (1,6,"PRUEBA");
  LCD_out (2,2,"Sensor HC-SR04");
  Delay_ms(2000);

       

 while (1) {
  delay_ms(100);
 TRIG=0xFF;
 Delay_ms(15);
 TRIG=0x00;

   
   r=ancho_pulso();

   if (r==0xFFF)
   {
    Lcd_Out(1,1,"ERROR");
   }
   else
            {

            int d;

            d=(r/58); //Paso a cm

            IntToStr (d,texto);
            Lcd_Cmd(_LCD_CLEAR);
            LCD_out (1,1,texto);

         }
}
}
 
Hola que tal, tengo un proyecto de programas un carro que evada obstáculos,
y pues el primer paso fue comprar el sensor que es un hc-sr04 pero no lo puedo probar por que no entiendo mucho de la implementación de los pulso echo y trigger.
Mi pregunta es, si tienen un programa para probarlo, o algo para decir si funciona o no ???
gracias
Es picc o ccs el compilador gracias y si esta simulado en proteus
aunque me ayudarían si me explicaran para armar el código

yo ya hice parte del código, me podrían ayudar por que solo me mide 001cm.
Pareciera de que no cuenta bien, y está bien conectado y todo (aclaro la idea la saque de un ejemplo de programa que encontré) Gracias




Código:
#include "C:\Users\User\Desktop\sensor prueba 1\pic c 3\main.h"
#define trig pin_b0
#define echo input(pin_b1)
#include "flex_lcd.c"
#include "kbd_lib.c"



int16 mide_distancia(void)
{
int16 centimetros=0; 
output_high(trig); // pulso de disparo
delay_us(50);
output_low(trig);

while(echo==0); 

while(echo==1)
{
centimetros++;
delay_us(58);

delay_ms(50);
return(centimetros);
}
}


void main()
{
int16 distancia;
int8 i;
lcd_init(); 


while (true)
{
distancia=mide_distancia(); 

lcd_gotoxy(1,1);
if(distancia>100)
{ // si lectura > 500cm entonces no es valida, osea no hay objeto
lcd_putc('\f'); // Borra LCD
printf(lcd_putc,"no objeto");
output_low(pin_c0);
}

else
{

printf(lcd_putc,"%03lucm ",distancia);
output_high(pin_c0);

}
}
}
 
Última edición por un moderador:
Hola amigos del Foro!...les cuento que soy estudiante de ingenieria electrónica. Actualmente estoy cursando una materia llamada Procesadores II, en la que aprendemos la estructura, funcionamiento y programacion de microcontroladores pic.

Estoy en por empezar un proyecto, el cual es un detector de distancia para vehículo. La idea es determinar la distancia entre dos vehículos para estacionar. El problema es que aun no vemos (y al parecer no nos enseñaran en esta materia) el uso de sensores de proximidad. He leído sobre algunos de ultrasonido, pero aun no logro entender bien como es su funcionamiento.

El motivo de este tema, es pedirles ayuda sobre el uso de sensores de este tipo, y si pueden facilitarme en lo posible material para estudiarlos y ver como funcionan, asi llevo adelante dicho proyecto. Aclaro que estuve buscando en google sobre sensores, pero no encontre hasta el momento información profundizada sobre esto.

Desde ya muchas gracias por tomarse su tiempo en leer mi inquietud.

Saludos a todos!
 
Hola amigos del Foro!...les cuento que soy estudiante de ingenieria electrónica. Actualmente estoy cursando una materia llamada Procesadores II, en la que aprendemos la estructura, funcionamiento y programacion de microcontroladores pic.

Estoy en por empezar un proyecto, el cual es un detector de distancia para vehículo. La idea es determinar la distancia entre dos vehículos para estacionar. El problema es que aun no vemos (y al parecer no nos enseñaran en esta materia) el uso de sensores de proximidad. He leído sobre algunos de ultrasonido, pero aun no logro entender bien como es su funcionamiento.

El motivo de este tema, es pedirles ayuda sobre el uso de sensores de este tipo, y si pueden facilitarme en lo posible material para estudiarlos y ver como funcionan, asi llevo adelante dicho proyecto. Aclaro que estuve buscando en google sobre sensores, pero no encontre hasta el momento información profundizada sobre esto.

Desde ya muchas gracias por tomarse su tiempo en leer mi inquietud.

Saludos a todos!

Mira en este enlace, a ver si te sirve algo. ULTRASONIDO
 
bueno como nadie pudo responder mi pregunta yo te la respondo a ti entre mas sensillo es la cosa es mejor yo tuve que comprar un sensor ultrasonico hc sr04 el cual me costo en colombia unos 30 dolares o 60000 pesos colombianos este es talvez el mas sencillo y cumple bien su tarea el manda un pulso cada cierto tiempo (lo indica el programa yo por ejemplo utilizo lenguajes c en pcw o pic c) el cual activa un contador tambien en el pic y calcula la distancias en el pic si compilas en pcw y decides comprarlos me dices para enviarte el codigo de prueba
 
bueno si vas a utilizar el ccs que creo que es el mismo pcw ese código de ejemplo no te funcionara o al menos a mi no me sirvio te paso uno que si me funciono solo hay que cuadrarle los centímetros pero te dice si tu sensor funciona o no

Código:
#include "main.h"
#use delay(clock=20000000) 
#include "flex_lcd.c"                        


int16 distancia, tiempo;
#define trig pin_B0
#define echo pin_B1

void main() 
{ 
output_low(PIN_C1);
lcd_init();                              
printf(LCD_PUTC, "\f Iniciando...");
delay_ms(1000);
printf(LCD_PUTC, "\fProbando Sensor\nUltrasonico"); 
delay_ms(1000);                              
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8); 

while(true)
{ 
output_high(trig);                     
delay_us(20);                         
output_low(trig); 
while(!input(ECHO))                      
{} 
set_timer1(0);                           
while(input(ECHO))                       
{} 
tiempo=get_timer1();                       
distancia=tiempo*0.028 + 1.093 ;                                   
printf(LCD_PUTC, "\fTiempo :%Lu \nDistancia = %Lu",tiempo,distancia); 
delay_ms(100); 

if (distancia>5)
{

      output_high(PIN_C1);
      


}
else
{
output_low(PIN_C1);
}

} 
}
las librería flex_lcd son modificadas por que yo utilizo un cristal de 20Mh me dices para subirlas librerías que luego las pegas en donde te compila tu proyecto

aaa y el sensor no se puede simular en proteus te toca estar quemando el pic (quemar es grabar por si acaso) e ir probando
 
Última edición por un moderador:
hola que tal estoy haciendo un proyecto de un sensor ultrasonico que me detecte un objeto a una distancia pero pues la verdad es que no se como hacerlo ni tampoco programar el pic estoy utilizando un pic 16f887 y sensor hc sr04 me gustaria que me ayudaran con esto y me dieran una idea de como arrancar
 
Mi pregunta es, ¿sabes programar? si es así, ¿que lenguaje manejas? si utilizas pic c este código te servirá.
Sólo mira que salidas cambian en tu pic, te servirá para probar si tu sensor funciona.

Código:
include "main.h"
#use delay(clock=20000000) 
#include "flex_lcd.c"                        


int16 distancia, tiempo;
#define trig pin_B0
#define echo pin_B1

void main() 
{ 
output_low(PIN_C1);
lcd_init();                              
printf(LCD_PUTC, "\f Iniciando...");
delay_ms(1000);
printf(LCD_PUTC, "\fProbando Sensor\nUltrasonico"); 
delay_ms(1000);                              
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8); 

while(true)
{ 
output_high(trig);                     
delay_us(20);                         
output_low(trig); 
while(!input(ECHO))                      
{} 
set_timer1(0);                           
while(input(ECHO))                       
{} 
tiempo=get_timer1();                       
distancia=tiempo*0.028 + 1.093 ;                                   
printf(LCD_PUTC, "\fTiempo :%Lu \nDistancia = %Lu",tiempo,distancia); 
delay_ms(100); 

if (distancia>5)
{

      output_high(PIN_C1);
      


}
else
{
output_low(PIN_C1);
}

} 
}
 
Última edición por un moderador:
Mi pregunta es, ¿sabes programar? si es así, ¿que lenguaje manejas? si utilizas pic c este código te servirá.
Sólo mira que salidas cambian en tu pic, te servirá para probar si tu sensor funciona.

Código:
include "main.h"
#use delay(clock=20000000) 
#include "flex_lcd.c"                        


int16 distancia, tiempo;
#define trig pin_B0
#define echo pin_B1

void main() 
{ 
output_low(PIN_C1);
lcd_init();                              
printf(LCD_PUTC, "\f Iniciando...");
delay_ms(1000);
printf(LCD_PUTC, "\fProbando Sensor\nUltrasonico"); 
delay_ms(1000);                              
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8); 

while(true)
{ 
output_high(trig);                     
delay_us(20);                         
output_low(trig); 
while(!input(ECHO))                      
{} 
set_timer1(0);                           
while(input(ECHO))                       
{} 
tiempo=get_timer1();                       
distancia=tiempo*0.028 + 1.093 ;                                   
printf(LCD_PUTC, "\fTiempo :%Lu \nDistancia = %Lu",tiempo,distancia); 
delay_ms(100); 

if (distancia>5)
{

      output_high(PIN_C1);
      


}
else
{
output_low(PIN_C1);
}

} 
}



Hola que tal! estoy usando tu codigo y acomodandolo para mi pic, pero que pic usaste con este programa? el 16F877A?
 
andres1594 no ha regresado al Foro desde 02/08/201, puede ser que no te conteste.

A tu consulta, puedes usar cualquier PIC que tenga Timer1, y también puedes usar la librería lcd.c de CCS en vez de la librería flex_lcd.c.

Al parecer si utilizó el PIC16F877/A u otro mediano como el PIC16F873/A que cuenta con el pin RC1
Si usas otro PIC más pequeño, cambia ese pin por otro y podrás usar ese código.

PD:
Esto también lo tienes que tomar en cuenta al usar otro PIC y la configuración de pines para la pantalla.
#define trig pin_B0
#define echo pin_B1

Suerte.
 
Última edición:
Estoy usando el 16F877A pero no me funciona nada. Existe alguna manera de comprobar si el sensor esta funcionando??

Tambien tengo una duda con respecto a:
#define trig pin_B0
#define echo pin_B1

El ayudante de la materia me dijo que colocara el Trigger en ccp1 y el echo en RA2 que se me haria mas facil ya que necesito una salida digital para que pueda conectar el sensor directamente al controlador de servo ( este: pololu . com / product / 1351) hice lo que me dijo pero ni siquiera compila por los errores :confused: si puedes ayudarme con esto te lo agradeceria mucho.
 
Infortunadamente no tengo ese sensor ni tampoco ese servo, pero prueba con ese mismo código.
Los pines que quieras usar para el echo y el trigger no tienen mucha importancia, puedes usar cualquier otro pin.
Por la configuración de los pines con ADC no te preocupes, el compilador configura ADCON1 = b'00000111'
O sea, con la configuración para que todos los pines con entradas análogas, funcionen como digitales.
Tampoco se está haciendo uso de interrupciones ni capturas, tan solo se está midiendo el tiempo de retorno.
El pin que no te recomiendo usar es RA4, porque es con drenador abierto.

Tal vez los errores de compilación que tienes se deban a que no se incluyó el archivo main.h
Pero prueba con el mismo código ahora con el agregado de la configuración de fuses y usando la librería LCD.C de CCS.
Código:
#include  <16f877a.h>
#fuses   nobrownout
#use     delay(crystal = 20MHz) 
#include <lcd.c>                       


int16 distancia, tiempo;
#define trig pin_B0
#define echo pin_B1

void main() 
{ 
output_low(PIN_C1);
lcd_init();                              
printf(LCD_PUTC, "\f Iniciando...");
delay_ms(1000);
printf(LCD_PUTC, "\fProbando Sensor\nUltrasonico"); 
delay_ms(1000);                              
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8); 

while(true)
{ 
   output_high(trig);                     
   delay_us(20);                         
   output_low(trig); 
   while(!input(ECHO)){} 
   
   set_timer1(0);                           
   while(input(ECHO)){} 
   
   tiempo=get_timer1();                       
   distancia=tiempo*0.028 + 1.093 ;                                   
   printf(LCD_PUTC, "\fTiempo :%Lu \nDistancia = %Lu",tiempo,distancia); 
   delay_ms(100); 

   if (distancia>5)
   {

   output_high(PIN_C1);
      
   }
   else
   {
   output_low(PIN_C1);
   }

   } 
}
Este programa ahora te debe compilar sin errores.
Para las conexiones de la pantalla, sigue el esquema adjunto y utiliza los pines que quieras para el sensor.

Suerte.
 

Adjuntos

  • Ultrasonic SCH.jpg
    Ultrasonic SCH.jpg
    107.2 KB · Visitas: 98
Buenas, estoy realizando una simple detección de movimiento con el módulo HCRS04 y el pic16f84. El problema es que no detecta la diferencia de la señal del eco inicial y las variaciones de las distancias. El código es el siguiente:

Los disparos para el HCRS04 (trigger) son en el pin RA0, y el eco retorna por el pin RB4

Como verán la función que se encarga de detectar la distancia es int cuenta(), la cual retorna la distancia. Ahora bien, cuando se envía el pulso (trigger) comienza la cuenta de la distancia hasta que el eco produce la interrupción por cambio descendente en el pueto RB4, el cambio descendente es cuando termina el pulso

Código:
#include <xc.h>

// CONFIG
#pragma config FOSC = XT        // Oscillator Selection bits (XT oscillator)
#pragma config WDTE = OFF       // Watchdog Timer (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (Power-up Timer is disabled)
#pragma config CP = OFF         // Code Protection bit (Code protection disabled

#define _XTAL_FREQ 3582056
#define __delay_us(x) _delay((unsigned long)((x)*(_XTAL_FREQ/3582056)))  
#define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/3582.056)))  

#define SALIDA PORTBbits.RB2

int variable=0;

#INT_RB
void interrupt isr(void) 
{ 
   INTCONbits.GIE=0;
if(INTCONbits.RBIE) 
{	
    variable=variable+1;
    
}
 INTCONbits.GIE=1;
 INTCONbits.RBIE=0;
 return;
}

int cuenta (void)
{ 
    int i=0; 
    int c=1;
     __delay_us(15); 
     PORTA=0xFF; 
     __delay_us(15); 
     PORTA=0x00; 
    
      while(c)
        {
              i++;      
             __delay_us(500);
             if(variable>0) 
             { 
                c=0;   
             }   
        } 
    
     return (i);
}

void main(void) {
    

        TRISB=0b111110001; 
        TRISA=0x00; 
        INTCON=0x98;
        OPTION_REG=0x98;
        int d1=0;
        int l1=0;
         
        d1=cuenta();
        l1=d1;
         variable=0;
             while(1)
             {
              l1=cuenta();   
               variable=0;
             if(l1!=d1) 
             {
                 SALIDA=1; 
        __delay_ms(1000); 
              d1=cuenta();  
              variable=0;
             }
             
             }
}
 
Tienes muy mal el código de ese programa.

Vamos a empezar por las dos redefiniciones; __delay_us(x) y __delay_ms(x)
El compilador muestra las siguientes advertencias:
warning: (111) redefining preprocessor macro "__delay_us" (C:\Program Files\Microchip\xc8\v1.37\include\pic.h)
warning: (111) redefining preprocessor macro "__delay_ms" (C:\Program Files\Microchip\xc8\v1.37\include\pic.h)

Como ya están declaradas en el archivo "pic.h", ya no es necesario que las incluyas.

Después estás mezclando directivas de PIC C Compiler en XC8:
#INT_RB No es reconocido por el compilador XC8
Y la información de compilación lo indica con otra advertencia:
warning: (107) illegal # directive "INT_RB"

Y en la configuración del registro TRISB, te sobra un bit: (Podría ser el de la izquierda o el de la derecha)
TRISB=0b111110001;
El registro TRISB al igual que el registro TRISA, son de 8 bits.
(Aunque en el 16F84A, el puerto A únicamente tenga 5 bits activos. <RA4:RA0>)
warning: (751) arithmetic overflow in constant expression

Ahora vamos al problema principal.
Dices que el eco lo recibes por cambio de estado en RB4, pero la configuración de registros en la rutina de servicio de interrupción, no es correcta.
El bit RBIE del registro INTCON, habilita o deshabilita la interrupción por cambio de estado en el los bits <RB7:RB4>
Pero tú lo estás usando para determinar si se incrementa la variable "variable" (Redundante, pero así la nombraste) :oops:
En C, es más simple escribir; variable ++; que variable = variable + 1; :cool:

Posteriormente desactivas la interrupción por cambio de estado, pero activando las interrupciones globales.
Entonces, al ya no tener un control sobre las interrupciones, se producirá un desborde o "Stack Overflow"
Y ya con eso tienes para que todos los procesos mueran. :rolleyes:

Corrige esos detalles y principalmente la rutina del servicio de interrupción.
Tal vez después de eso, el código restante funcione. :D
 
Última edición:
Atrás
Arriba