Node-RED MCU EditionでSensorノードを試してみた。

# はじめに

Node-RED MCU Edition独自のSensorノードを試してみました。

https://github.com/phoddie/node-red-mcu/blob/main/nodes/sensor/readme.md

Sensorノードは以下のECMA-419 Sensor Class Patternに準拠したセンサークラスをサポートしています。

- Accelerometer
- Ambient light
- Atmospheric pressure
- Humidity
- Proximity
- Temperature
- Touch

### ECMA-419とは

ECMAとは、情報通信技術の標準を策定している欧州電子計算機工業会です。
ECMAScriptとは、ECMAによって標準化されたJavaScriptなどの元の規格となった言語です。
ECMAScriptに関する規格は以下のとおりです。

- ECMA-262 ・・language specification
- ECMA-402 ・・internationalization API specification
- ECMA-414 ・・specification suite
- ECMA-419 ・・embedded systems API specification

# 前提条件

ビルド・インストール環境

- Intel MacBook Pro (2017)
- macOS Big Sur (バージョン 11.7)

マイコンデバイス

- M5Stick-C (MPU6886) (傾き・加速度 6軸センサー)
- M5Stack Basic
- M5Stack Gray (MPU9250) (傾き・加速度・磁気 9軸センサー)
- M5Stack Core2 (MPU6886) (傾き・加速度 6軸センサー)

センサーデバイス

- M5 ENV Ⅲ Unit (SHT30/QMP6988) (温度・湿度/気圧センサー)
- M5 ENV Ⅱ Unit (SHT30/BMP280) (温度・湿度/気圧センサー)
- M5 ENV Unit (DHT12/BMP280) (温度・湿度/気圧センサー)
- M5 ENV Hat Ⅲ (SHT30/QMP6988) (温度・湿度/気圧センサー)
- M5 ENV Hat Ⅱ (SHT30/BMP280/BMM150) (温度・湿度/気圧/磁気センサー)
- M5 ENV Hat (DHT12/BMP280/BMM150) (温度・湿度/気圧/磁気センサー)
- MLX90614 (非接触温度センサー)
- LM75B (温度センサー)

クラウド上のNode-RED環境

- HTTPサーバ、ダッシュボード (Node-RED, Dashboard)
- MQTTサーバ (Aedes MQTT broker)

環境構築と動作確認については以下を参照してください。

https://qiita.com/kitazaki/items/15cba2f4622bf3682083

GPIOの動作確認については以下を参照してください。

https://qiita.com/kitazaki/items/bac2b860b7d26fb450f4

ネットワーク接続(HTTP, MQTT)については以下を参照してください。

https://qiita.com/kitazaki/items/9b93992f6c342828e8f8

組み合わせと連動(IoT)については以下を参照してください。

https://qiita.com/kitazaki/items/83a2d0af01224e7d2ff0

## 動作確認状況

|センサーデバイス |M5StickC / Plus |M5Stack Basic |M5Stack Gray |M5Stack Core2 |メモ |
|---|---|---|---|---|---|
|MPU6886 |◯ |- |- |◯ |OK (I/OでSMBus、Busでinternalを指定) |
|MPU9250 |- |- |◯ |- |OK (I/OでSMBus、Busでdefaultを指定) |
|SHT30 |◯ |◯ |◯ |◯ |OK (I/OでI2C、Busでdefaultまたはhatを指定) |
|BMP280 |◯ |◯ |◯ |◯|OK (I/OでI2C、Busでdefaultまたはhat、configurationで{"mode": 3,"temperatureSampling": 2,"pressureSampling": 5,"filter": 4,"standbyDuration": 4}を指定) |
|LM75B |◯ |◯ |◯ |◯ |OK (I/OでSMBus、Busでdefaultを指定) |
|MLX90614 |◯ |◯ |◯ |◯ |OK (I/OでSMBus、Busでdefaultを指定) |

~~※ M5 ENV HatはI2CにGPIOポート(SDA:G0、SCL:G26)を使用しているためBusの指定ができずNG~~
※ M5Stack BasicのBusのdefaultはGroveポートでGPIO(SDA:G21、SCL:G22)を使用
※ M5Stack GrayのBusのdefault(Groveポート)とinternalは共通でGPIO(SDA:G21、SCL:G22)を使用
※ M5Stick-C、M5Stack Core2のBusのdefaultはGroveポートでGPIO(SDA:G32、SCL:G33)を使用
※ M5Stick-C、M5Stack Core2のBusのinternalはGPIOポート(SDA:G21、SCL:G22)を使用

# 手順

### 1-1. Node-REDをインストールする

```bash
$ mkdir node-red-mcu && cd node-red-mcu
$ npm init -y
$ npm install node-red
```

### 1-2. node-red-mcu-pluginをインストールする

```bash
$ npm install https://github.com/ralphwetzel/node-red-mcu-plugin
```

### 1-3. Sensorノードをインストールする

node-red-mcu-pluginをインストールすると、node-red-mcuもダウンロードされるため、それを使用してSensorノードをインストールする。

```bash
$ npm install node_modules/\@ralphwetzel/node-red-mcu-plugin/node-red-mcu/nodes/sensor
```

### 1-4. node-red-mcu/manifest_runtime.jsonにセンサードライバーを追加する

GitHubのREADMEにはnode-red-mcu/manifest.jsonにセンサードライバーを追加すると記載されているが、node-red-mcu/manifest.jsonはnode-red-mcu/manifest_runtime.jsonを読み込んでいるため、node-red-mcu/manifest_runtime.jsonにセンサードライバーを追加する。

```bash
$ vi node_modules/\@ralphwetzel/node-red-mcu-plugin/node-red-mcu/manifest_runtime.json
```

(追加する内容)

- "$(MODDABLE)/modules/drivers/sensors/sht3x/manifest.json"
- "$(MODDABLE)/modules/drivers/sensors/lm75/manifest.json"
- "$(MODDABLE)/modules/drivers/sensors/mpu6886/manifest.json"
- "$(MODDABLE)/modules/drivers/sensors/mpu9250/manifest.json"
- "$(MODDABLE)/modules/drivers/sensors/bmp280/manifest.json"
- "$(MODDABLE)/modules/drivers/sensors/mlx90614/manifest.json"

```json:manifest_runtime.json
{
        "include": [
                "$(MODDABLE)/examples/manifest_base.json",
                "$(MODDABLE)/modules/base/deepEqual/manifest.json",
                "$(MODDABLE)/modules/base/structuredClone/manifest.json",
                "$(MODDABLE)/modules/base/modules/manifest.json",
                "$(MODDABLE)/modules/data/base64/manifest.json",
                "$(MODDABLE)/modules/data/hex/manifest.json",
                "$(MODDABLE)/examples/io/tcp/mqttclient/manifest_mqttclient.json",
                "$(MODDABLE)/modules/io/manifest.json",
                "./nodes/rpi-ds18b20/manifest.json",
                "./nodes/httpserver/manifest.json",
                "./nodes/httprequest/manifest.json",
                "./nodes/websocketnodes/manifest.json",
                "./nodes/lower-case/manifest.json",
                "./nodes/csv/manifest.json",
                "./nodes/delay/manifest.json",
                "./nodes/join/manifest.json",
                "./nodes/batch/manifest.json",
                "./nodes/sort/manifest.json",
                "./nodes/trigger/manifest.json",
                "./nodes/sensor/manifest.json",
                "./nodes/file/manifest.json",
                "./nodes/template/manifest.json",
                "./nodes/udp/manifest.json",
                "$(MODDABLE)/modules/drivers/sensors/tmp102/manifest.json",
                "$(MODDABLE)/modules/drivers/sensors/sht3x/manifest.json",
                "$(MODDABLE)/modules/drivers/sensors/lm75/manifest.json",
                "$(MODDABLE)/modules/drivers/sensors/bmp280/manifest.json",
                "$(MODDABLE)/modules/drivers/sensors/mpu6886/manifest.json",
                "$(MODDABLE)/modules/drivers/sensors/mpu9250/manifest.json",
                "$(MODDABLE)/modules/drivers/sensors/mlx90614/manifest.json",
                "./nodes/openweathermap/manifest.json"
        ],
        "modules": {
                "*": [
                        "./nodered"
                ]
        },
        "preload": [
                "nodered"
        ],
        "defines": {
                "xs": {
                        "xsbug_hooks": 1
                }
        },
        "platforms": {
                "win": {
                        "error": "Node-RED MCU does not currently run on Windows "
                },
                "lin": {
                        "error": "Node-RED MCU does not currently run on Linux "
                }
        }       
}
```

### 1-5. Node-REDを起動する

Node-RED起動時のエラー(node-red-mcu-pluginがパッチを適用するutils.jsが存在しない)を回避するため、node_modules/node-redディレクトリで必要なモジュールをインストールします。

```bash
$ cd node_modules/node-red
$ npm install
$ cd ../..
```
Node-REDを起動します。

```bash
$ node node_modules/node-red/red.js -u ./
```

# Node-REDフローを作成する

フローエディタの左側のパレットに「MCU」カテゴリと「Sensor」ノードが表示されます。

![スクリーンショット 2022-10-17 0.09.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/b413c6fd-5969-337a-4c3e-f0397f341863.png)

「inject」ノードと「Sensor」ノードと「debug」ノードを使用し、以下のように接続します。
(正常に動作したSHT30を例に説明します)

![b-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/1af76261-18d3-dd68-033d-36f5c1ecdab5.jpeg)

(サンプルフロー)

```json:flows.json
[{"id":"90b0adb349eca3b8","type":"tab","label":"フロー 7","disabled":false,"info":"","env":[],"_mcu":{"mcu":false}},{"id":"0aa93b017b18277a","type":"sensor","z":"90b0adb349eca3b8","name":"SHT3x","io":"I2C","bus":"default","module":"embedded:sensor/Humidity-Temperature/SHT3x","configuration":"{}","_mcu":{"mcu":false},"x":370,"y":160,"wires":[["9499bd663d296a7c"]]},{"id":"69c45bd08ca2cd3a","type":"inject","z":"90b0adb349eca3b8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"5","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","_mcu":{"mcu":false},"x":170,"y":80,"wires":[["0aa93b017b18277a"]]},{"id":"9499bd663d296a7c","type":"debug","z":"90b0adb349eca3b8","name":"debug 8","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","_mcu":{"mcu":false},"x":540,"y":160,"wires":[]}]
```

M5Stick-CとM5 ENV Ⅲ UnitをGroveケーブルで接続します。

![IMG_2234.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/63beccf1-7069-fd61-30bd-19f054a8a98a.jpeg)

### 「Sensor」ノード

- Module → センサー毎に指定します (M5 ENV Ⅲ UnitはSHT30を使用しているためSHT3xを指定)
  - embedded:sensor/Accelerometer-Gyroscope/MPU6886
  - embedded:sensor/Accelerometer-Gyroscope/MPU9250
  - embedded:sensor/Humidity-Temperature/SHT3x
  - embedded:sensor/Barometer-Temperature/BMP280
  - embedded:sensor/Temperature/LM75
  - embedded:sensor/Temperature/MLX90614
- I/O → プルダウンメニューからI2C、または、SMBusを選択します (M5 ENV Ⅲ UnitはI2Cを選択します)
- Bus → default、または、internalを指定します (M5 ENV Ⅲ Unitはdefaultを指定します)
- Configure → センサーのパラメータを指定します (M5 ENV Ⅲ Unitは指定しません)

![b-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/098e0c05-718f-78dd-f701-769dd99d86c1.jpeg)

# M5Stick-Cへインストールする

以下のページの手順とおりです。

- M5Stick-Cへインストールする
  - node-red-mcu-pluginを使用する場合
  - Node-RED MCU Editionを使用する場合

https://qiita.com/kitazaki/items/9b93992f6c342828e8f8

# クラウド上のNode-REDと連携する

![スクリーンショット 2022-10-17 2.15.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/15e8f676-f0fd-af28-9717-b2c5f050693f.png)

センサーノードの出力を「mqtt out」ノードと接続します。

![b-80-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/fee79a1c-6727-7ca3-c784-d1e586db784c.jpeg)

クラウド上のNode-REDの「debug」ノードにセンサーデータが出力されることを確認します。

![b-80-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/09af85b8-0998-0980-49bf-d400ca8477b5.jpeg)

センサーデータの出力をダッシュボードの「chart」ノードで表示します。

![b-80-2-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/8640aade-4d42-9101-09ba-6451f0a40a13.jpeg)

![b-80-3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/92e44721-37de-ddbb-72c1-5549d4b8c73c.jpeg)

### 参考

(2022年10月21日 追記)

M5 ENV Hatの使用方法がわかりました。
$MODDABLE/build/devices/esp32/targets/m5stick_c/host/provider.jsにHatで使用するI2C (GPIO G0, G26)の定義を追加する必要があります。

```javascript:provider.js (抜粋)
const device = {
        I2C: {
                default: {
                        io: I2C,
                        data: 32,
                        clock: 33
                },
                internal: {
                        io: I2C,
                        data: 21,
                        clock: 22
                },
                hat: {
                        io: I2C,
                        data: 0,
                        clock: 26
                }
        },
```

SensorノードのBusで「hat」を指定すれば使用可能です。

![hat_image_02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/31f0ba60-9d42-78f7-896a-0ca1e6949d97.jpeg)

~~Moddable本家へプルリクエストを送ったので、マージされればprovider.jsの修正は不要になります。~~
Moddable本家へプルリクエストを送り、2022年10月22日にマージされましたので、provider.jsの修正は不要です。

https://github.com/Moddable-OpenSource/moddable/pull/946

![hat_image_03.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/221a3c25-2f93-511e-020b-74cc4ab2d306.jpeg)

![hat_image_04.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/0e4f378b-51ae-90ba-8d49-ac5b65509538.jpeg)

![hat_image_05_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/c89ebafa-5b20-44cf-03af-7208371fe99c.jpeg)

### 参考

(2022年10月20日 追記)

~~以下のセンサーについては毎回同じデータが表示され、正常に動作しませんでした。~~

- ~~BMP280 (Busはdefault、I/OはI2Cを指定)~~

![mcu_image_ng_00.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/c30f217b-5240-600c-ed32-73a263ceb332.jpeg)

![mcu_image_ng_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/36f29f5b-6fd0-fe5b-685b-1a51dfc8db73.jpeg)

Moddable SDKのサンプルコード($MODDABLE/examples/drivers/sensors/bmp280/main.js)を参照し、configurationを指定する必要があることがわかりました。

```javascript:main.js
sensor.configure({
        mode: 3,                                        // NORMAL
        temperatureSampling: 2,         // X2
        pressureSampling: 5,            // X16
        filter: 4,                                      // X16
        standbyDuration: 4                      // MS_500
});
```

![mcu_image_00.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/4b448043-4b49-7c36-2d24-9bc77524375b.jpeg)

![mcu_image_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/20dadfa8-32d3-2b14-2731-a1dac856e447.jpeg)

(2022年10月19日 追記)

~~以下のセンサーについては「no function!」と表示され、正常に動作しませんでした。~~

- ~~MPU6886 (Busはinternal、I/OはI2Cを指定)~~
- ~~MPU9250 (Busはdefault、I/OはI2Cを指定)~~
- ~~LM75B (Busはdefault、I/OはI2Cを指定)~~

![b-90.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/d2dcc88d-0c03-f99d-5a30-e72a13d81548.jpeg)

ししかわ ( https://twitter.com/meganetaaan )さんからアドバイスをいただき、I/OでSMBusを指定したらデータを取得できるようになりました。

![c-0.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/b5b12efd-43c3-95d0-6686-98d23c0174eb.jpeg)

![c-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/3e3bd315-2a32-b381-2b33-fe273e6773d2.jpeg)

![c-2_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/64b8bd48-9b4d-da2c-f1ec-7aacb5666cac.jpeg)

![d-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/43697958-2547-2e35-c648-54ee2d2c099c.jpeg)

![e-1_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/8a074218-61c1-ca56-843e-353ab1e16bda.jpeg)

### 参考 (サンプルコードの動作確認)

(MPU6886)

```bash
$ cd $MODDABLE/examples/drivers/m5stickc-imu
$ UPLOAD_PORT=/dev/cu.usbserial-C152AAC745 mcconfig -d -m -p esp32/m5stick_c
```

![b-99-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/3943c7e3-467d-9659-3850-a9f9260e6c94.jpeg)

(MPU9250)

```bash
$ cd $MODDABLE/examples/drivers/sensors/mpu9250/bounce
```

manifest.jsonの"platforms"に
"esp32/*": {},
を追加する。

```bash
$ vi manifest.json
```

```json:manifest.json
{
        "include": [
                "$(MODDABLE)/examples/manifest_base.json",
                "$(MODDABLE)/examples/manifest_commodetto.json",
                "$(MODDABLE)/modules/drivers/ili9341/manifest.json",
                "$(MODDABLE)/modules/drivers/sensors/mpu9250/manifest.json",
                "$(MODDABLE)/modules/io/manifest.json"
        ],
        "modules": {
                "*": [
                        "./main"
                ]
        },
        "config": {
                "orientation": "180"
        },
        "preload": [
                "pins/*"
        ],
        "resources": {
                "*": "./ball",
                "*-mask": "$(MODDABLE)/examples/assets/fonts/OpenSans-Semibold-18"
        },
        "platforms": {
                "esp/moddable_one": {
                },
                "esp32/moddable_two": {
                },
                "esp32/*": {
                },
                "...": {
                        "error": "Untested on this platform"
                }
        }
}
```

```bash
$ UPLOAD_PORT=/dev/cu.usbserial-015F99BB mcconfig -d -m -p esp32/m5stack
```

![b-99-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/afe363c8-03dd-cf67-74a6-496cb7380f50.jpeg)

(LM75B)

```bash
$ cd $MODDABLE/examples/drivers/sensors/lm75
$ UPLOAD_PORT=/dev/cu.usbserial-C152AAC745 mcconfig -d -m -p esp32/m5stick_c
```

![b-100.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/3a6f1776-c396-506f-fe3a-2d1173c1c43c.jpeg)

(SHT30)

```bash
$ cd $MODDABLE/examples/drivers/sensors/sht3x
$ UPLOAD_PORT=/dev/cu.usbserial-C152AAC745 mcconfig -d -m -p esp32/m5stick_c
```

(BMP280)

```bash
$ cd $MODDABLE/examples/drivers/sensors/bmp280
$ UPLOAD_PORT=/dev/cu.usbserial-C152AAC745 mcconfig -d -m -p esp32/m5stick_c
```

![mod_image_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/819bf5d0-e17f-862b-1206-4419e1b032c4.jpeg)

(MLX90614)

```bash
$ cd $MODDABLE/examples/drivers/sensors/mlx90614
$ UPLOAD_PORT=/dev/cu.usbserial-C152AAC745 mcconfig -d -m -p esp32/m5stick_c
```

![mlx.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/9479baee-a4e3-cbb3-e73b-7af6ec1e4b99.jpeg)