"Cartel luminoso" con display de 4 digitos y 7 segmentos

¡Hola! Aunque soy nuevo en Arduino quería compartir este programa que he hecho ya que me ha quedado muy chulo :smiley: No solo para que otros lo prueben y se diviertan un rato si no también para que me puedan decir fallos o cosas a mejorar :slight_smile:

Tengo que añadir que esta es mi primera toma de contacto con Arduino. Tras hacer el "Hola mundo" de los leds que se encienden y parpadean, me metí de lleno en este proyectito ya que me encantan los retos y debo ser masoca xD

Aun así, me gustaría que fuerais lo mas críticos posible, ya que es la única manera de aprender bien y tomar buenos hábitos. Y tranquilos, aunque no tengo ni idea de electrónica, llevo 2 años estudiando programación así que no me voy a asustar con lo que me digáis 8)

¡Gracias!

Se puede ver el "proyecto" montado y funcionando pinchando aquí

// Autor: RASK18

// Usamos define para constantes a sustituir y
// lo de C++ para constantes y variables a utilizar

// Pines del display

//     12 11 10  9  8  7
//      |  |  |  |  |  |
//  ------------------------
// |  ==    ==    ==   ==   |
// |  == o  == o  == o == o |
//  ------------------------
//      |  |  |  |  |  |
//      1  2  3  4  5  6

// Secciones de cada display

//    -------
//   |   A   |
//  f|       |B
//   |---G---|
//  E|       |C
//   |   D   |
//    -------  [] P

// Define: Seccion - Pin de Arduino / Pin del display
#define A 6 // 11
#define B 2 // 7
#define C 10 // 4
#define D 12 // 2
#define E 13 // 1
#define f 5 // 10 La F mayuscula no te deja y no se porque...
#define G 9 // 5
#define P 11 // 3

// Catodos comunes
#define CC1 7 // 12
#define CC2 4 // 9
#define CC3 3 // 8
#define CC4 8 // 6

const byte pines[12] = { A, B, C, D, E, f, G, P, CC1, CC2, CC3, CC4 };

//  A, B, C, D, E, f, G, P
const byte letras[41][8] = {
  { 0, 0, 0, 0, 0, 0, 0, 0 }, // Nada, espacio
  { 1, 1, 1, 0, 1, 1, 1, 0 }, // A
  { 0, 0, 1, 1, 1, 1, 1, 0 }, // b
  { 0, 0, 0, 1, 1, 0, 1, 0 }, // c
  { 0, 1, 1, 1, 1, 0, 1, 0 }, // d
  { 1, 0, 0, 1, 1, 1, 1, 0 }, // E
  { 1, 0, 0, 0, 1, 1, 1, 0 }, // F
  { 1, 1, 1, 1, 0, 1, 1, 0 }, // g
  { 0, 0, 1, 0, 1, 1, 1, 0 }, // h
  { 0, 1, 1, 0, 0, 0, 0, 0 }, // I
  { 0, 1, 1, 1, 1, 0, 0, 0 }, // J
  { 1, 0, 0, 1, 1, 1, 0, 0 }, // C
  { 0, 0, 0, 1, 1, 1, 0, 0 }, // L
  { 1, 1, 1, 0, 1, 1, 0, 0 }, // N
  { 0, 0, 1, 0, 1, 0, 1, 0 }, // n
  { 1, 0, 1, 0, 1, 0, 1, 0 }, // ñ
  { 0, 0, 1, 1, 1, 0, 1, 0 }, // o
  { 1, 1, 0, 0, 1, 1, 1, 0 }, // P
  { 1, 1, 1, 0, 0, 1, 1, 0 }, // q
  { 0, 0, 1, 0, 0, 0, 1, 0 }, // r
  { 1, 0, 1, 1, 0, 1, 1, 0 }, // S
  { 0, 0, 0, 1, 1, 1, 1, 0 }, // t
  { 0, 1, 1, 1, 1, 1, 0, 0 }, // U
  { 0, 0, 1, 1, 1, 0, 0, 0 }, // v
  { 0, 0, 1, 1, 1, 0, 0, 0 }, // v
  { 0, 1, 1, 0, 1, 1, 1, 0 }, // X
  { 0, 1, 1, 1, 0, 1, 1, 0 }, // y
  { 1, 1, 0, 1, 1, 0, 1, 0 }, // Z
  { 0, 0, 0, 0, 0, 0, 0, 1 }, // .
  { 0, 1, 0, 1, 1, 0, 1, 0 }, // ¿
  { 1, 1, 0, 0, 1, 0, 1, 1 }, // ?
  { 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
};

const char abecedario[41] = {
  ' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
  'M', 'N', 'Ñ', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
  'Z', '.', '¿', '?', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
};

char aMostrar;
byte mostrando[4] = { 0, 0, 0, 0 }; // Posiciones de las letras mostrandose
bool esperando = true;

void setup() {
  Serial.begin(9600);

  for (byte i = 0; i < 12; i++) {
    pinMode(pines[i], OUTPUT);
  }

  for (byte i = 8; i < 12; i++) // Catodos a HIGH para que no muestren nada
  {
    digitalWrite(pines[i], HIGH);
  }
}

void loop() {
  if (!(mostrando[0] + mostrando[1] + mostrando[2] + mostrando[3] == 0 && Serial.available() == 0)) {
    actualizar();
    pintar();
  }
  else {
    esperar();
  }
}

void actualizar() {
  mostrando[0] = mostrando[1]; // Los muevo
  mostrando[1] = mostrando[2];
  mostrando[2] = mostrando[3];

  if (Serial.available() > 0) {
    aMostrar = Serial.read();
    aMostrar = toUpperCase(aMostrar);

    if (aMostrar == ',') {
      aMostrar = '.';
    }

    for (byte i = 0; i < 41; i++)
    {
      if (abecedario[i] == aMostrar) {
        mostrando[3] = i; // Posicion, no letra
        break;
      }
    }

  }
  else {
    mostrando[3] = 0;
  }
}

void pintar() {
  for (byte i = 0; i < 20; i++) // 20 fps
  {
    for (byte j = 0; j < 4; j++) // 4 displays
    {
      for (byte k = 0; k < 8; k++) // 8 segmentos
      {
        if (letras[(mostrando[j])][k] == 1) {
          digitalWrite(pines[k], HIGH);
        }
        else {
          digitalWrite(pines[k], LOW);
        }
      }

      digitalWrite(pines[(j + 8)], LOW); // Muestra el que es en la posicion
      delay(5);
      digitalWrite(pines[j + 8], HIGH); // Lo quita
    }
  }

}

void esperar() {
  if (esperando) {
    delay(1000);
    esperando = false;
  }
  else {

    for (byte i = 8; i < 12; i++) // Para que salga en todos los displays
    {
      digitalWrite(pines[i], LOW);
    }

    digitalWrite(P, HIGH);
    delay(1000);
    digitalWrite(P, LOW);
    esperando = true;

    for (byte i = 8; i < 12; i++) // Devuelvo a HIGH ya que son compartidos
    {
      digitalWrite(pines[i], HIGH);
    }

  }
}

PD: Dejo el código también aquí por si alguien prefiere copiar y pegar a descargar el adjunto :stuck_out_tongue:

Display4-7.ino (4.5 KB)

Ayudaría un esquema para entender toda la idea.

surbyte:
Ayudaría un esquema para entender toda la idea.

Editado :wink: ¿Se entiende mejor ahora con el vídeo surbyte? :stuck_out_tongue:

Muy bien, código elegante y corto

Jopapa:
Muy bien, código elegante y corto

Gracias :3

Muy buen trabajo!!

Hola.
Partiendo de que me parece muy bien realizado tu código (y seguramente más legible que los que acostumbro a parir yo :P), voy a tratar de ser, como pedías al principio, "duro" (mirado desde el lado constructivo, ¿eh? ;)).

Primero una aclaración:

#define f 5 // 10 La F mayuscula no te deja y no se porque...

Creo que es debido a que en el entorno arduino existe una macro que precisamente se llama F. La usamos para almacenar cadenas constantes en memoria flash, en lugar de cargarlas a la preciada ram. Igual te suena de haber visto, por ejemplo Serial.print(F("Hola, mundo"))

Ahora me pongo en plan "tacaño" (suelo hacerlo con mis propios códigos, ya que en arduino no estamos sobrados de nada)
¿En qué se podría "adelgazar" tu código?
Podrías haber utilizado 1/8 de memoria utilizada en tu array definiendo letras tal que así:

const byte letras[41]={0, // Nada, espacio
B11101110, //A
B00111110, // b
etc...

Y trabajar con los operadores de bit para interpretar qué segmentos hay que encender.

      byte letra=letras[(mostrando[j])];
      for (byte k = 0; k < 8; k++) // 8 segmentos
      {
          digitalWrite(pines[k], letra & B00000001);
          letra>>=1;
      }

Pero ya estamos hablando de nivel tacaño enfermizo :wink:
Saludos.

surbyte:
Muy buen trabajo!!

Gracias :slight_smile:

noter:
Hola.
Partiendo de que me parece muy bien realizado tu código (y seguramente más legible que los que acostumbro a parir yo :P), voy a tratar de ser, como pedías al principio, "duro" (mirado desde el lado constructivo, ¿eh? ;)).

Primero una aclaración:

#define f 5 // 10 La F mayuscula no te deja y no se porque...

Creo que es debido a que en el entorno arduino existe una macro que precisamente se llama F. La usamos para almacenar cadenas constantes en memoria flash, en lugar de cargarlas a la preciada ram. Igual te suena de haber visto, por ejemplo Serial.print(F("Hola, mundo"))

Ahora me pongo en plan "tacaño" (suelo hacerlo con mis propios códigos, ya que en arduino no estamos sobrados de nada)
¿En qué se podría "adelgazar" tu código?
Podrías haber utilizado 1/8 de memoria utilizada en tu array definiendo letras tal que así:

const byte letras[41]={0, // Nada, espacio

B11101110, //A
B00111110, // b
etc...




Y trabajar con los operadores de bit para interpretar qué segmentos hay que encender.



byte letra=letras[(mostrando[j])];
     for (byte k = 0; k < 8; k++) // 8 segmentos
     {
         digitalWrite(pines[k], letra & B00000001);
         letra>>=1;
     }




Pero ya estamos hablando de nivel tacaño enfermizo ;)
Saludos.

¡¡Muchas gracias noter!! No me sonaba para nada que la F se usaba para eso xD Pero parece útil así que la usaré mas a menudo para ahorrar RAM :smiley:

Y en cuanto a tu mejora, es justamente el nivel tacaño enfermizo que estaba buscando jajajajaj No sabia que las operaciones con bits (que no veía desde que iba a la ESO xD) se podían usar así :stuck_out_tongue: Tampoco conocía el ">>", he aprendido bastante :slight_smile:

Mañana editaré el código con tus cambios y lo volveré a subir para dejar el post actualizado, y si tengo tiempo empezaré con el siguiente que tengo pensado, que como es un poco mas grande tardaré mas, pero también lo compartiré cuando lo termine :wink:

Un saludo y gracias por el 1/8 de memoria ahorrado, es mucha memoria :3