【Arduino】LEDMatrix(MAX7219)を使う

it

MAX7219をマトリクスパネルを使ってみました。
単色ですが視認性が良く鮮やかに発行するパネルを使った電光掲示板や簡単なゲーム画面にできます。
Arduino環境でRaspberryPiを使ったサンプルを紹介します。

記事の概要

LEDMatrix(MAX7219)でできることを簡単に紹介します。
実際に使って発光させたときの様子と、軽めの改造をした内容を記載しました。
MAX7219を使ったゲームの作例を紹介しています。
開発をするまでの準備と作って試したサンプルの配線とスケッチを紹介しています。
サンプルでは8×8パネルを1個使い、2個連結、3個個別の制御をしました。

LED Matrix(MAX7219)

簡単紹介

1パネル8×8のLEDパネルをコマンドで制御するモジュールです。
パネルは連結して使用したり、個々にCSを配線して個別に制御することができます。

パネルの色は赤、緑、青の販売をよく見かけますが、他にも白や黄発色もあるようです。
複数のパネルが連結したモジュールもあります。

パネルが複数連結しているモデルもあり、連結数や連結形状もさまざまです。

◆購入

Amazon、国内電子部品サイトで購入できます。
価格の目安です。

1パネル : \400前後
4パネル連結 : \700 ~ \1,000

◆その他

同ICチップを使った、8桁の7セグLEDパネルもあります。
ドットの配置が7セグLED配置に置き換わったものです。

後日記事を掲載します。

◆関連記事

ピン配置

図右側のピンヘッダにマイコンからSPI信号を入力します。
左側は連結する場合の出力側です。

外観

LEDパネルのシングルモデルです。

LEDパネルが4個連結されているモデルです。

使ってみた

◆表示

各色の発色状態を掲載します。
パネルが大きくドット間の距離も十分あるので視認性が良いと感じます。

パネルのLED色は購入時に決めます。
制御で色や明るさを変えることはできません。

赤、緑、青を点灯させました。

パネルは単体で販売されていることもあり、パネルを付け替えることで発光色を変更することができます。

パネルの端子はピン数が多くピン径は細いです。
取り外しや取り付けに横応力がかかるとピン曲がりの原因になるので力加減に注意して作業します。

下図は4個連結モジュールの2枚目と4枚目のパネルを青から赤に取り換えた例です。

◆連結

今回使ったのはLEDパネルが1×1のモデルと1×4のモデルです。
PCBにはSPI通信の入力側と出力側があり、出力側に次のパネルを接続することで連結することができます。
モジュールを連結した例はこちら

SPIなのでモジュールごとにCSを設定することで個別に制御できます。
モジュールを個別に制御した例はこちら

◆制御

ArduinoIDEで開発をしています。
今回しようしたライブラリは「MD_MAX72XX by majicDesigns」と「MD_Parola by majicDesigns」で簡単な命令セットを組み合わせることで、文字表示や電光掲示板スクロールを手軽に実装できました。
ドット単位の制御でゲーム画面にもなりました。

◆作例 : ブロックを隙間なく埋めると消える有名なゲームの例

◆使ってみて

簡単な命令でマトリクスLEDのパネル制御ができました。
ドットの輝度や間隔も十分で視認性の良いモジュールだと思います。
連結や個別制御もできて用途が広く使い勝手の良いモジュールです。
輝度や任意の色表示はできませんが、結果的に制御がシンプルで割り切って使用できます。

パネルの不点灯LEDがあります。
使っていて不点灯になるLEDがあり、復活することもなく修理ができないのでパネルを交換することになります。
個人で所有する数の不良率としては少し高い気がするので予備のパネルを用意しておきたいところです。

準備

開発環境

Arduino環境でRaspberryPi Picoを使用します。
Arduino環境の準備はこちらの記事で紹介しています。

◆ボードライブラリ

制御マイコンにはRaspberry Pi Picoを使用します。
Arduino IDEのボードマネージャからRP2040用のライブラリのインストールとボードの選択をします。
ボードライブラリには「Raspberry Pi Pico/RP2040 by Earle F. Philhower, III」を使用します。
Generic RP2040またはRaspberry Pi Picoを使用します。

追加のボードマネージャのURLhttps://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
検索RP2040
ボードライブラリRaspberry Pi RP2040 Boards(x.x.x)※
選択するボードRaspberry Pi RP2040 Boards(x.x.x) > Raspberry Pi Pico
※動作確認はバージョン 4.1.1です

◆モジュールライブラリ

モジュールライブラリには「MD_MAX72XX by majicDesigns」を使用します。

ライブラリ名検索動作確認時バージョン
MD_MAX72XX by majicDesignsMAX723.5.1
MD_Parola by majicDesignsMAX723.7.3

スケッチサンプル

ドット表示

説明

8×8パネル1枚のモジュールを使用して、ドットの点灯させます。

座標(0, 0)からX軸方向に1ドットずつ点灯します。
端まで点灯したら次のY軸方向を1ドットずつ点灯します。

全て点灯したら1ドットずつの消灯します。

このサンプルではモジュールライブラリ「MD_MAX72XX by majicDesigns」を使用します。

配線

スケッチ

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

#define HARDWARE_TYPE   MD_MAX72XX::FC16_HW //デバイス種別
#define MAX_DEVICES     (1)     //8x8のマトリクス表示のユニット数
#define MAX7219_MOSI    (19)
#define MAX7219_CS      (17)
#define MAX7219_SCK     (18)
MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, MAX7219_CS, MAX_DEVICES);
 
#define WAIT            (100)
void setup()
{
    //SPIのピン設定
    SPI.setTX(MAX7219_MOSI);
    SPI.setSCK(MAX7219_SCK);
    SPI.setCS(MAX7219_CS);
    SPI.begin();
    
    if(!mx.begin())
    {
      Serial.println("Initialization faled.");
      for(;;);
    }
}
 
void loop()
{
  const int16_t x_max = (7);
  const int16_t y_max = (7);
  int16_t x = (0 - 1);
  int16_t y = 0;
  bool stat = true;

   
  while(1)
  {
    x ++;
    if(x_max < x)
    {
      y ++;
      x = 0;
      if(y_max < y)
      {
        stat = !stat;
        y = 0;
      }
    }
    mx.setPoint(x, y, stat);
 
    delay(WAIT);
  }
}

結果

結果を静止画で撮影しています。
ドットが上部から1ドットずつ点灯されました。
全点灯後、同じように上から1ドットずつ消灯されました。

ドット表示(バウンドボール)

説明

8×8パネル1枚のモジュールを使用して、ドットの点灯させます。

座標(0, 0) から(7, 7)を点灯ドットを移動させます。
座標端に移動するごとに速度を変えながら反転動作をさせます。

このサンプルではモジュールライブラリ「MD_MAX72XX by majicDesigns」を使用します。

配線

スケッチ

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

#define HARDWARE_TYPE   MD_MAX72XX::FC16_HW //デバイス種別
#define MAX_DEVICES     (1)     //8x8のマトリクス表示のユニット数
#define MAX7219_MOSI    (19)
#define MAX7219_CS      (17)
#define MAX7219_SCK     (18)
MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, MAX7219_CS, MAX_DEVICES);
 
#define WAIT            (10)
void setup()
{
    //SPIのピン設定
    SPI.setTX(MAX7219_MOSI);
    SPI.setSCK(MAX7219_SCK);
    SPI.setCS(MAX7219_CS);
    SPI.begin();
    
    if(!mx.begin())
    {
      Serial.println("Initialization faled.");
      for(;;);
    }
}
 
void loop()
{
  const int16_t x_max = (7 - 1);
  const int16_t y_max = (7 - 1);
  int16_t x = 0;
  int16_t y = 0;
  int16_t old_x = x;
  int16_t old_y = y;
  int16_t add_x = 1;
  int16_t add_y = 1;

  const int16_t rand_max = 3;
  int16_t max_x = random(rand_max);
  int16_t max_y = random(rand_max);
  int16_t counter_x = max_x;
  int16_t counter_y = max_y;
  
  while(1)
  {
    counter_x --;
    counter_y --;
    if(counter_x < 0)
    {
      x += add_x;
      if((x < 1) || (x_max < x)){
        add_x *= -1;
        max_x = random(rand_max);
      }
      counter_x = max_x;
    }

    if(counter_y < 0)
    {
      y += add_y;
      if((y < 1) || (y_max < y))
      {
        add_y *= -1;
        max_y = random(rand_max);
      }
      counter_y = max_y;
    }

    mx.setPoint(old_x, old_y, false);
    mx.setPoint(x, y, true);
    old_x = x;
    old_y = y;
    
    delay(WAIT);
  }
}

結果

激しく動くバウンドボールが表現されました。

ドット表示(連結)

説明

8×8パネルを2モジュール使用して、ドットの点灯させます。

「ドット表示1」と同じ動作で、1枚目のパネル(赤点灯のパネル)は1ドットずつ点灯、2枚目のパネル(青店頭のパネル)は全点灯状態から1ドットずつ消灯します。

連結パネル2枚目はY軸が増えた(8×8が8×16)と同様の扱いをします。

このサンプルではモジュールライブラリ「MD_MAX72XX by majicDesigns」を使用します。

配線

スケッチ

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

#define HARDWARE_TYPE   MD_MAX72XX::FC16_HW //デバイス種別
#define MAX_DEVICES     (2)     //8x8のマトリクス表示のユニット数
#define MAX7219_MOSI    (19)
#define MAX7219_CS      (17)
#define MAX7219_SCK     (18)
MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, MAX7219_CS, MAX_DEVICES);
 
#define WAIT            (100)
void setup()
{
    //SPIのピン設定
    SPI.setTX(MAX7219_MOSI);
    SPI.setSCK(MAX7219_SCK);
    SPI.setCS(MAX7219_CS);
    SPI.begin();
    
    if(!mx.begin())
    {
      Serial.println("Initialization faled.");
      for(;;);
    }
}
 
void loop()
{
  const int16_t x_max = (7);
  const int16_t y_max = (7);
  int16_t x = (0 - 1);
  int16_t y = 0;
  bool stat1 = true;
  bool stat2 = false;

  for(int8_t i; i < 8; i ++)
  {
    mx.setColumn(i + 8, 0xff);
  }
 
  while(1)
  {
    x ++;
    if(x_max < x)
    {
      y ++;
      x = 0;
      if(y_max < y)
      {
        stat1 = !stat1;
        stat2 = !stat2;
        y = 0;
      }
    }
    mx.setPoint(x, y, stat1);
    mx.setPoint(x, y + 8, stat2);
    
 
    delay(WAIT);
  }
}

結果

バウンドボール(複数制御)

説明

パネルを3モジュールを使用して、バウンドボールします。
各モジュールごとに個別制御をするために、各モジュールにはCSを配線します。

このサンプルではモジュールライブラリ「MD_MAX72XX by majicDesigns」を使用します。
モジュールを個別に操作するためにモジュールごとにインスタンスを作成します。

配線

電源、SPI(SCK(CLK)、MOSI(DIN))は共通。
CSは各モジュールごとに専用配線。

スケッチ

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

#define  ModuleCount    (3)

#define HARDWARE_TYPE   MD_MAX72XX::FC16_HW //デバイス種別
#define MAX_DEVICES     (1)     //8x8のマトリクス表示のユニット数
#define MAX7219_MOSI    (19)
#define MAX7219_SCK     (18)

#define MAX7219_R_CS    (0)
#define MAX7219_G_CS    (1)
#define MAX7219_B_CS    (2)

int16_t TblCS[] = {MAX7219_R_CS, MAX7219_G_CS, MAX7219_B_CS};
MD_MAX72XX mx[ModuleCount] = {
   MD_MAX72XX(HARDWARE_TYPE, MAX7219_R_CS, MAX_DEVICES),
   MD_MAX72XX(HARDWARE_TYPE, MAX7219_G_CS, MAX_DEVICES),
   MD_MAX72XX(HARDWARE_TYPE, MAX7219_B_CS, MAX_DEVICES)
};
 
#define WAIT            (10)
void setup()
{
  //SPIのピン設定
  SPI.setTX(MAX7219_MOSI);
  SPI.setSCK(MAX7219_SCK);
  SPI.begin();

  for(int16_t i = 0; i < ModuleCount; i ++)
  {
    if(!mx[i].begin())
    {
      Serial.println("Initialization faled.");
      for(;;);
    }
  }
}

void loop()
{
  const int16_t x_max = (7 - 1);
  const int16_t y_max = (7 - 1);
  int16_t x[ModuleCount];
  int16_t y[ModuleCount];
  int16_t old_x[ModuleCount];
  int16_t old_y[ModuleCount];
  int16_t add_x[ModuleCount];
  int16_t add_y[ModuleCount];
  
  const int16_t rand_max = 3;
  int16_t max_x[ModuleCount];
  int16_t max_y[ModuleCount];
  int16_t counter_x[ModuleCount];
  int16_t counter_y[ModuleCount];
  
  for(int16_t i = 0; i < ModuleCount; i ++)
  {
    x[i] = 0;
    y[i] = 0;
    old_x[i] = x[i];
    old_y[i] = y[i];
    add_x[i] = 1;
    add_y[i] = 1;

    max_x[i] = random(rand_max);
    max_y[i] = random(rand_max);
    counter_x[i] = max_x[i];
    counter_y[i] = max_y[i];
  }

  while(1)
  {
    for(int16_t i = 0; i < ModuleCount; i ++)
    {
      counter_x[i] --;
      counter_y[i] --;
      if(counter_x[i] < 0)
      {
        x[i] += add_x[i];
        if((x[i] < 1) || (x_max < x[i])){
          add_x[i] *= -1;
          max_x[i] = random(rand_max);
        }
        counter_x[i] = max_x[i];
      }

      if(counter_y[i] < 0)
      {
        y[i] += add_y[i];
        if((y[i] < 1) || (y_max < y[i]))
        {
          add_y[i] *= -1;
          max_y[i] = random(rand_max);
        }
        counter_y[i] = max_y[i];
      }

      mx[i].setPoint(old_x[i], old_y[i], false);
      mx[i].setPoint(x[i], y[i], true);
      old_x[i] = x[i];
      old_y[i] = y[i];
    }     
    delay(WAIT);
  }
}

結果

使用したパネルは赤、緑、青です。
各モジュールで個別に制御をできました。

文字表示(連結パネル)

説明

8×8パネルが4個連結したモジュールを使用し文字列表示します。

ライブラリには「MD_MAX72XX by majicDesigns」と「MD_Parola by majicDesigns」を使います。

パネル状に”NEGI”と表示します。

配線

スケッチ

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

#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES   (4)
#define PIN_CS        (17)
#define PIN_MOSI      (19)
#define PIN_SCK       (18)

MD_Parola LED = MD_Parola(HARDWARE_TYPE, PIN_CS, MAX_DEVICES);
 
void setup()
{
  SPI.setTX(PIN_MOSI);
  SPI.setSCK(PIN_SCK);
  SPI.setCS(PIN_CS);
  SPI.begin();
  
  LED.displayReset();
  LED.begin();
  LED.displayText("NEGI", PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
  LED.displayAnimate();
}
 
void loop()
{
}

結果

ライブラリを使用することで少ないスケッチコードで文字表示ができました。
パネルの連結数が多いことで表現できる文字や情報も増えます。

コメント

タイトルとURLをコピーしました