martes, 28 de junio de 2011

Programador AVR dragon

Cuando se hace uso de microcontroladores para el desarrollo de aplicaciones, es necesario tener ciertas herramientas. Una herramienta esencial para desarrollar firmware para aplicaciones embebidas es el programador. Éste es fundamental, pues permite descargar el archivo compilado a la memoria de programa del dispositivo, e incluso permite programar la memoria de datos no volátil EEPROM. Sin un programador sería imposible desarrollar aplicaciones embebidas.

Los dispositivos AVR pueden ser programados de múltiples formas; sin embargo la más común y sencilla es a través de ISP. En cuanto a programadores, es posible fabricar un programador sencillo usando únicamente el puerto paralelo, el correspondiente cable y unas cuantas resistencias; sin embargo, como hoy en día ya casi ningún computador tiene puerto paralelo, esta opción no sería muy viable. Por otra parte, también es posible encontrar en línea diseños de programadores que hacen uso del puerto serial, pero lastimosamente también es obsoleto y se tendría que usar un cable convertidor o buscar otro tipo de solución.

Los programadores que se mencionaron anteriormente son de fabricación manual, y pueden fallar de vez en cuando en el momento de programar, por lo cual, siempre se debe efectuar verificación sobre la memoria programada.

Otra opción que es muy práctica, es el uso de bootloaders, que aprovechan una sección de la memoria de programa para guardar una rutina especial que permite auto-programar el dispositivo, el cual recibe los datos a través de un puerto serial o incluso USB. Este es el caso de los microcontroladores USB de Atmel, los cuales vienen por defecto con un bootloader que les permite ser programados a través del puerto USB, haciendo uso de un sencillo programa de Atmel (FLIP), que puede descargar y usar de forma gratuita. Sin embargo, este programa no funciona en el momento que se modifique el inicio del microcontrolador para que funcione como dispositivo USB y se realicen aplicaciones usando esta interfaz. Para este caso sí es necesario usar un programador.

Existen muchos programadores comerciales, sin embargo, una muy buena opción es el AVR DRAGON. Este programador es muy completo, y permite programación tanto a bajo voltaje como a alto voltaje, y además incluye una función de depuración sobre hardware, permitiendo incluir breakpoints en hardware.



¿Cómo usar esta herramienta?

Si es usuario de Windows, se recomienda usar el Dragon junto con el IDE AvrStudio de Atmel, el cual incluye una interfaz gráfica muy sencilla y una gran cantidad de herramientas para programar y depurar dispositivos. Permite modificar de forma amigable los fusibles del microcontrolador y escribir tanto en la memoria flash como en la EEPROM. Soporta todos los modos de programación del Dragon, y también permite actualizar el firware, y modificar parámetros como la frecuencia de oscilación del programador.

Lastimosamente la herramienta AvrStudio no está disponible para Linux, y si se tiene este sistema operativo se debe hacer uso de otra aplicación. La aplicación en Linux más usada para controlar el Dragon es el AvrDude, el cual se puede bajar e instalar fácilmente desde Internet; incluso está disponible en los repositorios de Ubuntu. En este caso, es necesario hacer la programación desde una ventana de comandos, donde se indica el dispositivo a programar, el modo de programación, la memoria a programar, etc. A continuación se muestra un ejemplo de comando de programación de dispositivo:

sudo avrdude -p atmega32u4 -c dragon_isp -P usb -U flash:w:programa.hex 

Para el anterior ejemplo "-p" indica el microcontrolador objetivo, "-c" el programador y el modo de programación, "-P" es el puerto al cual se encuentra conectado el programador y el comando "flash:w:programa.hex" indica que se escribirá la memoria flash con el programa almacenado en el archivo "programa.hex".

Por otra parte, el AvrDude incluye un modo consola, útil para depuración o para verificar sectores específicos de cualquiera de las memorias del microcontrolador. A continuación se muestra la forma para ingresar al modo terminal de AvrDude:


sudo avrdude -p atmega32u4 -c dragon_isp -P usb -t

Para este caso, se tienen en cuenta los mismos parámetros especificados anteriormente, excepto que se da la opción "-t" que indica entrada a modo consola.

Para información adicional acerca del AvrDragon, AvrStrudio o AvrDude, es posible encontrar muy buena documentación en línea en la página de Atmel, y en la página de documentación oficial de AvrDude.

Como recomendación final: el Dragon es una herramienta muy poderosa, pero también es extremadamente delicado, pues no incluye una caja de protección, sino que el circuito se encuentra completamente expuesto. No se debe tocar directamente, para evitar daños por descarga electrostática, tampoco se debe tocar cuando esté en funcionamiento porque se pueden ocasionar daños en los circuitos. Se debe tener mucho cuidado también para evitar cortocircuitos en los pines de programación, voltaje de alimentación adecuado, y conectar correctamente los correspondientes pines, por lo cual se deben revisar las conexiones dos veces antes de energizar y programar.

Link recomendado: http://www.administracionsatelital.com/

lunes, 13 de junio de 2011

Convertidor análogo-digital

Casi todas las variables que se pueden medir en la naturaleza varían de forma continua: sonido, luminosidad, humedad, temperatura, etc. Así, las señales que miden una variable física, constan de una serie de valores que cambian constantemente a lo largo de su variable independiente (generalmente tiempo o espacio). Por otra parte, los sistemas de control y de procesamiento son dispositivos completamente digitales, es decir, solamente aceptan determinados valores dentro de un rango específico. De esta forma, se deben controlar sistemas de naturaleza análoga, con dispositivos digitales.


Para convertir una variable física en una señal digital que pueda ser procesada por un microcontrolador, se deben llevar a cabo los siguientes pasos:


  1. Medición: Este procedimiento es realizado por un sensor, el cual incluye un transductor, mediante el cual es posible transformar las variables físicas en variables eléctricas (voltaje y corriente).
  2. Muestreo: Durante el muestreo se digitaliza la variable independiente, la cual generalmente es el tiempo. Para este caso, el muestreo consta en tomar valores de la señal original solamente en determinados instantes de tiempo. Los valores de la señal que se toman, aún conservan su naturaleza analógica.
  3. Cuantización: En el proceso de cuantización se asignan valores discretos a la señal muestreada. La asignación de estos valores depende directamente de la resolución.
  4. Codificación: Es el proceso final, en el cual a cada valor discreto de la señal se le asigna un código determinado, el cual, para el caso de los microcontoladores, es un número binario.

Un ADC lleva a cabo los pasos 3 y 4, cuantizando un determinado valor de voltaje (entre GND Y VCC), y posteriormente codificándolo en un número binario, cuyo rango depende de la resolución del ADC (para el caso de un ADC de 10 bits, entre 0 y 1023).

El módulo ADC de un microcontrolador es uno de sus módulos más importantes, hasta tal punto que la mayor parte de microcontroladores que se encuentran en el mercado hoy en día incluyen un módulo ADC, el cual permite adquirir señales analógicas, procesarlas y posteriormente enviar señales de control.

Existen varias técnicas para la conversión de señales análogas a digitales, entre las más importantes se encuentran: conversión por aproximaciones sucesivas, por integración, por contador y en paralelo. Cada una de estas técnicas tiene sus ventajas y sus desventajas. A continuación se explicará el método de aproximaciones sucesivas, ya que es el método que usa el módulo ADC de los microcontroladores AVR.

Conversión por aproximaciones sucesivas

El convertidor por aproximaciones sucesivas usa un convertidor digital/análogo, un circuito de lógica de control y un comparador. El proceso comienza desde el bit más significativo hasta el menos significativo. Así, la lógica de control activa cada bit y genera una señal análoga con el convertido digital/análogo, esta señal se compara con la señal de entrada y de acuerdo al resultado de la comparación el controlador cambia o deja el bit que se está examinando. Luego se continúa con el siguiente bit menos significativo hasta que se hace el recorrido por todos los bits. En la figura siguiente se muestra el proceso de conversión de un valor análogo (dado por la línea roja) usando un convertidor de 4 bits.



La principal ventaja de esta técnica es que el tiempo de conversión es siempre el mismo para cualquier entrada, pero su desventaja es la necesidad de usar un hardware complejo para su implementación.

Link recomendado: http://www.administracionsatelital.com/

martes, 7 de junio de 2011

Uso del comparador analógico en ATMEGA16

En esta entrada de Blog, mostraré un ejemplo ilustrativo del uso del comparador analógico de un microcontrolador AVR. La implementación se realiza en un microcontrolador ATMEGA16. En dicho ejemplo se usará el comparador para estimar la frecuencia de una señal sinusoidal.

Funcionamiento de comparador

El comparador análogo compara los valores de entrada en el pin positivo AIN0, y en el pin negativo AIN1. Cuando el voltaje en el pin positivo es mayor que el voltaje en el pin negativo, se activa la bandera del comparador análogo. Adicionalmente, se puede usar la salida de comparador análogo para activar la captura de eventos de la unidad Timer1 y también para activar interrupciones por flanco de subida, bajada o conmutación de la salida del comparador.

Por otra parte, es posible seleccionar cualquiera de los pines de las entradas analógicas (ADC7:0) para reemplazar la entrada negativa del comparador análogo. Así, se puede multiplexar la comparación de varias señales, conectadas a diferentes pines del microcontrolador. Para este caso, se hace uso del multiplexor del convertidor análogo/digital, y por tal motivo, éste se debe apagar mientras se realiza la multiplexación del comparador. Si el bit de habilitación de multiplexación del comparador análogo se encuentra activado (ACME=`1'), y el ADC se encuentra deshabilitado (ADEN=`0'), entonces los bits MUX2:0 en el registro ADMUX controlarán el pin de entrada que reemplazará la entrada negativa del comparador.

Ejemplo

Diseñar un programa que permita medir la frecuencia de una señal sinusoidal entre 0 y 5V, haciendo uso del comparador análogo y el módulo de captura del Timer1. La visualización del resultado debe realizarse en un arreglo de 4 displays de 7 segmentos.

Código solución

  1 // Dispositivo = ATMEGA16
  2 // Fclk = 1.0MHz
  3 // Incluir librería matemática libm.a en el proyecto
  4 
  5 #include<avr/io.h>            // Puertos y registros i/o
  6 #include<util/delay.h>        // Tiempos y retrasos
  7 #include<avr/interrupt.h>    // Interrupciones
  8 #include <util/atomic.h>    // Ejecución atómica de bloques
  9 
 10 // Prototipo de funciones
 11 void visualizar(int);    // Función para visualizar un dato en 4
 12                         // displays de 7 segmentos
 13 
 14 // Declaración de variables globales
 15 volatile unsigned int tiempo1=0, tiempo2=0, diff=0;
 16 
 17 int main(void)
 18 {
 19     // Variable flotante para calcular frecuencia
 20     volatile float freq;
 21 
 22     // Variable entera de contador
 23     int i;
 24 
 25     // Asignación de dirección de puertos
 26     DDRA=0xFF;        // Puerto A salida
 27     DDRC=0xFF;        // Puerto C salida
 28     DDRD=0x0F;        // Mitad de puerto D como salida
 29 
 30     // Configuración del comparador análogo
 31     // * El comparador activa el módulo de captura del Timer1
 32     ACSR|=(1<<ACIC);
 33 
 34     // Configuración de Timer1
 35     // * Modo normal
 36     // * Filtro cancelador de ruido en captura
 37     // * Captura por flanco de subida
 38     // * Reloj sin preescalador
 39     TCCR1B|=(1<<ICNC1)|(1<<ICES1)|(1<<CS10);
 40     TIMSK|=(1<<TICIE1);    // Habilitación interrupción de captura
 41 
 42     sei();    // Habilitación de interrupciones globales
 43 
 44     // Ciclo de polling
 45     while(1){
 46 
 47         // Mediante este macro es posible ejecutar un
 48         // bloque de forma atómica, es decir, sin que la
 49         // interrupción interrupa la ejecución de este bloque
 50         ATOMIC_BLOCK(ATOMIC_FORCEON)
 51         {
 52         // Se convierte la diferencia del registro de
 53         // comparación en frecuencia
 54         freq=1E6/((float)diff);
 55         }
 56 
 57         for(i=1;i<50;i++)
 58         // Visualización del valor de frecuencia
 59         visualizar(freq);
 60 
 61     }
 62 }
 63 
 64 // Función para visualizar un número entero de 4 dígitos
 65 // como máximo en un arreglo de 4 displays de 7 segmentos
 66 // de ánodo común, en los cuales los pines de los segmentos
 67 // se conectan al puerto C, y los ánodos se conectan al 
 68 // nibble menos significativo del puerto D
 69 void visualizar(int num)
 70 {
 71     // Vector que contiene el mapeo de cada dígito para
 72     // el display de 7 segmentos
 73     const int mapa7Seg[10]={
 74     0b11000000,    // 0
 75     0b11111001,    // 1
 76     0b10100100,    // 2
 77     0b10110000,    // 3
 78     0b10011001,    // 4
 79     0b10010010,    // 5
 80     0b10000010,    // 6
 81     0b11111000,    // 7
 82     0b10000000,    // 8
 83     0b10010000};// 9    
 84 
 85     // Variable para hacer el recorrido por cada display
 86     volatile char i;
 87 
 88     // Ciclo de graficación en cada display
 89     for(i=0;i<=3;i++)
 90     {
 91         // Se apagan los segmentos antes de cambiar de display
 92         PORTC=0xFF;
 93 
 94         // Cambio de display
 95         PORTD=8>>i;
 96 
 97         // Visualización de dígito
 98         PORTC=mapa7Seg[num%10];
 99 
100         // Tiempo de espera para visualización
101         _delay_ms(1);
102 
103         // División entre 10 y ruptura de ciclo de 
104         // graficación para no mostrar ceros a la izquierda
105         if((num/=10)==0)
106             break;    
107     }
108 
109 }
110 
111 // Rutina de servicio de interrupción por evento de captura
112 // de la unidad Timer1
113 ISR(TIMER1_CAPT_vect)
114 {
115     // Enciende bit 0 del puerto A para verificar
116     // que las interrupciones se ejecuten adecuadamente
117     PORTA=1;
118 
119     // Actualización de marcas de tiempo de eventos
120     tiempo1=tiempo2;
121     tiempo2=ICR1;
122 
123     if(tiempo2 > tiempo1)
124         // Diferencia entre eventos para hallar período
125         diff=tiempo2-tiempo1;
126     else
127         // Si la diferencia es negativa, significa que el
128         // contador tuvo overflow, por tanto se debe añadir 0x10000
129         diff=0x10000+tiempo2-tiempo1;
130 
131     // Apagado del bit 0 del puerto A
132     PORTA=0;
133 }

Diagrama esquemático de la solución


Explicación de la solución

El programa para solucionar este ejemplo hace uso del módulo de captura del Timer1 el cual se conecta a la salida del comparador, detectando de esta forma cada vez que se presente un evento de comparación de voltajes. Para medir la frecuencia de una señal sinusoidal, se compara la señal de entrada con respecto a una referencia de 2.5 V; cada vez que la onda sinusoidal cruza esta referencia, se tendrá medio período de la señal, a partir del cual se puede calcular su frecuencia. En la rutina de servicio de interrupción se agregan un par de líneas que activan y desactivan el pin 0 del puerto A, para verificar que se estén capturando correctamente los eventos.