domingo, 23 de junio de 2013

Implementación de SPI por software en 2 uC 18f4550

El SPI por software me pareció una característica bastante versátil pues puede ser usado con aquellos pic's que no cuenten con el modulo físico del mismo, a cambio de esto se consiguen velocidades un poco mas lentas.

Se utiliza el software PROTEUS para simular los programas, claro que siempre se recomienda implementar en un uC físico pues considero que a veces el ISIS es muy permisivo en algunos aspectos.
Aqui se tiene una imagen del programa, notaran que en los archivos que la LCD del esclavo no arroja ningún valor pero solo es cuestión de inicializarla.



Luego de hacer las conexiones se procedió a hacer la programación  en el área de ayuda del PIC C compiler trae un ejemplo para la implementación por software:

"#use spi(DI=PIN_B1, DO=PIN_B0, CLK=PIN_B2, ENABLE=PIN_B4, BITS=16)"

Decidi no utilizar el pin enable, y cambiar los BITS a 8, así como declarar el modo, esclavo/maestro, y los baudios, la linea para el maestro quedo de la siguiente manera:

"#use spi(MASTER,DI=PIN_B1, DO=PIN_B0, CLK=PIN_B2,baud=9600, BITS=8,MODE=0)"

y para el esclavo:
"#use spi(SLAVE,DI=PIN_B1, DO=PIN_B0, CLK=PIN_B2,ENABLE=PIN_B4, BITS=8,MODE=0)"

y para enviar o recibir se usa un solo comando que es:
"spi_xfer();"
que puede ser leído y debe llevar un parámetro entre los paréntesis aunque sea "0", la siguiente instrucción del programa muestra su utilización:

"ADCslave[0]=spi_xfer(0);"

Como resultado final tenemos que se imprimen los 3 bytes en la pantalla LCD del maestro (sin pasarlo a voltaje).
(nota el 42 es no es un valor de recepción)

Como pueden notar es bastante sencillo, si gustan checar los archivos en la siguiente carpeta ImplementacionSPI, donde incluyo la simulacion, los programas en C y los .hex

Saludos

martes, 18 de junio de 2013

Entendiendo I2C.
Lo básico acerca de este protocolo de comunicación.


Introducción
Antes de referirnos a los detalles del proyecto desarrollado con el protocolo I2C me ha parecido conveniente dejar información acerca del protocolo, esto con el fin de entender como funciona este.
I2C son las siglas de inter-integrated circuits (circuitos inter-integrados) y se trata de un bus de comunicación en serie desarrollado por Phillips. La primera versión 1.0 fue lanzada en 1992.
Tiene una velocidad de 100kbits/s pudiendo alcanzar velocidades de 3.4Mbits/s.
Su importancia radica en el hecho de que es muy utilizado en la industria para la comunicación de microcontroladores y sus periféricos en sistemas embebidos.

Características
La caraterística de este protocolo es que solo utiliza dos líneas para transmitir información: Una línea de datos (SDA) y una línea para la señal de reloj (SCL o SCK). Adicionalmente se agrega la tierra (GND) que aunque bien es una tercera línea no transmite información y su única finalidad es de referencia.
Las líneas de SDA y SCK son de drenador abierto. Esto amerita que deba utilizarse una resistencia de pull-up para su funcionamiento.

Los dispositivos conectados al bus pueden ser maestros o esclavos. El dispositivo maestro puede iniciar la transferencia de datos y dar la señal de reloj pero no es necesario que el dispositivo maestro sea siempre el mismo. Esto es, que dicha característica se puede ir pasando entre los dispositivos que tengan esta capacidad. Por esta propiedad, al protocolo I2C se le conoce como multimaestro.

¿Cómo se realiza la comunicación?
Las transacciones se realizan con el siguiente formato

| start | A7 A6 A5 A4 A3 A2 A1 | R/W | ACK | ... DATA ... | ACK | stop | idle |

Y los pasos son los siguientes:


El bus esta libre cuando SDA y SCL están en estado lógico alto.


En estado bus libre, cualquier dispositivo puede ocupar el bus I2C como maestro.


El maestro comienza la comunicación enviando un patrón llamado "start condition". Esto alerta a los dispositivos esclavos, poniéndolos a la espera de una transacción.


El maestro se dirige al dispositivo con el que quiere hablar, enviando un byte que contiene los siete bits (A7-A1) que componen la dirección del dispositivo esclavo con el que se quiere comunicar, y el octavo bit (A0) de menor peso se corresponde con la operación deseada (L/E), lectura=1 (recibir del esclavo) y escritura=0 (enviar al esclavo).


La dirección enviada es comparada por cada esclavo del bus con su propia dirección, si ambas coinciden, el esclavo se considera direccionado como esclavo-transmisor o esclavo-receptor dependiendo del bit R/W.


El esclavo responde enviando un bit de ACK que le indica al dispositivo maestro que el esclavo reconoce la solicitud y está en condiciones de comunicarse.


Seguidamente comienza el intercambio de información entre los dispositivos.


El maestro envía la dirección del registro interno del dispositivo que se desea leer o escribir.


El esclavo responde con otro bit de AC

Ahora el maestro puede empezar a leer o escribir bytes de datos. Todos los bytes de datos deben constar de 8 bits, el número máximo de bytes que pueden ser enviados en una transmisión no está restringido, siendo el esclavo quien fija esta cantidad de acuerdo a sus características.

Cada byte leido/escrito por el maestro debe ser obligatoriamente reconocido por un bit de ACK por el dispositivo maestro/esclavo.


Se repiten los 2 pasos anteriores hasta finalizar la comunicación entre maestro y esclavo.


Aun cuando el maestro siempre controla el estado de la línea del reloj, un esclavo de baja velocidad o que deba detener la transferencia de datos mientras efectúa otra función, puede forzar la línea SCL a nivel bajo. Esto hace que el maestro entre en un estado de espera, durante el cual, no transmite información esperando a que el esclavo esté listo para continuar la transferencia en el punto donde había sido detenida.


Cuando la comunicación finaliza, el maestro transmite una "stop condition" para dejar libre el bus.


Después de la "stop condition", es obligatorio para el bus estar idle durante unos microsegundos.

El código del kernel de Linux para el soporte I2C está separado en varias piezas lógicas:

I2C chip driver (maneja uno de los chips conectados al bus I2C, tanto si se comporta como maestro o como esclavo)

I2C bus driver

I2C algorithm driver

I2C core (la parte genérica del subsistema de I2C)

Y así es como se hace la comunicación n I2C. La ventaja de ya que sea un bus ya estandarizado permite que haya bibliotecas o bloques de código para algunos microcontroladores que nos permitan realizar todos los procesos de forma sencilla sin tener que estar "reinventado" o rompiendonos tanto la cabeza al realizar la comunicación.

sábado, 8 de junio de 2013

Optimizar el uso de un ADC

Cualquier estudiante de ingeniería se ha visto en la necesidad de implementar un ADC, y la verdad es que en casi todos los microcontroladores implementarlo es bastante sencillo. No obstante, en ocasiones no nos preocupamos por optimizar la manera en la que usamos el ADC, puede ser por que los requerimientos de nuestros proyectos no son tan exigentes, o en ocasiones por desconocimiento de las opciones que el microcontrolador nos brinda, pero que no lo hagamos no significa que no sea necesario, y quizá en algún momento cuando se necesite desarrollar un proyecto mas demandante donde la velocidad y la memoria son aspectos a cuidar, este tema podra ser de ayuda. De manera general este tema presenta algunas sugerencias en cuanto el uso del ADC,y la mejor forma de emplearlos y consumir la menor cantidad de recursos del sistema, cabe recalcar que en teoría en muchos microcontroladores es posible aplicar los consejos descritos a continuación, pero la dificultad para hacerlo es variable.

  ¿Debo usar un ADC por cada señal?

 Por lo general tendemos a usar un ADC por cada señal de interés, esto si bien es funcional, consume muchos recursos y memoria, y en situaciones mas estrictas, o bien para algún proyecto con fines de lucro, la memoria es un aspecto critico que se debe intentar optimizar al máximo. Cuando la velocidad de muestreo no es un aspecto muy critico, una opción es usar ADC duales o de doble canal, para alternar entre la lectura de 2 señales, y aunque el muestreo se ve reducido a la mitad, los requerimientos de memoria igual. Por otro lado, algunos microcontroladores mas poderosos como los de la familia 3 y 5 de Cypres por poner un ejemplo, permiten configura ADC para un muestreo múltiple, esto se logra mutiplexando la señales de entrada al ADC de una manera controlada ya sea por por software o por hardware. En internet se pueden encontrar algunos ejemplos de esto, que incluso procesan 16 señales diferentes con un mismo ADC.



  ¿Polling o interrupciones?

 El polling es una practica muy común cuando se intenta implementar de manera rápida algún proyecto de programacion, la finalidad del polling es crear una actividad sincrónica, es decir sincronizar algún tipo de proceso en base a la lectura de algun detonante. No obstante el polling podría ser visto con una pobre implementación en la búsqueda de sincronismo ya que constantemente se hacen consultas esperando hasta el momento en que consulta sea afirmativa, dichas consultas constantes degradan el rendimiento del equipo y el tiempo de ejecución de un programa se ve muy afectado. Si no a quedado muy claro que es el polling el siguiente pseudo código debe aclararlo.

  ciclo infinito{
 si (Conversion_ADC_Lista==Verdad)
 { //codigo aqui }
 }

 Si bien el polling es la mejor opción para la lecturas y sincronización de ciertos procesos como pueden ser la lectura de un acelerómetro. La mayoría de los procesos pueden ser sincronizados mas eficientemente de otros modos, como por ejemplo, pidiéndole al sistema operativo que informe cuando se desencadenado un evento que haga referencia al proceso, en java se les llama oyentes, en C# se les llama eventos, cuando trabajamos con microcontroladores son llamados interrupciones.

 El uso de interrupciones aparte de permitir llevar un control mas claro sobre donde y cuando se ejecutan cierto tipo de acciones relacionados con algún proceso, mejora dramáticamente el rendimiento del sistema ya que este no se preocupa por estar a la espera leyendo constantemente el estado de los procesos, si no que el controlador de interrupciones le avisa cuando un proceso debe ser ejecutado, el sistema deja lo que esta haciendo, hace caso a la petición, y posteriormente regresa al punto donde se había quedado y continua.

  ¿Entonces las interrupciones son la ultima maravilla o hay algo mas?

 Trabajar con interrupciones tiene sus limitantes, en primer lugar se tienen que ajustar prioridades en dado caso que varias interrupciones realicen una petición al mismo tiempo lo que puede ser algo problemático. En segundo lugar, el numero de interrupciones permitidas son limitadas, si bien en cada microcontrolador es diferente, es común que incluso en los mas poderosos, el numero de interrupciones permitidas no excedan las 32. Por ultimo y el aspecto mas critico de trabajar con interrupciones es saturar al sistema con ellas, imaginen que se habilitan todas las interrupciones de un microcontrolador y que varios de estos procesos son repetitivos o continuos, como el caso de un ADC, o la interrupción de fin de periodo de una señal PWM, etc. el sistema se vera saturado con dichas peticiones y esto perjudicara el rendimiento, ya que el código de programa principal no puede ser ejecutado a un ritmo constante. Para dicho problema existe algo llamado DMA(Direct Memory Acces) o Acceso directo a memoria.

 El DMA permite a cierto tipo de componentes de un computador acceder a la memoria del sistema para leer o escribir independientemente de la unidad central de procesamiento, esto permite a procesos de diferentes velocidades comunicarse sin someter a la unidad central a una carga masiva de interrupciones. El concepto es algo complicado, pero bastante útil y practico, la transferencia DMA consiste principalmente en copiar un bloque de memoria de un lado a otro. En lugar de que la unidad central inicie la transferencia, la transferencia se lleva a cabo por el controlador DMA.



En el caso que nos ocupa ahora, y por poner un ejemplo, se crea un controlador DMA para hacerse cargo de mover los valores obtenidos de la conversión de un ADC directamente a la RAM del microcontrolador, esto se hace sin interrumpir a la unidad central por lo que esta sigue ejecutando su código principal, en cualquier momento que se requiera la información, esta puede ser tomada de la RAM y así se han reducido dramáticamente los recursos requeridos y se aumenta la velocidad del sistema, de igual manera permite la agilización de operaciones, por ejemplo, se desea calcular un promedio de los últimos 10 valore obtenidos de un ADC, si se usaran interrupciones los datos tendrían que ser almacenados en variables y una vez que se tengan 10, calcular el promedio, si se define en la RAM un bloque de diez espacios en memoria para la transferencia del controlador DMA, solo basta con tomar los 10 valores de la RAM, y en ese mismo momento promediarse ahorrando valioso tiempo de ejecución.


 Estos son solo algunos consejos útiles para la optimización del uso de los ADC y de varios procesos en general, si conocen alguno no mencionado, son bienvenidos a comentarlo, si tienen algún comentario o critica igual es bien recibida.