ESP32のタッチセンサの使い方と外れ値処理

はじめに

Arduinoの無線版であるESP32(正式名称はESP-WROOM-32)モジュールにはデフォルトでタッチセンサが10個もついています。ライブラリもあって使うのは非常に簡単です。今回はタッチセンサの使い方と、実際に自作デバイスを作るときのノウハウについて書きます。

使い方

無線チップが乗っていてArduinoとしてプログラミングもできるモジュールESP32を使用します。


ちなみに20円安くwavesという所からも出てますが、ピンヘッダの半田付けが悪くブレッドボードに刺さりにくいというレビューがあったので、こちらのHiletgoの方をおすすめします。ピンヘッダも問題ありませんでした。

ArduinoIDEにライブラリをインストールするのはこちらを参考にしました。
ESP32-DevKitCを使ってみた〜環境構築からタッチセンサによるLチカまで〜

タッチセンサを使うプログラムはめちゃくちゃ簡単で、次のコードだけです。(サンプルコードそのまま)

// ESP32 Touch Test
// Just test touch pin - Touch0 is T0 which is on GPIO 4.

void setup()
{
  Serial.begin(115200);
  delay(1000); // give me time to bring up serial monitor
  Serial.println("ESP32 Touch Test");
}

void loop()
{
  Serial.println(touchRead(T0));  // get value using T0
  delay(1000);
}

何も宣言しなくても、「touchRead(T0)」を書くだけで値の取得ができます。T0ピンに触れていないときは40~70の値、触れてるときは10~30の値になります。

タッチ判定

このタッチセンサを使うシチュエーションとしては、センサに触ったら何かの動作をさせることが多いと思います。タッチの判定条件として一番簡単でよく使われているのは、「センサ値がt以下になった時、処理を実行する」です。

void setup() {
  Serial.begin(115200);
}

void loop() {

  int t0 = touchRead(T0);
  Serial.println(t0);
  
  if(t0 < 40){
    Serial.println("なんらかの処理");
    /*
     * なんらかの処理
     */

  }

  delay(10);

}

しかし、これだとセンサに触れている間はずっとt0<40になってしまい、処理が連続で実行されてしまいます。そこで、一度タッチしたらセンサから指を離すまで待つことが必要です。

void setup() {
  Serial.begin(115200);
}

void loop() {

  int t0 = touchRead(T0);
  Serial.println(t0);
  
  if(t0 < 40){
    Serial.println("なんらかの処理");
    /*
     * なんらかの処理
     */

    //継続して触れている間は何もしない
    while(t0 < 40){
      t0 = touchRead(T0);
      Serial.println(t0);
      delay(10);
    }
  }

  delay(10);

}

たまに外れ値が出る。。。

はじめは上のプログラムで動かしていたのですが、このタッチセンサはたまに触れていないのに0を出すことがあります。

センサ値をプロットしたところ、触れていないのに変な値が出ることがある

この外れ値は連続で出るわけではなく、一瞬出てすぐに普通の値に戻ります。そのような外れ値に対応するための処理として急激な変化の影響を少なくする、ローパスフィルタというものがあります。ローパスフィルタのプログラムは簡単で、前の値を覚えておいて今回の値の方にちょっとずらすことを繰り返します。

サンプルコードはこんな感じです。

int t0_old;

void setup() {
  Serial.begin(115200);
}

void loop() {

  int t0 = touchRead(T8)*0.1 + t0_old*0.9;
  t0_old = t0;
  
  Serial.println(t0);

  
  if(t0 < 40){
    Serial.println("なんらかの処理");
    
    while(t0 < 40){
      t0 = touchRead(T8)*0.1 + t0_old*0.9;
      t0_old = t0;
      Serial.println(t0);
      delay(10);
    }
  }

  delay(10);

}

このときのセンサ値をプロットしたものがこちらです。

ローパスフィルタによって外れ値が除去できました!

ローパスフィルタによって外れ値が除去できました。これでタッチ判定が誤作動することも無くなります。あとは何らかの処理を書けば、簡易スイッチの完成です!

帰宅したら自動で解錠するスマートロックを自作する①~オートロック編~

はじめに

ホテルとかオフィスのドアみたいに閉まると自動で施錠してくれるやつ、あれすごく便利ですよね。家を出るときにわざわざポケットから鍵を出して閉める動作が不要になるので、意外にも快適です。今回はこのオートロックを自作して自宅の玄関に取り付けた話です。

作りたいもの

まず、作りたいオートロックに必要な機能を決めます。

  1. ドアが閉まったら自動で施錠
  2. 暗証番号で解錠
  3. ICカードで解錠
  4. スマホを持って近づくだけで解錠

1→4になるほど難易度が高いと思います。この記事では最初の「ドアが閉まったら自動で施錠」をご紹介します。 まだ作ってる途中ですので、随時更新していきます。

必要なもの

  • ArduinoまたはESP8266 400円~2000円くらい
  • サーボモータSG92R  830円くらい
  • 100均の下駄箱ライト  108円

ArduinoまたはESP8266

Arduinoの種類は何でも大丈夫ですが、後々解錠にFelica(ICカード)を使う予定ならシリアル通信で152000bpsが使えるボードが必要です。一番良く使われているArduinoUnoは対応していません。下記の安いArduinoNano互換品とかでいいと思います。また今後スマホを使って解錠するなど、WiFiを使って何かすることを考えるならESP8266をおすすめします。ちなみに僕はESP8266で作ってます。

サーボモータ

サーボモータとは、指定した角度まで回転してくれるモーターです。室内側のサムターンを回すので、それなりにパワーのあるものが必要です。僕の家のサムターンはちょっと固めだったのか、持っていたSG90では回せませんでした。
不安な方はよりトルクの大きいSG92Rをおすすめします。こちらはSG90よりも動きが遅いらしいですが、楽々回してくれてかっこ良いです。

100均の開閉センサ付きライト

100均の下駄箱ライトは写真を撮るの忘れましたが、扉に磁石とセンサーを取り付けて双方が離れるとスイッチON、近づくとスイッチOFFするライトです。今回はこれの磁石とセンサー部分を切り取って使っています。100円で開閉センサが手に入るので便利です。
ここで紹介されているようなやつです。)

サムターン回し装置

まずモーターでサムターンを回す装置を作っていきます。3Dプリンターで部品を作っている人も見かけますが、CAD書いて出力するのも面倒なので割り箸とかで作っていきます。

どんな機構にするか

まずサムターンを回すための機構ですが、こんな感じになるように作ります。

サムターン回し機構。木のブロックがついた部分を左右に90度回すことによって鍵が開く。

木のブロックは余ってる木材の端材とかで全然OKです。それをサーボモーターに付属しているプラスチックのパーツに取り付けます。

木の端材をサーボモータについてるパーツにネジ止めしたところ

こうすることによって、ニュートラルにしておけば鍵を使って開けたり手で開けたりできます。モータで開閉するときは左右に90度回転させて、またニュートラルに戻すことで、手動とモータの動作を両立させることができます。

ドアノブに取り付け

割り箸とマスキングテープを使ってモータをドアノブに固定します。ここはドアノブの形状によって色々やり方があると思うので、ご自宅のドアにあったやり方で固定してください。

割り箸でモータを固定
ドアノブにつける。ここのやり方はお好みで。

開閉センサ

ドアが開いているか閉まっているかを検知するセンサを作ります。100均の下駄箱ライトを使えば簡単に作れます。100均のライトは片方が磁石、もう片方が金属板になっていて、磁石が近づくことで金属板が接触して電気が流れる仕組みになっています。今回はこの部分だけを切ってセンサ代わりに使います。

導線を切ってコネクタをはんだ付けする

2つの箱が近づくと導通、離れると絶縁です。

配線

サーボモータと開閉センサが用意できたら配線してみます。サーボモータは接続を間違えないようにESP8266のGND、Vin、D4(PWMピン)につなぎます。サーボモータから出ている線は茶色がGND、赤が5V、オレンジがPWM信号です。

開閉センサはGND、D0につなぎます。2本ありますがどちらの線をどちらにつないでもOKです。

配線イメージ

プログラム

ESP8266にこちらのプログラムを書き込みます。動作としてはすごく簡単で、開閉センサが「開」から「閉」になったタイミングでサムターンを回すだけです。せっかくWiFiが使えるESP8266を使ったので、WiFi経由で開け締めする機能も付けました!

#include <Servo.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

// ルータ設定
IPAddress ip(192,168,1,102);
IPAddress gateway(192,168,1,1);
IPAddress subnet(255,255,255,0);

// ESP8266のピン番号
const int servo_pin = 2;
const int door_pin = 12;

Servo myservo;             // サーボオブジェクトを生成
int door_sensor = LOW;
int door_sensor_last = LOW;
ESP8266WebServer server(80);  //サーバーオブジェクト


void door_open(){
  myservo.write(170);
  delay(1000);
  myservo.write(90);
}

void door_close(){
  myservo.write(10);
  delay(1000);
  myservo.write(90);
}

void handle_open(){
  door_open();
  server.send(200, "text/html", "opened");
}

void handle_close(){
  door_close();
  server.send(200, "text/html", "closed");
}

void setup() 
{ 
  
  Serial.begin(115200);
  delay(200);

  //固定IPで運用するときの設定
  WiFi.config(ip, gateway, subnet);
  WiFi.begin("WIFIのSSID", "WIFIのパスワード");

  // WiFiに接続するまで待つ
  Serial.println("");
  while(WiFi.status() != WL_CONNECTED){
    delay(1000);
    Serial.print(".");
  }
  
  Serial.println("");
  Serial.println("Connected!");
  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());

  // Webサーバを設定
  server.on("/open", handle_open);
  server.on("/close", handle_close);
  server.begin();

  // 開閉センサの入力を内部プルアップにする
  pinMode(door_pin, INPUT_PULLUP);

  // サーボ変数をピンに割り当て
  myservo.attach(servo_pin);

  door_close();
} 

void loop() 
{ 
  // サーバとして待ち受ける
  server.handleClient();

  // 現在のドアの開閉を検知
  // LOW=閉
  // HIGH=開
  door_sensor = digitalRead(door_pin);

  // 「開」→「閉」になったタイミングでサーボモータを回す
  if(door_sensor == LOW && door_sensor_last == HIGH){
    delay(1000);
    door_close();
  }
  
  door_sensor_last = door_sensor;
  
}

ルータ設定やWiFiパスワードの部分はご自身の環境に合わせて変えてください。

Arduinoを使う人はヘッダーファイルとか適宜変更して、それ以外はほとんどそのままで行けると思います。

完成!

プログラムができたら開閉センサを近づけたり離したりしてみてください。近づけたときにサーボモータが回るはずです。

ESP8266を使っている人はスマホやパソコンのURLのところに192.168.xxx.xxx/closeと入力しても動きます。

確認ができたらドアに取り付けてみます。

※注意 オートロックなので閉め出されないように鍵を持っておくこと!動作テスト中に閉め出されたら恥ずかしいです。

ドアに取り付けてマスキングテープでいい感じにしました

最大の問題はUSBケーブルが玄関まで届くかですね。僕は延長コードを3個経由しています。あと家から出るときに室内側からサムターンを回すのが少し大変です。慣れれば簡単に開けられますがちょっとモータが邪魔なので、今度は家の中からスイッチとかで開けられるようにしておきます。

今回は以上です。次回は帰ってきたときに暗証番号的なもので解錠する方法をご紹介します。

次回→