dsPIC33F – Capítulo 4: Módulo Input Capture

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.

El sensor de distancias con ultrasonidos: SRF05

No voy a extenderme hablando del sensor SRF05, puesto que mucho mejor de lo que yo podría hacerlo, ya lo hizo mi querido amigo Diego en su artículo: Circuito auxiliar de medición de distancias por ultrasonidos SRF04.

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);

#include "LCD_HD44780.h"
#include <stdio.h>
#include <timer.h>
#include <InCap.h>
#include <math.h>

char firma[] = {'M','i','c','r','o','p','i','c',' ','-',' ','2','0','0','8','\0'};
const proyecto[] = {'I','N','P','U','T',' ','C','A','P','T','U','R','E',' ','\0'};

// 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;

// Desactivados pines ADC
AD1PCFGL=0xFFFF;
AD2PCFGL=0xFFFF;

TRIS_IC1=0;

LCD_Inicializacion();
LCD_Goto (1,1);
LCD_EscribeCadena(firma);
LCD_Goto (2,2);
LCD_EscribeConstante(proyecto);
delay_ms(1000);

// Configuramos el Input Capture 1 para utilizar el Timer2 e interrumpir con cada flanco
closedCapture1(IC_IDLE_STOP & IC_TIMER2_SRC & IC_INT_1CAPTURE & IC_EVERY_EDGE);
T2CON = 0x8020; // Timer 2 On con prescaler 1:64

while(1) {
LCD_Goto (1,2);
Distancia=MideDistancia();
printf ("Dist.: %3.2fcm.",Distancia);
delay_ms(100);
};
}

Puedes descargar el proyecto completo aquí: Medición de distancias con SRF05

Y aquí dejo un vídeo ejemplo del programa anterior:

Share