商業雑誌連動企画！Jetson & Pi 電力測定ボードを発売してオリジナルノードを公開した話

## はじめに
とあるご縁で、商業雑誌 (シェルスクリプトマガジン) の連動企画で BitTradeOne から Jetson Nano と Raspberry Pi (以降、ラズパイ) で共通で使用可能な電力測定ボードを発売する企画の製作に協力することになり、Node-RED から電力測定ボードを操作するノードを作成しました。
製作過程の話とノード作成のノウハウをまとめておこうと思います。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/4eea18a8-37d7-4a64-f56c-7b62d98b22c6.png" width="50%">
https://shell-mag.com/vol-69/

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/111c85c4-6bac-1f4c-3ecd-eb7486574970.png" width="50%">
https://bit-trade-one.co.jp/adjtsb01/

## 製作過程
企画から発売まで約 8 ヶ月間かかりました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/e79963d1-3b27-813a-9142-58da23d7aa54.png" width="75%">

### 4 月
お話をいただいて大まかに企画を練りました。

 - Jetson Nano と ラズパイ の両方で使用可能とする
 - Jetson Nano でアプリケーションを実行した時のシステム全体の消費電流・電力を測れるものがあると面白いのではないか
 - 拡張ボードに電力を受けるMicro USB ポート、DC ジャックを設けて、GPIO ヘッダーへ 5V を入力する構成で、途中にシャント抵抗を入れて電流を計測する
 - Raspberry Pi 4 で USB Type-C 給電に変更されたため、Micro USB 給電を使える救済手段にもなる

### 拡張ヘッダーの互換性
Jetson Nano と ラズパイ とで拡張ヘッダーのピン配列に互換性があり、その特徴を生かして共通で使用可能なようにしました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/682a6955-1339-5605-6737-efb9e80cf094.png" width="75%">

### 5〜6 月
ブレッドボードとパーツを使用してプロトタイピングや動作確認を行い、基板の回路図を起こすまでをゴールとしました。シャント抵抗の接続方法は 2 種類 (ハイサイド接続とローサイド接続) ありますが、今回はローサイド接続としました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/f79ed2c5-8efe-a8d8-f91a-9005da0fe761.png" width="75%">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/d65f4a07-10d5-7ec9-7344-4476ac840157.png" width="75%">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/28f20167-d847-061d-a359-0b7eef0165e5.png" width="75%">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/d00ea324-8519-1d28-80d2-658d8c617631.png" width="75%">

### 7〜8 月
試作基板の製作に取り組みました。Raspberry Pi Zero W と同じサイズになるようにデザインしました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/d7244729-04da-de65-fb20-074631a73344.png" width="75%">

### 9〜10 月
試作基板の動作確認が問題なかったため、量産基板の製作に向けて基板にプリントするロゴを作成したり、10月に発表された Jetson Nano の新製品 (2GB) の動作確認を緊急で行いました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/55eeb616-1ce2-2784-ab9f-9a4999b44ed9.png" width="75%">

### 11 月
9月頃から原稿の執筆を開始し、査読・校正・校正確認・修正を経て無事に脱稿、印刷所への入稿 (11/14) となりました。物理書籍を 11/21 に受領しました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/51f925d6-42db-60b1-9648-014a5898bc6d.jpeg" width="34%"> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/5ad54f1d-ac84-42c9-a55a-08718d6ba90b.jpeg" width="60%">


## Node-RED のオリジナルノードを作成
雑誌は Adafruit 社製のライブラリを使用して Python コードで執筆しました。
他のプログラミング言語でも拡張ボードを簡単に使用できるようにしたかったため、執筆の傍ら、Node-RED のオリジナルノードを作成することにしました。 
ノードは
https://flows.nodered.org/node/node-red-contrib-ina-sensor
で公開しています。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/4844c139-f405-4dae-f8b6-1906a798615b.png" width="75%">

電力測定ボードには テキサス・インスツルメント社製デジタル出力電流・電力・電圧モニター IC (<a href="https://www.tij.co.jp/product/jp/INA260">INA260</a>) と 単色有機 EL ディスプレイ (SSD1306) が搭載されています。
このノードは INA260 を操作するためのノードです。
単色有機 EL ディスプレイ (SSD1306) については
https://flows.nodered.org/node/node-red-contrib-oled
が公開されています。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/fedc6e6e-ac11-64f0-0878-9d0e618bec89.png" width="75%">

### 実装
INA260 と SSD1306 は I2C 接続方式でアクセスする仕様のため、Jetson Nano と ラズパイ でノードを共通化でき、内部で <a href="https://npmjs.org/package/i2c-bus">i2c-bus npm モジュール</a>を使用しています。
また、内部で <a href="https://www.npmjs.com/package/ina226">ina226 npm モジュール</a>を使用しています。INA226 と INA260 の差分は電流を測定するためのシャント抵抗を外部に実装するか、内部に含まれるかの違いです。INA260 は 2 ミリオーム (2 mΩ) のシャント抵抗を内臓しているため、ノードのデフォルト設定 (I2C アドレス: 0x40、シャント抵抗: 0.002) で動作するようにしています。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/a973c091-5bd9-bc8d-4c59-40817a48c037.png" width="50%">
SSD1306 については I2C アドレスを 0x60 から 0x3c へ変更する必要があります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/085c07f2-37f4-b726-43ca-b9caab99262f.png" width="50%">


### ノードの公開
ノードの作成が完了し、GitHub レポジトリの作成、npm パッケージの登録までは順調でしたが、いざ Node-RED Library へ登録しようとした際になかなか公開されずに試行錯誤した結果、登録方法が自動から手動に変わっていたことが判明しました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/c593d2e4-8376-7e98-8c68-59a3fd769f12.png" width="75%">
この件については、<a href="https://qiita.com/kitazaki/items/c222c8f3906b6064d5cf">Node-REDノード公開方法が変わっていた件 (自動→手動登録)</a> で記事を書いています。

### Node-RED のインストール
Jetson Nano とラズパイとで Node-RED のインストール方法が多少異なります。

ラズパイの場合はシンプルに apt コマンドで Node-RED をインストールできます。

```bash
$ sudo apt install -y nodered
```

Jetson Nano の場合は apt コマンドで curl をインストールした後、Node-REDのインストーラーコマンドを実行します。
Ubuntu のソフトウェアセンターからも Node-RED をインストールできますが、オリジナルノードのビルドに必要なツール類がインストールされないため、手動コマンドでインストールします。

```bash
$ sudo apt install -y curl
$ bash <(curl -sL https://raw.githubusercontent.com/node-red/linux-installers/master/deb/update-nodejs-and-nodered)
```

インストーラーコマンドを実行した後、2つの質問に答える必要がありますので、いずれも「y」を選択します。

```bash:実行例
$ bash <(curl -sL https://raw.githubusercontent.com/node-red/linux-installers/master/deb/update-nodejs-and-nodered)

 
This script will remove versions of Node.js prior to version 12.x, and Node-RED and
if necessary replace them with Node.js 12.x LTS (erbium) and the latest Node-RED from Npm.
 
It also moves any Node-RED nodes that are globally installed into your user
~/.node-red/node_modules directory, and adds them to your package.json, so that
you can manage them with the palette manager.
 
It also tries to run 'npm rebuild' to refresh any extra nodes you have installed
that may have a native binary component. While this normally works ok, you need
to check that it succeeds for your combination of installed nodes.
 
To do all this it runs commands as root - please satisfy yourself that this will
not damage your Pi, or otherwise compromise your configuration.
If in doubt please backup your SD card first.
 
Are you really sure you want to do this ? [y/N] ? y

Would you like to install the Pi-specific nodes ? [y/N] ? y
```

インストーラーコマンド実行中は進捗が表示され、全て完了すると「All done.」と表示され、コマンドプロンプトに戻ります。

```bash:実行中
Running Node-RED install for user jetson at /home/jetson on ubuntu


This can take 20-30 minutes on the slower Pi versions - please wait.

  Stop Node-RED                       ✔
  Remove old version of Node-RED      ✔
  Remove old version of Node.js       ✔
  Install Node.js LTS                 ✔   Node v12.20.0   Npm 6.14.8
  Clean npm cache                     ✔
  Install Node-RED core               ✔   1.2.6 
  Move global nodes to local          
┌──────────────────────────────────────────────────────────┐
│                 npm update check failed                  │
│           Try running with sudo or get access            │
│           to the local update config store via           │
│ sudo chown -R $USER:$(id -gn $USER) /home/jetson/.config │
└──────────────────────────────────────────────────────────┘
  Move global nodes to local          -/nodered-install.log
  Install extra Pi nodes              ✔
  Npm rebuild existing nodes          ✔
  Add shortcut commands               ✔
  Update systemd script               ✔



All done.
  You can now start Node-RED with the command  node-red-start
  or using the icon under   Menu / Programming / Node-RED
  Then point your browser to localhost:1880 or http://{your_pi_ip-address}:1880

Started  2020年 12月  9日 水曜日 23:39:35 JST  -  Finished  2020年 12月  9日 水曜日 23:50:09 JST
```

### Node-RED の起動と停止
Node-RED の起動はコマンドラインから node-red と打つだけです。停止する場合は Ctrl + C を入力します。

```bash
$ node-red
```

サービスとして起動・停止する場合は以下のとおりです。

```bash
# 起動する場合
$ node-red-start
# 停止する場合
$ node-red-stop
```

### ノードの追加
ノードの追加方法はメニューを表示して「パレットの管理」→「ノードを追加」→「ノードを追加」→「node-red-contrib-ina-sensorを入力」→「追加ボタンを押下」で追加することができます。
node-red-contrib-oled についても同様の手順で追加することができます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/f05407da-5b89-3bb9-a9c6-bc86b977e780.png" width="100%">

## まとめ
これまで簡単な関数や機能をオリジナルノードで作成することはありましたが、ハードウェアを操作するノードの作成は今回初めて行いました。
今回の経験が同じ状況になった方に少しでもお役に立てれば幸いです。
では、良き Node-RED ライフを！