.. note::

    こんにちは、SunFounderのRaspberry Pi & Arduino & ESP32愛好家コミュニティへようこそ！Facebook上でRaspberry Pi、Arduino、ESP32についてもっと深く掘り下げ、他の愛好家と交流しましょう。

    **参加する理由は？**

    - **エキスパートサポート**：コミュニティやチームの助けを借りて、販売後の問題や技術的な課題を解決します。
    - **学び＆共有**：ヒントやチュートリアルを交換してスキルを向上させましょう。
    - **独占的なプレビュー**：新製品の発表や先行プレビューに早期アクセスしましょう。
    - **特別割引**：最新製品の独占割引をお楽しみください。
    - **祭りのプロモーションとギフト**：ギフトや祝日のプロモーションに参加しましょう。

    👉 私たちと一緒に探索し、創造する準備はできていますか？[|link_sf_facebook|]をクリックして今すぐ参加しましょう！

.. _1.1.6_js:

1.1.6 LEDドットマトリックスモジュール
======================================

はじめに
--------------------

このプロジェクトでは、LEDマトリックスモジュールについて学びます。LEDマトリックスモジュールは、MAX7219ドライバを使用して8 x 8のLEDマトリックスを駆動します。

必要な部品
------------------------------

このプロジェクトには、以下の部品が必要です。

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

一式を購入するのは非常に便利です。リンクは以下の通りです：

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

    *   - 名前
        - このキットのアイテム
        - リンク
    *   - Raphael Kit
        - 337
        - |link_Raphael_kit|

以下のリンクから別々に購入することもできます。

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

    *   - コンポーネントの紹介
        - 購入リンク

    *   - :ref:`cpn_gpio_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|

回路図
-----------------------

============ ======== ======== ====
T-Board Name physical wiringPi BCM
SPIMOSI      Pin 19   12       MOSI
SPICE0       pin 24   10       CE0
SPISCLK      Pin 23   14       SCLK
============ ======== ======== ====

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

実験手順
----------------------------

**ステップ1:** 回路を組み立てます。

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

.. note::

    実験を開始する前にSPIをオンにします。詳細は :ref:`spi_configuration` を参照してください。

**ステップ2:** コードのフォルダに移動します。

.. raw:: html

   <run></run>

.. code-block:: 

    cd ~/raphael-kit/nodejs/

**ステップ3:** 依存関係をインストールします。

.. raw:: html

   <run></run>

.. code-block:: 

    sudo npm install spi-device

**ステップ4:** コードを実行します。

.. raw:: html

   <run></run>

.. code-block:: 

    sudo node max7219_led_matrix.js 

コードを実行すると、LEDドットマトリックスは順番に0から9、AからZまでを表示します。

**コード**

.. 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(); 

**コード説明**

.. code-block:: js

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

SPI通信に必要なモジュールをインポートします。

.. note::
    SPI通信が必要な複数のデバイスがある場合、csピンを異なるピンに接続するだけです。

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

``MAX7219_LED_MATRIX`` クラスを実装し、それにカプセル化された ``write()`` 関数でマトリックスを点灯させることができます。

.. note::
    ``async`` キーワードは関数を修飾するために使用され、通常 ``await`` キーワードと組み合わせて使用されます。 ``await`` キーワードで修飾された文は、実行する前に前のコードが実行完了するのを待つ必要があり、同期的なブロッキングの効果を達成します。

* `非同期関数 <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function>`_

.. code-block:: js

    lm = new MAX7219_LED_MATRIX(0, 0);

``MAX7219_LED_MATRIX`` クラスのオブジェクトlmをインスタンス化し、内部のカプセル化された ``write()`` 関数を呼び出すことができます。

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

``write(row,date)`` 関数を使用すると、LEDドットマトリックスに指定した文字を表示できます。
第一引数はLEDマトリックスの行を選択します（合計8行）。
第二引数は、行の8つのLEDを制御する8ビットの2進数を入力します（0はオフ、1はオンを意味します）。

変数 ``j`` は、グリフを選択するために使用され、それは ``DISP[]`` です。合計35のグリフがあり、0~9およびA~Zがあります。

例えば、j=1の場合、LEDマトリックスは **1** の画像を表示する必要があります。

変数 ``i`` は、 ``DISP[]`` グリフの8つのデータを順番にLEDマトリックスに書き込むために使用されます。ループが完了すると、8x8のグラフィックが生成されます。

例えば、j=1、i=1の場合、 ``DISP[1][1]`` のデータがここに書き込まれます、つまり ``0x18`` です。
これにより、LEDマトリックスの2行目は ``00011000`` の画像を表示します。

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

現象の画像
-----------------------

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