bclose

Display de 7 segmentos y 4 dígitos

Displays numéricos de 7 segmentos

Objetivos

 

 

    • Nuestro primer display numérico de 4 digitos.
    • Multiplxando los digitos.
    • Aprendiendo a programar: Dividiendo el problema en funciones.
    • Vuelta a las operaciones con enteros
 

Material requerido.

Imagen de Arduino UNO

Arduino Uno o similar. Esta sesión acepta cualquier otro modelo de Arduino.

Protoboard

Una Protoboard .

conexiones

Cables de protoboard

componente

4 x resistencias de 330Ω.

digital tube x4

Un display de 7 segmentos y 4 dígitos.

Transistor 2N2222

4 x Transistor 2N2222

tienda online prometec

Los displays LED de 4 dígitos

 

En la sesión anterior, la cosa ha ido bastante bien con un dígito, pero ahora que le hemos cogido el puntillo, queremos poder usar 4 dígitos para, digamos dar la hora.

Y 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 (Si, el Mega sí que los tiene, pero recordad, elegancia, mucha elegancia), entonces si vosotros fabricarais estos displays ¿Cómo evitaríais usar 34 pines? Pensadlo, ¿Qué solución daríais vosotros al problema?

Pues una 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 ponéis 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 y 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. Ni que decir tiene que el ingeniero creativo pasó a jefe de proyectos.

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 que vamos a hacer es conectar los 8 segmentos del display a los pines del 2 al 10 de nuestro Arduino, para probarlos. Conectad GND al cátodo del primer digito con una resistencia y comprobad las conexiones.

 

Conexiones iniciales

 

De nuevo, tengo que insistiros en que leáis la hoja de características de vuestro display y no os fieis del diagrama de abajo, porque el vuestro puede ser distinto. Mirad el código de vuestro display y bajaros la data sheet de Internet. Leedla, aunque solo sea para comprobar si vuestros pines coinciden con el diagrama que os pongo debajo (Que es del manual de Parallax).

Este diagrama es para el display que tengo entre manos (5461AS) y el vuestro no tiene por qué usar los mismos pines ( Aunque la probabilidad de que sea así es alta, y en caso negativo tampoco es grave porque basta con que conectéis los pines correctos al mismo orden de vuestro Arduino).

Conexion a ArduinoLo 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

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);
         }
    }

Si todos se encienden, ya podemos pasar a la siguiente fase.

 

Diagrama de conexión

 

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, 12, 9, 8 y 6  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.

Diagrama ed conexion

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 terceo y el cuarto. El único trucos es hacerlo rápido, y eso se le da muy bien a nuestro Duino.

 

El programa de control

 

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: Prog_31_2

byte Digit[10][8] =
   { 
     { 1,1,1,1,1,1,0,0 },    // 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,0,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<13; i++)
                     pinMode(i, OUTPUT);
    }

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.

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<8 ; i++)    // Esto no cambia de la session anterior
            digitalWrite(i+2 , Digit[N][i]) ;

      digitalWrite(pos + 9, HIGH);      // Enciende el digito pos
  }

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.

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);
      Display(2 , Digit2);
      Display(1 , Digit1);
      Display(0 , Digit0);
   }

Por si acaso alguien faltó el día que hablamos de las operaciones con enteros haremos un caso concreto. Supongamos un número como 2.386. ¿Cómo obtenemos sus dígitos separados?

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);
   }

¿Creías que iba a ser difícil? Pues lo siento. Es así de sencillo. Ya conocíamos millis(), el reloj interno de nuestro Duino en milisegundos. Pues haciendo la división entera (otra vez) nos da un contador de hasta 999 segundos.

¿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.

void loop()
   {
       int n = millis() / 1000 ;       // Lo pasamos a segundos
       int segundos = n % 60  ;
       int minutos =  n / 60  ;

       int k = minutos * 100 + segundos ;
       CalculaDigitos(k) ;
   }

De nuevo a partir del reloj interno de nuestro Duino, millis(),(que cuenta en milisegundos por lo que lo dividimos por mil para pasarlo a segundos), calculamos los segundos y minutos, para luego llamar a CalculaDigitos() que espera un numero centesimal y por eso multiplicamos por 100 los minutos para que cuadre el display.

 

Os dejo como ejercicio que hagáis un reloj que efectúa una cuenta atrás desde un número dado.

 
  • 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 (Volveremos a hablar del asunto en un futuro próximo).

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.

 

Resumen de la sesión

 

 

    • Hemos presentado los displays LED de 7 segmentos y 4 digitos.
      • Lo suficiente como para comprender, que como ejercicio está bien, pero veremos otras maneras de incluir estos displays, menos trabajosas.
    • Hemos mejorado nuestra función Display(), para que podamos usarla en displays de digitos múltiples(Seria muy fácil extenderla a 8 digitos).
    • Hemos resuelto una serie de problemas lógicos, en pasos más pequeños de abordar para mejorar nuestra competencia en la búsqueda de algoritmos útiles.
    • Hemos visto que podemos abordar problemas complejos mediante pequeños pasos y funciones, que al combinarse resuelven problemas que inicialmente parecen inabordables.
 

 

 

 

(84) Comments

  • Hola podrían ayudarme con el diagrama de esto mismo pero con displays de 12v porfavor, he usado transistores 2n2222 pero se me han achicharrado porfavor ayuda

    • Hola Alejandro , qué display estás utilizando? La intensidad máxima colector-emisor de esos transistores es de 0.8A me parece. Recuerda colocar una resistencia apropiada en la base del transistor y una resistencia en cada LED el 7 segmentos.

    • Luis soto

    Buenas Tardes amigo, Gracias por compartir tus conocimientos, Una pequeña pregunta, ya que podremos controlar unas salidas de mayor potencia Gracias al transistor BJT, como Puedo saber o calcular el consumo del transistor cuando esta saturado al cerrar el circuito de cada digito, con respecto a las salidas del arduino, ?

    • Hola Luis, Siemoe puedes usar un multimetro para medir la corriente que cruza el circuito

    • Juan

    Hola, muy buenas, lo primero decir que muchas gracias por este tutorial, muy bien y fácil explicado y llegando a todos los niveles con entretenimiento y resultando interesante (que no es nada fácil). En mi caso había hecho bastantes cosas de circuitos y de programación en otros lenguajes, lo estoy usando para aprender arduino y C++ y no aburre para nada aunsabiendo de estos temas, lo hago con mi novia que ella aprende de 0 y la verdad que ella también lo está disfrutando sin necesidad de ayuda extra.

    Lo segundo, mi duda, estoy utilizando el display de 4 dígitos de 7 segmentos, intentando implementarlo sin transistores, al final está mi código con comentarios. Cambiando en él el valor de j, en la definición de variables antes del void setup, se puede obtener cualquier número con un buffer circular y distintos números en cada display con una relación matemáticas al activarlos (de momentos solo lo he implementado para 2 de los 4 displays, ampliarlo no parece dificil), mi pregunta viene al intentar hacerlo dinámico, las 4 últimas líneas del código.

    k=k+16*exp(-6);
    if (k=1)
    {j++;
    k=0;
    }

    Para evitar overflow defino k como double y lo inicializo en 0. Sabiendo que la frecuencia de procesador de arduino UNO (con la que trabajo) es de 16MHZ, quiere decir que hace 16*10^6 ciclos por segundo, le sumo a k la inversa 16*exp(-6) cada ciclo, de forma que después de un segundo (16*exp(-6)) ciclos k será igual a uno, aumento el número de j y por tanto el de cada display y reinicializo k en 0. Mi problema es que no consigo que funcione y no encuentro el error, si me podríais ayudar os lo agradecería.

    Un saludo
    Copio el código entero:

    int matrix[10][7]=
    { // Correspondencia les números
    {2,3,4,5,6,7,0}, //0
    {4,7,0,0,0,0,0}, //1
    {3,4,1,5,6,0,0}, //2
    {3,4,1,7,6,0,0}, //3
    {2,1,4,7,0,0,0}, //4
    {3,1,2,7,6,0,0}, //5
    {3,2,5,6,7,1,0}, //6
    {3,4,7,0,0,0,0}, //7
    {1,2,3,4,5,6,7}, //8
    {1,2,3,4,0,6,7} //9
    };
    int j=21;
    double k=0;
    int t=1;
    void setup()
    {// Del pin 1 al 8 está usado para escribir el número y del 10 al 13 para elegir que 7 segmentos usar
    for (int i=1;i<14;i++)
    pinMode(i,OUTPUT);

    digitalWrite(12,HIGH);
    digitalWrite(13,HIGH);

    }

    void loop()
    {
    /*Cada loop enciende y apaga el 7 segmentos 10 y 11 alternativamente, tan rápido que se ve de forma fija, al sacar num como
    un buffer circular puedo sacar dos número distintos en cada led, cambiando j al principio puedo poner cualquier número del
    1 al 9 en cada display
    */

    int num=j%9;
    digitalWrite(10,LOW);
    digitalWrite(11,HIGH);
    for (int i=0;i<7;i++)
    digitalWrite(matrix[num][i],HIGH);

    for (int i=0;i<7;i++)
    digitalWrite(matrix[num][i],LOW);

    digitalWrite(10,HIGH);
    digitalWrite(11,LOW);
    for (int i=0;i<7;i++)
    digitalWrite(matrix[num+3][i],HIGH);

    for (int i=0;i<7;i++)
    digitalWrite(matrix[num+3][i],LOW);

    k=k+16*exp(-6);
    if (k=1)
    {j++;
    k=0;
    }

    }

    • Hola Juan , muchas gracias por publicar tu codigo, pero siento decirte que me resulta imposible por falta de tiempo cargar y revisar tu programa porque estamos que no llegamos ya a anda

      Un saludo

    • David

    Estimado Buenas tardes, muy bien explicado el tutorial, te comento que estoy entrando en el mundo Arduino, y quiero hacer lo siguiente:

    un circuito que electrónico que tenga 5 switch y estos switch tengas cada uno un valor de 1000, 500, 100, 50 y 10 ademas que me sume la cantidad en otro display, será posible realizar esto mediante arduino???

    • Hola David, con switch supongo qu te refieres a interruptores no? Podrías hacerlo perfectamente, prueba un poco y si tienes dudas nos dices. Un saludo.

    • Richard Aguirre

    Buenas tardes soy programador pero quiero complementar mis estudios con electronica un amigo me obsequio como regalo el upgraded learning kit de arduino y estoy aprendiendo mucho con sus tutoriales. Ahora bien indico que me gusta probar por mi mismo he intentar que sin copiar mucho su codigo lograrlo por mi mismo. Hay algunos detalles tecnicos que no segui al pie de la letra pero logre implementar un relog a la “perfección”, entre comillas por que creo que estoy forzando el arduino.1.- No se por que pero creo que mi circuito esta un poco desordenado y que estoy invirtiendo los polos por que en la parte donde apago los pines que indican cada digito tuve que ponerlos en HIGH en vez de LOW para que apagaran. 2.- no implemente los Transistores. 3.- aun asi me funciona jajaja que locura no.

    Codigo:
    int Hora=02; //Cambiar este dato para la hora
    int Min=00; //Cambiar este dato para los min
    byte Digit[10][7]=
    { //a b c d e f g
    {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,1,0,1,1} //9
    };

    int counterx=10;
    void setup() {
    // put your setup code here, to run once:

    for(int i=2;i<=13;i++)
    {
    pinMode(i,OUTPUT);
    }
    }

    void loop() {
    int n = millis() / 60000 ; // Lo pasamos a segundos
    int segundos = n % 60 ;
    int minutos = n / 60 ;

    int k = minutos * 100 + segundos ;
    k=k+(Hora*100)+Min;
    CalculaDigitos(k) ;

    }

    void Display(int pos,int N)
    {
    digitalWrite(9 ,HIGH); // Apaga todos los digitos
    digitalWrite(10,HIGH);
    digitalWrite(11,HIGH);
    digitalWrite(12,HIGH);
    for (int j=0;j<=6;j++)
    {
    int valor=Digit[N][j];
    digitalWrite(j+2,valor);

    }

    digitalWrite(pos+9,LOW);

    }

    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);
    Display(2 , Digit2);
    Display(1 , Digit1);
    Display(0 , Digit0);

    }

    • Hola Richard, e sun plcer saber que avanzas, pero hemos tenido que dejar de revisar programas porque snecillamente no nos d ala vida. Prueba a comentarlo en el foro a ver si alguien se anima

  • Hola

    Estoy que me sale humo, intentando un contavueltas (Ascendente,descendente) mediante dos pulsadores y no lo logro con el problema añadido que son dos displays grandes de 10 cm y trabajan a una tensión de 10 v. Me puedes ayudar con el programa y la conexión ?
    Muchas gracias.
    Josep

    • No nos das muchas pistas Josep

      • Hola de nuevo y gracias por responder.

        Estoy intentando diseñar un contavueltas para las carreras de Dirt Track de las que por afición soy cronometrador y siempre veo sufrir al compañero de turno bajando las vueltas con unas plastificaciones con anillas y así poder hacer un regalo al club de mis amores MOTO CLUB SEGRE.

        No hace mucho sigo tu tutorial y agradecerte lo que ayuda y enseña, así que decidí hacer un paso adelante.

        Como dices tu en tus tutoriales , hay que ser practico, así que encontré un programa que me valía ( esto ha sido después del primer comentario).

        El problema de la programación y los pulsadores es que a veces te sube dos dígitos o te los baja, hice un antirrebote físico con una resistencia y un condensador, pero como es difícil saber el tiempo que tienes que poner el dedo en el pulsador para que no te suba o baje un dígito de mas.

        Adjunto el programa a ver si me puedes ayudar.

        #define A 2
        #define B 3
        #define C 4
        #define D 5
        #define E 6
        #define F 7
        #define G 8

        // Pulsadoes boton conectados a pines 9 y 10
        #define BTN1 14 //pulsador a A0
        #define BTN2 15 //pulsador A1
        #define led 13
        // Pines comunes de cada display de anodo comun
        #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 };

        const byte numbers[10] = { 0b1000000, 0b1111001, 0b0100100, 0b0110000, 0b0011001, 0b0010010, 0b0000010, 0b1111000, 0b0000000, 0b0010000};

        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, LOW);
        digitalWrite(BTN2, LOW);
        pinMode(CA1, OUTPUT);
        pinMode(CA2, OUTPUT);
        pinMode(led, OUTPUT);

        // digit1 = 9; digit2 = 10;

        }

        void loop()
        {
        // chequea boton1. Incrementa
        int val1 = digitalRead(BTN1);
        if (val1 == HIGH)
        {
        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);
        }

        // cheque boton2. Decrementa
        int val2 = digitalRead(BTN2);
        if (val2 == HIGH)
        {
        if (digit1 >= 0)
        {
        if (digit1 < 0)
        {
        digit1 = 0;
        }
        digit1–;
        }
        if(digit1 < 0)
        {
        digit1 = 9;
        if (digit2 < 0)
        {
        digit2 = 0;
        }
        digit2–;
        }
        if (digit2 < 0)
        {
        digit2 = 9;
        }
        }

        // 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);
        }

        void lightDigit2(byte number)
        {
        digitalWrite(CA1, HIGH);
        digitalWrite(CA2, LOW);
        lightSegments(number);
        }

        void lightSegments(byte number)
        {
        for (int i = 0; i < 7; i++)
        {
        int bit = bitRead(number, i);
        digitalWrite(segs[i], bit);
        }
        }

        El otro problema que comente de los displays de 7 segmentos de 10 cm de altura, ánodo común y tensión de alimentación de 8,4 a 10 v lo he solventado con los magníficos transistores NPN 2N2222 .

        Me puedes ayudar con el antirebote del programa para que si me paso un poquito con el dedo en el pulsador no me suba o baje dos dígitos con una sola pulsación.

        Muchas gracias por delante y si puedes ho te interesa te puedo conseguir una invitación para el Dirt Track de Barcelona este fin de semana.

        PD. Comenta a tu departamento de envíos , que hice un pedido (que llego rápido y bien ) y en la tarjeta del pedido había mezclado dirección de facturación con dirección de envió. El transportista me llamo y no hubo ningún problema.
        Si quieres por el email te lo puedo concretar un poco mas .

        Muchas gracias de nuevo.

  • Ivan tendras algun texto de referencia para saber como se utiliza el “void CalculaDigitos” ???

  • Hola Ivan, gracias por contestar.
    lo que quiero hacer es contador que “cuente” el paso de objetos a partir de la señal de un sensor. Ya he hecho la modificacion conforme a tu recomendacion, no estoy del todo seguro si la estè haciendo bien (obviament no, por que aun no me queda jeje), checa:

    void loop()
    {
    CalculaDigitos(valor);

    if (boton==HIGH)
    valor=(digitalRead, boton);

    valor++;
    }
    //declaradas mis variables globales int valor, int boton

    • Hola Tomás, esta es la función , la tienes en esta misma sesión: 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);
      Display(2 , Digit2);
      Display(1 , Digit1);
      Display(0 , Digit0);
      }

      Lo que tendrías que hacer es pasarle un valor que comience en 1 y que se incremente en 1 cada vez que aprietes el botón. Eso sí, me he fijado en la función y tienes que multiplicarlo por diez para que te encaje como un segundo cada pulsación. O sea o empezar en 10 y sumarle 10 con cada pulsación, o empezar en uno y sumarle uno en cada pulsación y multiplicarlo por diez antes de los cálculos. Si tienes alguna duda dime. Un saludote!

  • Hola,
    me podria orientar un poco sobre una duda, he tratado de modificar el programa para que el display cuente por cada pulso que dè un boton, haciendo pruebas he modificado el tiempo de millis y si responde a el cambio, por lo que pareciera que millis es el que controla el cambio, solo que no entiendo bien como trabaja esta funciona y no encuentro donde meter el pulso del boton.

    • Hola Tomás, no estoy seguro de entenderte del todo, pero si lo que quieres es que sume un segundo cada vez que pulsas un botón lo que tendrías que cambiar es el loop(). En vez de pasarle a la función CalculaDigitos( millis() / 100); le pasarías algo así como CalculaDigitos(valor);
      Con esto solo tendrías que meter un if para detectar la pulsación (quitando el rebote) y sumar 1 a la variable dentro de ese if.
      Un saludo!

    • Lucho

    Hola, muy bueno el tutorial!!!

    Te hago una consulta, si quiero usar este mismo metodo de multiplexado pero en un display grande, o sea un display armado por mi de 4 digitos de 7 segmentos pero de serie de 5 leds de 5mm por segmentos, como debo calcular el consumo, entiendo como conectarlos y que debo usar algún transistor para usarlos a un voltaje mayor al que trabaja el Arduino pero me refiero que si multiplexando debo calcular el consuma de un solo display o el delos 4 encendidos, se entiende?

    En limpio:

    Display grande.
    – Usaría leds de 2volt rojos de 20 mA. en series de a 5 por cada display, o sea que seria cada display de 7 segmentos de 5 leds en serie.

    Cuanto seria el voltaje de mi fuente si multiplexo esos 4 display.

    Gracias!!!

    • No m eatrevo a decirte gran cosa sin entrar en pruebas pero en principio deberia funcionar, el consumo dependera un poco de las necesidades de la electronica que uses pero no deberia haber grandes problemas

    • Carlos Piles

    ¿No seria conveniente poner en serie una resistencia de 220 ó 330 Omh entre los pines del arduino y los segmentos de led del display? Con el montaje mostrado, da la sensacion que si cometemos un error en el programa y no multiplexamos correctamente, la intensidad que pasara por el led será muy alta y o fundirá el led o el arduino; ya que los transistores en modo activado no reducen voltaje ni limitan la intensidad. No digo de poner la resistencia en los catodos en serie con los transistores, porque el brillo disminuiria conforme aumenta el numero de segmentos. ¿O es que el display ya incorpora las resistencias internamnete? Otra solucion seria utilizar analogWrite() en los pines 9-12 para controlar el brillo del display (o variar el ciclo activo de multiplexado con delayMicroseconds())

    • tienes toda la razonn carlos. fijate que el primer diagrama incluye una resistencia de 330ohm en el pin 12 que es el catodom comun por el que circula roda la,corriente y i
      limita sumintensidad

  • BUENAS noches, He realizado un pequeño cubo led 4x4x4 capa inferior (Led rojo ultrabrillante), segunda capa (Led Azul Ultrabrillante), Tercera capa Color Blanco y cuata capa verde, intento encender los cuatro Niveles (capas) y solo enciende la primera capa (color Rojo), pero también se puede encender las capas, 2,3 y 4 juntas pero no los rojos, cada capa esta controlada por un Transistor 3904 con una resistencia de saturación de 160 ohmios conectada a la salida del puerto c del pic 16f877A, las 16 columnas están conectadas por medio de una resistencia de160 ohmios al pic 16f877A, quisiera saber por que no encienden las cuatro capas juntas

    • Hola Efrain, yo te aconsejo que postees tu proyecto en el foro explicándolo lo mejor posible, para que te podamos ayudar un poco entre todos.

  • Hola, me gustaría saber como seria el programa para hacer una cuenta atrás. He intentado hacer esto:

    void loop()
    {
    int n = millis() / 1000 ;
    int segundos = n % 60 ;
    int minutos = n / 60 ;

    int k = 1000 – minutos * 100 – 40 – segundos + 0 ;
    CalculaDigitos(k) ;
    }

    pero entonces en vez de 10 minutos me pone 9 minutos 60 segundos.

  • Hola hay alguna forma de fijar un tiempo con switchs y que luego suene a ese tiempo, algo asi como un despertador ?

    • Hola Fran a que swithes te refieres?

    • Garser

    Una pregunta sabe como podria yo agregarle interrupciones a cada display para que se reinicie en cero?

    • No estoy muy seguro de lo que me preguntas

  • Hola de nuevo, admi, por aquí ando con los displays. Muy buenos los tutos y esclarecedores (ya ni les tengo pánico a los transistores…).

    Bueno, solo un par de cosas.

    1.- Siguiendo tu tuto, coge el array de los números de la sesión anterior, pero cuando lo ponía en marcha, algunos dígitos no salían correctos (el 3 al revés, al 4 le faltaba un led, el 6 era un 9, etc.). Esto está solucionado, cambiando los 1 y 0 gracias a la maqueta del tuto anterior (que ilustra perfectamente las cadencias de los leds), y ahora se ven correctamente.

    El display que uso no tiene el mismo patillaje que el tuyo, y lo descifré a base de buscar el común ir haciendo pruebas. Podría ser que al no ser el mismo patillaje, las combinaciones de 1 y 0 sean diferentes, y por eso he tenido que adaptarlas?

    2.- El display hace el conteo de segundos y minutos correctamente, hasta que llega a los 3 segundos. Al mostrar los dígitos 0.3.0, se reinicia el solito. Le he puesto una alimentación externa, por si acaso, pero hace lo mismo. No se si es un problema del programa, o a que puede deberse. Tienes idea de que problema puede haber?

    Gracias por la ayuda, e insisto, magníficos tutoriales.

    Saludos

    • Asi es Jauma,
      Dependiendo de que tu displaya sea de anodo comun o catodo comun hay que invertir el 0o el 1.
      En cuanto al reseteo al llegar a 3 minutos parece mas un tema de soft

      • Al programa? A que software te refieres?

  • for (int i= 0 ; i<8 ; i++) // Esto no cambia de la session anterior
    digitalWrite(i+2 , Digit[N][i]) ;

    Me parece que debería ser i<7

    En el ejercicio anterior trabajando con el D.P. (conectado al pin 9) se podía hacer,
    pero ahora el pin 9 es la activación del primer display.

    Para los que se le encienden todos los displays y le cambian de intensidad, a mi se me ha
    soluccionado haciendo este cambio.

    • Muchas gracias por la correccion Jose

    • Fernando

    Perdón, se me olvidaba un detalle: en mi esquema no he utilizado transistores. Dado que trabajando a 5V y con una resistencia de 330 Ohmios tenemos una corriente inferior a 10mA, se puede comandar los displays directamente desde la salida digital.

    De esta forma cada terminal común se conecta mediante una resistencia de 330 Ohms a la salida digital que comandará cada dígito.

    En cátodo común un 0 activará el dígito y en ánodo común será un 1 para la activación del dígito.

    Con los segmentos ocurre al contrario, en cátodo común será un 1 el que active los segmentos mientras que en ánodo común se hará con un 0.

    Esto se controla fácilmente mediante xor o not de la variable CommonTerminal que valdrá 1 para ánodo común y 0 para cátodo común.

    Un saludo.

    • Fernando

    Hola, acabo de recibir mi Arduino Nano y como cosa chula me he puesto a pincharle un display de 7 segmentos que tenía por ahí, el caso es que me he dicho que para que currarme todo si alguien ya lo habrá hecho y así es como he llegado aquí.

    Total, que una vez funcionando el tema, teniendo en cuenta que mi display es de ánodo común, le he pegado un repaso al código y este es el resultado:

    byte Digit[10][8] = {
    { 1, 1, 1, 1, 1, 1, 0, 0 }, // 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
    };

    byte Segments[] = { 2, 3, 4, 5, 6, 7, 8 };
    byte Digits[] = { 9, 10, 11, 12 };

    #define Anode 1
    #define Cathode 0
    int CommonTerminal = Anode;

    void setup() {
    for (int i = 0; i < sizeof(Segments); i++) pinMode(Segments[i], OUTPUT);
    for (int i = 0; i < sizeof(Digits); i++) pinMode(Digits[i], OUTPUT);
    }

    void Display (int Num) {
    for (int d = 0; d < sizeof(Digits); d++) {
    int N = (Num % int(pow(10, d + 1))) / pow(10, d);
    for (int i = 0; i < sizeof(Digits); i++) digitalWrite(Digits[i], not CommonTerminal);
    for (int i = 0; i < sizeof(Segments); i++) digitalWrite(Segments[i], CommonTerminal xor Digit[N][i]);
    digitalWrite(Digits[d], CommonTerminal);
    }
    }

    void loop() {
    Display( millis() / 100);
    }

    Como se puede ver permito configurar dónde se conecta cada segmento y dónde cada dígito del display de forma fácil, también permite definir de manera fácil si el display es de ánodo común o de cátodo común.

    Un saludo

    • Muchas gracias por tu aporte Fernando

  • Disculpe sabe como hacer el contador pero con botones para hacerlo decendente y acendente???

    • Hola Ernesto, Naturalmente que puedes hacer eso. basta con que mezcles los tutoriales de botones y este del display. SI te animas te echaremos una mano encantado y ademas si quieres lo publicamos como proyecto tuyo

Give a Reply

WordPress Anti-Spam by WP-SpamShield