Sipeed M1 dock suit (Dan Dock) を買ってからサンプルの顔検出プログラムを動かすまで

## はじめに
初めてQuitaに記事を書きます！はじめまして！
色々できるかなと思ってSipeed M1 dock suitという開発ボードを購入したのですが、色々あってデモアプリが動くまでに無限に時間が溶けました
せっかくなのでやったことを備忘録兼ねてまとめて記事にしたらいいんじゃね？という勢いで書いたのがこの記事です

##Sipeed M1 dock suitについて
近年注目されてるAIoT(AI + IoT)の開発を支援する開発ボードです
IoTのエッジ側でAIの推論等を行うことに特化したプロセッサであるMAIXを搭載しています。この特徴としては特徴としては

* 小さい（ラズパイの1/4くらい）
* 低消費電力
* 安い(このチップが乗ったボードはカメラとディスプレイがセットで$18.9)
* KPUというアクセラレータが載っており、ニューラルネットの処理が得意
* MaixPyというmicropythonベースの言語でプログラムが書ける
* Tensorflow Liteなど対応するニューラルネットのモデルが動く

すごい！

詳しくは以下の販売ページに記載されています
https://www.seeedstudio.com/Sipeed-M1-dock-suit-M1-dock-2-4-inch-LCD-OV2640-K210-Dev-Board-1st-RV64-AI-board-for-Edge-Computing-p-3211.html

##購入-組み立て
買って組み立てないことには始まりません
###購入
リンクに貼ったモデルは$18.90USDのモデルを、Seeedのオンラインストアで購入しました。
（購入後に気がつきましたがWi-fi通信ができるチップが乗ったものが$19.90で出てました。2019/04/07現在も品切れですが・・・・）
送料（Seeed carrer, 一番安いやつ）含めて$26.99USDでした。送料考えると何枚かを一気買いした方がよかったかなという感じです

Seeed carrerには20-30working daysと書いてありましたが、実際は日曜日に注文して、休日含め１１日後に届きました。思ってたより早かったです

###組み立て
ケースを開けるとチップ本体、ディスプレイ、カメラ、何に使うかよくわからないピンが二つ、USBのtype-BからCへの変換アダプタが入ってます。
あとステッカーが入っています。説明書的なものは何も入っていません。
ので、まずカメラとLCDディスプレイの接続で躓きました。

USB差込口が右側かつ裏側に来るような向きを基準にすると、ボード左端にLCDの配線差込口、ボード中央やや上よりにカメラの差込口があります。
LCDは画面がこっちをむく向きのまま右方向に、カメラはレンズがこっちをむく向きのまま上方向に差し込みます。

差し込み手順は

1. 差込口の黒い部分を上方向に開く
2. 向きに注意しながら配線を差し込む（角度などが正しいとスッ・・・・と差さる感じがします）
1. 最後に、1.で引き上げた黒い部分をパチンと戻す

出来上がり！

##電源投入-サンプルプログラム実行
いよいよ動かしていきます

多分Windowsでも大丈夫ですが、お手軽さを考えるとLinuxやMacがお勧めです。
（Windowsを使う場合の説明は割愛します、すみません・・・）

公式ドキュメント( https://maixpy.sipeed.com/en/ )に従ってファームウェアのアップデートを行います。

###ドライバ導入・環境構築
USBシリアル通信のモジュールとしてCH340が使われているため、これに対応するドライバを導入する必要があります。
ドライバが入っていない場合、USBケーブルを接続してもLCDディスプレイが光りません。

Mac(とWin)の場合は以下のサイトにある物をダウンロードして導入すると良いです
https://kig.re/2014/12/31/how-to-use-arduino-nano-mini-pro-with-CH340G-on-mac-osx-yosemite.html
(参考 : [Mac > CH341,CH340　のドライバ](https://qiita.com/sugasaki/items/f3258a8138c69d73069f))
Linuxの場合は初めから入ってるようなので、特別な操作は不要です。
----2019/04/12追記-----
Macの場合minicomで接続すると初期画面が出た後に操作ができなくなるみたいです・・・

ドライバが正しくインストールされた後にUSBケーブルでボードとPCを接続すると、LCDが光ります。
僕の場合は青い背景の上に`Welcome to MaixPy`という文字が表示されました。

ファームウェアアップデートに必要なツールも導入します。
python3とpython3のpipを導入し、pipからpyserialを導入してください

``` 
sudo apt update
sudo apt install git python3 python3-pip
sudo pip3 install pyserial
```
その上で、ファームウェア書き込みに使用するkflash.pyのリポジトリをクローンしてください

```
git clone https://github.com/sipeed/kflash.py
```

また、シリアル通信を行うプログラムも導入します。
ドキュメントには`minicom`か`screen`でできるよと書いてあります。
僕は`minicom`を入れました。

```
sudo apt install minicom
```

###ファームウェアアップデート
さて、ここからが僕が一番苦労し時間を溶かされた点です。
正しくドライバがインストールされ（ているはずで）、ディスプレイも点灯しているのに
何をどう頑張っても`/dev/ttyUSB0`などのデバイスファイルが現れず、アップデートが実行できませんでした。

結論から言うと、**接続ケーブル側に問題がありました。**
Type-B→Type-Cの変換アダプタがボードに同梱されていたので、アダプタをかまして家にあったType-BのUSBケーブル（データ転送対応）を接続していたのですが、どうもこれが良くなかったみたいです。
転がってた**USB Type-Cのケーブル**をダメ元でさしてみたところ、すんなり認識されました。
今までの苦労は何だったんだ・・・・
~~いや確かにドキュメントにはtypeCを使いましょうね旨書いてあるけど・・・~~

と言うことで最新版ファームウェアを落としてとっとと流し込んでやります。

ファームウェアは以下のgithubリポジトリからダウンロードしてください
https://github.com/sipeed/MaixPy/releases
`full`でも`minimum`でも大丈夫なはずですが`.kfpkg`形式のやつを選択してください。`.bin`の方だと顔検出のプログラムが含まれません
また、Linuxの場合`.kfpkg`ファイルがzipアーカイブとして認識されますが、展開せずこのまま使います。

ファームウェアを落としたら、kflash.pyでボードに転送します。
ファームウェアには全手順でダウンロードした.kfpkgファイルを指定してやりましょう。
「ポートのデバイスファイル」は`/dev/ttyUSB0`などです

```
sudo python3 kflash.py -p [ボードのデバイスファイル] -b 2000000 -B dan maixpy_v0.2.4_full(minimum)_with_model_at_0x300000.kfpkg
```
コマンドを動かしたら書き込まれるのを待ちましょう
（fullの場合、まあまあ時間がかかります）

ファームウェア(v0.2.4)が正しく書き込まれると、青い背景だったLCDディスプレイの表示が赤い背景になります。

###実行
いよいよ実行します。
micropythonで書いたプログラムをボードに書き込んで動かす他、シリアル通信で対話形式のコマンド実行もできます。
ここでは対話形式で実行します。

ボードをUSBケーブルでパソコンと接続してから、下記コマンドでminicomの設定を開いてください

```
sudo minicom -s
```

1. 上から三番目の`Serial port setup`を選択
1. `A`を押して`Serial Device`の設定変更モードに
1. 設定を、ボードのデバイスファイルに書き換えてEnterキー二回押す
1. 上から六番目の`Save setup as dfl`を押して変更を保存
1. Exitを押してシリアル通信のコンソール画面に移動

と言う手順で通信を開始してください
（ドキュメントを読むと他にも色々設定項目がありますが、とりあえずサンプルプログラムを動かすだけであればシリアルポートの設定だけで大丈夫です）

ポートが正しく指定されていると、MAIXPYの起動画面が表示されるか何も表示されないかのどちらかになります。
何も表示されない場合、Enterキーを押すと`>>>`が表示される場合、正常に接続できています。

あとは、プログラムを実行するだけです。
https://github.com/sipeed/MaixPy_scripts/blob/898a941ffb7a9d90856dcb69d5b4f012babd0951/machine_vision/demo_find_face.py にある以下のコードをそのまま打ち込んでやると、サンプルの顔検出プログラムが実行されます。

```python

import sensor
import image
import lcd
import KPU as kpu

lcd.init()
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.run(1)
task = kpu.load(0x300000) # you need put model(face.kfpkg) in flash at address 0x300000
# task = kpu.load("/sd/face.kmodel")
anchor = (1.889, 2.5245, 2.9465, 3.94056, 3.99987, 5.3658, 5.155437, 6.92275, 6.718375, 9.01025)
a = kpu.init_yolo2(task, 0.5, 0.3, 5, anchor)
while(True):
    img = sensor.snapshot()
    code = kpu.run_yolo2(task, img)
    if code:
        for i in code:
            print(i)
            a = img.draw_rectangle(i.rect())
    a = lcd.display(img)
a = kpu.deinit(task)
```
カメラの配線がカメラの下にくる向きで人の顔を写すと、人の顔に相当する部分が白い四角で囲まれてLCDに表示されます。

めでたしめでたし。

##おわりに
サンプルを動かすだけのはずなのに結構手こずったので、せっかくだしやり方をまとめようと記事にしてみました。
何か参考になるものがあれば幸いです。

（こうしたほうがいいよ、的な暖かいコメント・フィードバック等いただけるとめちゃくちゃ嬉しいです、よろしくお願いします）