Quien no dispone en su cajón desastre, de un conjunto de display a LED con dos, tres o cuatro dígitos. Este es el momento de reutilizar dicho display (multiplexado) en un contador cuya aplicación puede mejorar una presentación que tenía pendiente. En este artículo, veremos como aplicar código a un display multiplexado y como debe funcionar.
Actualmente es fácil encontrar en Internet códigos sobre pantallas LCD y cómo adaptarlas a distintas aplicaciones. En cambio, son muy pocos los sitios donde se describe cómo utilizar un display de siete segmentos y no digamos, cuando se trata de conjuntos de displays de 2, 3 o 4 dígitos multiplexados. Sin embargo, este dispositivo es bastante común en un gran número de
electrodomésticos que podemos desguazar y reutilizar su display. Aquí, con este artículo, voy a rellenar esta laguna.
Este artículo, no se puede considerar como una extensión a uno anterior que puede verse aquí. En aquella ocasión se contemplaba el caso de aplicar el contador de dos dígitos, como contador en una aplicación del propio Arduino que, como ejercicio es esclarecedor y consigue ayudar el interesado en realizar un contador de esas características. En esta ocasión, si bien, puede utilizarse con unos pequeños ajustes, del mismo modo, la diferencia radica en que se visualizará la cuenta obtenida reflejada en un pantalla o display de dos, tres o cuatro dígitos de siete segmentos a LED, mediante la multiplexación de los dígitos utilizados. Esta es la estructura del display
múltiple.
Estructura
Sin más, vamos a entrar en harina, como diría un panadero. La teoría, se puede ver en el mencionado artículo, así que sólo nos preocuparemos de los tipos de pantalla a utilizar, para este caso usaremos un display
múltiple (multiplexado). El display que vamos a utilizar aquí, tiene la particularidad en su encapsulado, es decir, que en una pieza ( o encapsulado) nos presenta varios dígitos. Tenemos que tener en cuenta que en algunos casos, las patillas que vienen en el encapsulado, parece que no están bien, ya que hay menos de las que se supone debería tener, esto es debido a que se han dispuesto de forma especial, lo que se llama multiplexado.
Los displays.
No voy a describir con detalle cómo se construye un display, más arriba se puede ver su estructura. El display que voy a utilizar en este artículo, es el de un display multiplexado, es decir, que sus segmentos están conectados de tal manera que al exterior sólo aparecen los correspondientes a los siete segmentos, más el común de cada uno de los dígitos que lo componen, en el caso de cuatro dígitos, muestra los siete pines de los siete segmentos, más cuatro correspondientes a cada uno de los cuatro dígitos. Estos son unos ejemplos de encapsulados.
Click para ampliar.
Si usted, no dispone de un encapsulado de este tipo y está interesado en poner en práctica un contador de los descritos aquí y en cambio, si dispone de los display individuales, tranquilo, usted puede auto construir uno fácilmente, con los dígitos que necesite, vea cómo está
construido el de 2 dígitos, de abajo y póngase a su construcción.
Se pueden apreciar con todo detalle, los dos cablecillos blancos que son los
comunes de cada dígito, por otra parte los siete hilos rojos, corresponden a los 7 segmentos, los cuales unen entre sí, los pares de segmentos de cada dígito en paralelo.
El circuito.
El circuito se muestra a continuación. Es muy sencillo y no creo necesario entrar a describir cada componente. Dos apuntes importantes:
Este mismo circuito, con sólo añadir unas resistencias, nos sirve, para el resto de ejemplos que se describen.
Los pines analógicos del Arduino (A0...A6), pueden tomarse como digitales, siguiendo el orden, A0 = A14; A1 = A15; ... A6 = A19.
El programa.
La cuestión importante radica en el propio programa. El programa consta de 3 partes bien diferenciadas:
La definición propia de los segmentos, de como se construyen los dígitos.
La asignación y correspondencia de los pines del display, del Arduino y pulsadores, para su aplicación sin posteriores por ese motivo.
Además de la configuración (Set up). Dentro del lazo (loop) se encuentran las subrutinas pertenecientes a los pulsadores.
1er. Ejemplo.
Esta es una primera versión y su correspondiente código. El display utilizado en este caso es de cátodo común (CC). Como de costumbre, puede seleccionar el código y pegarlo en su editor
dándole un nombre para guardarlo y su posterior ejecución.
// // Doble Didplay siete-segmentos LED con botones // // Basado en un trabajo de Natalia Fargasch Norman // // // Common Catode digit 1 pin 10 // Common Catode digit 2 pin 9 // // Modificado y mejorado 11.08.11 // V. García // // Utiliza 2202 bytes con Arduino v0013
// CA1 G F A B // | | | | | | -> pines y segmentos de control // --------- --------- // | A | | A | // F| |B F| |B // |---G---| |---G---| // E| |C E| |C // | D | | D | // --------- --------- // | | | | | | -> pines y segmentos de control // D DP E C CA2
// Pines digitales usados Arduino para encender // los correspondientes segmentos LED del display #define A 2 #define B 3 #define C 4 #define D 5 #define E 6 #define F 7 #define G 8
// Pulsadores
botón conectados a pines 9 y 10 #define BTN1 14 #define BTN2 15 #define led 13 // Pines comunes de cada display de
ánodo común #define CA1 9 #define CA2 10
// Pines para A B C D E F G, en secuencia // se pueden usar los que más interesen const int segs[7] = { 2, 3, 4, 5, 6, 7, 8 };
// Segmentos que componen cada número const byte numbers[10] = { 0b0111111, 0b0000110, 0b1011011, 0b1001111, 0b1100110, 0b1101101, 0b1111101, 0b0000111, 0b1111111, 0b1101111};
void lightSegments(byte number) { for (int i = 0; i < 7; i++) { int bit = bitRead(number, i); digitalWrite(segs[i], bit); } }
2º ejemplo.
En este segundo ejemplo, voy a utilizar otra forma de ver el programa y además aprovechando que dispongo de un display
múltiple de 4 dígitos, haré un contador de dos dígitos.
El circuito electrónico es similar al del ejemplo anterior, con unos pocos cambios, por lo que no lo mostraré aquí. El código se muestra a continuación.
// // Doble Display siete-segmentos LED con botones // // Basado en un trabajo de Natalia Fargasch Norman // // // Common Catode digit 1 pin 10 // Common Catode digit 2 pin 9 // // Modificado y mejorado 11.08.11 // V. García // // Utiliza 2138 bytes con Arduino v0013
// // CA1 G F A B // | | | | | -> pins and segments they control // --------- --------- // | A | | A | // F| |B F| |B // |---G---| |---G---| // E| |C E| |C // | D | | D | // --------- --------- // | | | | | -> pins and segments they control // D DP E C CA2
// Pines digitales usados Arduino para encender // los correspondientes segmentos LED del display #define A 2 #define B 3 #define C 4 #define D 5 #define E 6 #define F 7 #define G 8
// Pulsadores
botón conectados a pines 9 y 10 #define BTN1 14 #define BTN2 15 #define led 13 // Pines comunes de cada display de
ánodo común #define CC1 12 #define CC2 11
int estadobtn1 = 0; int estadobtn2 = 0; int count = 0;
// Pines para A B C D E F G, en secuencia // se pueden usar los que más interesen const int segs[7] = { 2, 3, 4, 5, 6, 7, 8 };
// Segmentos que componen cada número const byte numbers[10] = { 0b0111111, 0b0000110, 0b1011011, 0b1001111, 0b1100110, 0b1101101, 0b1111101, 0b0000111, 0b1111111, 0b1101111};
void lightSegments(byte number) { for (int i = 0; i < 7; i++) { int bit = bitRead(number, i); digitalWrite(segs[i], bit); } }
Este ejemplo, muestra un código mejorado al presentado en el primer ejemplo. Como puede apreciarse, he utilizado los mismos pines del Arduino, en cada ejemplo. Con esto, trato de minorar los errores de asignación en los distintos listados de código.
Problemas a causa del multiplexado.
El problema que se puede encontrar el programador, frente a una representación por multiplexado, radica en
la secuencia de los tiempos de muestreo de cada dígito, por este motivo, recomiendo que se tenga en cuenta, diría, muy en cuenta, no utilizar o minimizar los delay(), ya que éstos, tienden a producir el efecto de "parpadeo" que
normalmente se aprecia en los dígitos.
En un multiplexado, siempre se producirá un parpadeo, aunque éste sea poco apreciable, cuantos más dígitos se muestren, más evidente se hará
dicho parpadeo. Por ese motivo hay que reducir en lo posible los tiempos en
la secuencia de muestreo.
3er. ejemplo.
Voy a presentar el código de un contador de 3 dígitos en un display de 7 segmentos LED. El lector, puede apreciar las pocas diferencias que se presentan en este código. Un punto a tener en cuenta, se encuentra precisamente en la rutina de asignación de encendido de cada dígito, representados por la rutina:
// // Basado en un trabajo de: Natalia Fargasch Norman // // Modificado y actualizado por Vins el 12.08.11 // // Three seven-segment LED Display with buttons // Common Catode digit 9 - 10 // Common Catode digit 11
// CA1 G F A B // | | | | | -> pins and segments they control // --------- --------- // | A | | A | // F| |B F| |B // |---G---| |---G---| // E| |C E| |C // | D | | D | // --------- --------- // | | | | | -> pins and segments they control // D DP E C CA2 // Segments that make each number when lit: // 0 => -FEDCBA // 1 => ----BC- // 2 => G-ED-BA // 3 => G--DCBA // 4 => GF--CB- // 5 => GF-DC-A // 6 => GFEDC-A // 7 => ----CBA // 8 => GFEDCBA // 9 => GF-DCBA // Arduino digital pins used to light up // corresponding segments on the LED display #define A 2 #define B 3 #define C 4 #define D 5 #define E 6 #define F 7 #define G 8 // Pushbuttons connected to pins 9 and 10 #define BTN1 14 #define BTN2 15 #define led 13
// Pins for A B C D E F G, in sequence const int segs[7] = { 2, 3, 4, 5, 6, 7, 8 };
// Segments that make each number const byte numbers[10] = { 0b0111111, 0b0000110, 0b1011011, 0b1001111, 0b1100110, 0b1101101, 0b1111101, 0b0000111, 0b1111111, 0b1101111}; int estadobtn1 = 0; int estadobtn2 = 0; int digit1 = 0; int digit2 = 0; int digit3 = 0; int count = 0; int val; int val2;
void setup() { pinMode(A, OUTPUT); pinMode(B, OUTPUT); pinMode(C, OUTPUT); pinMode(D, OUTPUT); pinMode(E, OUTPUT); pinMode(F, OUTPUT); pinMode(G, OUTPUT); pinMode(BTN1, INPUT); pinMode(BTN2, INPUT); pinMode(CA1, OUTPUT); pinMode(CA2, OUTPUT); pinMode(CA3, OUTPUT); digitalWrite(BTN1, HIGH); // activa RPA digitalWrite(BTN2, HIGH); // activa RPA count = 0; } void loop() { // incrementa val = digitalRead(BTN1); // lee el valor de entrada y almacena en val delay(4); // 10 milisegundos son una buena cantidad de tiempo val2 = digitalRead(BTN1); // lee la entrada otra vez para comprobar rebotes if (val == val2) // asegurar que conseguimos 2 lecturas constantes { if (val != estadobtn1) // el estado de botón ha cambiado! { if (val == LOW) // compruebe si el botón es presionado { count++; count %= 1000; } } estadobtn1=val; }
// decrementa val = digitalRead(BTN2); // lee el valor de entrada y almacénalo en val delay(4); // 4 milisegundos son una buena cantidad de tiempo. val2 = digitalRead(BTN2); // lee la entrada otra vez para comprobar rebotes if (val == val2) // asegurar que conseguimos 2 lecturas constantes { if (val != estadobtn2) // el estado de botón ha cambiado! { if (val == LOW) // compruebe si el botón es presionado { if (count == 0) { count=999; } else { count--; } } } estadobtn2=val; } // display number digit1=count / 100; digit2=(count - (digit1*100)) / 10; digit3=count % 10; // lightDigit1(numbers[digit1]); delay(2); lightDigit2(numbers[digit2]); delay(2); lightDigit3(numbers[digit3]); delay(2); } void lightDigit1(byte number) { digitalWrite(CA1, LOW); digitalWrite(CA2, HIGH); digitalWrite(CA3, HIGH); lightSegments(number); } void lightDigit2(byte number) { digitalWrite(CA1, HIGH); digitalWrite(CA2, LOW); digitalWrite(CA3, HIGH); lightSegments(number); }
void lightSegments(byte number) { for (int i = 0; i < 7; i++) { int bit = bitRead(number, i); digitalWrite(segs[i], bit); } }
Veamos la importancia que tiene la reducción, de lo que yo llamo, los tiempos muertos, probemos a modificar estas líneas
(resaltadas en rojo), simplemente, comentemos las que aquí se muestran, compilemos y carguemos de nuevo el programa en el Arduino:
// incrementa
val = digitalRead(BTN1); // lee el valor de entrada y almacénalo en val
// delay(4); // 10 milisegundos son una buena cantidad de tiempo
// val2 = digitalRead(BTN1); // lee la entrada otra vez para comprobar saltos
// if (val == val2) // asegurar que conseguimos 2 lecturas constantes
// {
if (val != estadobtn1) // el estado de botón ha cambiado!
{
if (val == LOW) // compruebe si el botón es presionado
{
count++;
count %= 1000;
}
}
estadobtn1=val;
// }
// decrementa
val = digitalRead(BTN2); // lee el valor de entrada y almacénalo en val
// delay(4); // 10 milisegundos son una buena cantidad de tiempo
// val2 = digitalRead(BTN2); // lee la entrada otra vez para comprobar saltos
// if (val == val2) // asegurar que conseguimos 2 lecturas constantes
// {
if (val != estadobtn2) // el estado de botón ha cambiado!
{
if (val == LOW) // compruebe si el botón es presionado
{
if (count == 0)
{
count=999;
} else
{
count--;
}
}
}
estadobtn2=val;
// }
Habrá comprobado que ahora el parpadeo no parece afectar a la normal visión del contador. A esto es, a lo que me refería, con llevar cuidado al programar, evitando rutinas que tomen excesivo tiempo en tareas que retengan el normal desarrollo del microprocesador.
Ahora, puede eliminar de su código, las líneas que ha comentado, guarde el archivo, compile y cargue el programa en el Arduino y finalmente compruebe que la solución es la esperada.
4º ejemplo.
En este ejemplo, vamos a utilizar los cuatro dígitos del encapsulado del display (es uno que tenía de una impresora). En este programa la tarea de multiplexar se dedica a cuatro displays, lo que puede llevar algún problema si no se vigilan los tiempos. Si no utilizamos bien las rutinas, aparecerán dos consecuencias, el parpadeo y una notable bajada de luminosidad de los dígitos.
Veamos el listado del código, estos listados están probados y sin duda funcionan como se espera de ellos.
/* * * Esta es la colaboración que se a * modificado y mejorado por Vins el 12.08.11 * * Four seven-segment LED Display with two buttons * Un botón incrementa la cuenta. Otro botón decrementa la cuenta.
* Common Catode digit 1 pin 9-10 * Common Catode digit 2 pin 11-12
// CC1 A F CC3 CC2 B // | | | | | | -> pins and segments they control // --------- --------- --------- --------- // | A | | A | | A | | A | // F| |B F| |B F| |B F| |B // |---G---| |---G---| |---G---| |---G---| // E| |C E| |C E| |C E| |C // | D | | D | | D | | D | // --------- --------- --------- --------- // | | | | | | -> pins and segments they control // E D C G CC4
// Segments that make each number when lit: // 0 => -FEDCBA // 1 => ----BC- // 2 => G-ED-BA // 3 => G--DCBA // 4 => GF--CB- // 5 => GF-DC-A // 6 => GFEDC-A // 7 => ----CBA // 8 => GFEDCBA // 9 => GF-DCBA */
// Arduino digital pins used to light up // corresponding segments on the LED display #define A 2 #define B 3 #define C 4 #define D 5 #define E 6 #define F 7 #define G 8
// Pushbuttons connected to pins 9 and 10 #define BTN1 14 #define BTN2 15
// Pins driving common anodes #define CC1 9 #define CC2 10 #define CC3 11 #define CC4 12 // Pins for A B C D E F G, in sequence const int segs[7] = { 2, 3, 4, 5, 6, 7, 8 };
// Segments that make each number const byte numbers[10] = { 0b0111111, 0b0000110, 0b1011011, 0b1001111, 0b1100110, 0b1101101, 0b1111101, 0b0000111, 0b1111111, 0b1101111};
int estadobtn1 = 0; int estadobtn2 = 0; int digit1 = 0; int digit2 = 0; int digit3 = 0; int digit4 = 0; int count = 0; int val; int val2;
void loop() { val = digitalRead(BTN1); // lee el valor de entrada y almacena en val if (val != estadobtn1) // el estado de botón ha cambiado! { if (val == LOW) // compruebe si el botón es presionado { count++; count %= 10000; } } estadobtn1=val;
val = digitalRead(BTN2); // lee el valor de entrada y almacena en val if (val != estadobtn2) // el estado de botón ha cambiado! { if (val == LOW) // compruebe si el botón es presionado { if (count == 0) { count=9999; } else { count--; } } estadobtn2=val; } // display number digit1=count / 1000; digit2=(count - (digit1 * 1000)) / 100; digit3=(count - (digit1*1000) - (digit2*100)) / 10; digit4=count % 10;
void lightSegments(byte number) { for (int i = 0; i < 7; i++) { int bit = bitRead(number, i); digitalWrite(segs[i], bit); } }
A demás de lo comentado, el punto delicado de este sistema de multiplexado está en la
secuencia correcta de la rutina de control de presentación de dígitos, cuanto menor tiempo se utilice en comparaciones, retardos, etc. más rápido se logrará la activación del dígito a visualizar:
Esto es un pequeño vídeo de baja calidad que muestra el contador de 4 dígitos y 7 segmentos a LED, ciertamente no se ve con la calidad que hubiera deseado. También puede descargar una versión. desde aquí.
Con estos ejemplos, he querido llenar un vacío que, había entre tantos ejemplos que se pueden encontrar en diferentes foros de Arduino. Realmente, en los foros se puede encontrar mucha colaboración y en la web, muchos artículos que hablan de contadores, realizados con LCD. Sin embargo, no son muchos los que se inclinan por los displays de siete segmentos a LED. La mayoría de los que se encuentran, teorizan y hablan de como funcionan, pero que lo describan en español, hay pocos. Por ese motivo, me he tomado la tarea de introducir al interesado en este tema de la multiplexación, de unos dígitos. Tal vez le pueda ayudar a alguien en su trabajo.
Consideraciones.
Hemos estado considerando los casos habituales en los que, se produce un código alrededor de un esquema y se pasa a realizar la práctica, hasta obtener el resultado propuesto. Eso esta bien, sin embargo, no siempre se trata de una práctica, se supone que un proyecto requiere de ciertas entradas/salidas, así que, pronto veremos que nos faltan pines para nuestro servicio. Aquí es donde quiero incidir y por eso esta ampliación al presente tutorial.
En esos casos, es conveniente ayudarnos de un circuito integrado que se encargue de la decodificación de BCD a 7 segmentos. Con un circuito integrado de estas características, nos ahorramos tres pines. Para este requisito, en primer lugar, según el display que utilicemos, debemos elegir, si necesitamos el cátodo común, 74HC4511 o el 74LS47.
A continuación se muestran algunos detalles de los decodificadores mencionados.
En el caso de utilizar un display a ánodo común (aunque no es muy recomendable, sobre todo porque no hay demasiados integrados que cubran esta opción), como el HC4026/HC4033, se deberá añadir un circuito integrado con un array de siete transistores bipolares npn, para poder atacar los LED directamente, un circuito adecuado para esta necesidad, sería el ULN2003 que, puede servir tanto para un display de CA como de CC, su aplicación, se puede apreciarse en la imagen que sigue:
Sería de gran interés para el principiante, que se familiarizara con las funciones que hace cada uno de los circuitos integrados y de sus características, al menos de los que se emplean en cada montaje. Es el modo de aprovechar todas las posibilidades que nos ofrecen, además de ayudarnos a comprender su función en el proyecto.
Naturalmente, la rutina principal del programa, para mostrar los dígitos, por medio de estos circuitos integrados, se debe modificar sustancialmente, ya que el concepto es muy diferente. Este caso no se contempla en este documento.
No obstante, utilizando una tecnología más acorde con los actuales microcontroladores, lo ideal es aprovechar las cualidades del bus I2C. Dicha tecnología nos permite aumentar considerablemente los registros de E/S, para unas posibilidades de uso mayores. Para más detalle, véase el artículo de mi propiedad Expansor de puerto, en el que se describe el uso de un teclado de 12 pulsadores.
Como siempre, comentarios, criticas y sugerencias para mejorar este artículo, son bienvenidos y apreciados.
Esto es todo, por este simple tutorial, los que quieran leer más sobre el tema Arduino, revele esta sección. ( Mostrar/Ocultar)
Creada el: 11-08-11 Actualizada el: 25/09/2011
Como se puede comprobar, no tenemos patrocinador. Sin anuncios que molesten, esto lo agradece el lector.
Desde que se inició la andadura, en 1998 hasta el momento, el mantenimiento de este sitio, lo asume el propio
autor.
| declaración de privacidad | LSSI | Póngase en contacto con nosotros