M5UnitV2のインストールや備忘録

#1.はじめに
みんな大好きM5StackからUnitV2が発売されました。技適も通って手元に届いた報告もたくさんアップされつつあります。試したそばから忘れていくお年頃なので備忘録。
とりあえずやりたいこととか章立てしてますが、確認済み、確認予定項目入り混じっています。

#2.ドライバインストール
公式サイトの[Quick Start](https://docs.m5stack.com/en/unit/unitv2?id=quick-start)に沿って進めます。
#2.1.公式サイトからドライバをダウンロードして解凍する
  [ドライバダウンロード](https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/sr9900.inf_amd64.rar)
　デバイスドライバはsr9900.inf_amd64.rarというファイルなのでこれをダウンロードして解凍しておきます。
#2.2.PCとUSBケーブルで接続する
TypeCコネクタで接続します。USB2.0接続の様です。
#2.3.デバイスマネージャを立ち上げてUnitV2の接続を確認する
まずデバイスマネージャを立ち上げます。([デバイスマネージャの立ち上げ方](http://qa.elecom.co.jp/faq_detail.html?id=6505))
デバイスマネージャを開いて下画像の様に「ほかのデバイス」に「USB 10/100 LAN」というデバイスが表示されていれば、UnitV2が認識されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496179/78f2021d-8a15-95b6-93be-a13998681fd8.png)

#2.4.ドライバをインストールする
「USB 10/100 LAN」を右クリックし、「ドライバーの更新」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496179/839845bf-6316-b258-9971-8fd1f9099105.png)
「コンピューターを参照してドライバーを検索(R)」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496179/19edd503-42dd-9a33-9507-3c6b0d4488df.png)
「参照」ボタンから、解凍したデバイスドライバのあるフォルダを指定して「次へ」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496179/c2f1ca7a-a384-fe94-fdf6-50d589a82290.png)
ドライバが正常にインストール出来たら「ネットワークアダプー」に「Corechip SR9900 USB2.0 to Fast Ehternet Adapter」が追加される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496179/1d4fec86-e186-5888-8fba-4b0b22461db7.png)

#3.プリインストール機能
UnitV2には購入時点で13の機能がBuilt-in recognition functionとしてプリインストールされていて、Webブラウザを利用して簡単にアクセスできます。
また、スナップショットなどの便利機能もついています。

##3.1.プリインストール機能へのアクセス
ドライバインストールができたら、USBケーブルで接続したままWebブラウザで [http://10.254.239.1/](http://10.254.239.1/) にアクセス。
プリインストール機能は画面上段に表示されており、クリックするたでけで機能変更が可能。便利すぎですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496179/7ff47443-25ca-7bab-0fe2-302f780f8a85.png)

###3.1.1.スナップショット機能
①のカメラアイコンをクリックすると、⑥の画像表示エリアの画像が保存されます。
###3.1.2.ギャラリー
スナップショットをとると、⑧のギャラリーエリアが表示され、画像が一覧できます。
###3.1.3.ギャラリーの表示/非表示切り替え
②のアイコンをクリックすると、ギャラリーの表示/非表示が切り替わります。
###3.1.4.謎のトグルスイッチ
ギャラリーが表示されている状態でトグルを切り替えると非表示に切り替わります。
非表示→表示への切り替えはできません。謎。
###3.1.5.メニュー
④のエリアに13個のプリインストール機能が表示されており、クリック一つで切り替えできます。
###3.1.6.設定エリア
機能に応じて設定項目がある場合は⑤に表示され、パラメータを変更できます。
###3.1.7.表示エリア
⑥のエリアにはカメラ画像やFFTグラフィックが表示されます。スナップショット可能です。
###3.1.8.結果エリア
⑦のエリアに物体認識等の数値データが表示されます。
これをSerial出力すれば各種制御パラメータに活用できるようです。
###3.1.9.ギャラリー
⑧のエリアにスナップショットデータが表示され、サムネイルをクリックすると⑨の様にダウンロードと削除アイコンが表示されます。


##3.2.Camera Stream
一つ目の機能はCamera Srtreamです。実行すると、UnitV2のカメラで撮影した画像がリアルタイムストリーミング再生されます。
<blockquote class="twitter-tweet"><p lang="en" dir="ltr"><a href="https://twitter.com/hashtag/M5UnitV2?src=hash&amp;ref_src=twsrc%5Etfw">#M5UnitV2</a><br>camera streaming test <a href="https://t.co/WUq2OnP0s1">pic.twitter.com/WUq2OnP0s1</a></p>&mdash; AIRPOCKET＠rastaman vibration (@AirpocketRobot) <a href="https://twitter.com/AirpocketRobot/status/1397902740647419904?ref_src=twsrc%5Etfw">May 27, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

##3.3.Code Detector
二つ目の機能はQRコードリーダーです。
![qr.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496179/2be0571d-160c-1f5e-bacb-fdbc0a154757.png)


バーコードには非対応。ライブラリ入れたらできると思いますが。
![bar.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496179/ef000bb7-875e-2d49-2f9e-aaa103981ea9.png)

##3.4.Object Recognition
学習済みモデルは2種類、nanodet_80classとyolo_20classだそうです。
それぞれのclassは以下の通り。
###3.4.1.nanodet_80classのリスト
/home/m5stack/payload/uploads/models/nanodet_80class/model.jsonより。
"person","bicycle","car","motorbike","aeroplane","bus","train","truck","boat","traffic light","fire hydrant","stop sign","parking meter","bench","bird","cat","dog","horse","sheep","cow","elephant","bear","zebra","giraffe","backpack","umbrella","handbag","tie","suitcase","frisbee","skis","snowboard","sports ball","kite","baseball bat","baseball glove","skateboard","surfboard","tennis racket","bottle","wine glass","cup","fork","knife","spoon","bowl","banana","apple","sandwich","orange","broccoli","carrot","hot dog","pizza","donut","cake","chair","sofa","pottedplant","bed","diningtable","toilet","tvmonitor","laptop","mouse","remote","keyboard","cell phone","microwave","oven","toaster","sink","refrigerator","book","clock","vase","scissors","teddy bear","hair drier","toothbrush"
###3.4.1.yolo_20classのリスト
/home/m5stack/payload/uploads/models/yolo_20class/model.jsonより。
"aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car", "cat", "chair", "cow", "diningtable", "dog", "horse", "motorbike", "person", "pottedplant", "sheep", "sofa", "train", "tvmonitor"


##3.5.Color Tracker(予定）
##3.6.LaneLine Tracker(予定）
##3.7.Target Tracker(予定）
##3.8.Motion Tracker(予定）
##3.9.Online Classifier(予定）
##3.10.Face Recognition(予定）
##3.11.Face Detector(予定）
Face Detectorは顔検出です。個人の区別は行いません。
検出した顔はバウンディングボックスで囲まれてパラメータがJSONで出力されます。
パラメータ
"num":検出された顔の数
"face":検出された顔のパラメータ
"face":{["x":バウンディングボックスの左上のx座標
         "y":バウンディングボックスの左上のy座標
         "w":バウンディングボックスの幅
         "h":バウンディングボックスの高さ
         "prob":確率
         "mark":[{"x":右目のx座標　※画面上は向って左側の目
                  "y":右目のy座標
                 {"x":左目のx座標
                  "y":左目のy座標
                 {"x":鼻のx座標
                  "y":鼻のy座標
                 {"x":口の右端のx座標
                  "y":口の右端のy座標
                 {"x":口の左端のx座標
                  "y":口の左端のy座標
"running":稼働しているfunction

##3.12.Shape Detector(予定）
##3.13.Shape Matching(予定）
##3.14.Audio FFT(予定）
<blockquote class="twitter-tweet"><p lang="cy" dir="ltr"><a href="https://twitter.com/hashtag/M5UnitV2?src=hash&amp;ref_src=twsrc%5Etfw">#M5UnitV2</a><br>Audio FFT <a href="https://t.co/dGVWZt1fOd">pic.twitter.com/dGVWZt1fOd</a></p>&mdash; AIRPOCKET＠rastaman vibration (@AirpocketRobot) <a href="https://twitter.com/AirpocketRobot/status/1397913746719211525?ref_src=twsrc%5Etfw">May 27, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

#4.Jupyter Notebookの開発環境を試す
Jupyter Notebookを使ってpythonでの開発がとても簡単にできます。
ブラウザから[http://10.254.239.1/](http://10.254.239.1/) にアクセスし、右上の歯車をクリックしてFUNC PANELを開きます。「Switch to notebook mode」をクリックするとJupyter notebookが立ち上がります。
![note.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496179/62937709-c7fe-8ef8-8c67-8037d306aacf.png)

少し待ってブラウザのリロードボタンを押すとnotbookが表示されます。
01-Introduction to M5Stack UnitV2.ipynbというチュートリアルファイルがありますので、実行してnotebookの使い方を確認してみてください。

#5.SSH接続する
適当なterminalアプリでSSH接続可能です。
接続先は、本体の裏のシールに書かれています。
![DSC_3069.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496179/67500671-e9b4-1732-434b-86da36054040.jpeg)
IP:10.254.239.1
port:22
user:m5stack
pass:12345678
です。

接続には[MobaXterm](https://mobaxterm.mobatek.net/)を使用しました。
MobaXtermを立ち上げて、「Session」
![moba1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496179/f0ca38d0-ecd2-d2d8-d7db-a47c00765d2c.png)

「SSH」を選択して、「Remotehost」に「10.254.239.1」、Port「22」が選択されていることを確認して「OK」
![moba3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496179/96e32b8c-16fd-88c3-4b8f-1fdb7c3981d5.png)

usernameに「m5stack」、passordに「12345678」を入力。何か聞いてきますがよくわからなかったら「No」
![moba5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496179/696ca02a-2eeb-30e0-2815-e5dfe029bf23.png)

この画面が出たらログイン成功。
![moba6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496179/6a243a69-c188-ba0f-0f7d-f9d074b063cc.png)


ユーザーの権限が弱いのですが、さっそくsudoを使う方法が報告されていますので試してみます。
ミクミンP/Kazuhiro Sasao@ksasaoさんのTweetを参考にさせていただきました。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">UnitV2 で sudo できるようになった。Jupyter Notebook で下記を実行<br><br>!chown root:root /usr/bin/sudo &amp;&amp; chmod 4755 /usr/bin/sudo<br>!chown root:root /usr/libexec/sudo/sudoers.so<br>!chown root:root /etc/sudoers <a href="https://t.co/Z3Q4sF3RkM">pic.twitter.com/Z3Q4sF3RkM</a></p>&mdash; ミクミンP/Kazuhiro Sasao (@ksasao) <a href="https://twitter.com/ksasao/status/1397905827302838273?ref_src=twsrc%5Etfw">May 27, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

#6.Wi-Fiアクセスポイントにして接続（未実装？）
そもそも初期設定の状態でアクセスポイントになってて、
SSID:M5UV2_XXXX
pass:12345678
でログインできるはずのですが、APとして見えないですね。
Twitterでも接続できない報告があがっているのですが、全ユーザーなのか一部機体の問題なのかはまだ不明です。

#7.既存のWi-Fiネットワークに接続してSSHなど
Wi-Fi AP機能は動きませんが、sudoコマンドを使うことで、既存のWi-Fi環境に接続できます。
こちらもミクミンP/Kazuhiro Sasao@ksasaoさんのTweetから。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">UnitV2 が家の WiFi につながった(DHCP Client)。<br>/etc/wpa_supplicant.conf<br>に以下のような感じで SSID/パスワードを追記して、電源を入れなおし。 <a href="https://t.co/WbPCdZxdY7">pic.twitter.com/WbPCdZxdY7</a></p>&mdash; ミクミンP/Kazuhiro Sasao (@ksasao) <a href="https://twitter.com/ksasao/status/1397927629420863493?ref_src=twsrc%5Etfw">May 27, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

IPアドレスが変わるとアクセスできなくなるので固定しておくと便利。
resolv.confを見てDNSのアドレスを確認。私の環境では192.168.1.100

```shell
unitv2% cat resolv.conf
# Generated by dhcpcd from wlan0.dhcp
# /etc/resolv.conf.head can replace this line
domain **************
nameserver 192.168.1.100
nameserver 192.168.1.21
# /etc/resolv.conf.tail can replace this line
```

すでにWiFi接続できていて、いま接続しているアドレスに固定するなら、ifconfigでwlan0のアドレスを確認。私の環境では、192.168.1.203


```shell
unitv2% ifconfig
eth0      Link encap:Ethernet  HWaddr 00:30:1B:BA:02:DB
          inet addr:10.254.239.1  Bcast:10.254.239.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1467 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1257 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:116132 (113.4 KiB)  TX bytes:152344 (148.7 KiB)
          Interrupt:35

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:140 errors:0 dropped:0 overruns:0 frame:0
          TX packets:140 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1
          RX bytes:8856 (8.6 KiB)  TX bytes:8856 (8.6 KiB)

wlan0     Link encap:Ethernet  HWaddr 00:E0:4C:73:3D:62
          inet addr:192.168.1.203  Bcast:192.168.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:30800 errors:0 dropped:9 overruns:0 frame:0
          TX packets:1013 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:3409593 (3.2 MiB)  TX bytes:169583 (165.6 KiB)

wlan1     Link encap:Ethernet  HWaddr 02:E0:4C:73:3D:62
          inet addr:10.254.239.1  Bcast:10.254.239.255  Mask:255.255.255.0
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
```

あとは、/etc/dhcpcd.confをvim等のエディタで編集します。

```shell
sudo vim /etc/dhcpcd.conf
```

interface wlan0の下に次の3行を追加。IPアドレスには先ほど調べた値もしくは任意のアドレスを。

```shell
interface wlan0
static ip_address=192.168.1.203
static routers=192.168.1.100
static domain_name_servers=192.168.1.100
```


#8.serial出力読み込み
UnitV2のbuilt-in recognition functionの内、Camera StreamとAudio FFT以外の機能は、検出結果を問答無用でシリアル出力しています。データgrove端子を通じてUARTで出力されていますので、これを読み取れば外部の装置で検出結果を利用できます。
[公式ドキュメント](https://docs.m5stack.com/en/quick_start/unitv2/base_functions)のコードをM5StickC plus向けに修正しました。M5Stack/Stick/Atomどれでも読み取り可能です。
boudrateは115200、TX,RXのピン番号をお間違え無く。

```CPP
#include <M5StickCPlus.h>

void setup() {
  M5.begin();

  Serial.begin(115200);
  Serial2.begin(115200, SERIAL_8N1, 33, 32);  //33,32はそれぞれTX,RX。
}

void loop(){

  if(Serial2.available()) {
    String recvStr = Serial2.readStringUntil('\n');
    if(recvStr[0] == '{'){
      Serial.print(recvStr);
    }
  }
}
```


#8.1.ArduinoIDEでJSONファイル読み込み
ArduinoJsonというライブラリを使って、受け取ったデータをJsonデータに変換して利用します。
使い方は[こちらのサイト](https://rikoubou.hatenablog.com/entry/2021/04/16/162258)に詳しく紹介されていますので参考にさせて抱きました。多謝。
ライントレースの出力データを読み込む場合はこのような具合。

```CPP
#include <M5StickCPlus.h>
#include <ArduinoJson.h>

int x;
int y;
long k;
char data[50];

void setup() {
  M5.begin();
  Serial.begin(115200);
  Serial2.begin(115200, SERIAL_8N1, 33, 32);
}

void readJSON(void){
  String recvStr = Serial2.readStringUntil('\n');
  StaticJsonDocument<128> doc;
  DeserializationError error = deserializeJson(doc, recvStr);

  if (error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.f_str());
    return;
  }

  x = doc["x"];
  y = doc["y"];
  k = doc["k"];
  const char* running = doc["running"]; // "Lane Line Tracker"  
}

void loop(){
  if(Serial2.available()) {
    readJSON();
    sprintf(data,"x = %d , y = %d , k = %ld",x,y,k);
    Serial.println(data);
  }
}

```


#8.2.MicropythonでJSONファイル読み込み（予定）
Raspi picoのUARTで読もうと思ったのですが、どう頑張っても読めませんでした。
判る方がいらっしゃったら教えてください。


#9.その他リンクなど
##9.1.UnitV2Framework
https://github.com/m5stack/UnitV2Framework
##9.2.Built-in recognition functionの説明
https://docs.m5stack.com/en/quick_start/unitv2/base_functions