27 enero, 2016
Esta nota fue publicada originalmente en la edición 143 de revista POWER. Podes suscribirte a la versión impresa y/o digital aquí.
Por Sebastián Caccavallo (electgpl@gmail.com)
Actualmente en diversos dispositivos electrónicos podremos encontrar displays del tipo 7 segmentos de LED como indicadores. Por ejemplo en termómetros digitales, microondas, relojes despertadores, instrumentos de medición, etc. Existen varias maneras de gobernar estos displays pero en esta nota realizaremos una de las más eficientes y utilizadas.
Introducción
La técnica de multiplexado de displays se basa en turnos. En nuestro caso realizaremos un contador de 0 a 99 que se incrementa al presionar un pulsador, pero como sabemos un display de 7 segmentos es un componente de la familia opto electrónica, donde cada segmento maneja dos estados (1 o 0), y donde la combinación de encendido y apagado de los segmentos nos dará como resultado un número.
La forma más sencilla de crear un número en un display es alimentando los segmentos necesarios para crear el número. Hasta aquí es sencillo, enciendo los LEDs que deseo y se forma el número. Pero, ¿qué sucede si queremos realizar un número de 2 o más dígitos? Recordemos que cada digito requiere de 7 segmentos, por ende, serán 7 terminales, uno por cada LED. Si queremos dos dígitos serán 14 terminales, si queremos cuatro dígitos serán 28 terminales, etc. Podríamos manejar cada segmento de cada digito de forma individual, pero necesitaríamos de muchas conexiones y esto requiere de más circuitos y de placas más grandes, por lo que la técnica de multiplexado nos será de gran utilidad.
Imaginemos dos displays separados de 7 segmentos, donde tenemos 1 terminal común y 7 terminales, ahora interconectemos los 7 terminales de cada segmento del primer display con los 7 terminales del segundo display, lo que nos dará como resultado 9 terminales, 7 de los segmentos y 2 más ya que cada display tiene su terminal común.
Aquí viene el multiplexado. Teniendo en cuenta que los 7 segmentos de cada display están unidos, si nosotros alimentamos los segmentos que forman, por ejemplo, el número 4 y alimentamos los dos comunes (uno de cada display) deberíamos ver el número 44, ya que los 7 segmentos están unidos en ambos displays y alimentamos los dos comunes. Si en lugar de alimentar los dos comunes alimentamos solo el del dígito de las unidades, y el de las decenas lo dejamos sin alimentación, entonces veremos solo el número 4 en el display de las unidades y el de las decenas permanecerá apagado. Si repetimos este proceso, pero esta vez invertimos los comunes de los displays, alimentando las decenas y dejando sin alimentación a las unidades, entonces veremos el 4 en las decenas y las unidades se mantendrán apagadas.
Ahora, si queremos que el número sea por ejemplo 46, deberíamos prender el dígito de las decenas y alimentar los segmentos que forman el número 4. Luego apagamos el display de las decenas y encendemos el de las unidades, y ahora alimentamos los segmentos que forman el número 6. Si realizamos esta tarea indeterminadamente y lo suficientemente rápido como para que no notemos esta conmutación entre displays, entonces, para la persistencia de la visión leeremos el número 46.
El circuito de prueba
Al analizar el diagrama electrónico, podremos ver el microcontrolador PIC16F628A junto a una resistencia que sale del pin MCLR (Master Clear) hacia el positivo del circuito (VDD).
Conectaremos a cada segmento del display doble una resistencia limitadora de 470 ohms. Para el pulsador que activa a 1 lógico, debemos utilizar un pullDown entre 47k y 10k. En la práctica se le ha incorporado un capacitor electrolítico de 10uF/16V en paralelo al pulsador para que el mismo absorba el ruido eléctrico producto del contacto. El circuito completo se alimenta con 5V.
El Programa
Para realizar el multiplexado de los displays aplicaremos la técnica mencionada anteriormente conmutando los displays, y enviando el dato (número) necesario al display que se encuentre encendido en ese momento. También utilizaremos un pulsador externo para incrementar el valor numérico a mostrar en los dos displays.
Para la realización de este programa incluiremos el concepto de vectores, lectura de entradas e instrucción condicional if. Para comprender qué es un vector, debemos recordar qué es una variable.
Una variable es una dirección de memoria donde alojaremos un valor que se puede modificar en cualquier momento en el programa. Es decir, podríamos decir que la variable “var=0” contiene el valor 0, pero más adelante, en el mismo programa, podríamos modificar ese valor por “var=29” donde en esa misma variable ahora tendrá el número 29.
Ahora, si quisiéramos alojar más de un valor en una variable, nos será muy útil el vector. Ya que podríamos crear un vector “vec[5]={10, 20, 30, 40, 50};”, entonces aquí vemos que el vector vec[] posee 5 valores, por ello dentro de los corchetes hay un número 5 y dentro de sus llaves están los 5 valores. La forma de acceder a estos valores será modificando el índice del vector (el número que se encuentra dentro de los corchetes). Por ejemplo, si preguntamos qué hay en vec[0], nos mostrará el número 10; si preguntamos qué hay en vec[3] nos mostrará el número 40. Nótese que cuando definimos el vector pusimos 5 porque habían 5 valores, pero cuando buscamos el valor se deben utilizar del 0 al 4 que en definitiva son 5 posiciones.
Dentro del vector que realizamos en el programa pondremos las 10 combinaciones de los 7 segmentos del display, las combinaciones formarán los 10 números, del 0 al 9, a mostrar en cada display.
La instrucción “if()” será una instrucción condicional la cual realizará lo que posea inmediatamente luego de la condición si es que esta se cumpliera. Por ejemplo la función “if(var<10) output_high(LED);” pregunta si la variable “var” es menor que el número 10, entonces prende un LED. Si “var” es mayor o igual entonces no realizará ninguna acción porque no se cumple la condición.
La sentencia if como mencionamos recién realiza una acción si la condición que tiene entre paréntesis es verdadera. Si la condición es falsa existe la instrucción “else”, donde seguida de la misma se realizará otra acción.
Por ejemplo, “if(var<10) output_high(LED); else output_low(LED)”, entonces aquí, si var es menor que 10 el LED se encenderá pero si es mayor o igual el LED se apagará.
Nótese que siempre usamos una única acción, tanto después del if como después del else. Si quisiéramos realizar más de una acción deberíamos encerrar éstas dentro de llaves.
Para leer una entrada solo basta con utilizar la instrucción input(PIN_XX) dentro de un if, donde “XX” será el pin del microcontrolador a leer, por ejemplo: A2. El ejemplo quedará: if(input(PIN_A2)==1), esto quiere decir que si este pin A2 se encuentra a 1 lógico (5V), el if será verdadero y realizará la acción que tenga seguida del mismo. Si en lugar de poner un 1 pondríamos un 0 sería lo mismo, solo que la condición sería verdadera cuando ese pin A2 se encuentre a 0 lógico o GND.
Analicemos en detalle las líneas de código:
* Línea 03, 04, 05: definición del tipo byte (8 bit) del vector del tipo constante “CONS” que posee 10 posiciones, del 0 al 9, asignadas en formato hexadecimal: 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F. Cada uno de estos valores representa qué segmento poner a 1 y 0 del display para formar el número.
* Línea 07, 08, 09: definimos las variables cuenta (donde se aloja el valor que se incrementa cuando presionamos el pulsador), uni (donde se aloja el valor número, del 0 al 9, que mostraremos en el display de las unidades) y por último dec (donde se aloja el número, del 0 al 9, que mostraremos en el display de las decenas).
* Línea 11: mediante la instrucción output_a(0bxxxxxxxx) pondremos a 1 la salida RA0 y a 0 la salida RA1.
* Linea 12,15: mediante la instrucción output_b(DISPLAY[x]) enviaremos al puerto B del microcontrolador el valor que se encuentre en la posición del vector que llamemos con el valor del índice x. Por ejemplo si x es 4 quedaría: output_b(DISPLAY[4]), que traería el valor 0x66, el cual en binario es 01100110 y lo reemplazaría quedando output_b(0b01100110).
* Línea 13,16: aquí llamamos a la función delay, donde se le moverá el valor 15 en milisegundos. De esta forma cada conmutación entre los dígitos se realizará cada 15 ms, generando así un barrido lo suficientemente rápido como para no percibirlo con el ojo humano.
* Línea 14: mediante la instrucción output_a(0bxxxxxxxx) pondremos a 1 la salida RA0 y a 0 la salida RA1.
* Línea 17: en esta línea utilizaremos la función if para preguntar si el pulsador se encuentra presionado, mediante la lógica if(input(PIN_A2)==1) será verdadera cuando en la entrada RA2 exista un 1 lógico o 5V.
* Línea 18: el delay de 20 ms se utiliza para garantizar que el pulsador no se presiona de forma errática, es decir para evitar los repiques.
* Línea 19: aquí se vuelve a preguntar por el estado de la entrada RA2, pero luego del delay de 20 ms. Esta técnica de preguntar dos veces por el mismo pulsador pero con una diferencia de 20 ms, nos da la garantía de que realmente lo estamos pulsando nosotros y no es producto de ruido eléctrico.
* Línea 20: aquí preguntamos si cuenta es menor a 100, entonces podremos seguir incrementando la variable en una unidad cada vez que presionamos el pulsador.
* Línea 21: se incrementa la variable cuenta en una unidad.
* Línea 22: caso contrario de que no se cumpla la condición de que cuenta es menor que 100, por ende será igual o mayor a 100, entonces reiniciamos la variable.
* Línea 23: se inicializa la variable cuenta con cero.
* Línea 26: se divide la variable cuenta en 10 y se aloja el resultado en la variable de los decimales, que luego utilizaremos de índice en el vector cuando estemos enviando la decena al puerto B. Por ejemplo, si cuenta tiene el valor 46, entonces al dividirlo por 10, quedará 4 que se mostrará en el display de las decenas.
* Línea 27: en este caso, mediante el operador “%” se realiza la misma división que antes pero en lugar de tomar el resultado de la división se toma el resto, donde 46 dividido en 10 será 4 de resultado y 6 de resto. Entonces movemos el resto a la variable uni que luego será utilizada como índice del vector cuando estemos enviando la unidad por el puerto B.
Conclusión
En este programa pudimos analizar la técnica de multiplexado de displays, la cual nos simplifica sustancialmente el diseño del esquemático y circuito impreso. Al utilizar displays múltiples interconectados reducimos la cantidad de salidas necesarias del microcontrolador a una mínima cantidad, dejándonos la posibilidad de manejar hasta 8 dígitos multiplexados con un solo microcontrolador de 18 pines.
Display cuádruple
Otro derivado de los displays de 7 segmentos de LED son los displays, dobles, triples, cuádruples, etc. En el siguiente diagrama, podremos ver el interior de un display cuádruple de 7 segmentos. Esta interconexión interna nos resume los pines a los 7 segmentos más el punto, y el común de cada digito (que puede ser ánodo o cátodo). Esta es la manera más sencilla de utilizar el multiplexado de displays.
Display LCD
Además de los display de 7 segmentos convencionales, podemos encontrar los display LCD, los cuales se interconectan de la misma forma que los LED pero estos poseen un consumo significativamente menor, proporcionando una solución muy útil cuando debemos realizar un dispositivo de bajo consumo, junto a un microcontrolador de bajo consumo (denominados nanoWatt).