En este video se muestra la captura de vídeo analógico. Se puede apreciar como el filtro de mediana suaviza la imagen y consigue eliminar píxeles sueltos del fondo y minimizar el efecto de las luces y sombras que se producen en la mano al moverla.
La captura es a 48x48 píxeles a un poco menos de 25 fotogramas por segundo, velocidad limitada únicamente por el puerto serie que utilizamos para enviar las imágenes al ordenador.
sábado, 24 de marzo de 2012
Captura de vídeo
El vídeo analógico proveniente de la cámara es una señal analógica con una determinada temporización que nosotros no podemos controlar. Por tanto, para poder capturarla deberemos sincronizarnos adecuadamente con ella y realizar todas las tareas necesarias en tiempo real. Trabajaremos con vídeo compuesto en formato PAL.
La señal de vídeo tiene una estructura pensada para facilitar su visualización en los antiguos televisores con tubo de rayos catódicos. En el estándar PAL, cada fotograma mostrado en pantalla se divide en 625 líneas, y se envía en dos cuadros de 312,5 líneas, correspondiendo el primer cuadro a las líneas impares de la imagen y el segundo cuadro a las líneas pares. Se envían 50 cuadros por segundo, lo que corresponde a 25 fotogramas completos por segundo.

Cada línea de vídeo dura 64 microsegundos, de los cuales solo 52 se corresponden a vídeo, siendo el resto necesarios para sincronización. Un pulso de polaridad negativa respecto al nivel de tensión base de la señal indica el comienzo de cada línea, y en los 8 microsegundos siguientes se aprovecha para mandar varios ciclos de la portadora que modula las componentes de color de la señal compuesta de vídeo, para sincronizar el oscilador local del televisor. Este espacio estaba reservado para que el haz de electrones que dibujaba la imágen tuviera tiempo para desplazarse a la izquierda antes de comenzar a dibujar la siguiente línea.
Los 52us de vídeo son una señal continua cuya envolvente es la componente de luminancia, que es la que nos interesa a nosotros pues incluye la información de "blanco y negro" del vídeo. La información de color se envía modulada en una zona vacía del espectro de luminancia. La señal de luminancia adquiere niveles mayores de tensión cuanto más luminosa sea la imagen.

En la vida real, una parte de las líneas de video de la imagen no son visibles y al final de cada cuadro se incluyen una serie de pulsos de sincronismo vertical para dar tiempo a que el haz de electrones volviera a situarse en la esquina superior izquierda tras acabar de dibujar un cuadro. También hay parte de los 52us de vídeo por linea que no son visibles. Finalmente tendremos 288 líneas visibles por cuadro y unos 50,5 us visibles por línea de vídeo. En la imagen anterior se puede ver la temporización completa del video en formato NTSC, equivalente a la que utiliza PAL salvo por la diferencia en el número de líneas y la duración de cada línea. Comprobamos empíricamente que en el caso de PAL el vídeo visible comienza a partir de la línea 28, momento en que comenzamos la captura del cuadro.
Para capturar la señal aprovechamos los recursos disponibles del microcontrolador, ayudados por un circuito integrado LM1881 que extrae la información de sincronismo de la señal de vídeo y se la proporciona al PIC. Puede verse en el datasheet que se extraen los pulsos de sincronismo horizontal (al comienzo de cada línea de vídeo), las ráfagas de portadora que se mandan al principio de cada línea, la información referente a si el cuadro contiene líneas pares o impares y los pulsos de sincronismo vertical.
Conectamos las salidas de este integrado a varias entradas del PIC32 con capacidad para interrupción externa, según el siguiente esquema:

De las cuatro señales de sincronismo, utilizamos la que nos indica si el cuadro es par o impar (aparte de dar información de cuándo comienza el cuadro) y la señal que se sincroniza con las ráfagas de ciclos de portadora. También podría utilizarse de forma equivalente la señal de sincronismo horizontal si el sistema debiera lidiar con cámaras que no enviasen información de color.
Utilizamos un sistema basado en interrupciones y en el uso de los temporizadores para capturar la imagen, según el siguiente diagrama de flujo:

El PIC32 utiliza una arquitectura en la cual el tiempo que tarda en ejecutarse una instrucción no es determinista, debido a que depende de varios factores como los estados de espera que se hayan configurado para la flash y del estado de la caché de instrucciones en cada instante. Es por ello que debemos emplear un sistema basado en los periféricos del microcontrolador, y no en la cuenta de instrucciones, que es lo que suele hacerse en arquitecturas con tiempo de instrucción determinista.
Nuestra primera idea era capturar imágenes a 96x96 píxeles. Asiumiendo un tiempo de vídeo visible de 50,4us por línea, esto nos da que habría que muestrear la zona de vídeo cada 525ns. A 80MHz, esto nos da 42 ciclos de reloj entre cada interrupción para ejecutar el código que guarde el píxel capturado y de servicio a las interrupciones. Pudimos comprobar empíricamente que con este periodo de muestreo había casos en los que no daba tiempo a ejecutar todo el código y por tanto el tiempo de vídeo muestreado en la realidad era superior a 50,4us, saliéndose de la línea y muestreando erróneamente parte de la siguiente.
Ya que nuestra resolución de trabajo final iban a ser 24x24 píxeles, comprobamos si el filtro de mediana seguía trabajando bien a 48x48 píxeles, y tras comprobar que sí, decidimos muestrear finalmente la imagen a 48x48 píxeles, donde el tiempo entre muestras es suficiente, consiguiendo muestrear correctamente la línea completa de vídeo a intervalos regulares y deterministas.

Cada línea de vídeo dura 64 microsegundos, de los cuales solo 52 se corresponden a vídeo, siendo el resto necesarios para sincronización. Un pulso de polaridad negativa respecto al nivel de tensión base de la señal indica el comienzo de cada línea, y en los 8 microsegundos siguientes se aprovecha para mandar varios ciclos de la portadora que modula las componentes de color de la señal compuesta de vídeo, para sincronizar el oscilador local del televisor. Este espacio estaba reservado para que el haz de electrones que dibujaba la imágen tuviera tiempo para desplazarse a la izquierda antes de comenzar a dibujar la siguiente línea.
Los 52us de vídeo son una señal continua cuya envolvente es la componente de luminancia, que es la que nos interesa a nosotros pues incluye la información de "blanco y negro" del vídeo. La información de color se envía modulada en una zona vacía del espectro de luminancia. La señal de luminancia adquiere niveles mayores de tensión cuanto más luminosa sea la imagen.

En la vida real, una parte de las líneas de video de la imagen no son visibles y al final de cada cuadro se incluyen una serie de pulsos de sincronismo vertical para dar tiempo a que el haz de electrones volviera a situarse en la esquina superior izquierda tras acabar de dibujar un cuadro. También hay parte de los 52us de vídeo por linea que no son visibles. Finalmente tendremos 288 líneas visibles por cuadro y unos 50,5 us visibles por línea de vídeo. En la imagen anterior se puede ver la temporización completa del video en formato NTSC, equivalente a la que utiliza PAL salvo por la diferencia en el número de líneas y la duración de cada línea. Comprobamos empíricamente que en el caso de PAL el vídeo visible comienza a partir de la línea 28, momento en que comenzamos la captura del cuadro.
Para capturar la señal aprovechamos los recursos disponibles del microcontrolador, ayudados por un circuito integrado LM1881 que extrae la información de sincronismo de la señal de vídeo y se la proporciona al PIC. Puede verse en el datasheet que se extraen los pulsos de sincronismo horizontal (al comienzo de cada línea de vídeo), las ráfagas de portadora que se mandan al principio de cada línea, la información referente a si el cuadro contiene líneas pares o impares y los pulsos de sincronismo vertical.
Conectamos las salidas de este integrado a varias entradas del PIC32 con capacidad para interrupción externa, según el siguiente esquema:

De las cuatro señales de sincronismo, utilizamos la que nos indica si el cuadro es par o impar (aparte de dar información de cuándo comienza el cuadro) y la señal que se sincroniza con las ráfagas de ciclos de portadora. También podría utilizarse de forma equivalente la señal de sincronismo horizontal si el sistema debiera lidiar con cámaras que no enviasen información de color.
Utilizamos un sistema basado en interrupciones y en el uso de los temporizadores para capturar la imagen, según el siguiente diagrama de flujo:

El PIC32 utiliza una arquitectura en la cual el tiempo que tarda en ejecutarse una instrucción no es determinista, debido a que depende de varios factores como los estados de espera que se hayan configurado para la flash y del estado de la caché de instrucciones en cada instante. Es por ello que debemos emplear un sistema basado en los periféricos del microcontrolador, y no en la cuenta de instrucciones, que es lo que suele hacerse en arquitecturas con tiempo de instrucción determinista.
Nuestra primera idea era capturar imágenes a 96x96 píxeles. Asiumiendo un tiempo de vídeo visible de 50,4us por línea, esto nos da que habría que muestrear la zona de vídeo cada 525ns. A 80MHz, esto nos da 42 ciclos de reloj entre cada interrupción para ejecutar el código que guarde el píxel capturado y de servicio a las interrupciones. Pudimos comprobar empíricamente que con este periodo de muestreo había casos en los que no daba tiempo a ejecutar todo el código y por tanto el tiempo de vídeo muestreado en la realidad era superior a 50,4us, saliéndose de la línea y muestreando erróneamente parte de la siguiente.
Ya que nuestra resolución de trabajo final iban a ser 24x24 píxeles, comprobamos si el filtro de mediana seguía trabajando bien a 48x48 píxeles, y tras comprobar que sí, decidimos muestrear finalmente la imagen a 48x48 píxeles, donde el tiempo entre muestras es suficiente, consiguiendo muestrear correctamente la línea completa de vídeo a intervalos regulares y deterministas.
Procesado de imagen en C: filtro de mediana
- Filtrado de mediana
El filtro de mediana nos causó más complicaciones, debido fundamentalmente al uso de punteros en C.
El objetivo del filtro de mediana es eliminar ruido y suavizar la imagen; sus efectos pueden comprobarse en anteriores entradas. Debido a que este filtro tiene en cuenta el valor de los vecinos de cada píxel para determinar si éste deberá ser blanco o negro, para implementarlo fue necesario crear primero una subrutina "getUnos". Dado un array bidimensional de imagen y unas coordenadas de posición inicial y final, coge el parche correspondiente de dicha imagen y cuenta el número de bits 1 en el mismo. Este método incluye un paso por referencia de la variable en la que guardaremos el número de unos, y fue esto lo que nos causó una serie de problemas iniciales debido a nuestra falta de familiaridad con punteros.
Una vez creada esta subrutina, el método de filtro de mediana se simplifica: recorremos la imagen a procesar píxel a píxel, y para cada uno cogemos un parche de la imagen alrededor de ese píxel (el radio del parche se especifica en la llamada al método); el método getUnos nos devuelve el número de unos en ese parche y según superen o no un umbral reescribimos el píxel central como 0 o 1. De esta forma determinamos si un píxel debe ser blanco o negro según sus vecinos.
Por supuesto, tenemos en cuenta que no debemos salirnos de la imagen en ningún momento (si cogemos la coordenada (0,0) con radio 2, el parche irá de (0,0) a (2,2), sin coger coordenadas negativas). Además, en todo este proceso tenemos que tener en cuenta la agrupación por bytes de los bits de imagen, con lo cual realizamos varias multiplicaciones y divisiones por ocho a lo largo del código; para una mayor rapidez efectuamos estas operaciones mediante desplazamientos, y no como multiplicaciones per se.
Es quizás necesario hacer una especial mención a las dos últimas líneas del código. A fin de modificar únicamente el bit deseado en cada momento, lo editamos mediante el uso de una máscara. Así, si se determina que debe ser un 1, se produce:
if(unos>umbral)dstImg[i][j>>3] |= 0x80>>(j%8);
El filtro de mediana nos causó más complicaciones, debido fundamentalmente al uso de punteros en C.
El objetivo del filtro de mediana es eliminar ruido y suavizar la imagen; sus efectos pueden comprobarse en anteriores entradas. Debido a que este filtro tiene en cuenta el valor de los vecinos de cada píxel para determinar si éste deberá ser blanco o negro, para implementarlo fue necesario crear primero una subrutina "getUnos". Dado un array bidimensional de imagen y unas coordenadas de posición inicial y final, coge el parche correspondiente de dicha imagen y cuenta el número de bits 1 en el mismo. Este método incluye un paso por referencia de la variable en la que guardaremos el número de unos, y fue esto lo que nos causó una serie de problemas iniciales debido a nuestra falta de familiaridad con punteros.
Una vez creada esta subrutina, el método de filtro de mediana se simplifica: recorremos la imagen a procesar píxel a píxel, y para cada uno cogemos un parche de la imagen alrededor de ese píxel (el radio del parche se especifica en la llamada al método); el método getUnos nos devuelve el número de unos en ese parche y según superen o no un umbral reescribimos el píxel central como 0 o 1. De esta forma determinamos si un píxel debe ser blanco o negro según sus vecinos.
Por supuesto, tenemos en cuenta que no debemos salirnos de la imagen en ningún momento (si cogemos la coordenada (0,0) con radio 2, el parche irá de (0,0) a (2,2), sin coger coordenadas negativas). Además, en todo este proceso tenemos que tener en cuenta la agrupación por bytes de los bits de imagen, con lo cual realizamos varias multiplicaciones y divisiones por ocho a lo largo del código; para una mayor rapidez efectuamos estas operaciones mediante desplazamientos, y no como multiplicaciones per se.
Es quizás necesario hacer una especial mención a las dos últimas líneas del código. A fin de modificar únicamente el bit deseado en cada momento, lo editamos mediante el uso de una máscara. Así, si se determina que debe ser un 1, se produce:
if(unos>umbral)dstImg[i][j>>3] |= 0x80>>(j%8);
Donde las coordenadas del píxel considerado son (i,j). En suma, este píxel pertenece al byte[i][j/8], y su posición dentro del mismo será desde la izquierda el resto de j/8. Realizamos por tanto un OR del byte actual con una máscara con un 1 en la posición del píxel considerado, de forma que su valor quede en 1 sin variar el de los demás en el byte.
Código de medianFilter y getUnos.
viernes, 16 de marzo de 2012
Procesado de imagen en C: escalado
Después de comprobar el buen funcionamiento de los algoritmos en MATLAB (véase las entradas de "Primera aproximación con MATLAB" y "Algoritmo de escalado - MATLAB"), procedemos a implementarlos en C.
- Escalado
En esta ocasión comenzamos con el algoritmo de escalado por resultar más sencillo. Creamos un método de escalado por 4, que recorrerá la matriz de imagen, escalará y devolverá un array unidimensional que será la entrada de la red neuronal.
De nuevo se trata de coger parches de la imagen de tamaño 4x4 y sustituirlos por un solo bit de valor 0 o 1. Debido a que MATLAB permite el fácil calculo de medias y varianzas no nos requirió más que una función de media y una comparación con un umbral para decidir el valor del píxel escalado. En este caso, en cambio, optamos por considerar el número de unos en el espacio de 4x4 bits y compararlo con un umbral, que de momento fijamos en 8 (la mitad de los 16 bits del parche), aunque mediante una simulación en MATLAB puede comprobarse que los resultados no son tan buenos para un umbral fijo como para uno variable basado en el cálculo de media y varianza del fondo.
En lugar de contar bit a bit, recurrimos a una tabla para determinar el número de unos en cada grupo de 4 bits, fila a fila para cada una de las cuatro filas del parche 4x4; en cada posición de la tabla guardamos cuántos unos tiene el número de esa posición en binario. De esta forma basta con consultar la tabla cuatro veces por parche, sumar el número total de unos que corresponda, y comparar con 8.
Guardando posición a posición en un nuevo array unidimensional obtenemos la salida deseada.
Método scaleby4.
- Escalado
En esta ocasión comenzamos con el algoritmo de escalado por resultar más sencillo. Creamos un método de escalado por 4, que recorrerá la matriz de imagen, escalará y devolverá un array unidimensional que será la entrada de la red neuronal.
De nuevo se trata de coger parches de la imagen de tamaño 4x4 y sustituirlos por un solo bit de valor 0 o 1. Debido a que MATLAB permite el fácil calculo de medias y varianzas no nos requirió más que una función de media y una comparación con un umbral para decidir el valor del píxel escalado. En este caso, en cambio, optamos por considerar el número de unos en el espacio de 4x4 bits y compararlo con un umbral, que de momento fijamos en 8 (la mitad de los 16 bits del parche), aunque mediante una simulación en MATLAB puede comprobarse que los resultados no son tan buenos para un umbral fijo como para uno variable basado en el cálculo de media y varianza del fondo.
En lugar de contar bit a bit, recurrimos a una tabla para determinar el número de unos en cada grupo de 4 bits, fila a fila para cada una de las cuatro filas del parche 4x4; en cada posición de la tabla guardamos cuántos unos tiene el número de esa posición en binario. De esta forma basta con consultar la tabla cuatro veces por parche, sumar el número total de unos que corresponda, y comparar con 8.
Guardando posición a posición en un nuevo array unidimensional obtenemos la salida deseada.
Método scaleby4.
Algoritmo de escalado - MATLAB
A fin de limitar el número de neuronas necesarias en la red neuronal, y por lo tanto el número de parámetros que la describen y el espacio necesario para almacenarlos, buscamos obtener una imagen de entrada a la red neuronal de 24x24; es por tanto necesario realizar un escalado de la imagen obtenida de la cámara.
Con imágenes de 24x24, serán necesarias 576 neuronas de entrada; la capa oculta tendrá 50 neuronas y la de salida unas 37. Con esto sería necesario guardar 576x50+50x37=30650 valores de pesos aproximadamente. Si además añadimos sesgos, estos serían 50+37=87.
Para escalar las imágenes nos basamos en algoritmos de box filter. Partimos de imágenes de 96x96 y tenemos que escalarlas dividiendo su dimensión por 4.
Con imágenes de 24x24, serán necesarias 576 neuronas de entrada; la capa oculta tendrá 50 neuronas y la de salida unas 37. Con esto sería necesario guardar 576x50+50x37=30650 valores de pesos aproximadamente. Si además añadimos sesgos, estos serían 50+37=87.
Para escalar las imágenes nos basamos en algoritmos de box filter. Partimos de imágenes de 96x96 y tenemos que escalarlas dividiendo su dimensión por 4.
Realizamos el escalado mediante un proceso similar al filtrado de mediana descrito en la entrada de "Primera aproximación con Matlab". Tomamos parches cuadrados de la imagen de 4x4 y calculamos el valor medio de los mismos; este valor medio lo compararemos con un umbral, el cual inicialmente queda a 0.5, y según sea mayor o menor asignamos al píxel de la imagen escalada el valor 0 o 1.
La función boxfilter de MATLAB puede consultarse a pie de pie de página.
En la función Extractor ya citada en la anterior entrada "Primera aproximación a MATLAB" añadimos por tanto una llamada a la función de escalado modificada, a la que ahora pasaremos un umbral variable. Usaremos como umbral el mismo que valor empleamos para determinar si un píxel es blanco o negro en la función Extractor: umbral=media+A*varianza, con A=9.
Realizamos pruebas con la imagen Lena que resultaron bastante satisfactorias. Este escalado reemplaza hasta un punto el filtrado de mediana anteriormente descrito, pero siguen obteniéndose mejores resultados si se aplica el filtro de mediana y a continuación el escalado. Lo comprobamos empíricamente editando la función de MATLAB Extractor para que dibuje en cuatro ventanas diferentes:
- la imagen obtenida en blanco y negro
- la imagen en blanco y negro, una vez se le pasa el filtro de mediana
- la imagen en blanco y negro, tras pasarle el filtro de mediana y escalarla
- la misma imagen, escalada sin procesamiento previo de filtro de mediana
Las imágenes obtenidas, usando la imagen de prueba Mano ya empleada en la entrada de "Primera aproximación con MATLAB" son:
(clic en las imágenes para ampliarlas)
Función boxfilter.
Función Extractor. Modificada con respecto a la función Extractor de "Primera aproximación en MATLAB".
jueves, 8 de marzo de 2012
Primera aproximación con MATLAB
Antes de iniciar la programación en PIC32, realizamos una primera aproximación a la práctica en MATLAB. El objetivo consiste en determinar los procesos de tratamiento de imagen que será necesario implementar para el reconocimiento de gestos estáticos.
Capturamos una imagen de una mano sobre fondo monocromático negro y otra sobre fondo monocromático blanco. En primer lugar trabajamos sobre fondo negro; cargamos la imagen en una matriz y la pasamos de RGB a escala de grises; lo mismo con el fondo.
Como trabajaremos solamente con dos niveles de color (blanco o negro), debemos fijar un umbral de comparación para distinguirlos. Esto lo hacemos tomando como referencia la imagen de fondo monocromático: calculamos su media y su varianza con funciones de MATLAB, y fijamos el umbral en una combinación lineal de las mismas de la forma umbral=media+A*varianza. En concreto, tras varios ensayos verificamos que se obtenía un resultado bastante bueno para A=8, aunque resulta mucho mejor en A=9.
Todo esto viene implementado en la función de Matlab Extractor.
Como trabajaremos solamente con dos niveles de color (blanco o negro), debemos fijar un umbral de comparación para distinguirlos. Esto lo hacemos tomando como referencia la imagen de fondo monocromático: calculamos su media y su varianza con funciones de MATLAB, y fijamos el umbral en una combinación lineal de las mismas de la forma umbral=media+A*varianza. En concreto, tras varios ensayos verificamos que se obtenía un resultado bastante bueno para A=8, aunque resulta mucho mejor en A=9.
Todo esto viene implementado en la función de Matlab Extractor.
Apreciamos la aparición de cierto ruido, con lo que implementamos y aplicamos un filtro de mediana que pudiera reducirlo. Para cada valor de la matriz, realizamos un cálculo de la mediana de los valores que le rodean en un cierto área, y le asociamos el mismo. La función de MATLAB que realiza el filtrado tiene como parámetro de entrada el radio a considerar para realizar el filtrado.
El código correspondiente se encuentra en imgproc.
Enlaces:
El código correspondiente se encuentra en imgproc.
Surgen varios problemas a resolver:
- el fondo deberá ser monocromático.
- de momento hemos recortado la imagen manualmente, pero en el futuro será necesario encontrar la mano en la fotografía, centrarla, recortar alrededor de ella.
- tendremos que escalar la imagen para reducir el número de entradas a la red neuronal.
Enlaces:
miércoles, 7 de marzo de 2012
El entorno de desarrollo
Para llevar a cabo la práctica hemos decicido utilizar el entorno MPLABX 1.00 proporcionado gratuitamente por Microchip. Este entorno está basado en netbeans e incluye todas las herramientas oficiales para trabajar con los microcontroladores PIC32 como el que hemos elegido.
Como compilador utilizamos la versión gratuita del Microchip C32, que está basado en gcc e incluye un gran juego de librerías con macros y funciones para configurar y acceder a la gran selección de periféricos del microcontrolador de forma sencilla. Estas librerías de periféricos se incluyen de forma gratuita y vienen convenientemente documentadas en la ayuda y en la guía de utilización de las librerías que puede encontrarse en el siguiente enlace:
http://www.johnloomis.org/microchip/docs/32-bit-Peripheral-Library-Guide.pdf
La versión gratuita del compilador no permite algunas funciones como la habilitación de las optimizaciones más avanzadas, y no descartamos la posibilidad de utilizar la versión de prueba de 60 días del compilador completo si vemos que van a ser necesarias las funciones extra que ofrece.
El entorno de desarrollo dispone de numerosas funciones:

En la pantalla principal se nos presentan las diversas funciones, que en su mayoría son las típicas y esperadas de cualquier entorno de desarrollo, donde podemos tener nuestros proyectos organizados o ver qué archivos o librerías pertenecen o enlazan con cada proyecto. Como información específca disponemos de una pestaña especial donde podemos ver el modelo de microcontrolador que tenemos seleccionado e información sobre los recursos del mismo que vamos a consumir.

En las propiedades del proyecto podemos cambiar el microcontrolador a utilizar y modificar diversas opciones del compilador como los niveles de optimización que deseamos. También pueden modificarse parámetros como el tamaño de pila deseada o la asignación de memoria, que nosotros dejaremos en los valores por defecto.

El acceso al microcontrolador se realiza a través de un hardware externo que hace de interfaz con el ordenador. Microchip proporciona diversas herramientas hardware para programar o depurar sus líneas de microcontroladores. En nuestro caso hemos elegido el PICKIT 3, que hace las veces tanto de programador como de depurador. El entorno de desarrollo incluye opciones específicas para configurar este hardware, que se encuentran dentro del apartado de propiedades del proyecto.
Podemos configurar tanto la parte de la memoria que queremos programar, para por ejemplo evitar pisar una zona ocupada por un bootloader, y también podemos configurar opciones de energía, ya que el PICKIT3 es capaz de alimentar por sí mismo la placa a la que esté conectada si así se desea, y es necesario configurar esta opción para activarla o desactivarla según la placa disponga o no de su propia alimentación.

El núcleo MIPS del microcontrolador dispone de un puerto JTAG para depurar y programar a alta velocidad, que está accesible desde el exterior tanto directamente como virtualizado a través de una interfaz serie de dos líneas propietaria de microchip, que es la que utiliza PICKIT3. La virtualización se realiza por software a través de unas rutinas almacenadas en una memoria flash interna inaccesible desde el programa que se esté ejecutando en el microcontrolador. Esta virtualización limita en gran medida la velocidad de depuración.
El entorno de desarrollo permite controlar completamente la ejecución del programa en modo de depuración, pudiendo establecer puntos de parada y tener acceso al valor de las variables.
Como compilador utilizamos la versión gratuita del Microchip C32, que está basado en gcc e incluye un gran juego de librerías con macros y funciones para configurar y acceder a la gran selección de periféricos del microcontrolador de forma sencilla. Estas librerías de periféricos se incluyen de forma gratuita y vienen convenientemente documentadas en la ayuda y en la guía de utilización de las librerías que puede encontrarse en el siguiente enlace:
http://www.johnloomis.org/microchip/docs/32-bit-Peripheral-Library-Guide.pdf
La versión gratuita del compilador no permite algunas funciones como la habilitación de las optimizaciones más avanzadas, y no descartamos la posibilidad de utilizar la versión de prueba de 60 días del compilador completo si vemos que van a ser necesarias las funciones extra que ofrece.
El entorno de desarrollo dispone de numerosas funciones:

En la pantalla principal se nos presentan las diversas funciones, que en su mayoría son las típicas y esperadas de cualquier entorno de desarrollo, donde podemos tener nuestros proyectos organizados o ver qué archivos o librerías pertenecen o enlazan con cada proyecto. Como información específca disponemos de una pestaña especial donde podemos ver el modelo de microcontrolador que tenemos seleccionado e información sobre los recursos del mismo que vamos a consumir.

En las propiedades del proyecto podemos cambiar el microcontrolador a utilizar y modificar diversas opciones del compilador como los niveles de optimización que deseamos. También pueden modificarse parámetros como el tamaño de pila deseada o la asignación de memoria, que nosotros dejaremos en los valores por defecto.

El acceso al microcontrolador se realiza a través de un hardware externo que hace de interfaz con el ordenador. Microchip proporciona diversas herramientas hardware para programar o depurar sus líneas de microcontroladores. En nuestro caso hemos elegido el PICKIT 3, que hace las veces tanto de programador como de depurador. El entorno de desarrollo incluye opciones específicas para configurar este hardware, que se encuentran dentro del apartado de propiedades del proyecto.
Podemos configurar tanto la parte de la memoria que queremos programar, para por ejemplo evitar pisar una zona ocupada por un bootloader, y también podemos configurar opciones de energía, ya que el PICKIT3 es capaz de alimentar por sí mismo la placa a la que esté conectada si así se desea, y es necesario configurar esta opción para activarla o desactivarla según la placa disponga o no de su propia alimentación.

El núcleo MIPS del microcontrolador dispone de un puerto JTAG para depurar y programar a alta velocidad, que está accesible desde el exterior tanto directamente como virtualizado a través de una interfaz serie de dos líneas propietaria de microchip, que es la que utiliza PICKIT3. La virtualización se realiza por software a través de unas rutinas almacenadas en una memoria flash interna inaccesible desde el programa que se esté ejecutando en el microcontrolador. Esta virtualización limita en gran medida la velocidad de depuración.
El entorno de desarrollo permite controlar completamente la ejecución del programa en modo de depuración, pudiendo establecer puntos de parada y tener acceso al valor de las variables.
jueves, 1 de marzo de 2012
Selección de hardware
Como hardware principal utilizaremos una placa de desarrollo para PIC32 con el microcontrolador PIC32MX320F128H. En concreto utilizaremos una copia de fabricación casera similar al reciente ChipKIT Uno32 de Digilent, diseñado para sustituir a la conocida plataforma Arduino en aplicaciones que requieran microcontroladores más potentes. A pesar de poder programar esta placa en el lenguaje de Arduino, para nuestra práctica utilizaremos el entorno de desarrollo oficial de Microchip MPLABX y realizaremos la programación en C, apoyándonos únicamente en las librerías de control de periféricos que proporciona el entorno de desarrollo.
La captura de video analógico requiere cierto hardware extra que deberemos construir nosotros mismos. Un cicruito integrado modelo LM1881 se encargará de separar los pulsos de sincronismo tanto vertical como horizontal de la señal de vídeo analógico, indicando al micrcocontrolador los momentos en los que debe comenzar a muestrear las líneas de vídeo con los comparadores integrados. Para poder fijar el umbral de dichos comparadores utilizaremos un conversor digital-analógico externo que nos proporcionará 256 niveles de tensión ajustados al rango dinámico de la señal de vídeo mediante un potenciómetro. El DAC irá controlado mediante un bus I2C desde el PIC32. La señal de vídeo se inyectará en uno de los comparadores analógicos del PIC32 y se comparará con el umbral prefijado, formando el conjunto un ADC de un solo bit con umbral ajustable.
Datasheets:
-LM1881
-MCP4706 (DAC)
-PIC32MX320F128H
La captura de video analógico requiere cierto hardware extra que deberemos construir nosotros mismos. Un cicruito integrado modelo LM1881 se encargará de separar los pulsos de sincronismo tanto vertical como horizontal de la señal de vídeo analógico, indicando al micrcocontrolador los momentos en los que debe comenzar a muestrear las líneas de vídeo con los comparadores integrados. Para poder fijar el umbral de dichos comparadores utilizaremos un conversor digital-analógico externo que nos proporcionará 256 niveles de tensión ajustados al rango dinámico de la señal de vídeo mediante un potenciómetro. El DAC irá controlado mediante un bus I2C desde el PIC32. La señal de vídeo se inyectará en uno de los comparadores analógicos del PIC32 y se comparará con el umbral prefijado, formando el conjunto un ADC de un solo bit con umbral ajustable.
Datasheets:
-LM1881
-MCP4706 (DAC)
-PIC32MX320F128H
Suscribirse a:
Comentarios (Atom)



