ESP32

ESP32の内蔵タッチセンサを使用してみます

ESP32には、内蔵センサーとして、温度センサ、ホールセンサ、タッチセンサがあります。ホールセンサもちょっと気になるのですが、今回はタッチセンサを試してい見たいと思います。

タッチセンサの使用方法

ESP32には、10個のタッチセンサが内蔵されています。

GPIOの入力ポートからアナログ値を取得することが出来るようです。

対象のGPIOは、以下になります。

GPIOシンボル
IO4T0
IO0T1
IO2T2
IO15T3
IO13T4
IO12T5
IO14T6
IO27T7
IO33T8
IO32T9

このGPIOに、ジャンパーワイヤーをつないでタッチセンサとして使用します。

プログラム作成

タッチセンサ対応のGPIOからの入力を取得して、シリアルモニタに表示するプログラムを作成します。

プログラム

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

void loop() {
  const int tch0 = touchRead(T0);
  const int tch1 = touchRead(T1);
  const int tch2 = touchRead(T2);
  const int tch3 = touchRead(T3);
  const int tch4 = touchRead(T4);
  const int tch5 = touchRead(T5);
  const int tch6 = touchRead(T6);
  const int tch7 = touchRead(T7);
  const int tch8 = touchRead(T8);
  const int tch9 = touchRead(T9);

  Serial.printf("%2d %2d %2d %2d %2d %2d %2d %2d %2d %2d\n",
                tch0, tch1, tch2, tch3, tch4,
                tch5, tch6, tch7, tch8, tch9);

  delay(200);
}

プログラムについて簡単に説明いたします。

5~22行目のループで、各タッチセンサ対応のGPIOから値を取得して、それをシリアルモニタに表示しているだけの簡単なプログラムです。

touchRead(シンボル名)で、指定したGPIOの値を取得できます。実際にピンに触ると値が減少します。

動作確認

実際にジャンパーワイヤーを接続して、タッチピンの入力値を確認してみます。

まずは、タッチセンサに触っていない状態でのシリアルモニタの出力値です。

大体50~70ぐらいの値の範囲に収まっていますが、「T1」の入力だけ「1」しか入力されず、おかしくなっていました。まったく理由がわかっておりません。

※espressif公式サイトに以下のようなコメントがありました。T1は使用できないようです(T1はIO0に割り当てられています)。

 ESP32 DevKitC: 外部自動プログラム回路のため、GPIO 0を使用できません

また、値を観察していると同じ値がずっと入力されるわけではなく、ちょっと揺らぎがあるようです。たまに、「0」が入力されてくることもあります。

なにかに使用する場合は、これらの考慮が必要になりそうです。

それでは、タッチセンサとして接続したジャンパーワイヤーを触ってみます。

触ったGPIOから入力される値が減少しました。どうやら触り方によって値が変わるようです。

0番目(左端)のピン先端に触れただけの場合は、少しだけ値が減少しています。9番目(右端)のピンをつかんだ場合の値はかなり減少していました。

構成の変更

タッチセンサを使用してLEDのON・OFF制御をやってみたいと思います。

タッチセンサとして金属製品を追加します。そして、その金属製品をタッチすることでLEDの制御を行うように、プログラムを変更します。

接続変更

接続を変更していきます。まずは、タッチセンサ用のジャンパーワイヤーを1本だけにして、金属製品に接続します。

今回は、ダイソーで購入した「ステンレスマグネット付皿」を使用しました。ねじを無くさないように入れておくお皿なのですが、マグネットがお皿の底についているので、ねじがくっついて無くさない感じになっています。結構便利なので、愛用しています。

脱線しましたが、このお皿にジャンパーワイヤーを接続します。といってもお皿に近づけると磁石でくっつくので、このまま使います。

あとは、LEDと抵抗を付けて完了です。

プログラム

プログラムを以下のように変更します。

const int LED = 5;  // LEDピン
const int THRESHOLD_LEVEL = 10;  // タッチ閾値
bool lastTch = 0;           // 前回タッチ状態
bool fixedTch = 0;          // 確定タッチ状態
unsigned char ledSt = LOW;  // LED状態
unsigned long smpltmr = 0;  // サンプル時間

void setup() {
  pinMode(LED, OUTPUT);
}

void loop() {
  touchEvent();  // タッチイベント
}

void touchEvent() {
  if(millis() - smpltmr < 40) return;
  smpltmr = millis();

  bool tch = touchRead(T2) <= THRESHOLD_LEVEL ? true : false;
  bool cmp = (tch == lastTch);
  lastTch = tch;
 
  if(!cmp) return;

  if(!tch && (tch != fixedTch)){
    ledSt = (ledSt == LOW) ? HIGH : LOW;
    digitalWrite(LED, ledSt);  // LED制御
    fixedTch = tch;
  }

  if(tch){
    fixedTch = tch;
  }
}

プログラムについて簡単に説明いたします。

基本的には、ボタンのON・OFFでLEDを制御するイメージでプログラムを作成しました。前回に行ったボタン制御のチャタリング防止のプログラムを改造しています。

12~13行目のloop()で、タッチイベントの処理を繰り返し行っています。

16~35行目のtouchEvent()関数で、タッチした場合の入力値を監視して、LEDのON・OFFを行っています。

まず、20行目でタッチセンサ(T2)から取得した値が、閾値以下であるかチェックしています。この閾値は、環境によってことなるので、用意した環境でタッチした時に取得した値で閾値を決めるようにして下さい。

キャリブレーション的な感じで、タッチ前、タッチ後の値を認識する処理を入れてあげたり、タッチ前・後の値の比率によって制御したりするとカッコイイ感じがします。今回はべたうちですが・・・。

27行目で、前回のLEDの状態により、ONとOFFを制御しています。前回ONだったらOFF、OFFだったらONにする感じです。28行目でLEDピンに値を出力しています。

動作としては、タッチして手を離したらON、再度タッチして手を離したらOFFになります。

動作確認

実際に動作させて確認してみます。

タッチセンサとしての金属皿にタッチして手を離すことでLEDがONしました。再度タッチして手を離すことでLEDがOFFします。

思ったように動作してくれました。ボタンと違ってちょっと触れただけで制御できるのは、結構使いやすい感じです。

まとめ

ESP32の内蔵タッチセンサを試してみました。

内蔵センサ10個の制御を試してみましたが、シンボルT1のピンだけ正常に動作しませんでした。これは、壊れているのかもしれないので、別途調べてみたいと思います。

とりあえず他のピンはタッチセンサとして使えることがわかったので、良かったです。

制御としては対象ピンの値を読んで判断するだけと、とても簡単ですが、入力されてくる値が環境やピンに接続したものに影響されるようなので注意が必要そうです。

ちなみにタッチしていないときの値が、ジャンパーワイヤーのみ接続していた場合は、50~70ぐらいだったのにくらべ、さらにステンレス皿を接続した場合は、だいたい20ぐらいになっていました。

やっぱり、キャリブレーションや入力値の割合によって制御などをすると、接続するものに作用されないようになるので、良いかもしれません。

タッチセンサとしては思ったより反応が良く、ちゃんと動作してくれるので いろいろと利用できそうな感じがしました。ちょっと考えて何か作れればと思います。

【参考図書】