Arduino Nano EveryでグラフィックLCDでドット絵を動かしたメモ

# 概要
Arduino Nano Everyを使ってグラフィックLCD(TG12864E-02A)でドット絵を動かしたときの備忘録です。
動いたベースなのであまり厳密なことは~~わかりません~~書いていません。

**参考サイト**
[グラフィックＬＣＤモジュールに表示を行う (1/2)](http://zattouka.net/GarageHouse/micon/Arduino/GLCD/GLCD.htm)
※このサイトを参考にやってみたときの自分用メモなので、この記事を読むより参考サイトを見に行ったほうがいいと思います。

# 環境
Arduino Web Editor: 使ってみたかったのでお試しで使います。

# 用意するもの
- Arduino Nano Every: 秋月電子で1500円(税込)で買ってきました。安い。打つのが面倒なので以降Arduinoと言ったらArduino Nano Everyを指すことにします。
- USB A-micro Bのケーブル: 持っていたものを適当に使います。Arduino Uno等のType Bと比べればよく使う端子なのでありがたいです。
- TG12864E-02A: 128x64のグラフィックディスプレイモジュールです。青背景に白抜きで表示されるタイプ。秋月電子で1300円(税込)で買ってきました。
- ブレッドボード: はんだごてが無いのでブレッドボードでやります。
- 10Ωの抵抗1つ
- 10kΩの半固定抵抗1つ
- ジャンパワイヤ適宜
- 動かしたいドット絵(128x64)

# Arduino Web Editor を使う
## 準備
[ガイドページ](https://create.arduino.cc/projecthub/Arduino_Genuino/getting-started-with-arduino-web-editor-on-various-platforms-4b3e4a)に従えばOKです。
1. Arduinoアカウント作成
2. Pluginのインストール

これだけです！簡単ですね。

## てはじめにExample
初心者なのでまずはオンボードLEDをチカチカさせるExampleを試してみます。初心者なのでめちゃくちゃ初心者な感じのメモを残します。

1. Arduino Nano EveryとPCをつなぐ
    1. 用意したケーブルでつなぎます。
    1. 初回はドライバのインストールを求められるのでインストールします。
1. Exampleを書き込む
    1. Editor左のカラムからExamples > 01.BASICS > Blinkを選びます。オンボードLEDを1秒ごとに点滅させるコードです。
    1. せっかくなのでdelay(1000)をdelay(5000)に変えて点滅の間隔を変えてみます。
    1. コピーを保存したら上部にある「→」ボタンでArduinoに書き込みます。
    1. できた！

# LCDに画像を表示する
## データシートを眺める
買えば同封されていますが、秋月電子の通販サイトでもpdfでデータシートを見られるようになっています。
https://akizukidenshi.com/download/ds/shenzhen/TG12864E-02A_LCM_rc2.pdf
なんと**ピンピッチが2mm**です！**2.54mmじゃない**！買ってから気づいた！ユニバーサル基盤を使おうとしている方はご注意を！
CN2はどこにも接続されていないそうなので、CN1と書かれている側のピンを使います。
ピンごとにどう接続するかをまとめてみます。

| 番号 | 種類 | 備考 | どこにつなぐか |
| --- | --- | --- | --- |
| 1 | VDD | 0V | アースです。ブレッドボードの-のところを介してArduinoのGndにつなぎます。 |
| 2 | VDD | 5V(電源) | 電源です。ブレッドボードの+のところを介してArduinoの5Vにつなぎます。 |
| 3 | VO | コントラスト（液晶駆動電圧） | ここの電圧でコントラストが決まります。18番のVEEと5Vの間に半固定抵抗を介してつなぎます。 |
| 4 | RS | レジスタ選択 | Arduinoのデジタルピンのどこかしらにつなぎます。どこにつなぐかはコードで指定できます。 |
| 5 | RW | 読書選択 | 同上。 |
| 6 | E | 有効無効選択 | 同上。 |
| 7-14 | DB0-7 | データ信号線0～7ビット目 | 同上。 |
| 15-16 |CS1-2 | チップ選択 | 同上。それぞれが画面の半分ずつを担当します。 |
| 17 | RST | リセット | 同上。 |
| 18 | VEE | -10V出力(液晶駆動電圧) | 3番参照。 |
| 19 | A | バックライト電源 | ピン配置のところに5Vと書いてありますが、Electrical/Optical Characteristicsのところに4.2±0.15Vと書いてあります。内部で抵抗がかまされるわけではないようなので、抵抗を挟んで5Vにつなぎます。 |
| 20 | K | バックライト電源 | アースです。Gndにつなぎます。 |

Arduino Nano Everyは裏にピン配置が小さい文字で書いてあるので若干見づらいですが、以下のようなピン配置になっています。
![Pinout-NANOevery_latest.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679910/53941aac-04fb-098d-f2d7-c88a2380f58f.png)
出典：https://store.arduino.cc/usa/nano-every

これでつなぎ方はばっちりな感じがします。
回路図は参考サイトに書いてあるのでここでは割愛します。

## コードを読む
参考サイトでコードが公開されているので読みます。
コード解説的なものを書こうかと思っていたのですが、元からコメントがかなりしっかりと書かれていたので不要ですね。感謝の気持ちでいっぱいです。

## 画像を配列に変換する
Arduinoに載せるため、今回のコードでは画像を8bitずつの配列に変換する必要があります。
以下のサイトでグラフィック画面変換ツールが公開されています。
[グラフィック液晶表示器用ライブラリ](http://www.picfun.com/PIC24H/app24H01.html)
こちらのツールは複数枚変換するには向いていないので、適当にコードを書いて変換することにしました。
Arduinoの記事なのにCじゃなくてPythonなのかよ！とは思いますが……Pythonの方が好きだから……。

```python:img2array.py
# img_path下にある全ファイルを配列に変換し標準出力する
# 縦64x横128の画像ファイルを想定
import os
from PIL import Image
import numpy as np

img_path = "path/to/images"
for i, filename in enumerate(os.listdir(img_path)):
    img = Image.open(f"{img_path}/{filename}").convert('1')
    img_array = np.asarray(img)
    hex_array = []
    for y in range(0, 64, 8):
        for x in range(128):
            hex_array.append('0x{:X}'.format(img_array[y,x] * 1 +
                                             img_array[y+1,x] * 2 + 
                                             img_array[y+2,x] * 4 + 
                                             img_array[y+3,x] * 8 + 
                                             img_array[y+4,x] * 16 + 
                                             img_array[y+5,x] * 32 + 
                                             img_array[y+6,x] * 64 + 
                                             img_array[y+7,x] * 128))
    hex_array_str = str(hex_array).replace(' ', '').replace('[', '{').replace(']', '}').replace('\'', '')
    print(f"const char ImageData{i}[1024] = {hex_array_str};\n")
```
出力された`const char ImageData0[1024] = {0xFF, 0xFF, ...};`みたいなものたちを.hファイルに保存します。
これで画像の準備はOKです。

## ドット絵を動かす
上で生成した画像配列を`loop()`内で順番に表示させてやるだけです。
メモリの効率化とか考えるべきな気もしますが、今回自分が使った128x64 35枚程度なら載るので愚直にやります。

```c:GLCD.ino
// 略

void loop() {
    GLCD_PutImage(ImageData0);
    delay(100);
    GLCD_PutImage(ImageData1);
    delay(100);
    GLCD_PutImage(ImageData2);
    delay(100);
    GLCD_PutImage(ImageData3);
    delay(100);
    GLCD_PutImage(ImageData4);
    delay(100);
    // 以下使いたい枚数分だけ繰り返す
}

// 略
```

## 書き込む
これで書き込めば動くはず……。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679910/f5a51972-ea9f-1f37-7f38-ddbf94d22cbd.jpeg" width="400px">
モルモットが動いた！！！
（写真ではわかりませんがドット絵が切り替わって表示されています。）
（なぜモルモットなのかというとモルモットが好きだからです。）
（ピンピッチが2mmのところに無理矢理普通のジャンパワイヤを刺したので配線がぎゅうぎゅうですが、気にしてはいけません。動いたから良いのです。）

# まとめ
Arduino Nano Everyを使ってTG12864E-02A上に動くドット絵を表示することができました。
参考サイトにコードがあったので、一番時間がかかったのはドット絵を作る～配列に変換する段階でした。