本記事ではESP32でLINE通知するドアスイッチの制作過程を記しています。
不明な点などあればお気軽にコメントどうぞ!
完成イメージ
購入部品
M5stamp picoについて
切手サイズのマイコンで省電力に特化。
ボード自身にJTAGを持たないので、外付けのダウンローダーが必要
CPUはEspressif ESP32-PICO-D4を使用。ちなみにM5 atomもこのマイコンを使用。
M5stamp用のボード定義が必要になる。
技適有り
12個のピンが使用できるが、SPI、I2C、UARTとの共用。
参考文献
想定用途
子どもの帰宅確認
防犯チェック
薬箱開けて飲んだかチェック
競合製品
差別化になりうる要素
指定秒数超えたらブザーを鳴らす
ON/OFF切り替わりのタイミングで子機ブザーに信号送って鳴らす(CalltoUで実現済み、これ便利やな)
電源をどこから取るか問題
制作1日目。
部品選定やら設計構想を考えて購入。電源をどこからどのように取るかの判断がつかない…。
開発環境の整備
制作2日目、モノは届いてないが、開発環境だけ整えておく。
PlatformIOでM5stamp picoを探すも見つからない…調べたところ定義されていなかった。
QiitaにてM5stamp picoの定義情報を作る記事が大変参考になりました、ありがとうございます。
PlatformIOにM5Stamp Picoのボード定義を追加してみた
ボード定義とピン配列定義が必要とのこと。(以下参考記事をコピペさせていただいてます)
ボード定義
%UserProfile%\.platformio\platforms\espressif32\boardsにstamp-pico.jsonを追加。
後述しますが、M5stampはM5atomと同じマイコン使用なので、M5atomのvariantキーとnameキーをそれぞれ変更しているだけになります。
{
"build": {
"arduino":{
"ldscript": "esp32_out.ld"
},
"core": "esp32",
"extra_flags": "-DARDUINO_STAMP_PICO",
"f_cpu": "240000000L",
"f_flash": "40000000L",
"flash_mode": "dio",
"mcu": "esp32",
"variant": "stamp_pico"
},
"connectivity": [
"wifi",
"bluetooth",
"ethernet",
"can"
],
"frameworks": [
"arduino",
"espidf"
],
"name": "STAMP-PICO",
"upload": {
"flash_size": "4MB",
"maximum_ram_size": 327680,
"maximum_size": 4194304,
"require_upload_port": true,
"speed": 1500000
},
"url": "http://www.m5stack.com",
"vendor": "M5Stack"
}
ピン配列定義
%UserProfile%\.platformio\packages\framework-arduinoespressif32\variantsにstamp_picoというディレクトリを作成し、その中にpins_arduino.hを追加。
M5atomとピン配列が違うので注意(これが原因でボード定義が必要になっている)。
差分としては、
- I2Cのピン配置が異なる 26/32 ⇒ 21/22
- UARTの2chがstampには無い
- SPIのピン配置が異なる 19/33/23/22 ⇒ 19/26/36/18
- I/Oもばらばら
- ADCの3chがstampには無い&1ch/2chのピン配置が異なる
んー…M5stamp picoにM5atomボード定義を使うのは実質無理やね
#ifndef Pins_Arduino_h
#define Pins_Arduino_h
#include <stdint.h>
#define EXTERNAL_NUM_INTERRUPTS 16
#define NUM_DIGITAL_PINS 40
#define NUM_ANALOG_INPUTS 16
#define analogInputToDigitalPin(p) (((p)<20)?(esp32_adc2gpio[(p)]):-1)
#define digitalPinToInterrupt(p) (((p)<40)?(p):-1)
#define digitalPinHasPWM(p) (p < 34)
static const uint8_t TX = 1;
static const uint8_t RX = 3;
static const uint8_t SDA = 21;
static const uint8_t SCL = 22;
static const uint8_t SS = 19;
static const uint8_t MOSI = 26;
static const uint8_t MISO = 36;
static const uint8_t SCK = 18;
static const uint8_t G21 = 21;
static const uint8_t G22 = 22;
static const uint8_t G19 = 19;
static const uint8_t G26 = 26;
static const uint8_t G36 = 36;
static const uint8_t G18 = 18;
static const uint8_t G25 = 25;
static const uint8_t G32 = 32;
static const uint8_t G33 = 33;
static const uint8_t G1 = 1;
static const uint8_t G3 = 3;
static const uint8_t G0 = 0;
static const uint8_t DAC1 = 25;
static const uint8_t DAC2 = 26;
static const uint8_t ADC1 = 32;
static const uint8_t ADC2 = 33;
static const uint8_t ADC3 = 36;
#endif /* Pins_Arduino_h */
M5stampへのソフト書き込み&LINE通知
制作3日目、M5stampが到着。
とりあえずPC-ダウンローダ-M5stampの接続で、ROM書くのは何なくクリア。
家のWIFIネットワークからLINE通知させることもできた。
LINE通知は別記事にまとめたので気になる方はこちらをどうぞ。
明日、リードスイッチ他すべて揃う予定で本格的に動き始めます。
筐体に入れてみる
制作4日目、部材が届く。
M5stampを箱におさめてモバイルバッテリーから給電できるようにした。
電源入ってLINE通知飛ぶし、モノで見ると完成イメージが沸きますねえ。
またリードスイッチの動作確認。
はじめて使う部品でどう動くのが正しいか分かってないが、磁場の検知はスイッチ近くではなく足でやるのだろうか?
足周辺の磁場感度が非常に良い、どのサンプルも同じ挙動。
とりあえずAmazonレビュー書いといた。
https://www.amazon.co.jp/gp/customer-reviews/RYFFX57PG9DSV/ref=cm_cr_dp_d_rvw_ttl?ie=UTF8&ASIN=B08CMNYN79
…けど足で検出するのであれば、ダイオードみたいに一方の足が長くてもよいような。
GROVEコネクタをI2C用として使いたい
制作5日目。
将来的な構想としてI2Cでセンサ信号の送受信を考えており、それをふまえてどう設計するか考える。
通常I2Cは21/22の側面のピンに割り当てられているが、どう考えてもVcc, GND, I/O*2(32,33)のGROVEコネクタを使うのが便利としか思えない。
調べたところWire関数にてI/OをI2CのSCL,SDAに変換できるとのこと。
これをsetup関数に入れるわけだが、ただはじめにWire.end()をかませないとbeginで設定できなかった。
Wire.end();
Wire.begin(32, 33); // Grove端子をI2C通信に設定(SDA, SCL)
たったこれだけでI/OをI2Cとして利用できる、すごい。めちゃ便利。
手元にあったENV Ⅲユニットをつなげて、問題なく受信できることも確認しました。通信はできたから、後はどう表示するか。これやりだすと本筋を脱線するので追々詰める。
DeepSleep設定する
DeepSleepには外部信号、タイマ、タッチパッド、ULP(ESP32のコプロセッサ)の4つから選択できる。
サンプルコードはこちら。
RTC_DATA_ATTR int bootCount = 0;
//Method to print the reason by which ESP32 has been awaken from sleep
void print_wakeup_reason(){
esp_sleep_wakeup_cause_t wakeup_reason;
wakeup_reason = esp_sleep_get_wakeup_cause();
switch(wakeup_reason){
case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
}
}
// put function declarations here:
int myFunction(int, int);
void setup() {
Serial.begin(115200);
//Increment boot number and print it every reboot
++bootCount;
Serial.println("Boot number: " + String(bootCount));
//Print the wakeup reason for ESP32
print_wakeup_reason();
esp_sleep_enable_ext0_wakeup(GPIO_NUM_25,1); //1 = High, 0 = Low
Serial.println("Going to sleep now");
esp_deep_sleep_start();
Serial.println("This will never be printed");
}
RTC_DATA_ATTRはRTCスローメモリと呼ばれるdeepsleep中でも値が消えないメモリ領域のようで、そこにリブート回数を保存させてます。
print_wakeup_reason関数で復帰要因の確認。esp_sleep_get_wakeup_cause関数から復帰要因を引っ張り出せる。
esp_sleep_enable_ext0_wakeup関数で復帰設定。上記コードでは25番ピンがHighになったときに復帰する、という設定になっている。
esp_sleep.hを見てもらうと分かりますが、復帰に使えるピンは制限されていて、0,2,4,12-15,25-27,32-39のみになってます
esp_deep_sleep_start関数でDeepSleepに入る。復帰したらsetup関数が呼び出されます(=実質の初期化)
DeepSleepして復帰して、を繰り返すとこんな出力になりますよ。
Boot number: 1
Wakeup was not caused by deep sleep: 0
Going to sleep now
rst:0x5 (DEEPSLEEP_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
Boot number: 2
Wakeup caused by external signal using RTC_IO
Going to sleep now
rst:0x5 (DEEPSLEEP_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
Boot number: 3
Wakeup caused by external signal using RTC_IO
Going to sleep now
rst:0x5 (DEEPSLEEP_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
Boot number: 4
Wakeup caused by external signal using RTC_IO
Going to sleep now
復帰に使うピンを内部プルアップしたい
こんな感じで内部プルアップ設定できる。
pinMode(25,INPUT_PULLUP);
初期設定はどうなっているのか、そして抵抗値はいくつか。
データシートを参照すると、抵抗値は標準状態で45kΩ、初期値は分からん…どこを参照すればよいのやら。
製品化は困難であることを知る
完成に近づいてきたから製品化できるかなあ、と思ったが甘かった。
商工会にとりあえず相談に行ったら、特許だ、法律だ、販路どうするんだ、生産体制は…個人製作だからそこまで考えてないよお…メーカーの時散々やってきたのに、いざ自分でやるとすっかり忘れる始末。
けどたしかに特許侵害とPL法は特に注意しないと、一発で人生終わる。
体験キットとして売り出すか。使用は自己責任で、的な。
ちょっと用意しますわ。また更新します。
コメント