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