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.

9 comentarios:

  1. Hola que tal,Concuerdo con gonzalo con el uso del DMA, aqui les dejo un poco mas de informacion mas detallada: http://www.osdever.net/tutorials/pdf/howto_dma.pdf
    En la facultad estuvimos platicando con Gonzalo y con el maestro Romero a cerca de que es y como se puede utilizar un DMA"Direct Memory Access" básicamente este es un chip que evita que el procesador central del micro controlador haga tareas repetitivas de lectura o escritura de datos básicamente este puede substituir a un microcontrolador pequeño destinado a hacer estas tareas.

    por lo tanto con el DMA podemos evitar el uso ciclos infinitos que utilizan ciclos de reloj de mocrocontrolador o evitar algunas interrupciones y así el procesador puede estar haciendo otras operaciones al mismo tiempo que el DMA esta trabajando por lo que se puede llegar a ejecutar operaciones en paralelo.

    Uno ejemplo para entender mejor el uso de los DMA puede ser que por ejemplo si queremos sacar un promedio de los valores leídos por un ADC normalmente tendríamos que almacenar estos valores en una variable en el sistema e irles sumando continuamente y dividiendo entre el numero de datos que yo hay guardado, todas estas operaciones de lectura del ADC, guardado de los datos, suma de los datos y división de los datos implican muchos ciclos de reloj por lo que en ocaciones esto seria muy poco eficiente.
    por lo que para poder evitar esto seria mas facil utilizar un DMA que se dedique a almacenar los datos en unos registros automáticamente sin que el procesador se entere de que se esta esta haciendo esta operación, por ejemplo yo puedo separar 4 registros para almacenar los datos del ADC con el DMA este lo que va a hacer es ir escribiendo en cada registro los valores del adc e ir los actualizando, sobrescribiendo la ultima lectura del ADC en el ultimo byte utilizado y asi de esta manera cuando en mi proceso pincipal necesite este promedio unicamente mi procesador ejecutaría una instrucción de leer los 4 datos y dividirlos entre 4 y ya tendría el promedio.

    asi como esta hay muchas otras aplicaciones como por ejemplo: utilizar un DAC"Digital to Analog converter" para generar una onda sinusoidal sin que el procesador ejecute esta accion unicamente con el DMA accediendo a la tabla de los valores de la onda y escribiéndolo en el DAC.
    LES DEJO UN LINK EN EL CUAL PUEDEN VER EL VIDEO DE EXPLICACIÓN DE ESTE ULTIMO EJEMPLO:
    http://www.cypress.com/?rID=39390

    Reporto para ustedes : Carlos Del Castillo XD

    ResponderEliminar
  2. Excelente explicación sobre el uso de un ADC y la manera de optimizar la memoria. Para una aplicación que demandará mucha memoria el multiplexar las señales es una práctica bastante usual.
    Gracias a Gonzalo por la explicación y a Carlos por el link, la información es muy interesante.

    ResponderEliminar
  3. Muy buen aporte! Yo opté por utilizar el ADC SAR, mas sin embargo este está mucho más poderoso en cuanto al multiplexado de las señales de entrada y la resolución que tiene. De igual manera buenos datos con lo de las interrupciones.

    ResponderEliminar
  4. Muy buen aporte en lo personal no conocía el DMA, pero es una opción para a tomar en cuenta a la hora de realizar algún nuevo proyecto, por otra parte, lo de multiplexar los ADC es conveniente para ahorar recursos y no perder velocidad y por ultimo lo de las interrupciones siempre se debe de tener en mente a la hora de que realizas la lógica de tu programa para así saber cuales quieres que tengan mas prioridad y no te ocasione un mal funcionamiento a la hora de ejecución.

    ResponderEliminar
  5. Excelente aporte , siento que solo falto hablar sobre la frecuencia de muestreo optima

    ResponderEliminar
    Respuestas
    1. Ya que no conocía el DMA,me imagino que el módulo sube algunos centavos de dolar el precio, pero vale la pena tener estas características en los microcontroladores

      Eliminar
  6. Que buen dato Gonzalo, a veces pasamos por alto las capacidades físicas de nuestro microcontrolador y pensamos que nuestro programa correrá de la misma forma que lo haría en una pc. Es una buena forma de ahorrar recursos y optimizar la lectura de múltiples sensores. Con respecto a los DMA sólo me queda decir que son una muy buena opción, yo no la conocía, pero es bueno saber que existen para futuras proyectos, así como pasó con el amplificador aislador.

    ResponderEliminar
  7. Efectivamente concuerdo con Gonzalo, muchas veces no tomamos en cuenta las capacidades del microcontrolador, como nos comentaba el profesor Renán es muy importante saber elegir que resolución del ADC es el más optimo para la aplicación que se quiere implementar, igual hay que tomar en el tipo de referencia a tierra que se va a tomar:
    Rangos de entrada y referencias.
    El rango del ADC esta dado por ±VREF. Este parámetro se da en la ventana de recursos globales junto con la referencia para la tierra analógica. Podemos elegir 8 diferentes configuraciones para estos parámetros. El resultado de las conversiones depende de ellos. AGND es la referencia de cero volts para la parte analógica, si no tomamos esto en cuenta podríamos interpretar erróneamente los datos leídos. Por ejemplo un voltaje de 2.4 volts en las entradas (tomando como referencia la tierra digital Vss) cuando se tiene como tierra analógica un voltaje de 2.5 volts, equivale a tener una entrada de -0.1 volts con respecto a la tierra analógica, por lo que la salida del ADC será un numero negativo (En complemento a 2)

    Valor de REF MUX Voltaje de Entrada AGND

    (Vdd/2)+/-BandGap 1.2 – 3.8 V 2.5 (Vdd/2)
    (Vdd/2)+/-(Vdd/2) 0 – 5.0 (Vss-Vdd) 2.5 (Vdd/2)
    BandGap+/-BandGap 0 – 2.6 V 1.3 V
    (1.6 BandGap)+/-(1.6 BandGap) 0 – 4.16 V 2.08 V
    (2 BandGap)+/-BandGap 1.3 – 3.9 V 2.6 V
    (2 BandGap)+/-P2[6] (2.6-VP2.6) – (2.6+VP2.6) 2.6 V
    P2[4]+/-BandGap (P2.4-1.3)-( P2.4+1.3) P2.4V
    P2[4]+/-P2[6] (P2.4- P2.6)-( P2.4+ P2.6) P2.4 V


    Nota: Este es el caso para el PSOC, mas sin embargo son configuraciones similares para todos los microcontroladores, solo es cuestión de checar las hojas de datos de ellos.

    ResponderEliminar
  8. Frecuencia de muestreo óptima: vamos a suponer que tienes una señal que lleva cierta frecuencia, como por ejemplo audio o trenes de pulsos o algo así. En este caso deberás pensar en la frecuencia más alta que debe dar tu sensor y debes realizar las tomas de muestras (sample) con una frecuencia de al menos el doble de esta. Esto se conoce como el teorema de Nyquist, ahora que si la señal no presentará variaciones en el tiempo muy significativas pues creo que debes tomar muestras razonables.

    ResponderEliminar