Puck.js を Arduino IDE で開発できるようにしてみる

最初に述べておきますが、この記事は**上級者向け**です。
ボード自体を壊したり、元に戻せなくなったり、細かい作業が必要なので、電子工作・マイコン初心者の方にはおすすめしません。
Puck.js 以外の MDBT42Q 搭載モジュールを Arduino 化したいときにも使えるかもしれません。

# Puck.js とは

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29906/f6199a11-af3e-3732-a51a-76d56576d691.png" width="480">

[Puck.js](https://www.puck-js.com/) は、Bluetooth LE 対応のマイコンボードです。
[Espruino](https://www.espruino.com/) という JavaScript で開発可能な Web IDE 上で開発できます。
IoT ボタン的なガジェットとして使えて、500円玉より一回り大きいサイズ、CR2032 のボタン電池で動作します。
日本では買えないので、どこか海外のサイトから買う必要があります。例えば [Espruino Shop](https://shop.espruino.com/puckjs) とか。

小さく Bluetooth LE でつながる何かを作るには、なかなか便利なモジュールです。
だけど、なんだかんだでいろいろ開発していくと、純正の JavaScript 開発環境では足りてない部分が出てきたり、いろいろ Hack したくなってきちゃうんですよね。
~~特に、僕は [LINE Things](https://developers.line.biz/ja/docs/line-things/) に対応したガジェットを作りたかったのですが、Espruino では Pairing/Bonding に対応していません。~~
**[追記]** 現在は対応しています。[Bluetooth LE Security and Access Control - Espruino](https://www.espruino.com/BLE+Security)
[Espruino で書かれた LINE Things Starter](https://github.com/line/line-things-starter/tree/master/puckjs) もあります。

Puck.js は、写真からもわかるように [Raytac MDBT42Q](https://www.raytac.com/product/ins.php?index_id=31) という技適付き Bluetooth LE 対応モジュールを載せていて、この中に Cortex-M4 の CPU とアンテナが乗ってます。

- [Puck.js の Pinout](https://www.espruino.com/Puck.js#pinout)
- [Puck.js の回路図](https://github.com/espruino/EspruinoBoard/blob/master/Puck.js/pdf/puckjs_sch.pdf)

# Arduino で開発したい

やっぱり、マイコンでなにか開発するなら、Arduino IDE を使って開発したくなります。
MDBT42Q を採用している Arduino IDE が使えるマイコンボードというと、[Adafruit Feather nRF52 Bluefruit LE - nRF52832](https://www.adafruit.com/product/3406) があります。
このボード向けの Arduino コア [Adafruit_nRF52_Arduino](https://github.com/adafruit/Adafruit_nRF52_Arduino/) は大変よくできていて、[LINE Things development board](https://github.com/line/line-things-dev-board) とかでも使わせていただいています。(こちらはピン互換)

ただし、Puck.js と Adafruit のボードは、同じモジュールを載せていても、ピン配置が全く違ってそのままは使えないし、ブートローダーを書き込んで上げる必要があります。
なんとかして、この Adafruit のボードライブラリが使えないか試してみました。

## JTAG (SWD) ポートの位置

まず、何かしらファームウェアを書き換えることになるので、JTAG ポートを見つけていきましょう。
といっても、ボードを見れば明らかで、`SWIO` と `SWCK` のマーキングがある丸いパッドが MDBT42Q の右横にあります。
スルーホールではないので、なんとかこのポートにピンを当てられるようにしなければいけません。
はんだ付けしてしまうのも手ですが、ちょっと力を加えると比較的簡単にパッドが剥がれますので要注意。

JTAG ポートが必要なのは最初にブートローダーを書き込む時だけで、Adafruit の nRF52 のライブラリはシリアルポート経由の書き込みに対応しているので、それ以降は必要ありません。

## Adafruit_nRF52_Bootloader の書き込み

**ここから先の手順では、Puck.js の初期ファームウェアを破壊します**
必要に応じて、JTAG 経由でバックアップを取るなり、もう初期状態には戻さないと高を括るかしてください。

JTAG ポートを見つけたら、次に Adafruit の Adruino ライブラリに対応したブートローダ [Adafruit_nRF52_Bootloader](https://github.com/adafruit/Adafruit_nRF52_Bootloader) を書き込む方法を考えます。
このブートローダーを書き込めると、以降 JTAG を使わずに Arduino IDE から直接シリアルポート経由で、自分で書いたプログラムを書き換えることができます。
しかし、最初はこのブートローダーを JTAG で書き込む必要があります。

### Puck.js 向けにボードの定義を追加

[Adafruit_nRF52_Bootloader](https://github.com/adafruit/Adafruit_nRF52_Bootloader) は基本的に Adafruit のボード向けに作られたものなので、ピン配置が Puck.js とは互換性がありません。
特に、Adafruit の nRF52832 のボード向けのものをそのまま書き込んでも、シリアルポートや LED の位置が全く使い物になりません。
そこで、ちゃんと Puck.js 向けにポート配置を整えたものを、[`src/boards`](https://github.com/adafruit/Adafruit_nRF52_Bootloader/tree/master/src/boards) の下に定義します。

以下の、僕の GitHub リポジトリで Puck.js 向けの定義を追加したものを公開しているので、これをそのまま使えば問題ないと思います。
[https://github.com/techno/Adafruit_nRF52_Bootloader/tree/puckjs](https://github.com/techno/Adafruit_nRF52_Bootloader/tree/puckjs)

### J-Link で書き込み

その後、J-Link と Puck.js (`Vcc`, `GND`, `SWDIO`, `SWDCLK`) を接続して以下のコマンドを叩きます。
`nrfjprog` を使うので、J-Link である必要があります。ST-Link などには対応していません。
ARM 向けの gcc がインストールされている必要があります。

```
$ make BOARD=puckjs sd flash

Flashing: lib/softdevice/s132_nrf52_6.1.1/s132_nrf52_6.1.1_softdevice.hex
nrfjprog --program lib/softdevice/s132_nrf52_6.1.1/s132_nrf52_6.1.1_softdevice.hex -f nrf52 --chiperase  --reset
Parsing hex file.
Erasing user available code and UICR flash areas.
Applying system reset.
Checking that the area to write is not protected.
Programming device.
Applying system reset.
Run.
Flashing: _build-puckjs/puckjs_bootloader-0.2.10-3-g9d7de45-dirty-nosd.hex
nrfjprog --program _build-puckjs/puckjs_bootloader-0.2.10-3-g9d7de45-dirty-nosd.hex --sectoranduicrerase -f nrf52 --reset
Parsing hex file.
Erasing page at address 0x74000.
Erasing page at address 0x75000.
Erasing page at address 0x76000.
Erasing page at address 0x77000.
Erasing page at address 0x78000.
Erasing page at address 0x79000.
Erasing UICR flash area.
Applying system reset.
Checking that the area to write is not protected.
Programming device.
Applying system reset.
Run.
```

上記のような感じで、SoftDevice とブートローダーの書き込みが完了します。
正しく書き込めていれば、赤の LED がじわっと点滅するはずです。

プログラムの書き込みに使う UART のポートの定義は、以下のように定義してあります。
(Puck.js の JavaScript の UART のポートと同じです)

```
#define RX_PIN_NUMBER 29
#define TX_PIN_NUMBER 28
```

DFU ピンは Puck.js のボタン、FRST ピンは D11 に割り当てていますが、普通は使うことはないでしょう。
(使ってないからわからないけど、Puck.js のボタンは押すと Vcc 直結で pull-down で使わなきゃいけないが、ブートローダのコードは pull-up 前提にしか書かれていなくて、多分押しても動かない)

## Adafruit_nRF52_Arduino を使って開発する

ブートローダーが書き込めたら、[Adafruit_nRF52_Arduino](https://github.com/adafruit/Adafruit_nRF52_Arduino/) を使って Arduino IDE から開発・書き込みの準備はできました。
単純な GPIO の操作や、SoftDevice を使わない (Bluetooth LE を使わない) スケッチであれば、このまま動作します。
ただ、Serial や、その他ポートの配置が違うので、そういう系のものは、このままでは動かないです。
また、Puck.js は外部 LF クロックを載せていないので、設定が違って、SoftDevice を使うこともできません。

### Puck.js 向けにボードライブラリを改造

実際に Arduino で開発する上では、Bluetooth LE を飛ばすことができて、ポートマッピングがちゃんとしていないと使いものにならないので、この部分をきちんと合わせてあげましょう。
ボード別のポートのマッピングやその他設定は、[`variants`](https://github.com/adafruit/Adafruit_nRF52_Arduino/tree/master/variants) の下に定義されています。
さらに、実際のボードの定義を Arduino IDE に反映させるためには、[`boards.txt`](https://github.com/adafruit/Adafruit_nRF52_Arduino/blob/master/boards.txt) の編集も必要です。

以下に、Puck.js の定義を追加済みの Adafruit_nRF52_Arduino を公開したので、こちらを利用してください。
ダウンロードして、`~/Documents/Arduino/hardware/Adafruit/Adafruit_nRF52_Arduino` あたりに配置すると良いと思います。
[https://github.com/techno/Adafruit_nRF52_Arduino/tree/puckjs](https://github.com/techno/Adafruit_nRF52_Arduino/tree/puckjs)

<img width="480" alt="スクリーンショット 2019-04-12 21.13.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29906/f4fb40f7-6c0f-b18b-7239-b7bc2800e133.png">

訳がわからなくなるので、既に Adafruit_nRF52_Arduino をインストールしている人は削除したほうがいいかもしれません。
うまく Arduino IDE が Puck.js を認識したら、このようにボードの定義の中に Puck.js が見えるようになります。

### UART で書き込み

あとは、Adafruit のボードと同じようにスケッチを書いて、書き込みます。
UART は、ボード側 `Rx` が `D29` で `Tx` が `D28` です。
`DTR` によるリセット信号が必要で、`RST` パッドが JTAG パッドの下にあるので、書き込み時に、なんとかここにくっつけてください。
その際に、0.1uF 程度のコンデンサを `DTR` と `RST` の間に挟む必要があります。

UART はスルーホールのポートですが、ピンヘッダなどをつけてしまうと、Puck.js の元々のケースに入らなくなってしまうので、[スルーホール用のテストワイヤ](http://akizukidenshi.com/catalog/g/gC-09830/) などを利用するのが良いと思います。

### 動作確認

ちゃんと Bluetooth LE の電波も飛んで、うまく動きます。
LINE Things Starter を使ったサンプルを動かしています。
https://github.com/techno/line-things-snippets/tree/master/nrf52/arduino/puckjs-starter

でも、ちょっとこれで開発は辛いなぁ...

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">需要があるかわからないんだけど、Puck.js で LINE Things Starter をすごい頑張って動かすための記事を書いてる。万人向けでは無い。 <a href="https://t.co/scXbeIwW6h">pic.twitter.com/scXbeIwW6h</a></p>&mdash; Hirotaka Kawata (@hktechno) <a href="https://twitter.com/hktechno/status/1116679647335313410?ref_src=twsrc%5Etfw">2019年4月12日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>