Display de Mensajes Deslizantes con Matriz LED (4x 8×8 MAX7219) y Control de Velocidad con Potenciómetro

En la era digital, la comunicación efectiva y llamativa es fundamental. Este proyecto combina la versatilidad de la plataforma Arduino con la capacidad visual de las matrices de LED controladas por el chip MAX7219 para crear un display dinámico capaz de mostrar mensajes deslizantes de una manera cautivadora. Específicamente, utilizaremos un conjunto de cuatro módulos de matriz LED de 8×8 apilados verticalmente, lo que resulta en un área de visualización de 8 columnas por 32 filas. El mensaje, “Apóyanos en nuestras redes sociales”, se desplazará elegantemente de arriba hacia abajo, y lo más importante, el usuario tendrá control interactivo sobre la velocidad de este desplazamiento mediante un potenciómetro de 10k ohmios.

Este artículo detallado servirá como una guía completa para entusiastas de la electrónica, estudiantes y profesionales que busquen profundizar en la interconexión de microcontroladores y displays visuales, ofreciendo tanto la teoría como la implementación práctica, incluyendo el esquema de conexión y el código fuente comentado.



🔩Funcionamiento

El Cerebro del Sistema: Arduino Uno

El Arduino Uno es la plataforma de microcontrolador de código abierto elegida. Actúa como la Unidad Central de Procesamiento (CPU) de nuestra consola, ejecutando la lógica de juego, gestionando la física de las piezas (caída, rotación y colisión) y orquestando la comunicación con la pantalla y los controles.

  • Microcontrolador: ATmega328P. Este chip maneja el bucle principal (loop()) que constantemente verifica el tiempo de caída, las entradas de los botones y actualiza el display.
  • Pines Digitales: Los pines digitales son cruciales para dos funciones:
    1. Comunicación SPI (Pines 10, 11, 12): Se utilizan para enviar datos a la matriz de LEDs.
    2. Entradas analógicas, (Pines A0, A1, A2, A3, A4, A5): Permiten al usuario ajustar la velocidad del texto.
  • Memoria (RAM): Aproximadamente 2 KB de SRAM. Esto es un factor limitante, ya que aquí se almacena la matriz de juego interna (board[8][32]), las variables de posición de la pieza y las variables de control del juego.

El Chip Controlador MAX7219

El MAX7219 es un controlador de display LED de cátodo común. Su función principal es multiplexar las 64 LEDs de cada matriz 8×8, controlando individualmente cada LED mientras minimiza el número de cables y el consumo de energía del microcontrolador.

  • Comunicación: Utiliza el protocolo SPI (Serial Peripheral Interface). Esto permite controlar hasta 8 dispositivos encadenados (como nuestras 4 matrices) usando solo tres pines de Arduino (DIN, CLK, CS), un ahorro masivo comparado con intentar controlar los 4 x 64 = 256 LEDs directamente.
  • Almacenamiento: Cada MAX7219 tiene un registro de memoria interna que almacena el estado de los 64 píxeles, liberando a la pequeña RAM del Arduino de esta tarea.
  • Encadenamiento (Daisy-Chain): La salida de datos (DOUT) de un MAX7219 se conecta a la entrada (DIN) del siguiente. Esto permite que el Arduino envíe un flujo continuo de 32 bytes de datos (8 bytes por módulo) para actualizar toda la pantalla 32×8.

Los Módulos de Matriz de LEDs 8×8

Cada módulo contiene 64 LEDs y el chip MAX7219. Al encadenar cuatro módulos, obtenemos una gran superficie para visualizar el juego.

PINES del módulo Matriz 8×8 (MAX7219)

Pin módulo Matriz 8×8 (MAX7219)ProtocoloNotas Importantes
VCCAlimentaciónUso de 5V.
GNDTierraConexión de referencia.
CS (Chip Select)SS para SPISelecciona el módulo
DIN (Data In)MOSI para SPIEntrada de datos.
CLK (Clock)SCK para SPSeñal de reloj

🔨Componentes

ComponenteCantidadEspecificaciónFunción
Placa Arduino1Arduino Uno, Nano, etc.Control de componentes(cerebro)
Matriz LED48×8LEDs para mostrar los símbolos
Módulo multiplexor4MAX7219Controlador de matriz LED con interfaz SPI
Potenciómetro110kΩAjustar velocidad
Cables de conexiónnUnir los componentes


🔌Conexiones

Conexión módulo Display 8×8(MAX7219)

MAX7219 PinArduino Pin
VCC5v
GNDGND
DIND12
CSD10
CLKD11

Conexión de Potenciómetro:

Terminal del PotenciómetroArduino Pin
Extremo 15V (VCC)
Terminal Central (Wiper)A0 (Entrada Analógica 0)
Extremo 2GND (Tierra)

0️⃣Código

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#include <Arduino.h>
#include <SoftwareSerial.h>

void readBT();

SoftwareSerial bt(3,2);     // donde Rx = 3, Tx = 2
// Utilice la biblioteca Parola para desplazarse por el texto en la pantalla
//
// Demuestra el uso de la función de desplazamiento para mostrar el texto recibido 
// desde la interfaz serial
//
// El usuario puede ingresar texto en el monitor serial y esto se mostrará como un 
// mensaje desplazable en la pantalla. 
// La velocidad de la pantalla se controla mediante un potenciómetro en la entrada analógica SPEED_IN(A0). 
// La dirección de desplazamiento se controla mediante un interruptor en la entrada digital DIRECTION_SET. 
// La inversión ON/OFF se configura mediante un interruptor en la entrada digital INVERT_SET.
//
// UISwitch La biblioteca se puede encontrar en https://github.com/MajicDesigns/MD_UISwitch
// MD_MAX72XX La biblioteca se puede encontrar en https://github.com/MajicDesigns/MD_MAX72XX
//

#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>

// Establezca en 1 si estamos implementando la interfaz de usuario pot, switch, etc.
#define USE_UI_CONTROL 1

#if USE_UI_CONTROL
#include <MD_UISwitch.h>
#endif

// Activar declaraciones de depuración en la salida serial
#define DEBUG 0

#if DEBUG
#define PRINT(s, x) { Serial.print(F(s)); Serial.print(x); }
#define PRINTS(x) Serial.print(F(x))
#define PRINTX(x) Serial.println(x, HEX)
#else
#define PRINT(s, x)
#define PRINTS(x)
#define PRINTX(x)
#endif

const int PIN_POTENCIOMETRO = A0;
// Definir el número de dispositivos que tenemos en la cadena y la interfaz de hardware
// NOTA: Estos números de PIN probablemente no funcionarán con su hardware
// y es posible que sea necesario adaptarlos.
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
#define CLK_PIN   11
#define DATA_PIN  12
#define CS_PIN    10

// HARDWARE SPI
// MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
MD_Parola P = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);

// Parámetros de desplazamiento
#if USE_UI_CONTROL
const uint8_t SPEED_IN = A0;
const uint8_t DIRECTION_SET = 8;  // cambiar el efecto
const uint8_t INVERT_SET = 9;     // cambiar la inversión

const uint8_t SPEED_DEADBAND = 5;
#endif // USE_UI_CONTROL

uint8_t scrollSpeed = 75;    // valor de retardo de fotograma predeterminado
textEffect_t scrollEffect = PA_SCROLL_LEFT;
textPosition_t scrollAlign = PA_LEFT;
uint16_t scrollPause = 3000; // en milisegundos

// Buffers mensajes globales compartidos por las funciones seriales y de desplazamiento
#define	BUF_SIZE	75
char curMessage[BUF_SIZE] = { "" };
char newMessage[BUF_SIZE] = { "Siguenos en nuestras redes sociales" };
bool newMessageAvailable = true;

#if USE_UI_CONTROL

MD_UISwitch_Digital uiDirection(DIRECTION_SET);
MD_UISwitch_Digital uiInvert(INVERT_SET);

void doUI(void)
{
  // Establece la velocidad si ha cambiado
  {
    int16_t speed = map(analogRead(SPEED_IN), 0, 1023, 50, 150);

    if ((speed >= ((int16_t)P.getSpeed() + SPEED_DEADBAND)) ||
      (speed <= ((int16_t)P.getSpeed() - SPEED_DEADBAND)))
    {
      P.setSpeed(speed);
      scrollSpeed = speed;
      PRINT("\nChanged speed to ", P.getSpeed());
    }
  }

  if (uiDirection.read() == MD_UISwitch::KEY_PRESS) // DIRECCIÓN DE DESPLAZAMIENTO
  {
    PRINTS("\nChanging scroll direction");
    scrollEffect = (scrollEffect == PA_SCROLL_LEFT ? PA_SCROLL_RIGHT : PA_SCROLL_LEFT);
    P.setTextEffect(scrollEffect, scrollEffect);
    P.displayClear();
    P.displayReset();
  }

  if (uiInvert.read() == MD_UISwitch::KEY_PRESS)  // MODO INVERTIR
  {
    PRINTS("\nChanging invert mode");
    P.setInvert(!P.getInvert());
  }
}
#endif // USE_UI_CONTROL

void readSerial(void)
{
  static char *cp = newMessage;

  while (Serial.available())
  {
    *cp = (char)Serial.read();
    if ((*cp == '\n') || (cp - newMessage >= BUF_SIZE-2)) // Carácter de fin de mensaje o búfer lleno
    {
      *cp = '\0'; // Fin de la cadena
      // Reiniciar el índice para la próxima ola de llenado y marcar que tenemos un mensaje en espera
      cp = newMessage;
      newMessageAvailable = true;
    }
    else  // mover el puntero del carácter a la siguiente posición
      cp++;
  }
}

void setup()
{
  Serial.begin(9600);
  bt.begin(9600);   // 9600 es la  velocidad de trasnferencia serial por defecto del modulo bluetooth HC05
  Serial.print("\n[Parola Scrolling Display]\nType a message for the scrolling display\nEnd message line with a newline");

#if USE_UI_CONTROL
  uiDirection.begin();
  uiInvert.begin();
  pinMode(SPEED_IN, INPUT);

  doUI();
#endif // USE_UI_CONTROL

  P.begin();
  P.displayText(curMessage, scrollAlign, scrollSpeed, scrollPause, scrollEffect, scrollEffect);
  P.setIntensity(15);
}

void loop()
{

#if USE_UI_CONTROL
  doUI();
#endif // USE_UI_CONTROL

  if (P.displayAnimate())
  {
    if (newMessageAvailable)
    {
      strcpy(curMessage, newMessage);
      newMessageAvailable = false;
    }
    P.displayReset();
  }
  readSerial();
  readBT();
}

void readBT(){
   static char *cp = newMessage;

  while (bt.available())
  {
    *cp = (char)bt.read();
    if ((*cp == '\n') || (cp - newMessage >= BUF_SIZE-2)) // Carácter de fin de mensaje o búfer lleno
    {
      *cp = '\0'; // fin de la cadena
      // Reiniciar el índice para la próxima ola de llenado y marcar que tenemos un mensaje en espera.
      cp = newMessage;
      newMessageAvailable = true;
    }
    else  // mover el puntero del carácter a la siguiente posición
      cp++;
  }
}


🖌️Diseños


🎬Videos


📑Conclusión

Este proyecto ha demostrado exitosamente la integración de un sistema de visualización de alta capacidad (matriz LED 8×32) con una interfaz de usuario analógica (el potenciómetro) controlada por el microcontrolador Arduino. La clave del éxito radica en la eficiencia del chip MAX7219 y la robustez de la librería MD_Parola, que simplifican el manejo de la complejidad inherente a la manipulación de 256 LEDs.

Logramos un sistema de comunicación visual dinámico que cumple con tres objetivos principales:

  1. Escalabilidad: Se utilizó la configuración daisy-chain de los módulos MAX7219, permitiendo expandir fácilmente el área de visualización.
  2. Interactividad: El potenciómetro ofrece un control intuitivo y en tiempo real sobre la variable de tiempo, lo que añade una capa de personalización y respuesta inmediata al sistema.
  3. Comunicación Efectiva: El efecto de deslizamiento vertical (PA_SLIDE_DOWN) ofrece una presentación de mensaje llamativa y profesional.

En esencia, el proyecto transforma una serie de componentes electrónicos en un display informativo y ajustable, listo para ser utilizado como una herramienta eficaz de promoción o para la visualización de datos en cualquier entorno. La implementación de la lógica de mapeo (map( )) es un claro ejemplo de cómo el hardware analógico se traduce perfectamente en parámetros de control de software digital.


Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Carrito de compra