電池で駆動するNeoPixel制御ボードのサンプルプログラム⑤配列データを作って表示させてみる。


- ## 	RP2040-ZEROを使ってNeoPixelを制御するサンプルプログラム⑤です。

 
- ## 	サンプルサンプルプログラム内容
　アルファベットを色を変えて表示させる。
　6行6列の配列データを視覚的に作成して、データを送信するサンプルプログラムです。
　データ作成部分は、プログラミングスキルより絵心スキルが重要ですね。


- ## 	プログラム環境
	　ArduinoIDE バージョン：2.2.1
	　使用ライブラリAdafruit NeoPixel Library 1.12.0
　　最近は起動時にもう少しアップデート促されますね。

- ## 	ハードウェアの主な仕様
	　マイコン:PR2040-ZERO
	　NeoPixel接続ピン　GPIO8
	　乾電池2本でお外へ持ち出し可能。

- ## 	サンプルプログラム

```c++
#include <Adafruit_NeoPixel.h>

#define NUM_LEDS  36
#define LED_PIN    8
#define MATRIX_LINE  6
#define DELAY_TIME 1500

Adafruit_NeoPixel strip(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  strip.begin();
  strip.show();
  strip.setBrightness(64);
}

int data[][MATRIX_LINE][MATRIX_LINE] = {
  {{0,0,1,1,0,0},
   {0,0,1,1,0,0},
   {0,1,0,0,1,0},
   {0,1,1,1,1,0},
   {1,1,1,1,1,1},
   {1,1,0,0,1,1}}, // A

  {{2,2,2,2,0,0},
   {2,2,0,0,2,0},
   {2,2,2,2,0,0},
   {2,2,2,2,2,0},
   {2,2,0,0,0,2},
   {2,2,2,2,2,0}}, // B

  {{0,3,3,3,3,0},
   {3,3,0,0,0,3},
   {3,3,0,0,0,0},
   {3,3,0,0,0,0},
   {3,3,0,0,3,3},
   {0,3,3,3,3,0}},//C

  {{4,4,4,4,4,0},
   {0,4,0,0,0,4},
   {0,4,0,0,0,4},
   {0,4,0,0,0,4},
   {0,4,0,0,0,4},
   {4,4,4,4,4,0}},//D

  {{5,5,5,5,5,5},
   {5,5,0,0,0,0},
   {5,5,5,5,5,0},
   {5,5,0,0,0,0},
   {5,5,5,5,5,5},
   {5,5,5,5,5,5}},//E

  {{6,6,6,6,6,6},
   {6,6,0,0,0,0},
   {6,6,6,6,6,0},
   {6,6,6,6,6,0},
   {6,6,0,0,0,0},
   {6,6,0,0,0,0}},//F
  
  {{0,7,7,7,7,0},
   {7,7,0,0,0,0},
   {7,7,0,7,7,7},
   {7,7,0,0,7,7},
   {7,7,7,7,7,7},
   {0,7,7,7,7,0}},//G
  
  {{8,8,0,0,0,8},
   {8,8,0,0,0,8},
   {8,8,8,8,8,8},
   {8,8,8,8,8,8},
   {8,8,0,0,0,8},
   {8,8,0,0,0,8}},//H
  
  {{0,1,1,1,1,0},
   {0,0,1,1,0,0},
   {0,0,1,1,0,0},
   {0,0,1,1,0,0},
   {0,0,1,1,0,0},
   {0,1,1,1,1,0}},//I
  
  {{2,2,2,2,2,2},
   {0,0,0,2,2,0},
   {0,0,0,2,2,0},
   {0,0,0,2,2,0},
   {2,0,2,2,0,0},
   {0,2,2,2,0,0}},//J
  
  {{3,3,0,0,0,3},
   {3,3,0,0,3,0},
   {3,3,3,3,0,0},
   {3,3,3,3,0,0},
   {3,3,0,3,3,0},
   {3,3,0,0,3,3}},//K
  
  {{4,4,0,0,0,0},
   {4,4,0,0,0,0},
   {4,4,0,0,0,0},
   {4,4,0,0,0,0},
   {4,4,4,4,4,4},
   {4,4,4,4,4,4}},//L
  
  {{5,5,0,0,0,5},
   {5,5,5,0,5,5},
   {5,5,0,5,0,5},
   {5,5,0,5,0,5},
   {5,5,0,5,0,5},
   {5,5,0,5,0,5}},//M
  
  {{6,6,0,0,0,6},
   {6,6,6,0,0,6},
   {6,6,6,6,0,6},
   {6,6,0,6,6,6},
   {6,6,0,0,6,6},
   {6,6,0,0,0,6}},//N
  
  {{0,7,7,7,7,0},
   {7,7,0,0,7,7},
   {7,7,0,0,7,7},
   {7,7,0,0,7,7},
   {7,7,0,0,7,7},
   {0,7,7,7,7,0}},//O
  
  {{8,8,8,8,8,0},
   {8,8,0,0,0,8},
   {8,8,0,0,0,8},
   {8,8,8,8,8,0},
   {8,8,0,0,0,0},
   {8,8,0,0,0,0}},//P
  
  {{0,1,1,1,0,0},
   {1,1,0,1,1,0},
   {1,1,0,1,1,0},
   {1,1,0,1,1,0},
   {1,1,0,1,1,1},
   {0,1,1,1,0,1}},//Q
  
  {{2,2,2,2,2,0},
   {2,2,0,0,0,2},
   {2,2,0,0,0,2},
   {2,2,2,2,2,0},
   {2,2,0,2,2,0},
   {2,2,0,0,2,2}},//R

  {{0,3,3,3,3,0},
   {3,0,0,0,0,3},
   {0,3,3,3,3,0},
   {0,0,0,0,0,3},
   {3,0,0,0,0,3},
   {0,3,3,3,3,0}},//S

  {{0,4,4,4,4,4},
   {0,4,0,4,0,4},
   {0,0,0,4,0,0},
   {0,0,0,4,0,0},
   {0,0,0,4,0,0},
   {0,0,0,4,0,0}},//T

  {{5,5,0,0,0,5},
   {5,5,0,0,0,5},
   {5,5,0,0,0,5},
   {5,5,0,0,0,5},
   {5,5,0,0,0,5},
   {0,5,5,5,5,0}},//U

  {{0,6,0,0,0,6},
   {0,6,0,0,0,6},
   {0,6,0,0,0,6},
   {0,6,6,0,6,6},
   {0,0,6,0,6,0},
   {0,0,0,6,0,0}},//V

  {{0,0,0,0,0,0},
   {7,0,0,7,0,7},
   {7,0,0,7,0,7},
   {7,0,0,7,0,7},
   {7,0,0,7,0,7},
   {0,7,7,0,7,0}},//W

  {{0,0,0,0,0,0},
   {0,8,0,0,0,8},
   {0,0,8,0,8,0},
   {0,0,0,8,0,0},
   {0,0,8,0,8,0},
   {0,8,0,0,0,8}},//X
     
  {{0,1,0,0,0,1},
   {0,1,0,0,0,1},
   {0,0,1,0,1,0},
   {0,0,0,1,0,0},
   {0,0,0,1,0,0},
   {0,0,0,1,0,0}},//Y
   
   {{2,2,2,2,2,2},
   {0,0,0,0,2,0},
   {0,0,0,2,0,0},
   {0,0,2,0,0,0},
   {0,2,0,0,0,0},
   {2,2,2,2,2,2}},//Z     

   {{1,1,1,1,1,1},
   {2,2,2,2,2,2},
   {3,3,3,3,3,3},
   {4,4,4,4,4,4},
   {5,5,5,5,5,5},
   {6,6,6,6,6,6}},//Color check  

};

void loop() {
  for (int i = 0; i < sizeof(data) / sizeof(data[0]); i++) {
    updateMatrix(data[i]);
    strip.show();
    delay(DELAY_TIME);
  }
}

void updateMatrix(int data[MATRIX_LINE][MATRIX_LINE]) {
  // 左右反転
  int mirroredData[MATRIX_LINE][MATRIX_LINE];
  for (int i = 0; i < MATRIX_LINE; i++) {
    for (int j = 0; j < MATRIX_LINE; j++) {
      mirroredData[i][j] = data[i][MATRIX_LINE - j - 1];
    }
  }

  // データを左に90度回転して転置
  int rotatedData[MATRIX_LINE][MATRIX_LINE];
  for (int i = 0; i < MATRIX_LINE; i++) {
    for (int j = 0; j < MATRIX_LINE; j++) {
      rotatedData[i][j] = mirroredData[j][MATRIX_LINE - i - 1];
    }
  }

  // LEDに反映
  for (int i = 0; i < MATRIX_LINE; i++) {
    for (int j = 0; j < MATRIX_LINE; j++) {
      int index = i * MATRIX_LINE + j;
      switch (rotatedData[i][j]) {
        case 1: strip.setPixelColor(index, strip.Color(255,0,0)); break; // red
        case 2: strip.setPixelColor(index, strip.Color(255,105,0)); break;   // orange
        case 3: strip.setPixelColor(index, strip.Color(255,255,0)); break;   // yellow
        case 4: strip.setPixelColor(index, strip.Color(0,128,0)); break;   // green
        case 5: strip.setPixelColor(index, strip.Color(0,255,255)); break;     // aqua
        case 6: strip.setPixelColor(index, strip.Color(0,0,255)); break;     // blue
        case 7: strip.setPixelColor(index, strip.Color(128,0,128)); break;   // purple
        case 8: strip.setPixelColor(index, strip.Color(0,255,0)); break;   // lime
        case 9: strip.setPixelColor(index, strip.Color(255,0,255)); break;   // magenta
        default: strip.setPixelColor(index, strip.Color(0, 0, 0)); break;       // オフ      }
      }
    }
  }
}


```

- ## このプログラムを作成した時の考え方

data変数に6x6のデータを入れて、RP2040（マイコン）から
カラーLED＝WS2812B（製品型番？）＝NeoPixel（商品名？）に
データを送信して任意のデータを表示させています。
　
今回はRP2040-ZEROを左上に持ってきたときに表示させるように
送信するデータを加工していますので、データを作るときは
気にせずそのままのイメージが作成できます。
　
データ表示させたいときのボードの天地のイメージは、写真の状態になります。
あとはデータを加工処理すればどうにでもなるので
この位置関係は、サンプルプログラムを作るときの定義と思ってください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782127/ccffee58-464e-0448-ba3a-cd87fe13b01f.png)


下記はデータの最初の部分になります。
0は、黒色になります。
数字は、後ほど指定した色で点灯するようにしています。


```c++
int data[][MATRIX_LINE][MATRIX_LINE] = {
  {{0,0,1,1,0,0},
   {0,0,1,1,0,0},
   {0,1,0,0,1,0},
   {0,1,1,1,1,0},
   {1,1,1,1,1,1},
   {1,1,0,0,1,1}}, // A
   
```
このデータは、アルファベットのAになるように光らせたいところが1のデータになります。
データ作成は、プログラミングというよりは絵心スキルの部類になるかと思います。
個人的には、エンジニアに美的なセンスは必要と思っていますがいかがでしょうか？(笑)


 NeoPixelの配置は0番から35番まで下図の順番に並んでいるため
 そのまま送信すると反転して右に90度回転した状態で表示されてしまいます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782127/f7b3efcf-63f8-3c82-cdfb-7b7c02e11c6a.png)


それにしても表示データがアルファベットの文字数作ったので
メインプログラムに届くまで遠いですね。
なんとなくですがデータだけ別ファイルにしてインクルードすればよさそうな気がするので
そのほうがすっきりして管理も楽になりそうですね。
　
メインは配列データを読み出して
　updateMatrix(data[i]);
の関数にデータも一緒に引き渡して処理を行うようにしています。
　
DELAY_TIMEは、上のほうで1500msと定義しています。
表示の切り替わり時間の設定ですね！


```c++
void loop() {
  for (int i = 0; i < sizeof(data) / sizeof(data[0]); i++) {
    updateMatrix(data[i]);
    strip.show();
    delay(DELAY_TIME);
  }
}

```

メインからこちらにデータを投げて処理をさせているところになります。
「updateMatrix(data[i]);」
配列データで6x6を渡しています。
作ったデータを加工して作成したデータ表示になるように
まずは左右を反転させています。

次にデータを90度回転させて意図した通りにLEDが光るようにしています。


```c++
void updateMatrix(int data[MATRIX_LINE][MATRIX_LINE]) {
  // 左右反転
  int mirroredData[MATRIX_LINE][MATRIX_LINE];
  for (int i = 0; i < MATRIX_LINE; i++) {
    for (int j = 0; j < MATRIX_LINE; j++) {
      mirroredData[i][j] = data[i][MATRIX_LINE - j - 1];
    }
  }

  // データを左に90度回転して転置
  int rotatedData[MATRIX_LINE][MATRIX_LINE];
  for (int i = 0; i < MATRIX_LINE; i++) {
    for (int j = 0; j < MATRIX_LINE; j++) {
      rotatedData[i][j] = mirroredData[j][MATRIX_LINE - i - 1];
    }
  }
```

最後に色を情報をデータに従って与えています。
ちなみにですが一般的なRGBのオレンジ色は（255,165,0）ですが、
黄色と近い色になってしまったので、少し手を加えています。

ということで、配列データの数字は下記のサンプルプログラムで分かる通り
1＝red,
2=orange,
3=yellow,
4=green ...
というルールで色の割り当てを設定しています。
好きな色を追加することもできるのがメリットなのか選択肢が多過ぎると
選ぶのが億劫になるのかそこは悩みどころですね。


```c++
  // LEDに反映
  for (int i = 0; i < MATRIX_LINE; i++) {
    for (int j = 0; j < MATRIX_LINE; j++) {
      int index = i * MATRIX_LINE + j;
      switch (rotatedData[i][j]) {
        case 1: strip.setPixelColor(index, strip.Color(255,0,0)); break; // red
        case 2: strip.setPixelColor(index, strip.Color(255,105,0)); break;   // orange
        case 3: strip.setPixelColor(index, strip.Color(255,255,0)); break;   // yellow
        case 4: strip.setPixelColor(index, strip.Color(0,128,0)); break;   // green
        case 5: strip.setPixelColor(index, strip.Color(0,255,255)); break;     // aqua
        case 6: strip.setPixelColor(index, strip.Color(0,0,255)); break;     // blue
        case 7: strip.setPixelColor(index, strip.Color(128,0,128)); break;   // purple
        case 8: strip.setPixelColor(index, strip.Color(0,255,0)); break;   // lime
        case 9: strip.setPixelColor(index, strip.Color(255,0,255)); break;   // magenta
        default: strip.setPixelColor(index, strip.Color(0, 0, 0)); break;       // オフ      }
      }
    }
  }
  ```

 - ##  実行結果

絵心が欲しい今日この頃です・・・

  {{0,1,1,1,1,0},
   {0,0,1,1,0,0},
   {0,0,1,1,0,0},
   {0,0,1,1,0,0},
   {0,0,1,1,0,0},
   {0,1,1,1,1,0}},//I
   
![make39_31.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782127/c172efed-4886-42de-c37c-311d0c9d48ec.jpeg)

  {{0,7,7,7,7,0},
   {7,7,0,0,0,0},
   {7,7,0,7,7,7},
   {7,7,0,0,7,7},
   {7,7,7,7,7,7},
   {0,7,7,7,7,0}},//G
   
![make39_32.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782127/b5c24465-59ba-b91c-0e7c-c3ceb8320648.jpeg)

  {{5,5,5,5,5,5},
   {5,5,0,0,0,0},
   {5,5,5,5,5,0},
   {5,5,0,0,0,0},
   {5,5,5,5,5,5},
   {5,5,5,5,5,5}},//E
   
![make39_33.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782127/134d73b5-77ea-031c-128a-cb576e03493b.jpeg)


   {{1,1,1,1,1,1},
   {2,2,2,2,2,2},
   {3,3,3,3,3,3},
   {4,4,4,4,4,4},
   {5,5,5,5,5,5},
   {6,6,6,6,6,6}},//Color check 
ちなみにですが同じデータ内で色を変えても表示されます！
   
![make39_34.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782127/1b8e79bc-6607-5ee0-e678-e77f4a3fe3f8.jpeg)