El módulo Input Capture de nuestro dsPIC está especializado en medir frecuencias y anchos de pulso. Lo utilizaremos con un sensor de distancias por ultrasonidos, el SRF05
Y nuestro módulo efectúa sus capturas de una manera muy eficaz y sencilla, mediante interrupciones, dejando el corazón de nuestro micro libre para otras tareas.
La captura puede realizarse con una resolución máxima de 16 bits, y puede ser configurada para detectar flancos ascendentes, descendentes o ambos.
Para determinar el ancho de una captura, se apoya en Timer2 o Timer3, que pueden estar configurados mediante pulsos internos o externos. Esto nos abre un abanico muy amplio de posibilidades de medida.
En este diagrama se muestra el comportamiento de nuestro SRF05:
La principal diferencia entre el SRF04 de Diego, y el SRF05 que yo utilizo es que este último necesita sólo un pin para efectuar la comunicación, tal y como indico a continuación: - configuramos el pin como salida - enviamos un pulso alto de 10us - configuramos el pin como entrada - esperamos un pulso cuyo periodo nos indicará la distancia
El periodo de dicho pulso será de 0ms a 30ms. La relación entre tiempo y distancia es la siguiente: 58us = 1cm
La aplicación
El siguiente programa nos permite sensar una distancia con nuestro SRF05 y mostrarla por un display LCD. Su funcionamiento está explicado en los comentarios incorporados al código fuente.
#include <p33FJ64MC706.h> #define __33FJ64MC706_H
_FOSCSEL(1); // OSCILADOR INTERNO CON PLL _FOSC (195);
// Usaremos el módulo Input Capture 1, que está en el pin RD8 #define IC1 PORTDbits.RD8 #define TRIS_IC1 TRISDbits.TRISD8
unsigned int Duracion_Pulso; unsigned int Int_flag; // este flag permite saber cuándo ha terminado la captura
void __attribute__((__interrupt__)) _IC1Interrupt(void) { if (IC1) { // si la interrupción aparece al subir el pulso, iniciamos el Timer2 TMR2=0; } else { // si aparece al bajar el pulso, capturamos la anchura del pulso mirando Timer2 Duracion_Pulso=TMR2; // o bien, Duracion_Pulso=IC1BUF; Int_flag = 1; // y marcamos el flag para salir de la espera } IFS0bits.IC1IF = 0; }
float MideDistancia() { TRIS_IC1=0; // usamos el pin de comunicación con SRF05 poniéndolo como salida IC1=1; // y sacamos un pulso alto delay_us(10); // que dure 10 us IC1=0; // se termina el pulso señalizador TRIS_IC1=1; // y ponemos el pin como entrada para "escuchar" al SRF05 Int_flag=0; // mientras el flag sea 0, estaremos esperando la captura del pulso
// configuramos la interrupción Input Capture
ConfigIntCapture1(IC_INT_PRIOR_1 & IC_INT_ON);
while (!Int_flag); // y esperamos que el flag cambie de valor DisableIntIC1; // ya podemos desconectar la interrupción
return ((float)Duracion_Pulso/32.0); // según la datasheet del SRF05, la relación entre us y cm es 1/58 // Duración * Prescaler / MIPS / 58 // Duración * 64 / 35.31 / 58 // Duración / 32 } /***********************************************************************/ int main(void){ /***********************************************************************/
float Distancia, Frecuencia; int Nota;
// Oscilador interno a 35,34 CLKDIVbits.PLLPRE=2; CLKDIVbits.PLLPOST=1; PLLFBD=168; OSCTUN=38;
// Configuramos el Input Capture 1 para utilizar el Timer2 e interrumpir con cada flanco OpenCapture1(IC_IDLE_STOP & IC_TIMER2_SRC & IC_INT_1CAPTURE & IC_EVERY_EDGE); T2CON = 0x8020; // Timer 2 On con prescaler 1:64