PR

Arduino UNO R4 WiFiのLEDマトリックスを使用する

組み込みエンジニア
本記事はプロモーションが含まれています。

こんにちは、ENGかぴです。

Arduino UNO R4 WiFiはArduino UNOに準拠し、WiFiやBluetoothを備えたボードです。また、12×8のLEDマトリックスが実装されているため記号などのパターンを生成して表示することができます。

Arduino IDEにArduino UNO R4 WiFiのボードを追加し、LEDマトリックスを使って生成した複数のパターンでLEDを点灯させる方法をまとめています。

以下ではArduino UNO R4 WiFiをボードの追加部分を除いてUNOR4-WiFiと表記します。Arduinoのライブラリを使用して動作確認したことをまとめています。

Arduinoで学べるマイコンのソフト開発と標準ライブラリの使い方

Arduino UNO R4 WiFiボードを追加する

UNOR4-WiFiは、ルネサスエレクトロニクスの32ビットマイコンであるRA4M1を中心に、無線通信モジュールのESP32-S3-MINIを組み込んでWiFi及びBluetooth通信ができるのが特徴です。また12×8のLEDマトリックスが実装されており、簡単な文字や記号を表示することができます。詳細は下記のリンクで確認が確認できます。

UNO R4 WiFi | Arduino Documentation

ピンの配置はArduino UNOに準拠しているためArduino UNOと同様の配線で使用することができます。

Arduino IDEをインストールしていない場合は下記記事を参考にしてArduino IDEをインストールしてください。

Arduinoの開発環境の作り方とスケッチ例の使い方

Arduino IDEのボードマネージャでUNOR4-WiFiのボードを追加します。

Arduino UNO R4 Boardsを追加する
Arduino UNO R4 Boardsを追加する

ボードマネージャを開いて「arduino uno r4 boards」のように候補を指定して表示される「Arduino UNO R4 Boards」をインストールします。

インストールしていない状態で「Arduino UNO R4 WiFi」を選択すると”Arduino UNO R4 WiFi”用にコア”Arduino UNO R4 Boards[v 1.x.x]”をインストールする必要があります。今すぐインストールしますか?と表示されるので指示に従ってインストールする方法もあります。

手動でインストールを選択するとボードマネージャからインストールする手順と同じになります。

USBで接続するとポートが生成されるのでボードとセットとなるポートを指定するとソフトが書き込めるようになります。

Arduino環境ではスケッチ(Arduinoファイル)を作成するとsetup()関数とloop()関数が空の状態で記述されています。ユーザーは用途に応じて処理を追加します。

void setup() {
 //マイコンの初期化に関する設定を記述
}
void loop() {
 //ユーザーが処理する内容を記述する
}

setup()関数はArduino環境においてユーザーが初期化を行う関数で、マイコンの初期化時に一度だけ呼び出される関数です。setup()関数内にピン設定など各種設定を行います。

loop()関数はArduino環境においてマイコンの周回ごとに呼び出される関数です。ユーザーはloop()関数内に処理を追加して使用します。

PR:わからないを放置せず、あなたにあった最低限のスキルを身に着けるコツを教える テックジム 「書けるが先で、理解が後」を体験しよう!

LEDマトリックスを使用する

UNOR4-WiFiのLEDマトリックスは左上を1番とし右下が96番となるように12列8行の構成になるように実装されています。RA4M1マイコンのポートを操作して点灯パターンに応じてLEDの点灯/消灯を制御します。

LEDマトリックスの構成
LEDマトリックスの構成

LEDマトリックスの構成の着色している部分は32ビットの変数でパターンを生成する場合のLEDの分布です。後述のパターンの生成方法1で使用するpattern[]配列の構成となり、黄色がpattern[0]、緑がpattern[1]、水色がpattern[2]に対応しています。

赤文字の部分はグリッドの座標でパターンを生成する場合のLEDの分布です。後述のパターンの生成方法2で使用するgrid[][]配列の構成です。

ライブラリのインクルード

#include "Arduino_LED_Matrix.h" 

ArduinoLEDMatrix matrix;

Arduino_LED_Matrixライブラリをインクルードします。ArduinoLEDMatrixクラスの変数としてmatrixをインスタンス化(matrixオブジェクト)します。matrixオブジェクトはLEDマトリックスの操作を行うために使用します。

以下ではArduinoLEDMatrixクラスのメンバー関数を赤文字で表記します。

void setup() {
  
  matrix.begin();
}

begin()関数でLEDマトリックスを使用するための初期化を行います。初期化後はmatrixオブジェクトのメンバー関数を使用してLEDマトリックスを操作してLEDを点灯します。

以下で紹介するパターンの生成方法1とパターンの生成方法2はどちらも同じ動作になります。点灯パターンに応じて使い分けることができます。

パターンの生成に必要なRAMの容量を削減したいなら12バイトを使用するパターンの生成方法1を使用し、RAMの容量が気にならないなら96バイトを使用するパターンの生成方法2を使用する使い分けもできます。

最近のマイコンはRAM容量が多く気になることがないためパターンの作りやすさを判断して使い分けるとよいと思います。

PR:スキマ時間で自己啓発!スマホで学べる人気のオンライン資格講座【スタディング】まずは気になる講座を無料で体験しよう!

パターンの生成方法1

uint32_t pattern[] = {
  0x00000000,
  0x00000000,
  0x00000000
};

void PatternSet(void){
  uint8_t i,j;

  memset(&pattern, 0, sizeof(pattern)); //変数のクリア

  for( i=0; i<3; i++)
  {
    for( j=0; j<32; j++ )
    {
      pattern[i] |= 1 << (31 - j);
      matrix.loadFrame(pattern);
      delay(DELAY_SET);
    }
  }
  matrix.clear();
}

LEDマトリックスの配置に合わせたuint32_t型のpattern[]配列を準備して点灯パターンを生成します。pattern[0]のMSBがLEDマトリックスの1番目のLEDに該当し、pattern[2]のLSBがLEDマトリックスの最後尾のLEDに該当します。

各ビットがLEDのON/OFF状態を表し、ビット演算による効率的な制御ができるため処理が高速になるメリットがあります。

LEDマトリックスの1番目から96番目までを順番に点灯させるパターンを生成します。最初にpattern[]配列をクリアします(10行目)。

MSBから順番にLEDを点灯させるため1をシフトしながらパターンを生成します(16行目)。loadFrame()関数(17行目)で生成したパターンの配列を引数に指定してLEDマトリックスを操作します。

これをpattern[]配列分だけ繰り返すとLEDマトリックスが順番に点灯します。clear()関数(21行目)でLEDマトリックスをすべて消灯します。

パターンの生成方法2

uint8_t grid[MAX_Y][MAX_X] = {
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
};

void PatternSet1a(void){
  uint8_t x;
  uint8_t y;

  memset(&grid, 0, sizeof(grid));

  for( y=0; y<MAX_Y; y++)
  {
    for( x=0; x<MAX_X; x++)
    {
      grid[y][x] = 1;
      matrix.renderBitmap(grid, 8, 12);
      delay(DELAY_SET);
    }
  }
  matrix.clear();
}

LEDマトリックスの配置に合わせたuint8_t型のgrid[][]配列で準備して点灯パターンを生成します。grid[0][0]がLEDマトリックスの1番目のLEDに該当し、grid[7][11]がLEDマトリックスの最後尾のLEDに該当します。

グリッドによる座標で管理するため視覚的にレイアウトを把握しやすく、パターンが作りやすいメリットがあります。各座標の値が1ならLEDが点灯、0なら消灯状態になります。

LEDマトリックスの1番目から96番目までを順番に点灯させるパターンを生成します。最初にgrid[][]配列をクリアします(16行目)。

grid[][]配列の1行目の1列目に1を指定したパターンを生成します。renderBitmap()関数(23行目)を使用してLEDマトリックスを操作します。第1引数にパターンの配列を指定します。第2引数にLEDマトリックスの行数、第3引数にLEDマトリックスの列数を指定します。

これを8列目まで繰り返すことで1行目のLEDが順番に点灯します。2行目以降についても同様の処理を行うことでLEDマトリックスを順番に点灯させていきます。

clear()関数はLEDマトリックスをすべて消灯します。

【クリエイターズファクトリー】卒業がない!挫折する心配なし!Webスクール説明会申し込み

動作確認

LEDマトリックスの動作確認
LEDマトリックスの動作確認

電源を入れるとパターン1、パターン1-2、パターン2、パターン3、パターン1・・・を繰り返してLEDマトリックスを点灯させます。パターンを切り替えたときにシリアルモニターに操作中のパターンを表示します。

シリアルモニターを結果
シリアルモニターを結果

シリアルモニターを確認するとパターンが切り替わるごとにパターンが表示されていることが確認できました。

UNOR4-WiFiはUNOと互換のピン配置なのでUNOで動作確認したソースコードも流用することができるため様々な応用ができます。個人的にはルネサスエレクトロニクスのマイコンがメインとなっていることがうれしく感じています。

Arduinoで学べるマイコンのソフト開発と標準ライブラリの使い方

上記で紹介しているスターターキットなども併せて購入することでC++の学習や趣味で楽しむことができるので応用の幅が広がります。

スポンサーリンク

ソースコード全体

ソースコードは記事作成時点において動作確認できていますが、使用しているライブラリの更新により動作が保証できなくなる可能性があります。また、ソースコードを使用したことによって生じた不利益などの一切の責任を負いかねます。参考資料としてお使いください。

#include "Arduino_LED_Matrix.h" 

#define DELAY_SET 30
#define MAX_Y 8
#define MAX_X 12

const uint32_t allon[] = {
	0xffffffff,
	0xffffffff,
	0xffffffff
};

const uint8_t shift1[12][3] = {
  { 31, 19, 7 },
  { 30, 18, 6 },
  { 29, 17, 5 },
  { 28, 16, 4 },
  { 27, 15, 3 },
  { 26, 14, 2 },
  { 25, 13, 1 },
  { 24, 12, 0 },
  { 23, 11, 0xFF },
  { 22, 10, 0xFF },
  { 21, 9, 0xFF },
  { 20, 8, 0xFF}
};

const uint8_t shift2[12][4] = {
  { 0xFF, 27, 15, 3 },
  { 0xFF, 26, 14, 2 },
  { 0xFF, 25, 13, 1 },
  { 0xFF, 24, 12, 0 },
  { 0xFF, 23, 11, 0xFF },
  { 0xFF, 22, 10, 0xFF },
  { 0xFF, 21, 9, 0xFF },
  { 0xFF, 20, 8, 0xFF },
  { 31, 19, 7, 0xFF },
  { 30, 18, 6, 0xFF },
  { 29, 17, 5, 0xFF },
  { 28, 16, 4, 0xFF}
};

const uint8_t shift3[12][3] = {
  { 0xFF, 23, 11 },
  { 0xFF, 22, 10 },
  { 0xFF, 21, 9 },
  { 0xFF, 20, 8 },
  { 31, 19, 7 },
  { 30, 18, 6 },
  { 29, 17, 5 },
  { 28, 16, 4 },
  { 27, 15, 3 },
  { 26, 14, 2 },
  { 25, 13, 1 },
  { 24, 12, 0}
};

uint32_t pattern[] = {
  0x00000000,
  0x00000000,
  0x00000000
};

uint8_t grid[MAX_Y][MAX_X] = {
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
};

ArduinoLEDMatrix matrix;
uint32_t ptnhold[3];

/*プロトタイプ宣言*/
void PatternSet(void);
void PatternSet1a(void);
void PatternSet2(void);
void PatternSet3(void);

void setup() {
  
  Serial.begin(115200);
  matrix.begin();
}

void loop() {

  PatternSet();
  PatternSet1a();
  PatternSet2();
  PatternSet3();
}
/*パターン1*/
void PatternSet(void){
  uint8_t i,j;

  Serial.println("Pattern1 Start");
  memset(&pattern, 0, sizeof(pattern));

  for( i=0; i<3; i++)
  {
    for( j=0; j<32; j++ )
    {
      pattern[i] |= 1 << (31 - j);
      matrix.loadFrame(pattern);
      delay(DELAY_SET);
    }
  }
  matrix.clear();
}
/*パターン1-2*/
void PatternSet1a(void){
  uint8_t x;
  uint8_t y;

  Serial.println("Pattern1-2 Start");
  memset(&grid, 0, sizeof(grid));

  for( y=0; y<MAX_Y; y++)
  {
    for( x=0; x<MAX_X; x++)
    {
      grid[y][x] = 1;
      matrix.renderBitmap(grid, 8, 12);
      delay(DELAY_SET);
    }
  }
  matrix.clear();
}
/*パターン2*/
void PatternSet2(void){
  uint8_t i,j;

  Serial.println("Pattern2 Start");
  memset(&pattern, 0, sizeof(pattern));

  for( i=0; i<12; i++)
  {
    for( j=0; j<3; j++)
    {
      if( shift1[i][j] != 0xFF )
      {
        pattern[0] |= 1 << shift1[i][j];
        matrix.loadFrame(pattern);
        delay(DELAY_SET);
      }
    }

    for( j=0; j<4; j++)
    {
      if( shift2[i][j] != 0xFF )
      {
        pattern[1] |= 1 << shift2[i][j];
        matrix.loadFrame(pattern);
        delay(DELAY_SET);
      }
    }    

    for( j=0; j<3; j++)
    {
      if( shift3[i][j] != 0xFF )
      {
        pattern[2] |= 1 << shift3[i][j];
        matrix.loadFrame(pattern);
        delay(DELAY_SET);
      }
    }
    matrix.clear();
  }
}
/*パターン3*/
void PatternSet3(void){
  uint8_t i,j;
  uint8_t y;

  Serial.println("Pattern3 Start");
  memset(&grid, 0, sizeof(grid));

  for( y=0; y<MAX_Y; y++)
  {
    for( i=0; i<MAX_X; i++)
    {
      for( j=0; j<MAX_X-i; j++ )
      {
        grid[y][j] = 1;
        matrix.renderBitmap(grid, 8, 12);
        if( j != MAX_X-i-1 ){
          grid[y][j] = 0;
        }
        delay(DELAY_SET);
      }
    }
  }
  matrix.clear();
}

パターン1とパターン1-2は同じ動作になりますが、loadFrame()関数とrenderBitmap()関数を使用した例として比較するために実装しています。

関連リンク

Arduinoのライブラリを使って動作確認を行ったことを下記リンクにまとめています。

Arduinoで学べるマイコンのソフト開発と標準ライブラリの使い方

Seeeduino XIAOで学べるソフト開発と標準ライブラリの使い方

ESP32-WROOM-32Eで学べるソフト開発と標準ライブラリの使い方

Raspberry Pi Picoで学べるArduino環境でのソフト開発

PR:エンジニア転職なら100%自社内開発求人に強い【クラウドリンク】

最後まで、読んでいただきありがとうございました。

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