RobotyPic son proyectos básicos de electrónica con microcontroladores PIC, de aplicación en el mundo de la robótica didáctica, con archivos fuente creados mediante el compilador CCS PIC C COMPILER en lenguajeC.

Medida de distancias con SRF05

A diferencia del artículo referente a la medida de distancias con el  SRF04 o SRF05 en modo de funcionamiento 1, en esta ocasión se va a emplear el sensor  de ultrasonidos SRF05 en el modo de funcionamiento 2, es decir, empleando el mismo pin como entrada del pulso de test y como salida para el pulso eco que nos dará la información de la distancia en función de su duración en tiempo.

Para conectar el sensor de ultrasonidos en este modo de funcionamiento,  el pin de “modo” (sin conectar en SRF04 o SRF05 modo 1) debe llevarse a 0v. De esta forma, el pin empleado para dar el pulso de test será el que nos ofrezca igualmente el pulso ECO.


El proceso consiste en un ciclo que se repite cada vez que se toma una nueva medida.



Traducido al código de programación del PIC, primero damos el pulso trigger o de disparo (mínimo 10 uS) con el pin RC1 (CCP2) como salida y deshabilitada la interrupción...

disable_interrupts(INT_CCP2); //Deshabilitación interrupción
                                modo comparación
trisc=0x00;                   //Puerto C todos los pines todo salidas

BIT_TEST_ON;                  //Comienzo del pulso de disparo
delay_us(10);                 //Tiempo del pulso de disparo   
BIT_TEST_OFF;                 //Fin del pulso de disparo

...e inmediatamente después se vuelve a configurar dicho pin como entrada y a habilitar la interrupción para detección de flanco...

trisc=0b00000010;            //Pin RC1 como entrada para lectura eco
PIR2=0;                      //Reset del flag de la interrupción
enable_interrupts(INT_CCP2); //Habilitación interrupción para medida de pulso eco

.. y se espera la lectura del pulso eco...

while(NuevoEco==0) {}

Como se ve, es imprescindible resetear el flag de interrupción mediante su puesta a cero (PIR2=0). Sino se hace, nos detectará interrupción por flanco de subida desde el mismo momento de habilitar la interrupción.

Cuando, esperando el flanco de subida del eco, se activa la interrupción, deberemos guardar el valor que en ese momento se carga en el registro CCP2, y memorizar que el próximo flanco será de bajada.

if(TipoFlanco==0){              //Si es flanco de subida...
    Contador_FS=CCP_2;          //Guarda el valor del registro CCP2
    setup_ccp2(CCP_CAPTURE_FE); //Modo captura en flanco de bajada
    TipoFlanco=1;               //Próximo flanco debe ser de bajada
}

Ahora, el programa continua esperando en la misma instrucción (While) en la que aguardaba a recibir el comienzo del pulso eco, hasta activarse de nuevo la interrupción, pero esta vez por la recepción del flanco de bajada. En ese mismo momento, volveremos a tomar el valor del registro CCP2. Además, memorizaremos que el pulso eco en curso ha finalizado y que por tanto, el próximo flanco será de subida por tratarse de un nuevo pulso eco.

 Contador_FB=CCP_2;                //Guarda el valor del registro CCP2
 setup_ccp2(CCP_CAPTURE_RE);       //Modo captura en flanco de subida
 TipoFlanco=0;                     //Próximo flanco debe ser de subida
 NuevoEco=1;                       //Pulso eco actual finalizado.

Al indicar que el pulso eco ha finalizado, salimos del bucle while y se continúa con la ejecución del programa para calcular, a partir de los valores leídos del registro CCP, el valor de la distancia al objeto. Primero obteniendo los incrementos totales producidos en el contador del registro CCP2 (Timer 1) desde el flanco de subida hasta el de bajada.

Contador_FT=(Contador_FB-Contador_FS); //Valor entre flanco de subida y bajada.

Ahora, si multiplicamos este numero de incrementos por el tiempo (en microsegundos) que tarda en producirse cada uno de ellos, obtendremos el tiempo total del pulso eco. En este caso, al emplearse un oscilador para el PIC de 4 MHz, el tiempo de cada incremento es de 1uS, por lo que se multiplicará por 1.0

T_PulsoEco=Contador_FT*1.0;   //Valor pulso leido en us de 100u a 25ms

Para saber el tiempo de cada incremento del contador en función del oscilador empleado, partimos de esta expresión:

T = Tcm * Preescaler 

Tcm es el ciclo máquina y que corresponde con 4 ciclos del oscilador (4/Frec.Reloj)
Preescaler es la escala empleada para el Timer1. En este caso Preescaler=1

T = (4/4.000.000) * 1 

De donde obtenemos que el tiempo T es de 1uS para una frecuencia de reloj de 4MHz.

Para obtener la distancia en centímetros en función del tiempo del eco, lo dividimos por 58.3

Distancia = T_PulsoEco/58.3;    //Distancia del obstáculo en cm

Esta constante es siempre fija y nos da el resultado en cm. La proporciona el fabricante del sensor en la hoja de características pero se podría obtener considerando la velocidad del sonido en el aire (340m/s) y que éste recorre el doble del espacio medido, puesto que dicho trayecto es de ida  y vuelta.

Finalizado el cálculo, volvemos a dejar el pin RC2 como salida y deshabilitamos temporalmente la interrupción para que no nos detecte el propio pulso de disparo. Y avisamos de que queda listo para una nueva media.

NuevoEco=0;                 //Listo para recibir nuevo pulso eco
disable_interrupts(INT_CCP2);
trisc=0b00000000;           //Pin RC1 como salida para nuevo disparo



[+/-] Ver / Ocultar programa completo en C


En la animación se mestra el funcionamiento empleando el simulador del SRF05 para proteus.



Todos los archivos del proyecto en este enlace de descarga:




El proyecto contenido en el artículo ha sido diseñado con la versión v4.084 de CCS PIC C COMPILER



Última revisión del artículo: Agosto 2013


8 comentarios:

Unknown dijo...

& EN QUE REGISTRO GUARDA LA MEDIDA EN DECIMAL CENTIMETROS?

Robotypic dijo...

Brxan, la variable "distancia" primero toma el tiempo del impulso recibido. Después divide ese valor para 58 para obtener el equivalente a cm. y lo vuelve a guardar en la misma variable "distancia".

AXEL dijo...

Hola que tal me podría explicar como es que logra el tiempo exacto de pulso eco de 100u a 25 ms al multiplicar por 1.0 y dividir entre 58

Robotypic dijo...

Hola Axel.
Aquí se multiplica por 1 pero se podría evitar esa multiplicación en este caso concreto. Este valor depende de la frecuencia del cristal resonador que emplees. El valor del ccp se incrementa cada 4 ciclos de reloj. Considerando, que el periodo es el inverso de la frecuencia y que la frecuencia de reloj es 4 Mhz, el tiempo que tarda cada incremento del registro ccp será:

(1/4MHz) * 4 = 0,000001 seg.

Como el pulso eco recibido nos viene referenciado en microsegundos ese valor hay que convertirlo a microsegundos:

0,000001seg. * 1000000 = 1

La división por 58 es un factor que ofrece el fabricante del sensor para obtener la distancia en centímetros en función del tiempo del pulso en uS.

AXEL dijo...

Excelente muchas gracias ahora entiendo la razón del por qué no me salía la medida ya que yo estoy trabajando con una frecuencia de reloj de 12 mhz

AXEL dijo...

El programa corre y me marca las medidas en la pantalla pero no me sale el valor correcto, estoy usando un sensor diferente al propuesto por usted, tiene características similares y en teoría debería funcionar es el ping de parallax, ya utilicé el mismo oscilador pero difiere la medida no tendrá idea del por qué? Gracias de antemano saludos

Robotypic dijo...

Hola Axel.
Creo que ambos sensores trabajan igual. Debería funcionarte.

AXEL dijo...

Sí la verdad no sé a qué se deba, intentaré cambiando el Pic creo que por ahí tengo otro.
Saludos

Related Posts Plugin for WordPress, Blogger...

CONTACTA - (Haz referencia del artículo sobre el que trata la consulta o comentario)