Arduino Uno R4 WifiのLEDディスプレイに日本語やドット絵アニメーションを流す

ついにArduino Uno R4 Wifiの技適が通ったらしく、国内で買えるようになったのでさっそく注文しました。

Arduino Uno R4 WiFi

Arduino Uno R4 WiFi

  • Arduino (アルドゥイーノ)
Amazon

箱!!
中身!!

一応説明しておくとArduino Unoというのはいわゆるいちばん普通のArduinoで、初めてArduinoを買う人は特別な理由がない限りこれを買えばOKという感じのやつです。

ちょっと前はArduino Uno R3というバージョンだったのですが、さいきん新バージョンのR4が出ました。R4になってこれまでの機能を踏襲したR4 Minimaと、ネットワーク機能を搭載したR4 Wifiに分かれました。

↑こっちはMinima

左が旧機種のR3、右が一足先に出てたネットワーク機能なしのR4 Minima
で、R4 Wifi(再掲)

繰り返しになりますがWifiのほうはネットワーク機能付きというのが主な変更点なんですけど、それ以外にどうしても気になるのがこちら

なんか虫の卵みたいにびっしりついたLED!
いままで本体にディスプレイ的な機能をあまり搭載してこなかったArduinoに、唐突にLEDマトリックスが搭載されました。なんか急!

で、ディスプレイがあったら文字を流したいですよね。いや絵でもいいんですけど、ここにドット絵が出たらめちゃめちゃかわいいと思いますけど、絵心とかないじゃないですか。だから文字を流します。
これに日本語をスクロール表示させるのが今回の目的です。

最初からなんか出る

ところで自分のオリジナルのプログラムを書く前に、買ったままの初期状態で電源を挿すとなんか出ます。

右だけ爪が長いのはギタリストだからなので放っておいてください

テトリスみたいにブロックがガコガコっと降ってくるアニメーションのあと、ハートがドキッとします。いままでのArduinoシリーズにはなかったサービス精神です。どういう心境の変化があったのでしょうか…、

サンプルコードを動かす(ドット絵編)

LEDマトリックスの使い方のマニュアルはここにあります。(英語)

https://docs.arduino.cc/tutorials/uno-r4-wifi/led-matrixdocs.arduino.cc

ざっと見た感じ、まずドット絵を出すのが簡単そうですね。

ドキュメントの真ん中へんにこんなコードがあります。

#include "Arduino_LED_Matrix.h"

ArduinoLEDMatrix matrix;

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

uint8_t frame[8][12] = {
  { 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 leftEye(){
  //Left eye
  frame[1][3] = 1;
  frame[1][4] = 1;
  frame[2][3] = 1;
  frame[2][4] = 1;
}

void wink(){
  //Wink with the left eye
  frame[1][3] = 0;
  frame[1][4] = 0;
  frame[2][3] = 1;
  frame[2][4] = 1;
}

void rightEye(){
  //Right eye
  frame[1][8] = 1;
  frame[1][9] = 1;
  frame[2][8] = 1;
  frame[2][9] = 1;
}

void mouth(){
  //Mouth
  frame[5][3] = 1;
  frame[5][9] = 1;
  frame[6][3] = 1;
  frame[6][4] = 1;
  frame[6][5] = 1;
  frame[6][6] = 1;
  frame[6][7] = 1;
  frame[6][8] = 1;
  frame[6][9] = 1;
}

void loop(){
leftEye();
rightEye();
mouth();

matrix.renderBitmap(frame, 8, 12);

delay(1000);
wink();

matrix.renderBitmap(frame, 8, 12);
delay(1000);
}

まずこれをそのまま動かしてみました。

顔の絵がウィンクします。
プログラムを見ていくと、frame[8][12]の二次元配列を最初に表示内容として設定して(といっても真っ白なのですが)、そのあとleftEye()、wink()、rightEye()、mouth()の各関数で顔のパーツを足して(変更のあるピクセルだけ設定している)、最終的にmatrix.renderBitmap で描画しているようです。

ここでは真っ白の配列に必要な部分だけ書き足すような処理の流れになっていますが、最初から二次元配列の中にドット絵の情報を入れてやれば、簡単にアニメーションも作れそうですね。
というわけで一回やってみます。

ドット絵を出す

さっき「絵心とかないじゃないですか。だから文字を流します。」と書いたんですけど、えっ、いつの間にか絵を描く流れになってませんか。

しょうがない、背に腹は代えられませんので血の涙を流しながら絵を描こうと思います。


ちょうどハロウィンの時期なので、おばけの2コマアニメを描きました。

ドット絵の制作には「ミニドット絵メーカー3」をお借りしました。ありがとうございます。

このドット絵を0と1の配列に書き直してプログラムにします。

#include "Arduino_LED_Matrix.h"

ArduinoLEDMatrix matrix;

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

uint8_t frame1[8][12] = {
  { 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 },
  { 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 },
  { 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0 },
  { 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0 },
  { 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 },
  { 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0 },
  { 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0 },
  { 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0 }
};

uint8_t frame2[8][12] = {
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 },
  { 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 },
  { 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0 },
  { 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0 },
  { 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 },
  { 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0 },
  { 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0 }
};

void loop(){
matrix.renderBitmap(frame1, 8, 12);
delay(200);

matrix.renderBitmap(frame2, 8, 12);
delay(200);
}

かわいい~~

おばけというか腕立て伏せみたいになってしまいましたが、かわいいので良しとしましょう。
こんな感じでめちゃくちゃ簡単にアニメーションの表示ができました。

ちなみに後で気づいたのですが、LED MATRIX EDITORという専用のドット絵ツールが用意されていました。

なんかこんな感じでプレビューしながらアニメーションを作ることができて、上にある</>のボタンを押すと

こんな感じで配列定義をDLすることができます。
あとは

#include "Arduino_LED_Matrix.h"

ArduinoLEDMatrix matrix;

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

//ここにDLしたコードを貼る
const uint32_t animation[][4] = {
	{
		0x7c482,
		0xaaaaaba8,
		0x2a82a7c4,
		66
	},
	{
		0x7c082,
		0x482aabaa,
		0xaa8247c0,
		66
	},
	{
		0x7c482,
		0xaaaaaba8,
		0x2a82a7c4,
		66
	}
};
//ここまで

int frame_count = 3; //DLしたコードのフレーム数

void loop(){
  for(int i=0;i<frame_count;i++){
    matrix.loadFrame(animation[i]); //配列名(例では"animation")をDLしたコードと合わせること
    delay(animation[i][3]); //ここも配列名を合わせる
  }
}

こんな感じにするとアニメーションを表示することができます。動きが速すぎる場合は各フレームの配列の4つ目、上の例でいうと「66」を編集すると速度が変えられます。

というか、このツールどうもArduinoとシリアル通信してリアルタイムでアニメーションのプレビューができそうな雰囲気なんですよ。上にArduinoで再生するボタンがあるし、ドキュメントにも「File > Examples > LED_Matrix > LivePreviewのスケッチを書き込め」とか書いてある。でも言われた通りやってもうまくいかなかったので、やり方がわかる人がいたら教えてください。

文字を出す(サンプルコード)

寄り道してしまいましたが、いよいよ文字を出します。これもドキュメントにサンプルコードがあるので動かしてみましょう。「Scrolling Text Example」と書いてあるところのサンプルコードです。

これはArduinoGraphicsというライブラリを使っているので、あらかじめ「ツール>ライブラリを管理...」から行けるライブラリマネージャでインストールしておく必要があります。

ボードに書き込むと、動画を撮り忘れましたが、「UNO r4」という文字がしばらく表示された後、「Hello World!」がスクロールします。
このように簡単に文字が表示できるのですが、このライブラリはご察しの通り英語しか出せません。なので我々日本人は(いつもどおり)ここで苦労を強いられることになります……。

日本語を出す

というわけで苦労してプログラムを作りましたがその過程を書いても地味なので割愛しまして、成果物だけ紹介します。

表示には美咲フォントという8x8(7x7と余白)ピクセルのフォントをArduinoで使えるようにした、Arduino-misakiUTF16というライブラリを使います。
github.com
これはライブラリマネージャからインストールできないので、リンク先の「Code>Download ZIP」からDLして、中の「misakiUTF16」フォルダをArduinoのライブラリフォルダ(自分の場合は、C:\Users\ユーザ名\OneDrive\ドキュメント\Arduino\libraries でした)に入れる必要があります。

LEDへの表示・スクロールのためのコードはこのページを参考にしました。

工夫した点としては、misakiUTF16ライブラリでgetFontDataして得られる文字データは横方向のピクセルがバイト化されているので、縦方向のバイトになるように回転させたデータを作ってやる必要があります。

とりあえずこれで動きました。(もうちょっと効率的に書けるかもしれない)

#include "Arduino_LED_Matrix.h"
#include <misakiUTF16.h>

ArduinoLEDMatrix matrix;
char *str="表示させたい文字列";
byte buf[40][8];   //フォントデータ格納用。一つめの要素数が文字数(多めでいい)
byte matrix_buff[2000];  //表示用90度回転ピクセルデータ。文字数×8ぶん必要?(多めでいい)

//スクロール時間
#define SCROLL_TIME 100   //ミリ秒
unsigned long tm = 0;

int idx = 0, max_idx;

void setup() {
  char *ptr = str;

  max_idx = 10;
  byte line = 0;

  int n=0;
  while(*ptr) {
    ptr = getFontData(&buf[n++][0], ptr);  // フォントデータの取得
  }

  for (byte j=0; j < n; j++) { //文字
    for (byte k=0; k<8;k++) { //横
      for (byte i=0; i < 8; i++) { //縦
        line = bitWrite(line, 7-i, bitRead(buf[j][i],7-k));
      }
      matrix_buff[max_idx] = line;
      max_idx++;
    }
  }
}

void loop() {

  int ic1, ic2;

  //スクロール時間が経過したらスライドさせる。末端に到達したら始めに戻る
  if(tm + SCROLL_TIME <= millis()) {
    if (idx < max_idx)
      idx++;
    else{
      idx = 0;
    }

    //経過時間を再計測
    tm = millis();
  }

  //12x8LED View
  for(ic1 = 0; ic1 < 8; ic1++){
    for(ic2 = 0; ic2 < 12; ic2++){
      turnLed(ic1 * 12 + ic2 , matrix_buff[idx + ic2] >> (7 - ic1) & 0x01);
      delayMicroseconds(20);  //これを入れないとLEDがちらつく
    }
  }
}
出ました。

misakiUTF16はArduinoに書き込むためにかなり文字数が削減されているので、漢字はけっこう制約が厳しいです。どうしても自由な文字を出したい場合は、上に貼った参考ページのように使いたい文字を配列データで持ってしまうのが楽かもしれません。

以上、Arduino Uno R4で日本語を表示させる方法でした。

Arduino Uno R4 WiFi

Arduino Uno R4 WiFi

  • Arduino (アルドゥイーノ)
Amazon

おしらせ

オライリージャパンより「雑に作る ―電子工作で好きなものを作る近道集」発売中です!!

完全に独学で“雑に”電子工作をサバイブしてきた3人による電子工作の初心者向け実践書。

「完成度は低くてもまずは完成させること」を目標に、最低限の技術を身につける方法、雑に使える電子部品など、限界まで敷居の低いノウハウを紹介。1つの技術で数多くの作品を作る方法、「そのうちやろう」問題への立ち向かい方など、アイデアを生み出ところからそのアイデアを完成まで導くマインドセットまで紹介します。

とりあえず入門書を一冊読んでみたけど「このあと自分の作品どうやったら作れるのか全然わからんな…」という人にピッタリです。