年末年始だし M5StickC を 触って、NTP 時計付 人感センサー赤外線スイッチを作る (M5StickC事始め)

# Overview

[Switch Science](https://www.switch-science.com/) で、 [M5StickC](https://www.switch-science.com/catalog/5517/) が売っていたので、年末に遊んでみようと購入していたのだが、通電確認しかしていなかったので、情報をまとめながら、試してみる。

ありがちではありますが、M5StickCには赤外線リモコンLEDが内蔵されていますので、人感センサー赤外線スイッチを作るまで。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100425/b9ab3629-1d1e-275b-7c42-01499a10c5a9.jpeg" width=80%>



# M5StickCとは

* M5Stackをstick上のミニサイズにしたものです。 See [公式サイト](https://docs.m5stack.com/#/en/core/m5stickc)
* すごいところは、
    * Size：48.2mm x 25.5mm x 13.7mm
    * 重量：15.1g
    * 80mAhのバッテリー内蔵 (LiPo)
    * ESP32-Pico (4MB Flash+520KB SRAM)
    * 2.4GHz WiFi/BT
    * 赤外線LED
    * Red LED*1, Button*2,マイク!, 磁気センサー, 6軸センサーまで内蔵していることです

# まずはM5StickCハードウェアを知る

![公式サイトの回路図](https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/schematic/Core/M5StickC/m5stickC.jpg)

* [M5StickC公式回路図のpdf](https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/schematic/Core/M5StickC/20191118__StickC_A04_3110_Schematic_Rebuild_PinMap.pdf)

* [ESP32-Pico-D4](https://www.espressif.com/sites/default/files/documentation/esp32-pico-d4_datasheet_en.pdf) ( [ここにも](https://github.com/m5stack/M5-Schematic/blob/master/Core/esp32-pico-d4_datasheet_en.pdf) )

## ESP32 - M5StickC Pin Map

https://docs.m5stack.com/#/en/core/m5stickc を見ながら、PICO-D4におけるpin mappingをまとめる.

| ESP32 pin | Desc | Assign on M5StickC | GPIO as M5StickC | Type | MUX |
| ---: | :--- | :--- | :--- | :---: | :--- |
| 1 | VDDA | | |
| 2 | LNA_IN | | |
| 3 | VDDA3P3 | | |
| 4 | VDDA3P3 | | |
| 5 | SENSOR_VP | Ext. G36 | GPIO36 | I | GPIO36, ADC1_CH0, RTC_GPIO0 |
| 6 | SENSOR_CAPP | Button A(m5) | GPIO37 | I | *GPIO37(Input)*, ADC1_CH1, RTC_GPIO1 |
| 7 | SENSOR_CAPN | |
| 8 | SENSOR_VN | Button B(side) | GPIO39 | I | *GPIO39(Input)*, ADC1_CH3, RTC_GPIO3 |
| 9 | EN |
| 10 | IO34 | MIC (SPM1423)(SDA) | GPIO34 | I | ADC1_CH6, RTC_GPIO4 | 
| 11 | IO35 | | 
| 12 | IO32 | GROVE(SDA) | GPIO32 | I/O | 32K_XP (32.768 kHz crystal oscillator input), ADC1_CH4, TOUCH9, RTC_GPIO9 |
| 13 | IO33 | GROVE(SCL) | GPIO33 | I/O | 32K_XN (32.768 kHz crystal oscillator output), ADC1_CH5, TOUCH8, RTC_GPIO8 | 
| 14 | IO25 | |
| 15 | IO26 | Ext. G26| GPIO26 | I/O | GPIO26, DAC_2, ADC2_CH9, RTC_GPIO7, EMAC_RXD1 | 
| 16 | IO27 | |
| 17 | IO14 | |
| 18 | IO12 | |
| 19 | VDD3P3_RTC | |
| 20 | IO13 | ST7735S(TFT_MOSI) | GPIO15 | I/O | ADC2_CH3, TOUCH3, RTC_GPIO13, MTDO, HSPICS0, HS2_CMD, SD_CMD, EMAC_RXD3 |
| 21 | IO15 | ST7735S(TFT_CLK) | GPIO13 | I/O | ADC2_CH4, TOUCH4, RTC_GPIO14, MTCK, HSPID, HS2_DATA3, SD_DATA3, EMAC_RX_ER |
| 22 | IO2 | |
| 23 | IO0 | Ext. G0 / MIC (SPM1423)(SCL) | GPIO0 | I/O | ADC2_CH1, TOUCH1, RTC_GPIO11, CLK_OUT1, EMAC_TX_CLK |
| 24 | IO4 | |
| 25 | IO16 | |
| 26 | VDD_SDIO | |
| 27 | IO17 | |
| 28 | SD2 | IR トランスミッタ | GPIO9 | I/O | *GPIO9(Output)*, SD_DATA2, SPIHD, HS1_DATA2, U1RXD|
| 29 | SD3 | Red LED | GPIO10 | I/O |  *GPIO10(Output)*, SD_DATA3, SPIWP, HS1_DATA3, U1TXD |
| 30 | CMD | |
| 31 | CLK | | 
| 32 | SD0 | |
| 33 | SD1 | |
| 34 | IO5 | ST7735S(TFT_CS) | GPIO5 | I/O | GPIO5, VSPICS0, HS1_DATA6, EMAC_RX_CLK |
| 35 | IO18 | ST7735S(TFT_RST) | GPIO18 | I/O | GPIO18, VSPICLK, HS1_DATA7 |
| 36 | IO23 | ST7735S(TFT_DC) | GPIO23 | I/O | GPIO23, VSPID, HS1_STROBE |
| 37 | VDD3P3_CPU | |
| 38 | IO19 | |
| 39 | IO22 | SCL: MPU6886, PMIC AXP192 | GPIO22 | I/O | GPIO22, VSPIWP, U0RTS, EMAC_TXD1|
| 40 | U0RXD | | 
| 41 | U0TXD | |
| 42 | IO21 | SDA: MPU6886, PMIC AXP192 | GPIO21 | I/O | GPIO21, VSPIHD, EMAC_TX_EN |
| 43 | VDDA | |
| 44 | XTAL_N_NC | |
| 45 | XTAL_P_NC | |
| 46 | VDDA | |
| 47 | CAP2_NC | |
| 48 | CAP1_NC | |


## AXP192 - M5StickC Pin Map

| LDO | Connected device |
| :--- | :--- |
| LDO0 | Microphone |
| LDO1 | RTC |
| LDO2 | LCD Backlight |
| LDO3 | LCD |
| DC-DC | ESP32, 6 Axes (MPU6886 or SH200Q) |
| IPS OUT | +5V on GROVE |


# ペリフェラルのデータシート と アドレス

| Peripheral | link for data sheet | SLA |
| :--- | :--- | :--- |
| ESP32-PICO | [ESP32-Pico D4](https://www.espressif.com/sites/default/files/documentation/esp32-pico-d4_datasheet_en.pdf) |
| LCD | [ST7735S](https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/datasheet/core/ST7735S_v1.1_en.pdf) |  |
| RTC | [BM8563](https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/datasheet/core/BM8563_V1.1_cn.pdf) | 0x51 (0xA3? 0x A2?) |
| 6 Axes sensor | * [MPU6886](https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/datasheet/core/MPU-6886-000193%2Bv1.1_GHIC_en.pdf)<br>* [SH200Q](https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/datasheet/core/SH200Q_en.pdf) | * 0x68(MPU6886)(Up to 400KHz, SA0=L)<br>* 0x6C(SH200Q) |
| PMIC | [AXP192](https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/datasheet/core/AXP192_datasheet_en.pdf) | 0x34 |
| MIC | [SPM1423HM4H-B](https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/datasheet/core/SPM1423HM4H-B_datasheet_en.pdf) |


# まずは初期出荷ファームウェアのバックアップから

## esptool.pyの入手

```
$ cd ~/work/tools
$ git clone https://github.com/themadinventor/esptool/
$ cd esptool
$ sudo python setup.py install
```

git cloneの代わりにzip downloadでも大丈夫ですよ。


## backup

M5StickCは4MのFlash ROMを内蔵しているので、4M分backupしておきます。

```
$ esptool.py --chip esp32 -b 1500000 --port /dev/cu.usbserial-Cxxxxxx read_flash 0x00000 0x400000 bkup-m5c-4M.bin
esptool.py v2.9-dev
Serial port /dev/cu.usbserial-Cxxxxxx
Connecting.....
Chip is ESP32-PICO-D4 (revision 1)
Features: WiFi, BT, Dual Core, 240MHz, Embedded Flash, VRef calibration in efuse, Coding Scheme None
Crystal is 40MHz
MAC: d8:a0:1d:xx:xx:xx
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 1500000
Changed.
4194304 (100 %)
Read 4194304 bytes at 0x0 in 36.7 seconds (913.9 kbit/s)...
Hard resetting via RTS pin...
```

# Arduino環境のsetup

いくつか開発環境はありますが、以前 [ESP8266で IoT開発環境を整えた](https://qiita.com/hidenorly/items/0eadcf6cc8ba04c0145d) こともありますので、Arduinoベースにしていきます。

ESP8266と基本は同じです
( [公式サイトのQuick Startもご参考](https://docs.m5stack.com/#/en/quick_start/m5stickc/m5stickc_quick_start_with_arduino_MacOS) )

1. https://www.arduino.cc/en/Main/Software から Arduino開発環境をdownloadしてinstall (1.8.10(Arduino2)をinstallしないと私の古いversionではesp32の追加に失敗しました)

2. Preferenceの追加の開発ボードマネージャーに```https://dl.espressif.com/dl/package_esp32_index.json```を追加<br>すでに入力されている場合は、以下のように ```,```で区切れば良いみたいです。<br> ```https://dl.espressif.com/dl/package_esp32_index.json,http://arduino.esp8266.com/stable/package_esp8266com_index.json,https://raw.githubusercontent.com/sparkfun/Arduino_Boards/master/IDE_Board_Manager/package_sparkfun_index.json,http://digistump.com/package_digistump_index.json```

3. ツール→マイコンボード→ボードマネージャーから、esp32を検索で追加

4. ツール→マイコンボード→M5StickCを選択<br>1500000bpsが使えるようです。シリアルポートの設定も忘れずに。<br>(なお、USBはCP210xをinstallしておけば良いようです。)

5. M5StickC Libraryのinstall (スケッチ -> ライブラリをインクルード -> ライブラリ管理 から M5StickCを検索してインストール)

# 動作確認

動作確認がてら何か作ろうと思ったのですが、せっかくM5StickCには赤外線LEDが搭載されているので、赤外線リモコンからスタートしてみようかなと思います。

が、いわゆる、赤外線受光部は残念ながらM5StickCには入っていないので、そこは接続します。
以前秋月で買ってあった赤外線リモコン用の受光素子(32KHzのパルスをdecodeしてくれる)を使っても良かったのですが、[M5Stack用赤外線送受信ユニット](https://www.switch-science.com/catalog/5699/) も同時に買ってあったので、とりあえずこれを使います。+5Vなのですが、分圧抵抗が入っているので、I/Oに直結できます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100425/a95cf8eb-d5b1-086c-680b-9a03f6da2f95.png" width=50%>

こんな風につなぎます。

| 赤外送受信ユニット | M5StickC |
| :---: | :---: |
| IN | G36 |
| OUT | G26 |
| +5V | +5V |
| GND | GND |

(右のブレッドボードのは秋月のを使ってESP8266でつなげていたのを引っ剥がしてM5StickCにつなげようかと思った残骸です。赤外線送受信ユニット買ったの忘れていたwww)

## まず、送信したいリモコンのコードを調べる

https://github.com/crankyoldgit/IRremoteESP8266
を使わせてもらいます。

Arduino上で、

1. スケッチ -> ライブラリをインクルード -> ライブラリ管理 から IRremoteESP8266を検索してインストール

2. スケッチ例 -> IRremoteESP8266 -> IRrecvDumpV2を選択

3. 下記を変更して適当な場所に保存
```
- const uint16_t kRecvPin = 14;
+ const uint16_t kRecvPin = 36;
```

4. ビルド＆焼き込んで実行
5. ツール→シリアルモニターで

```
IRrecvDumpV2 is now running and waiting for IR input on Pin 36
```

が、表示されていたら、受信したいリモコンを押してdumpしましょう。

```
Timestamp : 000163.203
Library   : v2.7.1

Protocol  : NEC
Code      : 0x41B67D82 (32 Bits)
uint16_t rawData[71] = {9000, 4552,  538, 598,  536, 1728,  536, 598,  536, 622,  512, 622,  510, 622,  512, 598,  536, 1728,  538, 1728,  536, 596,  536, 1728,  536, 1754,  510, 624,  510, 1754,  512, 1728,  536, 622,  512, 596,  536, 1728,  536, 1730,  536, 1728,  536, 1728,  536, 1754,  512, 596,  536, 1730,  534, 1728,  538, 596,  536, 600,  534, 622,  510, 598,  536, 596,  538, 1730,  534, 622,  512, 41504,  9026, 2324,  512};  // NEC 41B67D82
uint32_t address = 0x6D82;
uint32_t command = 0xBE;
uint64_t data = 0x41B67D82;
```

こんなのが出ればOkです

## Ir送信を試してみる

同様にスケッチ例で、IrSendDemoを使い試してみると、、、M5StickC内蔵のIrはどうも赤外線LEDのドライブ能力が低いようで、
全然飛びません。1mぐらいが限界みたいです。。。

```
const uint16_t kIrLed = 32; // M5StickCはGPIO9で内蔵IRを利用できるのですが、先程のGROVE赤外線送受信ユニットが、USB type Cの下にある4 pin端子に直接接続できたのでG32を使って赤外線出力してみました。
```

というわけで、先程の赤外線送受信ユニットを試すと、2mぐらいは十分届きそうなので、こちらをつかうことにしました。


## PIRセンサーを利用して、人がいる間だけON/OFFする。

PIRセンサーもたくさん実は持っているのですが、[M5StickCにブロックのように接続できるもの](https://www.switch-science.com/catalog/5756/)が売っていたので、一緒にポチっていました。

| 赤外送受信ユニット | M5StickC |
| :---: | :---: |
| IN | G33 |
| OUT | G32 |
| +5V | +5V |
| GND | GND |

| PIRユニット | M5StickC |
| :---: | :---: |
| OUT | G36 |
| +3.3V | +3.3V |
| GND | GND |
| NC | +5V |
| NC | G0 |
| NC | G26 |
| NC | BAT|
 

のように接続されています


https://github.com/hidenorly/m5stickC_PIRSwitch
においておきました。

なお、要件とその背景ですが

* PIRセンサーは動きがないと検出結果としてをH出力しない (一定以上未検出でOFFを出力する必要がある)
* Ir送信はIr受信側で確実に受信してくれるとは限らない (複数回送信)
* せっかくLCDがあるので、ON/OFFみたいな表示はしたい。
* せっかくボタンがあるので、マニュアル的にON/OFFしたい。
* 人が来たらすぐにON、人がいなくなってから一定期間経過してかるOFF (上のPIRセンサーの特徴からON中に人が検出したらON延長)

をサポートしています。

最初、ESP8266_IoTを移植したのですが、だいぶゴージャスになりすぎたので、
上は綺麗サッパリさせてあります。
(それでも、Class化を多用していますが。。。)

## M5StickCで、WiFiやNTPを使う

M5StickCだと、WiFiをつなげるのがなぜかESP8266で書いたコードがそのまま動かなくて少しハマりました (delay（）をWiFi.mode()する前後に入れないと動かないなど)。

https://github.com/hidenorly/M5StickC_NtpSwitch
にあげました。

![IMG-0962.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100425/bbaf5c94-3360-70ac-ba71-7be1787e7e0e.jpeg)

例によって、最初はAPモードで起動しますので、MAC AddressのAPに接続して、```192.168.10.1``` に接続して、SSIDとパスワードを設定すれば、APに接続できます。

結果、NTPサーバーに接続して、日時を表示できます。
ON/OFFの変化の際に、そちらも表示されます。

また、NTP clientですが、標準で取り込まれているので、

```
configTime(9 * 3600L, 0, "ntp.pool.org");
```

のような感じでNTPサーバーに接続できました。


# センサー MPU6886/SH200Qを使う

```
23:16:37.303 -> g:3995.85,3995.73,  4.52
23:16:37.379 -> a:  0.51,  0.24,  0.87
23:16:37.379 -> g:3995.54,3995.12,  4.58
23:16:37.483 -> a:  0.52,  0.25,  0.87
23:16:37.483 -> g:3995.79,3995.24,  4.33
```

のように取れるように

```
int IMU_Init(void);
void IMU_getGyroData(float* gyroX, float* gyroY, float* gyroZ);
void IMU_getAccelData(float* accelX, float* accelY, float* accelZ);
void IMU_getAhrsData(float* pitch, float* roll, float* yaw);
```

のwrapperを作っておきました。


なお、センサードライバー自体は、[M5StickVでのC framework向けに開発](https://qiita.com/hidenorly/items/4c3ce6afddd1eb908736#m5stickv%E3%81%A7%E3%81%AEc%E3%81%A7%E3%81%AEapplication%E3%81%AEbase-framework)したものを移植したものです。

https://github.com/hidenorly/M5StickC_Base
においておきました。


# 番外編

## 久々にMacをつかった方へ : gitコマンドとかを使えるように 

先日、m2 SSDを交換して、Mojaveをupgrade installしたばかりだったので、Xcodeが使えなくなっていました。
そうすると、

```
$ git status
xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun
```

のようにエラーが出ていました。

```
$ xcode-select --install
```

のようにして、xcodeを再インストールしてください。