Un display 7 segmentos es nada mas que 7 LED encapsulados formando un 8, de modo que es posible lograr mostrar los dígitos 0~9. También se encuentran encapsulados de 2, 3 y 4 dígitos. Algunos llevan un octavo LED para representar el punto decimal. De modo que para manejar un dígito se requieren los 7 elementos que normalmente son nombrados con letras a, b, c, d, e, f y g, ademas un pin común a todos los LED que puede ser ánodo común o cátodo común. Si tiene punto decimal este normalmente se nombra como DP.
Ya que el circuito electrónico es mas complejo y hay bastantes opciones de equivocarse, les recomiendo avanzar paso a paso y no pasar al siguiente paso si no lograron el anterior.
Los componentes son muy simples.
Como practica podrías intentar hacer funcionar un display de ánodo común.
Con este código pretendemos comprobar que las conexiones electrónicas son las correctas. Lo que deberías lograr ver aquí es que cada uno de los 7 segmentos se van prendiendo en secuencia y en orden (a, b, c...), al terminar el ciclo hay una pausa de 2 seg antes de volverla a repetir.
void setup(){ pinMode(7, OUTPUT); //g pinMode(8, OUTPUT); //f pinMode(9, OUTPUT); //e pinMode(10, OUTPUT); //d pinMode(11, OUTPUT); //c pinMode(12, OUTPUT); //b pinMode(13, OUTPUT); //a } void loop(){ for (byte i=13; i>=7; i--){ digitalWrite(i, HIGH); delay(500); digitalWrite(i, LOW); } delay(2000); }
Si alguno de los segmentos no prende o el orden de la secuencia no es el correcto debes revisar el cableado correspondiente.
Ahora que tenemos todos los segmentos funcionando adecuadamente daremos un paso adelanto para mostrar números entre 0 y 9. En esta primera oportunidad en secuencia con un intervalo de 0.5 segundo y al final u na pausa de 1 segundo.
const byte dig[10][7]={ {1,1,1,1,1,1,0}, //0 {0,1,1,0,0,0,0}, //1 {1,1,0,1,1,0,1}, //2 {1,1,1,1,0,0,1}, //3 {0,1,1,0,0,1,1}, //4 {1,0,1,1,0,1,1}, //5 {1,0,1,1,1,1,1}, //6 {1,1,1,0,0,0,0}, //7 {1,1,1,1,1,1,1}, //8 {1,1,1,0,0,1,1} //9 }; void setup(){ for (byte i=7; i<=13; i++){ pinMode(i, OUTPUT); } } void loop(){ for (byte n=0; n<=9; n++){ for (byte i=7; i<=13; i++){ digitalWrite(i, dig[n][13-i]); } delay(500); } delay(1000); }
En esta oportunidad hemos usado 7 pines digitales para manejar el display.
Simplifiquemos nuestro código y elevemos los requerimientos. Usaremos la función random() para generar el numero aleatorio. Por lo que ahora los números mostrados sean aleatorios. Ademas se hizo un gran ahorro en la matriz guardando los segmentos como un numero binario.
const byte dig[10]={ B1111110, //0 B0110000, //1 B1101101, //2 B1111001, //3 B0110011, //4 B1011011, //5 B1011111, //6 B1110000, //7 B1111111, //8 B1110011 //9 }; void setup() { for (byte i=7; i<=13; i++){ pinMode(i, OUTPUT); } randomSeed(analogRead(0)); } void loop() { byte n = random(10); for (byte i=7; i<=13; i++){ digitalWrite(i, bitRead(dig[n],i-7)); } delay(500); }
En este ejemplo intentaremos manejar 5 dígitos por este método, por lo que tendríamos que usar 5 pines digitales adicionales (Ej: 2~6) para a través de un transistor (NPN para cátodo común) prender un dígito a la vez mientras al mismo tiempo enviamos el numero a mostrar por el bus de datos (pin 7~13). Este proceso debería ser muy rápido para engañar al ojo humano y que crea que los 5 dígitos están prendidos a la vez.
const byte dig[10]={ B1111110, //0 B0110000, //1 B1101101, //2 B1111001, //3 B0110011, //4 B1011011, //5 B1011111, //6 B1110000, //7 B1111111, //8 B1110011 //9 }; void setup() { for (byte i=2; i<=6; i++){ pinMode(i, OUTPUT); digitalWrite(i, HIGH); } for (byte j=7; j<=13; j++){ pinMode(j, OUTPUT); } } void loop() { for (unsigned int i=10000; i<99999; i++){ for (byte j=0; j<50; j++){ //1ro ver(i%10); digitalWrite(2, LOW); delay(1); digitalWrite(2, HIGH); //2do ver((i/10)%10); digitalWrite(3, LOW); delay(1); digitalWrite(3, HIGH); //3ro ver((i/100)%10); digitalWrite(4, LOW); delay(1); digitalWrite(4, HIGH); //4ro ver((i/1000)%10); digitalWrite(5, LOW); delay(1); digitalWrite(5, HIGH); //5to ver(i/10000); digitalWrite(6, LOW); delay(1); digitalWrite(6, HIGH); } } } void ver(byte n){ for (byte i=7; i<=13; i++){ digitalWrite(i, bitRead(dig[n],i-7)); } }
Para que NO notes el parpadeo la frecuencia de refresco debe ser superior a 25 Hz, en otras palabras todo el proceso debe hacerse en menos de 40 ms. En este ejemplo gastamos 1 ms por dígito osea 5 ms, por eso repetimos este proceso varias veces para que el contador avance a una velocidad razonable 50 x 5 = 250 ms.
Es este ejemplo ya estamos usando 12 pines (5 dígitos + 7 segmentos), por lo que quizás ya estamos al limite a nos ser que echemos mano de los pines analógicos (14~19) y no requeririamos hacer nada mas. En este caso uso display de bajo consumo (1 mA x segmento) por lo que como máximo tengo 7 mA en los pines 2~6. Otro tipo de display requiere transitores.
Otra opción interesante cuando tienes que manejar display 7 segmentos es usar un IC decodificador de BCD a 7 segmentos como el 7448 o 4011. Su principal virtud es que te ahorra pines de Arduino ya que no tendrás que usar 7 pines sino solamente 4. Ademas mejoramos nuestro código usando la función bitRead()
void setup() { for (byte i=10; i<=13; i++){ pinMode(i, OUTPUT); } } void loop() { byte n = random(10); for (byte i=10; i<=13; i++){ digitalWrite(i, bitRead(n,13-i)); } delay(500); }
En esta oportunidad hemos usado 4 pines digitales para manejar el display.
Pero gracias a la comunidad tenemos la libreria SevSeg.h que simplifica tremendamente las cosas incluso manejaremos 4 digitos al mismo tiempo.
hardwareConfig | Descripción |
---|---|
COMMON_CATHODE | Catodo comun sin driver |
COMMON_ANODE | Anodo comun sin driver |
N_TRANSISTORS | Catodo comun con NPN |
P_TRANSISTORS | Anodo comun con PNP |
NP_COMMMON_CATHODE | Catodo comun con doble transitor |
NP_COMMMON_ANODE | Anodo comun con doble transitor |
#include <SevSeg.h> SevSeg sevseg; //Instanciamos el object void setup() { byte hardwareConfig = N_TRANSISTORS; //Indica que es cátodo común con NPN byte numDigits = 4; byte digitPins[] = {2,3,4,5}; byte segmentPins[] = {13,12,11,10,9,8,7,6}; bool resistorsOnSegments = true; //true indica que resistencia esta en el pin de segmento bool updateWithDelays = false; //Recomendado bool leadingZeros = true; //true muestra ceros a izquierda sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments, updateWithDelays, leadingZeros); sevseg.setBrightness(90); //Establece brillo a 90% } void loop() { static unsigned long hora = millis(); static int deciSeconds = 0; if (millis() >= hora) { deciSeconds++; hora += 100; if (deciSeconds == 10000) { deciSeconds=0; } sevseg.setNumber(deciSeconds, 1); } sevseg.refreshDisplay(); }
Si requerirás 8 display 7 segmentos con la ayuda de IC externos una buena idea es enviar toda la información de manera serie (bus I2C). Esto se puede hacer por ejemplo con un Shift Register como el 74164 o 74595. Su principal virtud es que te ahorra pines de Arduino ya que no tendrás que usar 7 pines sino solamente 3 (Ck, data, MR). Ademas mejoramos nuestro código usando la librería ShiftDisplay.h
Método | Descripción | Posibles |
---|---|---|
set() | Guardar próximo valor a mostrar | display.set(valor) display.set(valor, decimales) display.set(valor, decimales, alineamiento) |
show() | Mostrar valor almacenado | display.show() display.show(milisegundos) display.show(valor, milisegundos) display.show(valor, milisegundos, alineamiento) |
Fuente: ShiftDisplay.
#include <Wire.h> #include <RTClib.h> #include <ShiftDisplay.h> RTC_Millis rtc; const byte DATA_PIN = 5; const byte LATCH_PIN = 6; const byte CLOCK_PIN = 7; const int DISPLAY_TYPE = COMMON_CATHODE; //COMMON_CATHODE o COMMON_ANODE const byte DISPLAY_SIZE = 6; //Numero de digitos ShiftDisplay display(LATCH_PIN, CLOCK_PIN, DATA_PIN, DISPLAY_TYPE, DISPLAY_SIZE); void setup() { rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); } void loop() { DateTime hoy = rtc.now(); String hora = ""; if (hoy.hour() < 10){ hora = '0'; } hora = hora + hoy.hour(); if (hoy.minute() < 10){ hora = hora + '0'; } hora = hora + hoy.minute(); if (hoy.second() < 10){ hora = hora + '0'; } hora = hora + hoy.second(); display.set(hora); display.show(1000); }
Si puedes mejorar o simplificar mas aun este código de ejemplo dímelo aquí
Eston otras librerias para 7 segmentos que podrias investigar como son: