.. note::

    ¡Hola, bienvenido a la comunidad de entusiastas de SunFounder Raspberry Pi, Arduino y ESP32 en Facebook! Sumérgete más profundamente en Raspberry Pi, Arduino y ESP32 con otros entusiastas.

    **¿Por qué unirse?**

    - **Soporte experto**: Resuelve problemas postventa y desafíos técnicos con la ayuda de nuestra comunidad y equipo.
    - **Aprende y comparte**: Intercambia consejos y tutoriales para mejorar tus habilidades.
    - **Vistas previas exclusivas**: Obtén acceso anticipado a anuncios de nuevos productos y avances.
    - **Descuentos especiales**: Disfruta de descuentos exclusivos en nuestros productos más recientes.
    - **Promociones festivas y sorteos**: Participa en sorteos y promociones de temporada.

    👉 ¿Listo para explorar y crear con nosotros? Haz clic en [|link_sf_facebook|] y únete hoy mismo!

.. _1.1.6_js:

1.1.6 Módulo de Matriz de LED
=====================================

Introducción
----------------

En este proyecto, aprenderás sobre el Módulo de Matriz de LED. Este módulo utiliza el controlador MAX7219 para manejar la Matriz de LED de 8 x 8.

Componentes Necesarios
---------------------------

En este proyecto, necesitamos los siguientes componentes. 

.. image:: ../img/list_dot.png

Es definitivamente conveniente comprar un kit completo, aquí está el enlace: 

.. list-table::
    :widths: 20 20 20
    :header-rows: 1

    *   - Nombre	
        - ELEMENTOS EN ESTE KIT
        - ENLACE
    *   - Kit Raphael
        - 337
        - |link_Raphael_kit|

También puedes comprarlos por separado en los enlaces a continuación.

.. list-table::
    :widths: 30 20
    :header-rows: 1

    *   - INTRODUCCIÓN DEL COMPONENTE
        - ENLACE DE COMPRA

    *   - :ref:`cpn_gpio_extension_board`
        - |link_gpio_board_buy|
    *   - :ref:`cpn_breadboard`
        - |link_breadboard_buy|
    *   - :ref:`cpn_wires`
        - |link_wires_buy|
    *   - :ref:`cpn_dot_matrix`
        - |link_led_matrix_buy|

Diagrama Esquemático
-------------------------

================== ======== ======== ====
Nombre del T-Board físico   wiringPi BCM
SPIMOSI            Pin 19   12       MOSI
SPICE0             pin 24   10       CE0
SPISCLK            Pin 23   14       SCLK
================== ======== ======== ====

.. image:: ../img/schematic_dot.png

Procedimientos Experimentales
---------------------------------

**Paso 1:** Construye el circuito.

.. image:: ../img/1.1.6fritzing.png

.. note::

    Activa el SPI antes de comenzar el experimento, consulta :ref:`spi_configuration` para más detalles. 

**Paso 2:** Ve a la carpeta del código.

.. raw:: html

   <run></run>

.. code-block:: 

    cd ~/raphael-kit/nodejs/

**Paso 3:** Instala las dependencias.

.. raw:: html

   <run></run>

.. code-block:: 

    sudo npm install spi-device

**Paso 4:** Ejecuta el código.

.. raw:: html

   <run></run>

.. code-block:: 

    sudo node max7219_led_matrix.js 

Después de ejecutar el código, la Matriz de LED muestra del 0 al 9 y de la A a la Z en secuencia.

**Código**

.. code-block:: js

    const Gpio = require('pigpio').Gpio;
    const spi = require('spi-device');

    class MAX7219_LED_MATRIX {
        constructor(bus, device) {
            this.bus = bus;
            this.device = device;
        }
        delay(ms) {
            return new Promise((resolve, reject) => {setTimeout(resolve, ms)});
        }

        async write(addr, data) {
            return new Promise((resolve, reject)=>{
                const max7219 = spi.open(this.bus, this.device, (err)=>{
                    if (err) reject(err);
            
                    const message = [{
                        sendBuffer: Buffer.from([addr, data]),
                        receiveBuffer: Buffer.alloc(2),
                        byteLength: 2,
                        speedHz: 20000
                    }];
        
                    max7219.transfer(message, (err, message)=>{
                        if (err) reject(err);
                        else resolve();
                    })
                })
            })
        }
        async init() {
            await this.write(0x09, 0x00);
            await this.write(0x0a, 0x03);
            await this.write(0x0b, 0x07);
            await this.write(0x0c, 0x01);
            await this.write(0x0f, 0x00);
        }
    }

    const DISP=[
        [0x3C,0x42,0x42,0x42,0x42,0x42,0x42,0x3C],//0
        [0x08,0x18,0x28,0x08,0x08,0x08,0x08,0x08],//1
        [0x7E,0x2,0x2,0x7E,0x40,0x40,0x40,0x7E],//2
        [0x3E,0x2,0x2,0x3E,0x2,0x2,0x3E,0x0],//3
        [0x8,0x18,0x28,0x48,0xFE,0x8,0x8,0x8],//4
        [0x3C,0x20,0x20,0x3C,0x4,0x4,0x3C,0x0],//5
        [0x3C,0x20,0x20,0x3C,0x24,0x24,0x3C,0x0],//6
        [0x3E,0x22,0x4,0x8,0x8,0x8,0x8,0x8],//7
        [0x0,0x3E,0x22,0x22,0x3E,0x22,0x22,0x3E],//8
        [0x3E,0x22,0x22,0x3E,0x2,0x2,0x2,0x3E],//9
        [0x8,0x14,0x22,0x3E,0x22,0x22,0x22,0x22],//A
        [0x3C,0x22,0x22,0x3E,0x22,0x22,0x3C,0x0],//B
        [0x3C,0x40,0x40,0x40,0x40,0x40,0x3C,0x0],//C
        [0x7C,0x42,0x42,0x42,0x42,0x42,0x7C,0x0],//D
        [0x7C,0x40,0x40,0x7C,0x40,0x40,0x40,0x7C],//E
        [0x7C,0x40,0x40,0x7C,0x40,0x40,0x40,0x40],//F
        [0x3C,0x40,0x40,0x40,0x40,0x44,0x44,0x3C],//G
        [0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44],//H
        [0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x7C],//I
        [0x3C,0x8,0x8,0x8,0x8,0x8,0x48,0x30],//J
        [0x0,0x24,0x28,0x30,0x20,0x30,0x28,0x24],//K
        [0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7C],//L
        [0x81,0xC3,0xA5,0x99,0x81,0x81,0x81,0x81],//M
        [0x0,0x42,0x62,0x52,0x4A,0x46,0x42,0x0],//N
        [0x3C,0x42,0x42,0x42,0x42,0x42,0x42,0x3C],//O
        [0x3C,0x22,0x22,0x22,0x3C,0x20,0x20,0x20],//P
        [0x1C,0x22,0x22,0x22,0x22,0x26,0x22,0x1D],//Q
        [0x3C,0x22,0x22,0x22,0x3C,0x24,0x22,0x21],//R
        [0x0,0x1E,0x20,0x20,0x3E,0x2,0x2,0x3C],//S
        [0x0,0x3E,0x8,0x8,0x8,0x8,0x8,0x8],//T
        [0x42,0x42,0x42,0x42,0x42,0x42,0x22,0x1C],//U
        [0x42,0x42,0x42,0x42,0x42,0x42,0x24,0x18],//V
        [0x0,0x49,0x49,0x49,0x49,0x2A,0x1C,0x0],//W
        [0x0,0x41,0x22,0x14,0x8,0x14,0x22,0x41],//X
        [0x41,0x22,0x14,0x8,0x8,0x8,0x8,0x8],//Y
        [0x0,0x7F,0x2,0x4,0x8,0x10,0x20,0x7F],//Z
    ];

    lm = new MAX7219_LED_MATRIX(0, 0);

    async function main(){
        lm.init();
        while(1){
            for(let j=0;j<36;j++){
                for(let i=1;i<9;i++){
                    lm.write(i, DISP[j][i-1]);
                }
                await lm.delay(1000);
            }
        }
    }
    main(); 

**Explicación del Código**

.. code-block:: js

    const spi = require('spi-device');

Importar los módulos necesarios para la comunicación SPI.

.. note::
    Cuando tengas múltiples dispositivos que necesiten comunicación SPI, solo conecta los pines CS a diferentes pines.

.. code-block:: js

    class MAX7219_LED_MATRIX {
        constructor(bus, device) {
            this.bus = bus;
            this.device = device;
        }
        delay(ms) {
            return new Promise((resolve, reject) => {setTimeout(resolve, ms)});
        }

        async write(addr, data) {
            return new Promise((resolve, reject)=>{
                const max7219 = spi.open(this.bus, this.device, (err)=>{
                    if (err) reject(err);

                    const message = [{
                        sendBuffer: Buffer.from([addr, data]),
                        receiveBuffer: Buffer.alloc(2),
                        byteLength: 2,
                        speedHz: 20000
                    }];

                    max7219.transfer(message, (err, message)=>{
                        if (err) reject(err);
                        else resolve();
                    })
                })
            })
        }

Implementar una clase ``MAX7219_LED_MATRIX``, y la función ``write()`` encapsulada en ella puede iluminar la matriz.

.. note::
    La palabra clave ``async`` se usa para modificar la función y generalmente se combina con la palabra clave ``await``. La declaración modificada por la palabra clave ``await`` necesita esperar a que el código anterior termine de ejecutarse antes de continuar, logrando el efecto de bloqueo sincrónico.

* `Función Asíncrona <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function>`_

.. code-block:: js

    lm = new MAX7219_LED_MATRIX(0, 0);

Instanciar un objeto lm de la clase ``MAX7219_LED_MATRIX``, para que podamos llamar a la función ``write()`` encapsulada en su interior.

.. code-block:: js

    while(1){
        for(let j=0;j<36;j++){
            for(let i=0;i<8;i++){
                lm.write(i, DISP[j][i]);
            }
            await lm.delay(1000);
        }
    }

La función ``write(row, date)`` te permite mostrar caracteres especificados en la matriz de puntos LED.
El primer parámetro selecciona la fila de la Matriz LED (un total de 8 filas).
El segundo parámetro ingresa un número binario de 8 bits para controlar los 8 LEDs de la fila (0 significa apagado, 1 significa encendido).

La variable ``j`` se usa para seleccionar el glifo, que es ``DISP[]``. Hay un total de 35 glifos, del 0 al 9 y de la A a la Z.

Por ejemplo, cuando j=1, la Matriz LED debería mostrar la imagen **1**.

La variable ``i`` se usa para escribir los 8 datos en el glifo ``DISP[]`` en la Matriz LED en orden. Después de completar el bucle, se puede generar un gráfico de 8x8.

Por ejemplo, cuando j=1, i=1, se escribirá aquí el dato de ``DISP[1][1]``, que es ``0x18``,
Esto hará que la segunda fila de la Matriz LED muestre la imagen ``00011000``.

.. image:: ../img/led_not.png
    :width: 400

Imagen del Fenómeno
-----------------------

.. image:: ../img/1.1.6led_dot_matrix.JPG
