ATOM Lite ( M5Stackシリーズ ) の初期不良チェック方法

# ATOM Liteを初めて手に入れた
何か目的があるわけでもないのにM5StackシリーズのATOM Liteを手に入れた。
この手のモジュール/ボードを手に入れたときの問題は初期不良。
初期不良が確認できれば販売店などに交換依頼をすればいいのだが、確認が面倒で後で気が付いてもそれこそ「あとの祭り」。

似たようなマイコンボードであるmicro:bitは最初に動作確認できるようにパッケージングされている。
ATOM Liteにはそのような親切なものはないので自分なりに初期不良のチェック方法を確立しておきたいと考えた。

# ほぼ初心者
この手のモジュール/ボードの経験が豊富であればいいのだがmicro:bitをちょっと触った以外はなく、オフィシャルページから色々たどって右往左往したあげく小1時間で動作確認はできた。
が、これからATOM Liteを毎日触るわけでもなく、1年後に同じように右往左往したくないのでまとめてみた。

# 環境
Windows PC：Windows 10 Pro 64bit (1909)
Arduino IDE：V1.8.13
M5Atomライブラリ：バージョン 0.0.1
FastLEDライブラリ：バージョン 3.3.3
IRremoteESP8266ライブラリ：バージョン2.7.11

**＊Arduino IDEを使わずUIFlow（M5Stackシリーズ用ビジュアルプログラミング環境）を使う方法もあるが、購入直後であればArduino IDEを使う方がはるかに簡単。**

# チェック手順

**ATOM LiteにUIFlow用ファームウェアがインストール(Burn)されている場合、ファームウェアが上書きされてしまう。チェック実行後、UIFlow用ファームウェアを再インストール(Burn)する必要があるので注意**

## 1. Arduino IDEをダウンロードしてインストール

1. [Arduinoオフィシャルサイトのダウンロードページ](https://www.arduino.cc/en/Main/Software) から「Windows installer」か「Windows ZIP file」を選択
2. 「JUST DOWNLAOD」を選択してダウンロード
3. Arduino IDEをPCにインストール

## 2. ATOM LiteをPCに接続してポートの設定をする。

1. ATOM LiteのType-CポートとPCをUSBケーブルで接続
2. COMポートを確認。COMポートはPCのデバイスマネージャー上で[USB Serial Port(COM *x*)]として表示される。

## 3. Arduino IDEを起動して、対象ボードを設定

1. [ファイル]メニュー → [環境設定] → [追加のボードマネージャURL]に”[https://dl.espressif.com/dl/package_esp32_index.json](https://dl.espressif.com/dl/package_esp32_index.json)"　を設定
2. [ツール]メニュー → [ボード:"xxxxx"] → [ボードマネージャ]を選択
3. "esp32"を検索してインストール
4. [ツール]メニュー → [ボード:"xxxxx"] → [ESP32 Arduino] → [M5Stick-C]を選択
5. [ツール]メニュー → [シリアルポート:COM *x*]に先ほど確認したCOMポート番号を選択

## 4. 必要なライブラリを追加

1.[スケッチ]メニュー → [ライブラリをインクルード] → [ライブラリを管理...]
2. "M5Atom"を検索してインストール
3. "FastLED"を検索してインストール
4. "IRremoteESP8266"を検索してインストール

## 5. スケッチを実行

```cpp:ATOMLiteTest.ino
#include <M5Atom.h>
#include <IRremoteESP8266.h>
#include <IRsend.h>

const uint16_t kIrLed = 12; // M5Atom IR LED GPIO pin

IRsend irsend(kIrLed);  // Set the GPIO to be used to sending the message.

uint16_t rawData[] = {'A', 'T', 'O', 'M', 'L', 'i', 't', 'e'};        // 送信データ(ダミー)
                        
void setup()
{
  M5.begin(true, false, true);

  irsend.begin();
    
  M5.dis.drawpix(0, 0xf00000);                // (暗めの)緑

  delay(50);
}

uint8_t FSM = 0;
uint16_t cnt;

void loop(){

  if (M5.Btn.wasPressed()){

    FSM++;
    if (FSM >= 5){
      FSM = 0;
    }

    switch (FSM){

      case 0:
            M5.dis.drawpix(0, 0xf00000);      // (暗めの)緑
            break;
      case 1:
            M5.dis.drawpix(0, 0x00f000);      // (暗めの)赤
            break;
      case 2:
            M5.dis.drawpix(0, 0x0000f0);      // (暗めの)青
            break;
      case 3:
            M5.dis.drawpix(0, 0x707070);      // (暗めの)白
            break;
      case 4:
            M5.dis.drawpix(0, 0x000000);      // 黒
            for (cnt=0; cnt<1000; cnt++){
              irsend.sendRaw(rawData, sizeof(rawData) / sizeof(uint16_t), 38);  // Send a raw data capture at 38kHz.
            }
            break;
      default:
            break;
    }

  }
  
  delay(50);
  M5.update();
}
```

1. 上記スケッチを既にあるスケッチと置き換える（コピー＆ペースト等）
2. [スケッチ]メニュー → [マイコンボードに書き込む]
3. ATOM Liteのボタンを押すごとにLEDが [緑] → [赤] → [青] → [白] → [黒(赤外線)] → [緑] ...と変わればOK

**(注意)**
+ 赤外線は光ってすぐ消える（バッテリーと熱を考慮）
+ 赤外線は上部のLEDの場所ではなく、USBコネクターの反対側（シール横の1mm程度の穴）から出る。
+ 赤外線は目に見えない。スマホやデジタルカメラに向けるとぼおーと白っぽく映る。
+ スマホやカメラによっては赤外線は映らない（例えば、iPhone 7のアウターカメラには映らないが、インナーカメラには映る）

**(スケッチをATOM Liteに書き込むときのエラー)**
ATOM Liteに限らずM5Stick-CやM5Stack Grayで書き込み時のエラーを経験した。
デバイスドライバーにはちゃんと[USB Serial Port(COM *x*)]が表示されているのでUSBでちゃんと接続されている。
しばらく使用していなかった個体で内部的な回路や内蔵フラッシュ(内部ROM)に何らかの問題が出てしまったのかもしれない。
いったん書き込みに成功するとそれ以降何事もなかったかのように書き込めるようになるのでかなり厄介。

書き込み時にエラーが発生した場合は（基本的だが）以下の点を確認

+ 余計なものは接続しない（バッテリーやM5Stack ユニット等はすべてはずす)
+ 転送スピードを落としてみる（Arduino IDEの[ツール]メニュー → [Upload Speed："xxxxxxx"]を初期値より小さな数字に変更する。ただし、転送スピードを落とせばそれだけ書き込みは遅くなる）
+ USBケーブルは付属品を使用する（ただし、ATOM LiteにはUSBケーブルは付属しない）
+ USBケーブルは細いものや、長いものは使用しない
+ USBケーブルはPC本体のUSBポートに接続する（USBハブは使用しない）
+ PC本体の違うUSBポートに接続してみる（特に、PCのUSB3.xポートに接続している場合はUSB2.0ポートに接続してみる。USB2.0ポートに接続してる場合はUSB3.xポートに接続してみる）

# 【おまけ】色指定（RGB値）

上記サンプルスケッチの中では次のようにLEDの色を指定している。

```cpp:ATOMLiteTest.ino
　　　　　　　　　　　　　：
            M5.dis.drawpix(0, 0xf00000);      // (暗めの)緑
　　　　　　　　　　　　　：
```

"0xf00000"が色になるのだが実はこの部分がちょっとおかしい。
"0xf00000"の部分はFastLEDライブラリで定義されているCRGB構造体で1バイト目がR(赤)値、2バイト目がG(緑)値、3バイト目がB(青)値になっている。

```LED_Display.h
　　　　　　　　　　　　　：
class LED_Display : public Task
{
　　　　　　　　　　　　　：
    void drawpix(uint8_t Number, CRGB Color);
　　　　　　　　　　　　　：
};
　　　　　　　　　　　　　：
```

```cpp:pixeltypes.h
　　　　　　　　　　　　　：
struct CRGB {
	union {
		struct {
            union {
                uint8_t r;
                uint8_t red;
            };
            union {
                uint8_t g;
                uint8_t green;
            };
            union {
                uint8_t b;
                uint8_t blue;
            };
        };
		uint8_t raw[3];
	};
　　　　　　　　　　　　　：
}
　　　　　　　　　　　　　：
```

普通に考えば"0xf00000"は（R,G,B）= (0xf0, 0x00, 0x00)で赤になると思えるのだが、M5Atom Liteでは緑になってしまう。同様に"0x00f000"は（R,G,B）= (0x00, 0xf0, 0x00)で緑になると思えるのだが、M5Atom Liteでは赤になってしまう。
一方、"0x0000f0"は（R,G,B）= (0x00, 0x00, 0xf0)でM5Atom Liteでもちゃんと青になる。


|CRGB値|RGB値|表示されるべき色|実際の色|
|:-----:|:----:|:-------------------:|:-----------:|
|0xf00000|(0xf0, 0x00, 0x00)|`rgb(240,0,0)`|`rgb(0,240,0)`|
|0x00f000|(0x00, 0xf0, 0x00)|`rgb(0,240,0)`|`rgb(240,0,0)`|
|0x0000f0|(0x00, 0x00, 0xf0)|`rgb(0,0,240)`|`rgb(0,0,240)`|

つまり、緑と赤が逆になってしまっている。


実はFastLEDライブラリを使うときにCRGBとRGB LEDとの対応をちゃんとしないといけないらしいのだが現在提供されているM5Atomライブラリではその部分がおかしいらしい。（[Issue #5](https://github.com/m5stack/M5Atom/issues/5)、[pull #29](https://github.com/m5stack/M5Atom/pull/29)を参照）


具体的にはM5AtomライブラリのLED_DisPlay.cpp内の初期化部分とdisplaybuff()関数内

```LED_DisPlay.cpp
　　　　　　　　　　　　　：
LED_Display::LED_Display(uint8_t LEDNumbre)
{
    FastLED.addLeds<WS2812, DATA_PIN>(_ledbuff, LEDNumbre);
　　　　　　　　　　　　　：
}
　　　　　　　　　　　　　：
void LED_Display::displaybuff(uint8_t *buffptr, int8_t offsetx, int8_t offsety)
{
            _ledbuff[x + y * 5].raw[1] = buffptr[2 + ((setdatax + x) % xsize + ((setdatay + y) % ysize) * xsize) * 3 + 0];
            _ledbuff[x + y * 5].raw[0] = buffptr[2 + ((setdatax + x) % xsize + ((setdatay + y) % ysize) * xsize) * 3 + 1];
            _ledbuff[x + y * 5].raw[2] = buffptr[2 + ((setdatax + x) % xsize + ((setdatay + y) % ysize) * xsize) * 3 + 2];
　　　　　　　　　　　　　：
}
```

を次のように書き換えてしまえばよい。("`, GRB`"を追加、raw[0]とraw[1]の入替)

```LED_DisPlay.cpp
　　　　　　　　　　　　　：
LED_Display::LED_Display(uint8_t LEDNumbre)
{
    FastLED.addLeds<WS2812, DATA_PIN, GRB>(_ledbuff, LEDNumbre);
　　　　　　　　　　　　　：
}
　　　　　　　　　　　　　：
void LED_Display::displaybuff(uint8_t *buffptr, int8_t offsetx, int8_t offsety)
{
            _ledbuff[x + y * 5].raw[0] = buffptr[2 + ((setdatax + x) % xsize + ((setdatay + y) % ysize) * xsize) * 3 + 0];
            _ledbuff[x + y * 5].raw[1] = buffptr[2 + ((setdatax + x) % xsize + ((setdatay + y) % ysize) * xsize) * 3 + 1];
            _ledbuff[x + y * 5].raw[2] = buffptr[2 + ((setdatax + x) % xsize + ((setdatay + y) % ysize) * xsize) * 3 + 2];
　　　　　　　　　　　　　：
```

M5Atomライブラリを書き換えてしまうリスクはあるが、CRGB::Red(赤)やCRGB::Blue(青)といった定義済みの色指定がちゃんと使えるようになる。

(参考) [FastLEDライブラリ解説](https://lang-ship.com/blog/work/fastled/)