PicManía by RedRaven
 

Búsqueda personalizada

 

PROYECTOS : AUX SRF04

 

 

Circuito auxiliar de medición de distancias por ultrasonidos SRF04

Descripción:
 

   El objetivo de este circuito auxiliar es el de medir distancias, utilizando para ello dos transceptores de ultrasonidos, uno emisor y otro receptor, basándonos en el tiempo que tarda la señal en ir desde el emisor hasta el objeto obstáculo y volver rebotada desde éste hasta el receptor. Midiendo dicho tiempo podemos calcular con suficiente precisión y exactitud la distancia entre el objeto y nuestros transceptores.
 

   Primero unos pocos datos e ideas de teoría física básica y la descripción de los cálculos que necesitamos hacer para implementarlos en nuestro programa:
 
  • Los ultrasonidos son antes que nada sonido, exactamente igual que los que oímos normalmente, salvo que tienen una frecuencia mayor que la máxima audible por el oído humano. Ésta comienza desde unos 16 Hz y tiene un límite superior de aproximadamente 20 KHz, mientras que nosotros vamos a utilizar sonido con una frecuencia de 40 KHz. A este tipo de sonidos es a lo que llamamos Ultrasonidos.

  • (1) El sonido se desplaza en el aire a una velocidad de 340 m/s a una temperatura de 20º C, con una variación térmica de 0.6 m/s por cada grado centígrado. Así, por ejemplo, a 30º C de temperatura del aire, la velocidad del sonido es de 340 m/s + (0.6 m/s/º C * 10º C) = 346 m/s (Intervienen otros parámetros pero que vamos a dejar de lado en este trabajo por complicarnos excesivamente sin aportarnos mayor resolución)

  • (2) La distancia d recorrida por un móvil es directamente proporcional a la velocidad v de éste y al tiempo t empleado en ello. Podemos escribirlo como una fórmula en la sencilla forma:

    d = v * t

    dónde d es la distancia recorrida en metros, v la velocidad en metros por segundo y t el tiempo en segundos.

    esta misma relación la podemos escribir de otra forma que nos relacione el tiempo con las otras variables, estableciendo que el tiempo t que tarda un móvil en recorrer una distancia d es inversamente proporcional a la velocidad v del mismo e directamente proporcional a la distancia d a recorrer:

    t = d / v

    dónde t el tiempo en segundos, v la velocidad en metros por segundo y d es la distancia en metros.
     

  • Si deseamos medir una distancia usando los ultrasonidos tenemos que emitir un pulso ultrasónico breve, esperar que llegue hasta el obstáculo a sensar, se refleje en éste y vuelva hasta nuestro dispositivo sensor, midiendo entonces el tiempo t que ha tardado en hacer todo el trayecto de ida y vuelta mediante nuestro microcontrolador PIC. Conociendo la velocidad v a que se ha desplazado nuestra onda tal como hemos visto en (1), podemos fácilmente calcular según lo expresado en (2) la distancia d entre el sensor y el objeto.

  • Por ejemplo:

    Un objeto situado a 15 cm. de nuestro sensor, con una temperatura del aire de 20º C, debe emitir un eco tras nuestro pulso que debe tardar en llegar  t = (0.15 m / 340 m/s) * 2 = 0.000882 segundos (o escrito de otra forma 882 uS, microsegundos)

    Nota el detalle de que multiplicamos por 2 el tiempo empleado debido a que el sonido debe ir y volver reflejado desde el objeto, por lo que recorre dos veces la distancia que separa al sensor del objeto.

Implementación, Hardware:
 

   Para nuestro proyecto me he decidido por el sensor ultrasónico modelo SRF04 de la casa británica Robot Electronics, adquirido en la sevillana casa de Superrobotica.
 


 

   Tensión 5V
   Consumo 30 mA Tip. 50mA Max.
   Frecuencia: 40 Khz.
   Distancia Mínima: 3 cm.
   Distancia Máxima: 300 cm.
   Sensibilidad: Detecta un palo de escoba a 3 m.
   Pulso de Disparo 10 uS min. TTL
   Pulso de Eco: 100 uS - 18 mS
   Retardo entre pulsos: 10 mS Mínimo
   Pulso de Eco: 100 uS - 18 mS
   Tamaño: 43 x 20 x 17 mm
   Peso: 10 gr.

 

   Este sensor tiene la particularidad de manejarse solo con dos hilos, aparte de los de alimentación. Por uno de ellos se le envía el pulso de disparo (trigger) y por el otro recibimos el pulso de eco (echo) cuya amplitud es directamente proporcional a la distancia a la que ha sido detectado el obstáculo interpuesto. Según el cronograma siguiente:

 

 

 


 


El conexionado eléctrico del SRF04 es como sigue:
 

   Finalmente en cuanto a Hardware, vamos a utilizar nuestra querida RRBOARD1 con su infatigable amiga AUX RS232, para implementarle el programa de medición y monitorización de la medida realizada, enviándola al monitor de mi PC. Los pines que vamos a utilizar son los dos primeros publicados en el conector de 10X que tiene dicha placa: PIN RA0 y PIN RA1. El pulso de disparo (trigger) lo sacaremos por RA1 y la lectura del eco lo haremos por RA0. Además RRBOARD1 le suministrará la alimentación 5V necesaria para su funcionamiento.
 

El conexionado entre el SRF04 y la RRBOARD1 queda como puede verse en la foto inferior:
 

 

Implementación, Software:
 

Nuestro programa debe realizar las siguientes funciones:
  • Emitir un pulso ultrasónico de corta duración
  • Esperar el inicio del pulso de eco resultante y poner a cero un temporizador.
  • Esperar el fin del pulso de eco y guardar el estado de dicho temporizador al ocurrir esto.
  • Calcular el tiempo de duración de dicho eco, que como sabemos es proporcional al tiempo empleado en ir y venir hasta y desde el objeto.
  • y por último, Calcular la distancia sabiendo el tiempo empleado en recibir el eco y la velocidad de la onda de sensado. Y transmitirlo.

   Para la medida de tiempos vamos a utilizar el contador de 16 bits TIMER1 del PIC 16F628, configurado con el oscilador interno y a Preescaler 1:1. Esto nos da un Tick de incremento del contador de 1uS (microsegundo) para un ciclo de reloj externo de 4.00 Mhz.
 

   La base del programa es una variación del RROS v 2.0 desarrollado para el control de la RRBOARD1. Marcado en rojo está la implementación del sensor:

 

 
rr_srf04_test.c
 
 
  /////////////////////////////////////////////////////////////////////////////////////////
//
// RROS para RRBOARD1 : SRF04 Test
//
// © 18.03.2006 By RedRaven
//
// Hardware: PIC16F628
//
// RA0 SRF04 Input Echo
// RA1 SRF04 Trigger
// RA2,RA3 Leds
// RB1 USART RX
// RB2 USART TX
// RB5 Buzzer Driver
// RB6,RB7 ICSP
//
// Xtal Ext. 4.00 Mhz
//
// Idioma: CCS PICC v.3.242
//
//
/////////////////////////////////////////////////////////////////////////////////////////

#include <16f628a.h>
#fuses XT,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_B2, rcv=PIN_B1)

#include <stdlib.h>

// Constantes y definiciones ////////////////////////////////////////////////////////////

#define SRF04_PORT_TRIGGER PIN_A1 // Pin usado para el pulso de Disparo
#define SRF04_PORT_ECHO PIN_A0 // Pin usado para recibir el eco ultrasónico

#define TIME_TRIGGER_uS 10 // Longitud del pulso de disparo 10 uS (microsegundos)
#define TIME_NEXT_TRIGGER_mS 10 // Espacio entre echo y siguiente disparo 10 mS (milisegundos)
#define MAX_ECHO_RESPONSE_Ticks 35000 // Maximo tiempo de espera del eco en Ticks de Timer1 (35 ms)
#define CALC_DISTANCE(t) (t / 58) // Convierte de Ticks a distancia
#define DISTANCE_INFINITE (0xffff) // Distancia infinita, no hay obstaculo en el rango de medida

// De RROS

int const MAXLENBUFF=24; // Maxima longitud de los bufferes
int const MAXLENCOMMAND=12; // Maxima longitud de un comando (sin argumentos)
int const NUMPAGSEEPROM=7; // Numero de paginas (de 16 bytes) de la EEPROM interna

// Variables Globales ///////////////////////////////////////////////////////////////////

long echo_delay;
long distance = DISTANCE_INFINITE;

// De RROS

char buffrec[MAXLENBUFF]; // Buffer de Recepcion
int xbuffrec=0x00; // índice del Buffer de Recepcion
int1 new_command=0; // Flag para indicar comando disponible
int1 pdte_send_prompt=0; // Flags para enviar echo fuera de la int_rda
int1 pdte_send_tmp_prompt=0;
char xcommand[MAXLENCOMMAND]; // Comprobador de comando recibido

// Declaracion de Funciones /////////////////////////////////////////////////////////////

void On_reset(void); // Tras RESET del Micro
void Send_listen(void); // Monitoriza RS232 : Comienzo
void Send_opts(void); // Monitoriza RS232 : Presenta opciones
void Send_prompt(void); // Monitoriza RS232 : Presenta el Cursor
void Send_tmp_prompt(void); // Monitoriza RS232 : Presenta el Cursor y el comando actual
void Ini_buffrec(void); // Borra el buffer de recepción
void Add_buffrec(char c); // Añade un caracter al buffer de recepción
void Procesa_comando(void); // Procesado de comandos

void realiza_medida(void); // Realiza una medida completa

// INTERRUPCIONES ///////////////////////////////////////////////////////////////////////

// INTERRUPCION RDA - Recepción USART -

#int_rda
void serial_isr() {
  if(kbhit()){ // Si hay algo pendiente de recibir ...
    Add_buffrec(getc()); // lo recibo y lo añado al Buffer de Recepcion
  }
}

// Control del Buffer de recepcion ---------------------------------------

void Ini_buff_rec(void){ // Inicia a "\0" el Buffer de Recepcion

  int i;
  for(i=0;i<MAXLENBUFF;i++){ // Bucle que pone a 0 todos los
    buffrec[ i ]=0x00; // caracteres en el Buffer de Recepcion
  }
  xbuffrec=0x00; // Inicializo el indice de siguiente caracter recibido
}

void Add_buffrec(char c){ // Añade caracter al Buffer de Recepcion

  switch(c){
    case 0x0D: // [Enter] -> Habilita Flag para procesar comando en Main
      new_command=1;
      break;
    case 0x08: // [Del] -> Borra último caracter del Buffer
      if(xbuffrec>0){ // Si hay algo en el buffer
        buffrec[--xbuffrec]=0x00; // decremento el índice, escribo un cero y ...
        pdte_send_tmp_prompt=1; // habilito flag para refrescar el prompt
      }
      break;
    case 0x01B: // [Esc] -> Borra el Buffer completamente y ...
      Ini_buff_rec(); // habilito flag para refrescar el prompt
      pdte_send_prompt=1;
      break;
    case 0x009: // [Tab] -> Refresca el prompt y el comando tal como esté
      pdte_send_tmp_prompt=1;
      break;
    default:
      buffrec[xbuffrec++]=c; // Añade caracter recibido al Buffer
      putc(c); // y lo monitorizo
  }
}

// Rutinas y Funciones de RROS ///////////////////////////////////////////

void On_reset(void){ // Inicializacion del Micro tras RESET

  disable_interrupts(GLOBAL); // todas las interrupciones desactivadas
  delay_ms(100);

  output_low(SRF04_PORT_TRIGGER); // A bajo el pin del disparador
  setup_timer_1(T1_INTERNAL | T1_DIV_BY_1); // Timer1 con preescaler 1:1

  Ini_buff_rec(); // Inicializo Buffer de recepcion
  new_command=0; // Desactivo flag de comando pendiente.
  pdte_send_prompt=0; // Desactivo Flags para enviar echo fuera de la int_rda
  pdte_send_tmp_prompt=0;

  enable_interrupts(int_rda); // interrupcion RDA habilitada
  enable_interrupts(global); // todas las interrupciones activadas

  Send_opts(); // Presenta Comienzo
  Send_prompt(); // Presenta el Cursor
}

void Send_listen(void){ // Presenta Comienzo

printf("SRF04 Ultrasonic Ranger Test\r\n\n" );
}

void Send_opts(void){ // Relación de comandos válidos

  printf("\r\n\n" );
  Send_listen();
  printf("\n" );
  printf("[?] comandos válidos\r\n" );
  printf("[r] realiza una medición\r\n\n" );
}

void Send_prompt(void){ // Presenta el cursor

  printf("\r\n>" );
}

void Send_tmp_prompt(void){ // Presenta el cursor con el comando actual

  printf("\r>%s",buffrec);
}

// MAIN Programa Principal ///////////////////////////////////////////////

void main(void)
{
  On_reset();

  do {

    // Deteccion de la necesidad de procesar comandos pendientes ///////
    if(new_command==1){ // Si hay un nuevo comando ...
      new_command=0; // deshabilito el aviso y ...
      Procesa_comando(); // Procesado de comandos
      Ini_buff_rec(); // inicializo todo para nuevo comando y ...
      pdte_send_prompt=1; // mando prompt.
    }

    // Deteccion de la necesidad de enviar echos ///////////////////////
    if(pdte_send_prompt==1){
      pdte_send_prompt=0;
      Send_prompt();
    }
    if(pdte_send_tmp_prompt==1){
      pdte_send_tmp_prompt=0;
      Send_tmp_prompt();
    }
  } while(TRUE);
}

// Funciones de Comando //////////////////////////////////////////////////

void realiza_medida(void){

  delay_ms(TIME_NEXT_TRIGGER_mS); // Espero para asegurarme que hay espacio entre eco y disparo
  output_high(SRF04_PORT_TRIGGER); // Envío el pulso de disparo
  delay_us(TIME_TRIGGER_uS); // espero el ancho de pulso requerido
  output_low(SRF04_PORT_TRIGGER); // termino el pulso
  for ( ; !input(SRF04_PORT_ECHO); ); // Espero el inicio del pulso del eco (flanco de subida)
  set_timer1(0); // Cuando llegue pon a cero el Timer1
  for ( ; input(SRF04_PORT_ECHO); ); // Espero al final del pulso del eco (flanco de bajada)
  echo_delay = get_timer1();
  if (echo_delay >= MAX_ECHO_RESPONSE_Ticks){
    distance = DISTANCE_INFINITE;
  }
  else {
    distance = CALC_DISTANCE(echo_delay);
  }
}

// Procesa_comando: Hace cosas o manda hacerlas ... //////////////////////

void Procesa_comando(void){

  int1 procesado_ok=0;
  int waddress, wbyte;

  // COMANDO = "" intro en blanco ---------------------------------------
  strcpy(xcommand,"" );
  if(!strcmp(buffrec,xcommand)){
    procesado_ok=1;
    goto fin_procesa;
  }
  // COMANDO = "?" ------------------------------------------------------
  strcpy(xcommand,"?" );
  if(!strncmp(buffrec,xcommand,strlen(xcommand))){
    Send_opts();
    procesado_ok=1;
    goto fin_procesa;
  }
  // COMANDO = "r" ------------------------------------------------------
  strcpy(xcommand,"r" );
  if(!strncmp(buffrec,xcommand,strlen(xcommand))){
    realiza_medida();
    printf(" -> %lu cm (%lu) \r\n",distance,echo_delay);[/color]
   
procesado_ok=1;
    goto fin_procesa;
  }

fin_procesa:

  // COMANDO ERRÓNEO - ¿ezo qué é lo que é ?-----------------------------
  if(procesado_ok==0){
    printf("\r\n?%s",buffrec);
  }

}
 
 
 

Descargar fuentes de _rr_srf04_01.c

 
 
Resultados:
Y como siempre, por último un volcado de la pantalla donde se muestran los resultados obtenidos:

¡Ya tenemos un desarrollo necesario para nuestro futuro RRBOT! ... (continuará)

 

Esta página se modificó el 27/12/2008


Esta página usa la letra Ñ

Nota pública importante sobre las consultas al Webmaster de PicManía.


Sugerencias a Picmanía... (que serán leídas pero seguramente no podrán ser contestadas)

Esta página pertenece al grupo de páginas de Diego RedRaven

 

 



Nota: Esta página Web esta repleta de imágenes, textos, logotipos y demás material extraídos de los mas variados medios de los que no soy ni autor ni depositario de los correspondientes derechos de autor, uso y/o reproducción. Si Ud. es depositario de dichos derechos y desea que el material correspondiente sea eliminado de esta Web no dude en ponerse en contacto conmigo mediante e-mail y será inmediatamente retirado. Gracias.
 
Visitas
Totales : 15418 Hoy: 1 Activas: 1 Vistas: 15418

Esta página fue modificada el 07-08-2010 15:42:19

           
 DmSoft WAMP Escribir Unreal