Descripción
Los displays LED de 4 dígitos
Si queremos mostrar 4 dígitos… ¿Vamos a multiplicar 8 cables x 4 dígitos más tensión y GND, en total 34 pines?
Los displays LED de 4 dígitos
Si queremos mostrar 4 dígitos… ¿Vamos a multiplicar 8 cables x 4 dígitos más tensión y GND, en total 34 pines?
Para empezar, Arduino UNO no tiene tantos pines. ¿Cómo puede un fabricante evitar usar 34 pines? Pues una forma fácil ( y barata que es lo que les gusta a los que fabrican) es la de mantener 8 pines para iluminar los 7 segmentos más el punto, y poner otros 4 pines para indicar a cuál de los dígitos corresponde la información que se pone en a, b, c, d, e, f, g, h.
La cosa va por ahí, pero para eso habría que poner unas memorias y latch como en el shift register, pero alguien dijo: No, no, más barato aun. Y un ingeniero creativo dijo: pues si hacemos que esos 4 pines para indicar la posición vayan a tierra pasando por un transistor cada uno podemos hacer que se ilumine solo uno cada vez. Y si hacemos el ciclo lo bastante rápido, pasando de uno a otro, ni se enteran.
Y eso es todo. Simplemente seguimos utilizando 8 pines para iluminar los segmentos, pero solo hay uno activo en un momento concreto. Y haciendo un ciclo rápido, iluminamos uno cada vez rápidamente y pasamos al siguiente y luego al siguiente y problema resuelto.
Así que lo primero fijaros que en esta ocasión vamos a considerar a al segmento horizontal de arriba, según el dibujo. y los números indican la masa de los 4 dígitos.
Materiales
Placa de Arduino
4 resistencias de 330
1 Display de 7 Segmentos y 4 dígitos
Protoboard, cables para conexiones y un cable USB para conectar arduino al PC y que sirve además de alimentación.
Esquema 1
A continuación lo que vamos a hacer es conectar los 8 segmentos del display a los pines del 2 al 10 de nuestro Arduino, y conectar GND al cátodo de cada digito con su correspondiente resistencia de 330 ohmios y comprobad las conexiones.
Montaje 1
En el montaje no he encontrado el display que nos ocupa, solo tenía disponible el que ve en pantalla, pero este tiene dos patillas más en la fila de arriba y en la fila de abajo. Así que los he ignorado y empiezan por el pin de la izquierda de cada fila. Está cableado según el esquema y basado en el croquis de más arriba donde se muestran a que corresponde cada patilla.
Código 1
De nuevo, tengo que insistir en que hay que leer la hoja de características de cada display y no hay que fiarse del esquema y montaje aquí propuesto, porque el display que se tenga en la mano puede ser distinto. Mirad el código del display y bajar la data sheet de Internet. Leerla, aunque solo sea para comprobar si los pines coinciden con el diagrama aquí propuesto.En caso negativo tampoco es grave porque basta con conectar los pines correctos al mismo orden del Arduino.
Lo que yo he hecho (porque mi display solo tiene 12 pines), es conectar los 8 segmentos y enviar el cátodo a masa mediante una resistencia, para probar el primer digito y ya me preocupare del resto luego. Es imperativo que os aseguréis de conectar correctamente los segmentos antes que nada.
Podeís correr un programa simple como este, para comprobar la conexión de los segmentos, que los va encendiendo y apagando en secuencia: Prog_31_1
Si todos se encienden, en orden ya podemos pasar a la siguiente fase. Vamos a comprobar que se muestran los número correctamente con el siguiente código
Podeís correr un programa simple como este, para comprobar la conexión de los segmentos, que los va encendiendo y apagando en secuencia: Prog_31_1
void setup(){
for ( int i=2 ; i<10 ; i++){
pinMode( i, OUTPUT);
}
}
void loop(){
for (int j=2; j<10 ; j++){
digitalWrite( j, HIGH);
delay(300);
digitalWrite( j, LOW) ;
delay(300);
}
}
byte Digit[10][8] = // Arduino UNO va muy justo de memoria. Por eso lo
{
{ 1,1,1,1,1,1,0,1 }, // 0
{ 0,1,1,0,0,0,0,0 }, // 1
{ 1,1,0,1,1,0,1,0 }, // 2
{ 1,1,1,1,0,0,1,0 }, // 3
{ 0,1,1,0,0,1,1,0 }, // 4
{ 1,0,1,1,0,1,1,0 }, // 5
{ 1,0,1,1,1,1,1,0 }, // 6
{ 1,1,1,0,0,0,0,0 }, // 7
{ 1,1,1,1,1,1,1,0 }, // 8
{ 1,1,1,0,0,1,1,0 } // 9
};
void setup(){
for (int i= 2; i<11; i++){
pinMode(i, OUTPUT);
}
}
void loop(){
for ( int k=0 ; k<10 ; k++){ // Llama a Display para k de 0 a 9, los digitos
Display(k);
delay(1000);
}
}
void Display(int N){
for (int i= 0 ; i<8 ; i++){
int valor = Digit[N][i];
int pin = i+2;
digitalWrite(pin , valor) ; // digitalWrite(i+2 , Digit[N][i] ) ;
}
}
Esquema 2
Ahora que estamos seguros de que nuestros 7 segmentos están enchufados donde corresponde viene la cuestión de utilizar 4 pines de Arduino para elegir cual se ilumina.
Nuestra primera idea sería conectar esas salidas del display, 1, 2, 3 y 4 a 4 pines de nuestro Arduino. Si mantenemos esos pines en HIGH excepto el que queremos iluminar, que ponemos en LOW, parece que cerraría el circuito a GND y ya está.
Pero no. El consumo típico de cada segmento, (como de cada LED) es de entre 15 y 20mA. Como son 8 segmentos cuando escribamos el 8 más el punto, el consumo será de 8 x 15 = 120 mA y pudiendo llegar a 160mA. Muy por encima de los 40 mA que un pin de nuestro Arduino puede suministrar o drenar, así que mejor que pensemos otra cosa antes de que huela a quemado.
Y la solución, queridos amigos, es, naturalmente, utilizar un transistor para permitir cerrar el circuito de cada dígito.
El 2N2222 es ya un viejo conocido (No os olvidéis de la resistencia de la base, es imprescindible), poniendo a LOW los pines 9, 10, 11, y 12 los transistores están al corte, y ningún digito puede iluminarse. Si ponemos tensión en el pin 12, su transistor se satura y permite la salida a Ground del primer digito que encenderá los segmentos que le indiquen los pines 2 al 8.
Ahora ponemos en LOW el pin 12 y en HIGH el 11. Los valores de los segmentos iluminaran ahora el segundo digito. Y luego el tercero y el cuarto. El único trucos es hacerlo rápido, y eso se le da muy bien a nuestro Duino.
Montaje 2
Código 2
Vamos a reaprovechar la función Display () que escribimos en la sesión anterior para dibujar los dígitos en el display, que si recordáis se apoyaba en un array para saber que segmentos encender:
Pero vamos a extender Display para que escriba un digito en la posición que queramos, donde la posición 0 son las unidades, 1 las decenas, 2 las centenas y 3 los miles.
Como veis, es la misma función en la parte de iluminar segmentos, pero hemos hecho que al entrar los apague todos, luego levanta los pines que queremos y solo luego activamos el transistor de salida de la posición que queremos, lo que hace que ilumine la posición pedida en pos.
Vamos a reaprovechar la función Display () que escribimos en la sesión anterior para dibujar los dígitos en el display, que si recordáis se apoyaba en un array para saber que segmentos encender:
byte Digit[10][8] = // Arduino UNO va muy justo de memoria. Por eso lo
{
{ 1,1,1,1,1,1,0,1 }, // 0
{ 0,1,1,0,0,0,0,0 }, // 1
{ 1,1,0,1,1,0,1,0 }, // 2
{ 1,1,1,1,0,0,1,0 }, // 3
{ 0,1,1,0,0,1,1,0 }, // 4
{ 1,0,1,1,0,1,1,0 }, // 5
{ 1,0,1,1,1,1,1,0 }, // 6
{ 1,1,1,0,0,0,0,0 }, // 7
{ 1,1,1,1,1,1,1,0 }, // 8
{ 1,1,1,1,0,1,1,0 } // 9
};
void setup(){
for (int i= 2; i<13; i++){
pinMode(i, OUTPUT);
}
void Display(int pos, int N){
digitalWrite(9 ,LOW); // Apaga todos los digitos
digitalWrite(10,LOW);
digitalWrite(11,LOW);
digitalWrite(12,LOW);
for (int i= 0 ; i<7 ; i++){ // 0a,1b,2c,3d,4e,5f,6g es el número de segmentos
digitalWrite(i+2 , Digit[N][i]) ;
digitalWrite(pos + 9, HIGH); // Enciende el digito pos
}
}
Calculamos el pin de salida como pos + 9, porque a las posiciones 0, 1, 2, 3 les corresponden los pines 9, 10, 11, 12, también aquí, la elección del orden de los pines juega a nuestro favor.
Una vez que tenemos resuelto dibujar el número buscado en la posición elegida tenemos que escribir otra función que descomponga un número dado en unidades, decenas, centenas y miles.
En un alarde de creatividad he bautizado a esta función como CalculaDigitos()
void CalculaDigitos( int Num){
int Digit0 = Num % 10 ;
int Digit1 = (Num % 100) / 10 ;
int Digit2 = (Num % 1000) / 100 ;
int Digit3 = Num/1000 ;
Display(3 , Digit3);
delay(5);
Display(2 , Digit2);
delay(5);
Display(1 , Digit1);
delay(5);
Display(0 , Digit0);
delay(5);
}
2386 % 10 = 6 Porque el % nos devuelve el resto de dividir por 10, o sea 6.
2386 % 100 = 86 Ahora hacemos la división entera por 10 o sea 8,los decimales se tiran
2386 % 1000 = 386 386 / 100 = 3
2386 / 1000 = 2 Directamente, para eso se inventó la división entera.
Y a continuación le pedimos directamente que nos saque los dígitos al display.
Por ultimo para la función principal, empecemos pidiéndole que cuente décimas de segundo (La cuenta atrás la hacemos, luego)
void loop(){
CalculaDigitos( millis() / 100);
}
¿Y si queremos hacer una cuenta atrás? Venga pensad un momento antes de mirar la solución.
Muy fácil también. Como nuestro contador va hasta 9999 basta con restarle a esto el cálculo de arriba, o simplemente poner en lugar del 9999 la cifra desde la que deseamos descontar.
Más interesante, y práctico supone convertir esa cifra a minutos y segundos sexagesimales para hacer un reloj.
Más interesante, y práctico supone convertir esa cifra a minutos y segundos sexagesimales para hacer un reloj.
void loop(){
int n = millis() / 1000 ; // Lo pasamos a segundos p
int segundos = n % 60 ;
int minutos = n / 60 ;
int k = minutos * 100 + segundos ;
CalculaDigitos(k) ;
}
Aquí está el código completo
El circuito que hemos visto, es el correcto para garantizar que el display tenga una vida larga y pacífica, de hecho es el que recomienda el fabricante.En internet encontrareis bastantes ejemplos en los que, en vez de transistores usan resistencias de un cierto valor para limitar la intensidad en los controles de salida. He preferido no hacerlo así, a sabiendas de que el montaje que os he propuesto es bastante más pesado.
Algunos comentarios finales
Cablear este montaje es un asco y si fuera un circuito comercial seria caro (Porque aunque los componentes sean baratos, montarlos cuesta pasta, más que los componentes en este caso).
byte Digit[10][8] = // Arduino UNO va muy justo de memoria. Por eso lo
{
{ 1,1,1,1,1,1,0,1 }, // 0
{ 0,1,1,0,0,0,0,0 }, // 1
{ 1,1,0,1,1,0,1,0 }, // 2
{ 1,1,1,1,0,0,1,0 }, // 3
{ 0,1,1,0,0,1,1,0 }, // 4
{ 1,0,1,1,0,1,1,0 }, // 5
{ 1,0,1,1,1,1,1,0 }, // 6
{ 1,1,1,0,0,0,0,0 }, // 7
{ 1,1,1,1,1,1,1,0 }, // 8
{ 1,1,1,1,0,1,1,0 } // 9
};
void setup(){
for (int i= 2; i<13; i++){
pinMode(i, OUTPUT);
}
}
void loop(){
int n = millis() / 1000 ; // Lo pasamos a segundos p
int segundos = n % 60 ;
int minutos = n / 60 ;
int k = minutos * 100 + segundos ;
CalculaDigitos(k) ;
}
void Display(int pos, int N){
digitalWrite(9 ,LOW); // Apaga todos los digitos
digitalWrite(10,LOW);
digitalWrite(11,LOW);
digitalWrite(12,LOW);
for (int i= 0 ; i<7 ; i++){ // 0a,1b,2c,3d,4e,5f,6g es el número de segmentos
digitalWrite(i+2 , Digit[N][i]) ;
digitalWrite(pos + 9, HIGH); // Enciende el digito pos
}
}
void CalculaDigitos( int Num){
int Digit0 = Num % 10 ;
int Digit1 = (Num % 100) / 10 ;
int Digit2 = (Num % 1000) / 100 ;
int Digit3 = Num/1000 ;
Display(3 , Digit3);
delay(5);
Display(2 , Digit2);
delay(5);
Display(1 , Digit1);
delay(5);
Display(0 , Digit0);
delay(5);
}
El circuito que hemos visto, es el correcto para garantizar que el display tenga una vida larga y pacífica, de hecho es el que recomienda el fabricante.En internet encontrareis bastantes ejemplos en los que, en vez de transistores usan resistencias de un cierto valor para limitar la intensidad en los controles de salida. He preferido no hacerlo así, a sabiendas de que el montaje que os he propuesto es bastante más pesado.
Algunos comentarios finales
Cablear este montaje es un asco y si fuera un circuito comercial seria caro (Porque aunque los componentes sean baratos, montarlos cuesta pasta, más que los componentes en este caso).
Así que en la práctica os desaconsejo que uséis estos displays de por si, en vuestros proyectos. Hay demasiados cables y siempre hay alguno dando guerra. Lo normal es usar un display tipo I2C o similar que lleven un circuito de control interno, o bien usar un integrado de control BCD como el Max7219.
Y ¿Por qué a pesar de todo hemos hecho esta práctica? Pues porque es importante que entendáis cómo funcionan las cosas y el concepto de multiplexado es uno de los claves básicas para entender la electrónica digital.
Por cierto, ¿Os habéis dado cuenta de que, al hacer un multiplexado de los dígitos basado en que nuestro Duino recorra el ciclo completo en menos tiempo de lo que nuestro ojo percibe, cualquier uso de un delay() dará al traste con el invento?. Meted uno por donde queráis y ved lo que ocurre.
Aunque hasta ahora hemos usado y abusado de los delays, son algo poco práctico y potencialmente muy peligroso a medida que los proyectos que presentemos se vayan complicando, y este es uno de esos casos. Ya hablaremos de las soluciones.
No hay comentarios:
Publicar un comentario