Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Microcontroladores I
(Semana 8)
MULTIPLEXACIÓN DE DISPLAY´S DE SIETE SEGMENTOS CON ARDUINO Y SU
PROGRAMACIÓN.
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 intentar rellenar esta laguna.
En esta ocasión, 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 internamente de tal manera que al exterior sólo aparecen (normalmente) 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.
Hay que tener en cuenta que podemos encontrar estos displays en cátodo común y en ánodo común. 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 (porque son dos) de
cada dígito en paralelo. Recuerde utilizar todos en ánodo o cátodo común.
digitalWrite(A, HIGH);
digitalWrite(B, HIGH);
digitalWrite(C, HIGH);
digitalWrite(D, HIGH);
digitalWrite(E, HIGH);
digitalWrite(F, HIGH);
digitalWrite(G, HIGH);
delay(600);
digitalWrite(A, LOW);
digitalWrite(B, LOW);
digitalWrite(C, LOW);
digitalWrite(D, LOW);
digitalWrite(E, LOW);
digitalWrite(F, LOW);
digitalWrite(G, LOW);
delay(600);
}
Por supuesto que este código se puede reducir, sin embargo, he querido mostrarlo de esta forma para que los
que se inician puedan seguirlo con mayor facilidad.
Circuito de 2 dígitos.- 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.
1 er. Ejemplo
Esta es una primera versión y su correspondiente código realizado con Arduino v.013 y v.023. El display
utilizado para 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.
Contador con dos display de 7 segmentos.
int digit1 = 0;
int digit2 = 0;
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);
digitalWrite(BTN1, HIGH); // activa RPA
digitalWrite(BTN2, HIGH); // activa RPA
pinMode(CA1, OUTPUT);
pinMode(CA2, OUTPUT);
pinMode(led, OUTPUT);
// digit1 = 9; digit2 = 9;
}
void loop()
{
// chequea boton1. Incrementa
int val1 = digitalRead(BTN1);
if (val1 == LOW)
{
if (digit2 >= 9 && digit1 >= 9)
{
digit2 = 0;
digit1++;
digit1 %= 10;
if (digit1 >=9)
{
digit2++;
}
} else if (digit1 >= 9)
{
digit2++;
digit2 %= 10;
}
digit1++;
digit1 %= 10;
delay(10);
}
// display numero
unsigned long startTime = millis();
for (unsigned long elapsed=0; elapsed < 300; elapsed = millis() - startTime)
{
lightDigit1(numbers[digit1]);
delay(5);
lightDigit2(numbers[digit2]);
delay(5);
}
}
void lightDigit1(byte number)
{
digitalWrite(CA1, LOW);
digitalWrite(CA2, HIGH);
lightSegments(number);
}
2 do. Ejemplo.
En este segundo ejemplo, voy a utilizar otra forma de resolver 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.
int estadobtn1 = 0;
int estadobtn2 = 0;
int count = 0;
int digit1 = 0;
int digit2 = 0;
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);
digitalWrite(BTN1, HIGH); // activa RPA
digitalWrite(BTN2, HIGH); // activa RPA
pinMode(CC1, OUTPUT);
pinMode(CC2, OUTPUT);
pinMode(led, OUTPUT);
// digit1 = 9; digit2 = 9; // para depurar
}
void loop()
{
// chequea boton1. Incrementa
int val1 = digitalRead(BTN1);
if (val1 == LOW)
{
if (digit1 >= 9 ) { digit1 ++; } if (digit1 > 9)
{
digit1 = 0;
digit2++;
if (digit2 > 9)
{
digit2 = 0;
}
}
}
// display numero
unsigned long startTime = millis();
for (unsigned long elapsed=0; elapsed < 200; elapsed = millis() - startTime) {
-- lightDigit1(numbers[digit1]);
delay(5);
lightDigit2(numbers[digit2]);
delay(5);
}
}
Este ejemplo, muestra un código mejorado al representado 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.
// 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
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 almacénelo en val
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énelo 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=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);
}
Veamos la importancia que tiene la reducción de lo que yo llamo tiempos muertos, probemos a modificar
estas líneas, simplemente, comentemos las que aquí se muestran, compilemos y carguemos 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 almacenalo 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 to. 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.
Contador con 4 displays de 7 segmentos.
/*
* 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 10
* Common Catode digit 2 pin 5
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 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);
digitalWrite(BTN1, HIGH); // activa RPA
digitalWrite(BTN2, HIGH); // activa RPA
pinMode(CC1, OUTPUT);
pinMode(CC2, OUTPUT);
pinMode(CC3, OUTPUT);
pinMode(CC4, OUTPUT);
count = 0;
}
void loop() {
val = digitalRead(BTN1); // lee el valor de entrada y almacénlo 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;
lightDigit1(numbers[digit1]);
delay(2);
lightDigit2(numbers[digit2]);
delay(2);
lightDigit3(numbers[digit3]);
delay(2);
lightDigit4(numbers[digit4]);
delay(2);
}
A demás de lo comentado, el punto delicado de este sistema de multiplexado está en la elección 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:
// display number
digit1=count / 1000;
digit2=(count - (digit1 * 1000)) / 100;
digit3=(count - (digit1*1000) - (digit2*100)) / 10;
digit4=count % 10;
aresteguiramos@hotmail.com
aresteguiramos@gmail.com
938300999