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.

CMUcam4 con PIC

En el artículo "CMUcam4 controlado por un PC" se ha mostrado como contactar con una CMUcam4 desde un PC con la intención de tener un primer contacto y familiarizarnos con ella. Aquí, las actuaciones que en ese artículo se han mostrado desde el PC las vamos a realizar controlando la cámara con un PIC. Es decir, vamos a rastrear un objeto de un color concreto con la cámara soportada por los servos PAN y TILT. Los comandos enviados así como la respuesta recibida de la cámara lo mostraremos en un LCD. 

Para la conexión eléctrica del PIC con la CMUcam hay que tener en cuenta un detalle muy importante. En la comunicación serie, los datos son transmitidos por el PIC a 5V. Sin embargo, los datos recibidos los envía la CMUcam a niveles en torno a los 3,3V, por lo que aunque la tarjeta de la cámara entiende los comandos del PIC, éste no es capaz de descifrar la información que recibe de la CMUcam y en el LCD aparecen caracteres ilegibles. Por tanto va a ser necesario pasar esos niveles de 3,3V a niveles de 5V detectables por el PIC bien por comparadores, puertas AND, etc., o como aquí se ha hecho, con el MAX232 conectado como se ve en el esquema.
Se han empleado algunos comandos. La totalidad de ellos con su descripción y forma de usarlo se puede consultar en la documentación técnica del componente. 

Para programar el PIC, por tanto, habrá que configurar la conexión serie con las características que por defecto lleva la CMUcam.

#use rs232(baud=19200,xmit=pin_c6,rcv=pin_c7,bits=8,stop=1,parity=n, errors)

Hay que considerar que la CMUcam tarda más tiempo en reiniciarse que el PIC. Le daremos un tiempo antes de enviar el primer comando para evitar que se bloquee. Aquí, mientras espera, muestra un mensaje en el LCD.

/** Espera hasta que CMUcam se reinicie **/
   printf(lcd_putc, "\f  Iniciando...  ");
   delay_ms (6000);                        //Tiempo para inicio de la CMUcam

En esta demostración se envían varios comandos antes de rastrear el objeto como muestra de cual es la respuesta de la cámara. Solicitamos obtener la versión.

/** Valor del la versión de la CMUcam **/
   strcpy (CMUcam_comando, "GV");          //En CMUcam_comando se guarda comando
   puts(CMUcam_comando);                   //Envío del comando a la CMUcam

strcpy guarda la cadena GV en la variable CMUcam_comando. Y luego se envía por el puerto serie a la cámara con putsEstas dos instrucciones C pueden sustituirse por una sola:

   puts("GV");                            //Envío del comando a la CMUcam

Pero el comando que enviamos a la cámara lo guardamos en una variable para mostrarlo también en el LCD.

/** Muestra los primeros 16 caracteres del comando en la primera línea **/
   for(i=0;i<strlen(CMUcam_comando);i++)
        printf(lcd_putc,"%c",CMUcam_comando[i]);
   
/** Muestra los caracteres posteriores al 16 recibidos en la segunda línea **/
   if (strlen(CMUcam_comando)>16){
        lcd_gotoxy(1,2);                   //En 2ª linea y 1ª columna del LCD...
   for(i=16;i<strlen(CMUcam_comando);i++)
        printf(lcd_putc,"%c",CMUcam_comando[i]);
   }

strlen nos dice cuantos caracteres tiene la cadena contenida en CMUcam_comando para imprimir en el LCD los 16 primeros en la primera linea y el resto en la segunda.

El siguiente comando solicita la lectura de los valores umbral del color a rastrear. Por defecto la cámara ajusta todo el rango de 0 a 255 de cada uno de los 3 colores primarios.

/** Valores actuales umbral rastreo de color **/
   strcpy (CMUcam_comando, "GT");         //En CMUcam_comando se guarda comando
   puts(CMUcam_comando);                  //Envío del comando a la CMUcam

A continuación se envía a la cámara los valores umbral deseados correspondientes al color del objeto que vamos a rastrear. Hasta ahora los comandos ejecutados no eran imprescindibles, se trataba tan solo de una demostración, pero este comando si es necesario. Estos valores umbral se han obtenido con el software CMUcam4GUI tal como se muestra en el artículo "CMUcam4 controlada desde un PC"

/** Fija nuevos valores umbral rastreo de color **/
   strcpy (CMUcam_comando, "ST 58 107 152 188 46 97");/
   puts(CMUcam_comando);                  //Envío del comando a la CMUcam

Ahora, en el programa ejemplo, hacemos de nuevo una lectura de los valores umbral como se ha hecho antes para verificar que han sido adquiridos por la cámara. Normalmente suelen variar algo con respecto a los enviados.

El siguiente paso es poner los servos PAN y TILT en modo automático. 

/** Control automático del servo PAN para rastreo de color **/
   strcpy (CMUcam_comando, "AP 1 1");      //En CMUcam_comando se guarda comando
   puts(CMUcam_comando);                   //Envío del comando a la CMUcam
/** Control automático del servo TILT para rastreo de color **/ 
   strcpy (CMUcam_comando, "AT 1 1");      //En CMUcam_comando se guarda comando
   puts(CMUcam_comando);                   //Envío del comando a la CMUcam

Se ha empleado el modo inverso puesto que los servos empleados así lo requerían. Cuando el servo en cuestión se desplaza en sentido contrario al movimiento del objeto hay que cambiarle el modo de funcionamiento de directo a inverso.

Ahora mismo la cámara está lista para detectar el objeto cuyo color hemos definido. En un bucle while() además vamos a leer y mostrar en un LCD las posiciones de los servos a tiempo real. Primero la del servo TILT...

/** Lectura del valor del pulso de control servo TILT en mseg.**/
   puts("GS 0");              //Envío del comando a la CMUcam
   //Si el 4º caracter recibido no es un número lo borra del buffer recepción
  if((CMUcam_recepcion[3]<48)||(CMUcam_recepcion[3]>57))CMUcam_recepcion[3]=' ';
   lcd_gotoxy(1,1);           //En primera linea y primer caracter del LCD...
   //...muestra valor obtenido
   printf(lcd_putc,"Servo TILT: %c%c%c%c", CMUcam_recepcion[0], CMUcam_recepcion[1], CMUcam_recepcion[2], CMUcam_recepcion[3]);

...y a continuación en la segunda línea del LCD la del servo PAN.

/** Lectura del valor del pulso de control servo PAN en mseg.**/
   puts("GS 1");              //Envío del comando a la CMUcam
   //Si el 4º caracter recibido no es un número lo borra del buffer recepción
  if((CMUcam_recepcion[3]<48)||(CMUcam_recepcion[3]>57))CMUcam_recepcion[3]=' ';
   lcd_gotoxy(1,2);           //En segunda linea y primer caracter del LCD...
   //...muestra valor obtenido
   printf(lcd_putc,"Servo PAN:  %c%c%c%c", CMUcam_recepcion[0], CMUcam_recepcion[1], CMUcam_recepcion[2], CMUcam_recepcion[3]);

Solo se mostrarán los caracteres numéricos, es decir, se evitará mostrar el carácter ":" con el que finaliza el envío la CMUcam.

Para la recepción de datos de la CMUcam se ha habilitado la interrupción por recepción serie.

   enable_interrupts(int_rda);         // Habilita Interrupción RDA

Cuando el PIC detecta que ha recibido algo, salta a la función de la interrupción. Allí obtiene el último carácter recibido y lo añade al buffer de recepción donde se guarda la cadena de texto completa de respuesta de la CMUcam.

   siguiente_caracter=getc();          // se descarga y ...
   //...se añade el caracter recibido al Buffer de recepción
   CMUcam_recepcion[indice_buffer]=siguiente_caracter;  

Después de recibir un carácter, se incrementa su indice en 1 para dejarlo preparado para la recepción del siguiente de la cadena de texto completa.

/** Indice del buffer para el próximo caracter a recibir **/
    indice_buffer++;     

Dentro de la cadena de texto recibida, se encuentra el ACK o NCK. Estos 3 caracteres son extraídos y guardados en un buffer aparte para ser tratados de la forma que más convenga. 

/** Si recibe ACK o NCK lo guarda en un buffer aparte **/   
   if (CMUcam_recepcion[indice_buffer]=='K'){
      if (CMUcam_recepcion[indice_buffer-1]=='C'){
         if (CMUcam_recepcion[indice_buffer-2]=='A'){
            strcpy (CMUcam_ACK, "ACK");  //En CMU_ACK se guarda texto 'ACK'
            for (i=indice_buffer-2;i<=indice_buffer;i++)CMUcam_recepcion[i]=' ';
            indice_buffer=255;   //Reinicio del indice del buffer
         }
         else if (CMUcam_recepcion[indice_buffer-2]=='N'){
            strcpy (CMUcam_ACK, "NCK");  //En CMU_ACK se guarda texto 'NCK'
            for (i=indice_buffer-2;i<=indice_buffer;i++)CMUcam_recepcion[i]=' ';
            indice_buffer=255;   //Reinicio del indice del buffer
         }
      }
   }

En este ejemplo, este ACK o NCK tan solo se muestra en las últimas posiciones del LCD separados del resto de la cadena recibida.

/** Muestra ACK o NCK en los 3 últimos dígitos del LCD **/
   lcd_gotoxy(14,2);                   //En 2ª linea y columna 14 del LCD...
   printf(lcd_putc,"%s",CMUcam_ACK);


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


En este vídeo se muestra el resultado de todo lo hasta aquí argumentado.


Y en este enlace de descarga disponibles todos los archivos y documentación.




Artículo relacionado>> Control CMUcam4 desde un PC


El proyecto contenido en el artículo ha sido diseñado y probado  utilizando estas versiones de software:
- Windows 7
- CCS PIC C COMPILER v4.084

No hay comentarios:

Related Posts Plugin for WordPress, Blogger...

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