arduino-cli を試してみる (Windows10)

(2018/9/11) 追記
Typo 修正．`board.local.txt` → `boards.local.txt`．
OTA 対応していないようです．素直に `espota` コマンドををたたきましょう．

(2018/9/6) 追記
`Library` について．
`compile` の `--build-properties` について．
`M5Stack` のアップロード．

(2019/9/5) 編集
`compile.go` を変更．

(2018/9/3) 追記
esp32 のスケッチを無理やりアップロードする．

(2018/8/31) 追記
esp8266,esp32 の core の導入(esp8266 は手元にないので検証していません)．
esp32 のスケッチアップロードは出来ませんでした．

## 1. はじめに

[Qiita](https://qiita.com/tab4moji/items/1c760fc2ca48c9ee10ee) の投稿で `arduino-cli` がリリースされたのを知ったので，`alpha` release で動かないかなと思いながらも試してみました．元の投稿にあるように `Windows 0.2.0-alpha.preview` では，動作しなかったので，ソースから導入します．


## 2. Go 言語の導入

[The Go Programming Language](https://golang.org/) から，`go1.11.windows-amd64.msi` ダウンロードしてインストールします．msi でインストールすると環境変数(`GOPATH`,`PATH`)の設定も自動でやってくれます．デフォルトでは C ドライブ直下に入ります．私は，手動で設定するので `go1.11.windows-amd64.zip` を用いました．Go のインストールは，他のサイトを参考にして下さい．`PATH` に `%GOPATH%\bin` の設定がされていることを前提に進めます．


## 3. arduino-cli

### 3.1. インストール

コマンドプロンプトを立ち上げて，下記のコマンドでインストールします．

```cmd
> set http_proxy=http://hostname:port/  (プロキシ環境なら設定)
> set https_proxy=%http_proxy%

> go get -u github.com/arduino/arduino-cli
```

デフォルトの `GOPATH` は，`%USERPROFILE%\go` になっていると思いますので，`%GOPATH%\bin` に `arduino-cli.exe` が出来ていることを確認します(おそらく，C:\User\xxx\go\bin になると思います．xxx はユーザ名)．

`Arduino IDE` と環境を分けたいので，`%GOPATH%\bin` に 下記の内容で，`.cli-config.yml` を作成します．フォルダの場所はどこでも構いませんが，自動で作成されないので，あらかじめ作っておきます．

```yaml:.cli-config.yml
sketchbook_path: D:\Users\xxx\Documents\MyProjects\ArduinoCli\Arduino
arduino_data: D:\Users\xxx\Documents\MyProjects\ArduinoCli\.arduino15
```

### 3.2. 動作確認

[arduino/arduino-cli](https://github.com/arduino/arduino-cli) の `Getting Started` の手順のままです．ただし，`Arduino UNO` を用いたのでその部分は変更しています．動作の確認をしたいので `--debug` を付けていることもあります．`Arduino UNO` とパソコンに USB ケーブルで接続済みです．


```cmd
> arduino-cli.exe --debug sketch new MyFirstSketch

(D:\Users\xxx\Documents\MyProjects\ArduinoCli\Arduino\MyFirstSketch\MyFirstSketch.ino を編集)

> arduino-cli.exe --debug core update-index

> arduino-cli.exe board list
(このときは，FQBN は表示されないと思います)

> arduino-cli.exe core search arduino
> arduino-cli.exe core search uno

> arduino-cli.exe --debug core install arduino:avr
> arduino-cli.exe core list

> arduino-cli.exe board list
(FQBN が arduino:avr:uno になります)

> arduino-cli.exe --debug compile --fqbn arduino:avr:uno Arduino/MyFirstSketch
(sketchbook_path を見てくれないようで，コンパイルに失敗します)

> cd D:\Users\xxx\Documents\MyProjects\ArduinoCli
> arduino-cli.exe --debug compile --fqbn arduino:avr:uno Arduino/MyFirstSketch

> arduino-cli.exe upload -v -p com10 --fqbn arduino:avr:uno Arduino/MyFirstSketch
(ポートは，board list で表示される)
```

まだ，`alpha` release なのでどんどん変更されていくと思いますが，`2018/08/28` の時点では，上記手順で動作しています． 

### 3.3. ESP32(ESP8266) の core 導入　(2018/8/31) 追記

Arduino がコマンドラインで動作するようになってので，ESP32 の core も導入して試してみます．`.cli-config.yml` に追記します．

```yaml:.cli-config.yml
board_manager:
  additional_urls:
  - http://arduino.esp8266.com/stable/package_esp8266com_index.json
  - https://dl.espressif.com/dl/package_esp32_index.json
```

- `arduino-cli.exe core update-index` で esp8266,esp32 の json ファイルを持ってきます．
- `arduino-cli.exe core search esp` で esp8266,esp32 の core が表示されるか確認します．
- `arduino-cli.exe core install esp32:esp32` で core を導入します．

このままでは，コンパイルに失敗するので`{arduino_data}\packages\esp32\hardware\esp32\1.0.0`　にある `platform.txt` を修正します．コンパイル時間短縮のため，core については，キャッシュして再利用するようです．`esp8266` の `platform.txt` には修正が入っているようですが，`esp32` の `platform.txt` では，修正されてないようです．正しいか分からいのですが，`"{build.path}/arduino.ar"` を `"{archive_file_path}"` に変更します．

```diff
--- platform.org.txt	2018-08-31 10:41:45.446260200 +0900
+++ platform.txt	2018-08-31 10:55:04.990430100 +0900
@@ -71,10 +71,10 @@
 recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.S.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" -DARDUINO_VARIANT="{build.variant}" {compiler.S.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
 
 ## Create archives
-recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{build.path}/arduino.ar" "{object_file}"
+recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}"
 
 ## Combine gc-sections, archives, and objects
-recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -Wl,--start-group {object_files} "{build.path}/arduino.ar" {compiler.c.elf.libs} -Wl,--end-group -Wl,-EL -o "{build.path}/{build.project_name}.elf"
+recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -Wl,--start-group {object_files} "{archive_file_path}" {compiler.c.elf.libs} -Wl,--end-group -Wl,-EL -o "{build.path}/{build.project_name}.elf"
 
 ## Create eeprom
 recipe.objcopy.eep.pattern={tools.gen_esp32part.cmd} -q "{runtime.platform.path}/tools/partitions/{build.partitions}.csv" "{build.path}/{build.project_name}.partitions.bin"
```

`compile,upload` と行きたいのですが，`0.2.1-alpha.preview` では，esp32 の `upload` には対応してないようです．
 
```cmd
> arduino-cli.exe --debug compile -v --fqbn esp32:esp32:esp32 Arduino\EPS32Sketch
> arduino-cli.exe upload -v -p com5 --fqbn esp32:esp32:esp32 Arduino\EPS32Sketch
```
`boards.txt` に `upload.speed` を設定しても，TEMP フォルダに出来る `EPS32Sketch.ino.partitions.bin` を `EPS32Sketch.esp32.esp32.esp32.partitions.bin` の名前で スケッチのある ~~ディレクトリ~~ フォルダにコピーする必要があるなど，今回は時間切れです．~~`beta release` が出たあたりで試してみます．~~

### 3.4. ESP32 のスケッチのアップロード　(9/3 追記)

目覚めが悪いので少しだけ検証しました．Arduino IDE の方は，コンパイルされたスケッチを`build.path`（OS の TEMP フォルダ）に保存し，`build.path` のコンパイル済みのスケッチを書き込むので問題がないようですが，arduino-cli は，親切にもコンパイルされたスケッチを`スケッチ`のフォルダにリネームしてコピーしてくれます．リネームは，`fqbn` の `:` を `.` に変更してスケッチに付与したものです．

仕方ないので，ソースファイルに下記内容を追記して，`arduino-cli.exe` を作り直します．`go get -u github.com/arduino/arduino-cli` でインストールしたソースファイルは，`%GOPATH%src\github.com\arduino\arduino-cli` にあるので，`commands\compile\compile.go` を編集します．Go 言語は初心者なので，適当です．

```go:compile.go
　// Copy .partitions.bin file to sketch directory
　srcPbin := paths.New(outputPath[:len(outputPath)-3] + "partitions.bin")
　dstPbin := paths.New(sketch.FullPath).Join(sketch.Name + "." + fqbn + ".partitions.bin")
　if _, err := srcPbin.Stat(); err == nil {
　　logrus.WithField("from", srcPbin).WithField("to", dstPbin).Print("copying sketch build output")
　　if err = srcPbin.CopyTo(dstPbin); err != nil {
　　　formatter.PrintError(err, "Error copying partitions.bin file.")
　　　os.Exit(commands.ErrGeneric)
　　}
　}
} 　←（元からある最終行）
```

(2019/9/5) 編集
`compile.go` の変数の定義の簡略化？

```
var srcPbin = 
var dstPbin =
↓
srcPbin :=
dstPbin :=
```

(2019/9/5) ここまで

コマンドプロンプトを立ち上げて，下記コマンドを実行します．

```cmd
> cd %GOPATH%\src\github.com\arduino\arduino-cli
> go install
```

これで，‘partitions.bin‘ はコピーされるようになりますが，スケッチをアップロードする速度を指定する必要があります．{arduino_data}\packages\esp32\hardware\esp32\1.0.0　に `boards.local.txt` を作成して，下記内容を追加します．

```:boards.local.txt
esp32.upload.speed=921600
```

後は，スケッチの作成，コンパイル，アップロードします．

```cmd
> arduino-cli.exe --debug sketch new EPS32Sketch
> arduino-cli.exe --debug compile -v --fqbn esp32:esp32:esp32 Arduino\EPS32Sketch
> arduino-cli.exe upload -v -p com5 --fqbn esp32:esp32:esp32 Arduino\EPS32Sketch
```

まぁ，取り敢えず動作しただけなので，試す方は自己責任でお願いします．デバイスが壊れても責任持てません:sweat_smile:
 
### 3.5. ライブラリについて　(9/6 追記)

特段に書くこともないのですが，`arduino-cli.exe lib list --all` では，`core` のライブラリしか表示しないですね．

```cmd
> arduino-cli.exe lib search m5stack
> arduino-cli.exe --debug lib install M5Stack
> arduino-cli.exe lib list
```

`{sketchbook_path}\libraries`　に導入されます．

### 3.6. `--build-properties`　について　(9/6 追記)

`compile` の `--build-properties` ですが，ESP32 の問題だと思いますが，`platform.txt` に

```:platform.txt
tools.esptool.upload.pattern="{path}/{cmd}" --chip esp32 --port "{serial.port}" --baud {upload.speed}  --before default_reset --after hard_reset write_flash -z --flash_mode {build.flash_mode} --flash_freq {build.flash_freq} --flash_size detect 0xe000 "{runtime.platform.path}/tools/partitions/boot_app0.bin" 0x1000 "{runtime.platform.path}/tools/sdk/bin/bootloader_{build.boot}_{build.flash_freq}.bin" 0x10000 "{build.path}/{build.project_name}.bin" 0x8000 "{build.path}/{build.project_name}.partitions.bin"

tools.esptool.upload.pattern.linux=python "{path}/{cmd}" --chip esp32 --port "{serial.port}" --baud {upload.speed}  --before default_reset --after hard_reset write_flash -z --flash_mode {build.flash_mode} --flash_freq {build.flash_freq} --flash_size detect 0xe000 "{runtime.platform.path}/tools/partitions/boot_app0.bin" 0x1000 "{runtime.platform.path}/tools/sdk/bin/bootloader_{build.boot}_{build.flash_freq}.bin" 0x10000 "{build.path}/{build.project_name}.bin" 0x8000 "{build.path}/{build.project_name}.partitions.bin"
```

にあるように，{build.boot}，{build.flash_freq} など `upload` にも？必要なパラメータを保持てくれないので，`--build-properties build.boot=qio,build.flash_freq=80m` のように指定できますが，`boards.local.txt` で設定する方が今の所無難です．

当然だと思うのですが，`boards.txt` → `boards.local.txt` → `--build-properties` の順で設定値は上書きされます．設定した値は  `--show-properties` で確認できます．

```cmd
> arduino-cli.exe compile --build-properties build.boot=qio,build.flash_freq=80m --show-properties --fqbn esp32:esp32:esp32 Arduino\EPS32Sketch
```
あくまで，私の備忘録なので，間違っているかもしれません．

### 3.7. M5Stack　(9/6 追記)

放置していた `M5Stack Gray` があったので，サンプルをアップロードしてみました．

~~`board.local.txt`~~ `boards.local.txt` に下記内容を追加します．

```:boards.local.txt
m5stack-core-esp32.build.boot=qio
m5stack-core-esp32.build.flash_freq=80m
m5stack-core-esp32.upload.speed=921600
```
`{sketchbook_path}\libraries\M5Stack\examples`　を `{sketchbook_path}` にコピーします．ここでは，`Basics\Display` をコピーしました．`arduino-cli.exe board list` でシリアルポートを確認して，下記コマンドでコンパイル，アップロードします．

```cmd
> arduino-cli compile -v --fqbn esp32:esp32:m5stack-core-esp32 Arduino\Display
> arduino-cli upload -v -p com3 --fqbn esp32:esp32:m5stack-core-esp32 Arduino\Display
```

GUI を使う必要がないので，個人的には満足です:grin:

(2018/9/11) 追記．
Typo の修正がてらに，`board list` に関して追記しておきます．

`ESP32` の場合，`core` を導入しても，`board list` で `FQBN` は表示されないです．Arduino で表示されるのは，`boards.txt` にある `USB` の `VID/PID` と比較しているからです．`M5Stack` では，`Silicon Labs` の `CP210x` の USB シリアル変換機を使っているので，変換機の先に繋がったデバイスを判断することができないのです．