出遅れました。Raspberry Pi Picoの入荷メールがスイッチサイエンスさんから届いていたので(翌日朝)買いにいったらもう在庫0でした。凄い人気だね。ゲーム機みたい?ところで本日の話はPicoではありませぬ。傾斜スイッチでございます。Uno/Wio/M5StickCのArduino環境3機種で割り込み受けしてみます。
※「部品屋根性」投稿順Indexはこちら
さて傾斜スイッチです。大分前に一度調べたことがあります。
そこでは方式とメーカさんの表なども掲げましたが、今回は例によってお楽しみの中華部品キットKuman社K4の部品箱からみつけた
SW-520D
という傾斜スイッチです。これまた例によってですが、データシートは付属しているのにメーカ名が入っていません。なお、例によってちょっと残念な日本語マニュアルには「振動センサ」と訳されているのですが、「傾斜(振動)スイッチ」というのが日本では一般かと思います。なお、SW-520Dというデバイス自体は「Arduino業界」ではかなり一般的な「型番」のようです。同一型番でソース複数??シリンダを寝かせると導通せず、シリンダを15度以上傾けると導通するというだけのデバイス。中に金属球が入っている完全メカニカルなスイッチ。
完全メカニカルというところがミソで、待ち受け時の消費電力ゼロ、というのが最大の利点です。使い方としては大きく二つあり
-
- まれに起こる倒れた、崩れた、傾いた、という事象を監視するために使う
- 振動の発生を監視するために使う
です。私自身は、10年くらい前に「あるとき崩れる筈」の砂の中で崩落を何か月も見張るという目的で使ったことがあります。その時はシリンダが縦のときに導通せず、傾くと導通するタイプを使い「イベントの予兆」をうまく検出できました。結局メカニカルなデバイスなので、うまくいくかどうかは、設置の方法や位置に左右されます。待ち受け時の消費電力ゼロは、電池駆動で長時間動かすときには魅力です。加速度センサやジャイロセンサでいつ動くか分からない崩れをじっと待ち続けるのは電気がかさみます。
それもあって、マイコンがスイッチをポーリングしつづける、という方法は折角のスイッチの利点を損ないます。ソフトがくるくるLoopしているだけで電気を食うので。よって、スイッチが倒れたら寝ているマイコンを割り込みで叩き起こし、イベントを報告させる、というのが第一の使い方でのあるべき姿かと思います。
今回は、Arduino環境でソフトをビルドできる以下の3機種で、傾斜スイッチの導通をトリガにして割り込みをかけてみました。今回はテキトーな実験なので、スイッチONになったときに大電流流れると困るのでテキトーに直列抵抗いれただけで電源-GND間に接続しましたが、設置前や、単発のイベント検出後に電流が流れつづけないようにするためには、もう1端子つかって電源を制御(設置OKでON、検出トリガしたらOFF)した方が良いかと思います。
Arduino Uno(互換機だけれども)の場合
Uno互換機と結線と抵抗をかませるためのブレッドボード、そして傾斜スイッチを接続したところがこちら。ブレッドボードには傾斜を検出したことを知らせるLEDものってます。
スイッチとLEDを制御するソフトがこちら。後で気付きましたがちょっとズルしていますで。
#define LEDPIN (8) #define TILTSW (2) #define INTNUM (0) volatile int swStat; void detectTilt() { swStat = 1; } void setup() { pinMode(LEDPIN, OUTPUT); pinMode(TILTSW, INPUT); attachInterrupt(INTNUM, detectTilt, FALLING); swStat = 0; digitalWrite(LEDPIN, HIGH); } void loop() { if (swStat == 1) { swStat = 0; digitalWrite(LEDPIN, LOW); } else { digitalWrite(LEDPIN, HIGH); } delay(1000); }
ズルしているのは、外部ピンからの割り込みを関数と結びつけるattachInterrupt関数のところですね。Arudinoのリファレンスを読むと、直接割り込み番号を書くのでなく、以下にピン番号を渡して割り込み番号に変換してもらうのが正しい使い方のようです。
digitalPinToInterrupt()
ただ、Unoに関していえば、以下の2つしか使えないらしいので、上のようなキメウチな書き方にしてしまった、と。
-
- ピン2が割り込み0番
- ピン3が割り込み1番
Wio Terminalの場合
「IoT何をいまさら第69回」で作った治具で背中から取り出せている端子、D2とD3に傾斜スイッチとLEDをとりつけてみました。またどの端子にどのような機能がアサインされているかは、「IoT何をいまさら第67回」でどこみりゃいいのか判明しています。結論から言えば
デジタル入出力Dxと呼ばれている端子はどれも割り込み端子にできる
です。ただし、物理的な割り込みソースは16個しかないので、1つのソースに複数の端子がアサインされています。複数の割り込み端子や内部割込みと併用する場合には同じ番号の割り込みに繋がっていないか要確認かと思います。
Wioの場合、端子番号と割り込み番号の関係が多対1なのでdigitalPintoInterrupt()に変換をお願いしました。それ以外はピン番号を変更しただけです。
#define LEDPIN (3) #define TILTSW (2) volatile int swStat; void detectTilt() { swStat = 1; } void setup() { pinMode(LEDPIN, OUTPUT); pinMode(TILTSW, INPUT); attachInterrupt(digitalPinToInterrupt(TILTSW), detectTilt, FALLING); swStat = 0; digitalWrite(LEDPIN, HIGH); } void loop() { if (swStat == 1) { swStat = 0; digitalWrite(LEDPIN, LOW); } else { digitalWrite(LEDPIN, HIGH); } delay(1000); }
これにて動作OK。
M5StickCの場合
M5StickCの頭にでている「HAT」拡張用の3端子について割り込み受けられるのか全てやってみました。G26とG0は入出力、G36は入力専用ですが、全端子割り込み端子として使えました。ただし、割り込みソースと端子の関係は不明です。
M5StickCのコードとUnoやWio Terminalのコードはほとんど同じなのですが、決定的なところが1箇所違います。
attachInterrup()
の第1引数です。UnoやWioでは割り込み端子にしたいピン番号に対応づけられている割り込み番号を与える必要があったのですが、M5StickCでは、端子番号そのものを与えて初期化できました。割り込み番号(ベクタ)と端子の関係がちと分かりませぬ。しかしコードは動作します。
#define LEDPIN (0) #define TILTSW (26) volatile int swStat; void detectTilt() { swStat = 1; } void setup() { pinMode(LEDPIN, OUTPUT); pinMode(TILTSW, INPUT); attachInterrupt(TILTSW, detectTilt, FALLING); swStat = 0; digitalWrite(LEDPIN, HIGH); } void loop() { if (swStat == 1) { swStat = 0; digitalWrite(LEDPIN, LOW); } else { digitalWrite(LEDPIN, HIGH); } delay(1000); }
傾斜センサ自体は、そんな受け側のソフトに関わりなくしっかり動作。まあいいか。