Recientemente he tenido que aprender a usar pantallitas de 4 dígitos con 7 segmentos en Arduino. Es decir, algo como ésto:
Como pasa con todo la primera vez siempre cuesta. Y más si hay distintos tipos de displays y por tanto varias formas de hacer las cosas según el modelo que te haya caído a ti (los chinos no son muy dados a mandar manuales de uso para estas cosas). Y no son sutilezas, más bien hay dos formas, totalmente opuestas, así que os voy a dejar un par de ejemplos.
Antes de verlos decir que en cualquier caso es necesario entender que la pantalla hay que pintarla una y otra vez. Es decir, no basta con pintar y dejarlo encendido, porque eso es imposible. Básicamente porque en realidad «pintar la pantalla» no es una tarea, son cuatro: pintar el primer dígito, luego el segundo, luego el tercero y finalmente el cuarto.
Y cuando digo «luego» quiero decir unos milisegundos más tarde. No se pueden hacer las cuatro tareas a la vez, sólo se puede pintar de dígito en dígito. Seguramente esto se entienda viendo un esquema de pines:
Como podéis ver hay 4 pines, uno para cada dígito. Esos son los pines que usaremos para seleccionar el dígito que queramos pintar. ¿Se entiende ahora lo de que son 4 tareas que no se pueden hacer a la vez?
Pues visto esto, vamos a los casos concretos:
Primer ejemplo:
Para el display de la primera imagen, que es de tipo cátodo común y tiene 12 pines (por cierto, ojo que un trasto de estos te deja casi sin pines en arduino!), comprado en Dealextreme por 2$:
//pseudocódigo
En loop():
(1) Poner los 4 cátodos a HIGH (los selectores de dígito)
(2) Los segmentos deseados a HIGH
(3) El cátodo del primer dígito a LOW
(4) Delay (sleep)
Repetir para el dígito 2
Repetir para el dígito 3
Repetir para el dígito 4
Ahora que más o menos tenemos la idea, vamos a ver código de verdad:
//Declare what pins are connected to the digits
int digit1 = 12; //Pin 12 on my 4 digit display
int digit2 = 9; //Pin 9 on my 4 digit display
int digit3 = 8; //Pin 8 on my 4 digit display
int digit4 = 2; //Pin 6 on my 4 digit display
//Declare what pins are connected to the segments
int segA = 11; //Pin 11 on my 4 digit display
int segB = 7; //Pin 7 on my 4 digit display
int segC = 4; //Pin 4 on my 4 digit display
int segD = 5; //Pin 2 on my 4 digit display
int segE = 6; //Pin 1 on my 4 digit display
int segF = 10; //Pin 10 on my 4 digit display
/*int segH = 13; //Pin 3 on my 4 digit display*/
int segG = 3; //Pin 5 on my 4 digit display
void setup() {
for(int i=2; i<=13; i++) {
pinMode(i, OUTPUT);
}
}
void loop() {
printStop();
delay(15);
}
// clear selection
void digitsHigh() {
digitalWrite(digit1, HIGH);
digitalWrite(digit2, HIGH);
digitalWrite(digit3, HIGH);
digitalWrite(digit4, HIGH);
}
//clear segments
void clearDigit() {
digitalWrite(segA, LOW);
digitalWrite(segB, LOW);
digitalWrite(segC, LOW);
digitalWrite(segD, LOW);
digitalWrite(segE, LOW);
digitalWrite(segF, LOW);
digitalWrite(segG, LOW);
//digitalWrite(segH, LOW);
}
//print "STOP"
void printStop() {
//S
digitsHigh();
digitalWrite(segA, HIGH);
digitalWrite(segF, HIGH);
digitalWrite(segG, HIGH);
digitalWrite(segC, HIGH);
digitalWrite(segD, HIGH);
digitalWrite(digit1, LOW);
delayMicroseconds(500);
clearDigit();
//t
digitsHigh();
digitalWrite(segF, HIGH);
digitalWrite(segG, HIGH);
digitalWrite(segE, HIGH);
digitalWrite(segD, HIGH);
digitalWrite(digit2, LOW);
delayMicroseconds(500);
clearDigit();
//O
digitsHigh();
digitalWrite(segA, HIGH);
digitalWrite(segB, HIGH);
digitalWrite(segC, HIGH);
digitalWrite(segD, HIGH);
digitalWrite(segE, HIGH);
digitalWrite(segF, HIGH);
digitalWrite(digit3, LOW);
delayMicroseconds(500);
clearDigit();
//P
digitsHigh();
digitalWrite(segA, HIGH);
digitalWrite(segB, HIGH);
digitalWrite(segG, HIGH);
digitalWrite(segF, HIGH);
digitalWrite(segE, HIGH);
digitalWrite(digit4, LOW);
delayMicroseconds(500);
clearDigit();
}
Segundo ejemplo:
Este otro display es casi igual, solo que tiene dos puntos en medio y por tanto un pin más, pero lo importante es que el funcionamiento es opuesto al que acabamos de ver:
//pseudocódigo
(1) Poner los 4 dígitos a LOW (es decir, los 4 pines selectores)
(2) Poner todos los segmentos a HIGH
(3) Los segmentos deseados a LOW
(4) El primer dígito a HIGH
(5) Delay (sleep)
Repetir para el dígito 2
Repetir para el dígito 3
Repetir para el dígito 4
¿Diferente verdad? Veamos código de verdad:
//Declare what pins are connected to the digits
int digit1 = 12; //Pin 12 on my 4 digit display
int digit2 = 9; //Pin 9 on my 4 digit display
int digit3 = 8; //Pin 8 on my 4 digit display
int digit4 = 2; //Pin 6 on my 4 digit display
//Declare what pins are connected to the segments
int segA = 11; //Pin 11 on my 4 digit display
int segB = 7; //Pin 7 on my 4 digit display
int segC = 4; //Pin 4 on my 4 digit display
int segD = 5; //Pin 2 on my 4 digit display
int segE = 6; //Pin 1 on my 4 digit display
int segF = 10; //Pin 10 on my 4 digit display
/*int segH = 13; //Pin 3 on my 4 digit display*/
int segG = 3; //Pin 5 on my 4 digit display
void setup() {
for(int i=2; i<=13; i++) {
pinMode(i, OUTPUT);
}
}
void loop() {
printStop();
delay(15);
}
// write 'level' to all segments
void allSegments(int level) {
digitalWrite(segA, level);
digitalWrite(segB, level);
digitalWrite(segC, level);
digitalWrite(segD, level);
digitalWrite(segE, level);
digitalWrite(segF, level);
digitalWrite(segG, level);
}
//write 'level' to all digit selectors
void allDigits(int level) {
digitalWrite(digit1, level);
digitalWrite(digit2, level);
digitalWrite(digit3, level);
digitalWrite(digit4, level);
}
//print "STOP"
void printStop() {
//S
allDigits(LOW);//clear digits
allSegments(HIGH);//clear segments
digitalWrite(segA, LOW);
digitalWrite(segF, LOW);
digitalWrite(segG, LOW);
digitalWrite(segC, LOW);
digitalWrite(segD, LOW);
digitalWrite(digit1, HIGH);
delayMicroseconds(500);
//t
allDigits(LOW);
allSegments(HIGH);
digitalWrite(segF, LOW);
digitalWrite(segG, LOW);
digitalWrite(segE, LOW);
digitalWrite(segD, LOW);
digitalWrite(digit2, HIGH);
delayMicroseconds(500);
//O
allDigits(LOW);
allSegments(HIGH);
digitalWrite(segA, LOW);
digitalWrite(segB, LOW);
digitalWrite(segC, LOW);
digitalWrite(segD, LOW);
digitalWrite(segE, LOW);
digitalWrite(segF, LOW);
digitalWrite(digit3, HIGH);
delayMicroseconds(500);
//P
allDigits(LOW);
allSegments(HIGH);
digitalWrite(segA, LOW);
digitalWrite(segB, LOW);
digitalWrite(segG, LOW);
digitalWrite(segF, LOW);
digitalWrite(segE, LOW);
digitalWrite(digit4, HIGH);
delayMicroseconds(500);
}
Eso es todo, espero que os sirva, a mi me llevó varias horas dar con la fórmula para cada uno de los displays 😛