ガイド · 読了まで11分

ESP32のタッチピン:touchRead、しきい値、割り込み、スライダー

ESP32のタッチピンのガイドです。T0〜T9のピン表、touchReadの値としきい値、アルミホイルで作るボタンとスライダー、touchAttachInterrupt、タッチによるディープスリープからの復帰を解説します。

ESP32のタッチピンは、チップに内蔵された静電容量式タッチセンサーにつながっている特別なGPIOです。無印ESP32には10本(T0〜T9)あり、追加のモジュールなしで、ワイヤーやアルミホイル、銅箔テープへのタッチを検知できます。使う関数は1つだけ、touchRead()です。指をパッドに近づけると回路に小さな静電容量が加わり、ESP32はその変化を数値として返します。これを使えば、機械式の押しボタンなしで、タッチスイッチや照明の調光器、スライダー、隠し開閉ボタンを作れます。

このガイドでは、まずどのGPIOがどのタッチチャンネルにつながっているか、どのピンを避けるべきかを確認します。次にtouchReadの値を読み、適切なしきい値を選び、自動キャリブレーションとヒステリシスを備えた安定したタッチボタンを作ります。さらに、アルミホイルや銅箔テープでパッドを作る方法、3枚のパッドのスライダーでLEDの明るさを調整する方法、touchAttachInterruptで割り込みを使う方法、タッチでESP32をディープスリープから復帰させる方法も学びます。最後のセクションでは、湿気とノイズの問題、ESP32-S3の違い、MicroPythonの短い例を取り上げます。

ESP32開発ボード
無印ESP32にはT0〜T9という10個の静電容量式タッチチャンネルがあり、追加のモジュールは不要です。

ESP32のタッチピンはどのように動作しますか?

各タッチピンはチップ内部の測定回路につながっています。この回路はピンの充電と放電を繰り返し、一定時間に何回の充放電サイクルが完了するかを数えます。ピンにつながったワイヤーとパッドは小さなコンデンサのように働きます。指を近づけると、体がこのコンデンサに数ピコファラッドを加えるため、充電と放電が遅くなり、同じ時間に完了するサイクル数が減ります。そのため無印ESP32ではタッチするとtouchReadの値が下がります。短いワイヤーなら、触れていないときはたいてい40〜80、指で触れると10〜25程度まで下がります。これらの数値はワイヤーの長さ、パッドの大きさ、ボード、周囲の環境によって変わるので、しきい値を記憶に頼ってコードに直接書かず、必ず自分の環境で測定してください。

特徴無印ESP32ESP32-S2 / ESP32-S3
タッチチャンネル数10(T0〜T9)14(T1〜T14)
タッチ時の値下がる上がる
待機時の一般的な値40〜80数千〜数万
touchReadの戻り値の型uint16_tuint32_t
割り込みのしきい値絶対値、これを下回ると発生待機時の値からの増加量
ディープスリープからの復帰複数のパッド1つのパッド

ESP32のタッチピン表(T0〜T9)

タッチチャンネルは特定のGPIOにしかつながっていないため、ほかのピンでtouchReadを使っても意味のある値は得られません。Arduinoコアにはこれらのチャンネル用にT0やT1などの定数が用意されているので、コードでtouchRead(T0)と書くのはtouchRead(4)と書くのと同じです。一部のピンは、起動時にボードの起動方法を決めるストラッピングピンです。タッチピンとして動作はしますが、最初の選択肢にはしないでください。

チャンネルGPIO使用上の注意
T0GPIO 4安全、第一候補
T1GPIO 0BOOTボタンに接続され、30ピンのボードでは外に出ていないため使わないほうがよい
T2GPIO 2オンボードLEDに接続、ストラッピングピン。値がふらつくことがある
T3GPIO 15ストラッピングピン(起動メッセージに影響)。注意して使う
T4GPIO 13安全
T5GPIO 12ストラッピングピン(フラッシュ電圧)。起動時にHIGHになっているとボードが起動しない
T6GPIO 14安全、起動時に短いPWM信号を出力
T7GPIO 27安全
T8GPIO 33安全
T9GPIO 32安全
T8とT9の順番に注意してください。T8はGPIO 33、T9はGPIO 32です。逆のように見えますが、これで正しいのです。また、タッチピンには3.3 Vを超える電圧をかけないでください。同じピンをタッチ入力とデジタル出力に同時に使うのも避けてください。ボード上のピンの位置は「ピン配置」ツールで確認できます。

パッドを作る:ワイヤー、アルミホイル、銅箔テープ

導電性のある面なら何でもタッチパッドになります。いちばん簡単なのは、ピンに挿したジャンパーワイヤーのむき出しの先端です。もっと触りやすい面にするなら、2×2 cmのアルミホイルや粘着式の銅箔テープを使えます。銅箔テープははんだ付けもできるので、長く使うプロジェクトに向いています。パッドは厚紙やプラスチックケースの内側、木片の裏側に貼れます。1〜3 mmのプラスチック、アクリル、ガラス越しでもタッチは検知されます。ただし値の下がり幅が小さくなるので、しきい値を測り直す必要があります。パッドとESP32をつなぐワイヤーは短くしてください。20〜30 cmを超えるワイヤーはアンテナになり、ワイヤー自体に触れても反応してしまいます。

パッドの材料おすすめのサイズ長所注意点
ジャンパーワイヤーの先端ワイヤーの先準備不要感度が低く、テスト向け
アルミホイル2×2〜3×3 cm安く、どこでも手に入るはんだが付かないので、ワイヤーはテープやクリップで固定
銅箔テープ1.5×1.5〜3×3 cmはんだが付き、きれいに切れる粘着剤が導電性でなければ、ワイヤーを表面にはんだ付け
ユニバーサル基板またはPCBのパッド直径1〜2 cm長く使えて見た目もきれい周囲にGNDのエリアを設けるとノイズが減る
金属の物(ネジ、ドアノブ)物による隠しボタンを作れる大きな金属は待機時の値を大きく下げる

touchReadの値を読み、しきい値を決める

まずは自分の環境での実際の数値を確認します。下のスケッチはGPIO 4(T0)とGPIO 27(T7)をそれぞれ8回読み取り、平均を表示します。Arduino IDEの「ツール」メニューからシリアルプロッタを開くと、2本の線をリアルタイムで確認でき、タッチしたときに値がどう下がるかがわかります。

C++ (Arduino IDE)
1// ESP32 dokunmatik değer okuma / ESP32 touch value reading
2// GPIO 4 = T0, GPIO 27 = T7
3
4void setup() {
5  Serial.begin(115200);
6  delay(500);
7}
8
9void loop() {
10  uint32_t t0 = 0, t7 = 0;
11  for (int i = 0; i < 8; i++) {      // 8 ölçümün ortalaması / average of 8 readings
12    t0 += touchRead(T0);
13    t7 += touchRead(T7);
14  }
15  Serial.print("T0:");
16  Serial.print(t0 / 8);
17  Serial.print(" T7:");
18  Serial.println(t7 / 8);            // Seri Çizici için / for the Serial Plotter
19  delay(100);
20}

値を見ながら、3つの状態を記録してください。パッドに何も触れていないとき、指がパッドに触れているとき、指がパッドの1〜2 cm上にあるときです。たとえば待機時に62、タッチ時に14、近づけたときに45なら、安全なしきい値は待機時の値の約60%、つまり37前後です。しきい値を待機時の値に近づけすぎると指を近づけただけで反応し、低くしすぎると軽いタッチを見逃します。

状態値の例コメント
待機時、短いワイヤーと2×2 cmのアルミホイル55〜70基準値
指が1〜2 cmの距離40〜50反応してはいけない
指でタッチ10〜20確実なタッチ
1 mmのプラスチック越しにタッチ25〜35しきい値を少し上げる
長く宙に浮いたワイヤー不安定、30〜70ワイヤーを短くし、平均を取る

自動キャリブレーション付きのタッチボタン

しきい値をコードに直接書く代わりに、ボードの起動時にパッドの待機時の値を測り、そこからしきい値を計算するほうがずっと確実です。下のスケッチは起動時に50回の測定値を平均し、40%下がったらタッチとみなしてLEDを切り替えます。値が待機時の値の80%を超えて戻ったら、パッドから指が離れたとみなします。このように2つのしきい値を使うことをヒステリシスといいます。値がちょうど境目で揺れたときに、何度も反応するのを防ぎます。ボタンの機械的な側面が気になる場合は、「Arduinoに押しボタンをつなぐ方法」の記事を参照してください。

C++ (Arduino IDE)
1// Otomatik kalibrasyonlu dokunmatik buton / self-calibrating touch button
2// GPIO 4 (T0) dokunma pedi, GPIO 2 kart üstü LED
3// GPIO 4 (T0) touch pad, GPIO 2 onboard LED
4
5const uint8_t DOKUNMA_PIN = T0;   // GPIO 4
6const uint8_t LED_PIN = 2;
7
8uint32_t bosDeger = 0;            // dokunulmamış değer / untouched value
9uint32_t basEsik, birakEsik;      // histerezisli eşikler / thresholds with hysteresis
10bool basili = false;
11bool ledDurum = false;
12
13uint32_t ortalamaOku(uint8_t pin, int adet) {
14  uint32_t toplam = 0;
15  for (int i = 0; i < adet; i++) {
16    toplam += touchRead(pin);
17    delay(2);
18  }
19  return toplam / adet;
20}
21
22void setup() {
23  Serial.begin(115200);
24  pinMode(LED_PIN, OUTPUT);
25  delay(300);                                  // açılışta pede dokunma / do not touch at boot
26  bosDeger = ortalamaOku(DOKUNMA_PIN, 50);
27  basEsik = bosDeger * 60 / 100;               // %40 düşüş = dokunma / 40% drop = touch
28  birakEsik = bosDeger * 80 / 100;             // %20 altına dönünce bırakıldı / released
29  Serial.printf("Bos: %u  Bas: %u  Birak: %u\n", bosDeger, basEsik, birakEsik);
30}
31
32void loop() {
33  uint32_t deger = ortalamaOku(DOKUNMA_PIN, 4);
34
35  if (!basili && deger < basEsik) {            // yeni dokunma / new touch
36    basili = true;
37    ledDurum = !ledDurum;
38    digitalWrite(LED_PIN, ledDurum);
39    Serial.println("Dokunuldu / touched");
40  } else if (basili && deger > birakEsik) {    // parmak çekildi / finger lifted
41    basili = false;
42  }
43  delay(20);
44}
コードの部分役割
ortalamaOku()(トルコ語で「平均を読む」)複数の測定値を平均して、ランダムなスパイクをならす
bosDeger(bosはトルコ語で「空」、Degerは「値」)起動時に測る、触れていない状態の値。環境が変わったらボードを再起動するとキャリブレーションが更新される
basEsik = 60%(basは「押す」、esikは「しきい値」)値がこれを下回ると新しいタッチとみなす
birakEsik = 80%(birakは「離す」)値がこれを上回ると指が離れたとみなす
basili変数(トルコ語で「押されている」)指が触れたままのとき、LEDが何度も切り替わるのを防ぐ
起動時のキャリブレーション中はパッドに触れないでください。ボードがケースに入っていて、電源を入れたときに誰かがパッドに触れる可能性がある場合は、待機時の値をEEPROMやPreferencesに保存して起動のたびに確認するか、待機時の値をごくゆっくり追いかける平均(たとえば1秒ごとに1%ずつ更新)を使ってください。

touchAttachInterruptによるタッチ割り込み

touchReadをずっと呼び出す代わりに、タッチ用のハードウェアにバックグラウンドで測定させ、値がしきい値を下回ったら関数を呼び出させることができます。それを行うのがtouchAttachInterrupt(pin, 関数, しきい値)です。無印ESP32では、測定値がしきい値を下回ったときに割り込みが発生し、指がパッドに触れている間は測定サイクルごとに何度も発生します。そのため割り込み関数ではフラグを立てるだけにして、実際の処理はloop()の中で時間をチェックしながら行います。割り込みの一般的なルールは「Arduinoの割り込み」の記事で解説しています。

C++ (Arduino IDE)
1// touchAttachInterrupt ile dokunma kesmesi / touch interrupt
2// GPIO 27 (T7) pedi; eşik touchRead ile ölçülerek seçilmeli
3// GPIO 27 (T7) pad; pick the threshold from your touchRead values
4
5const uint8_t PED = T7;            // GPIO 27
6const uint16_t ESIK = 40;          // ESP32: değer bunun ALTINA inince tetikler / fires below this
7volatile bool dokunuldu = false;
8
9void IRAM_ATTR dokunmaKesmesi() {
10  dokunuldu = true;                // kesmede yalnız bayrak / only set a flag in the ISR
11}
12
13void setup() {
14  Serial.begin(115200);
15  touchAttachInterrupt(PED, dokunmaKesmesi, ESIK);
16}
17
18void loop() {
19  static unsigned long sonDokunma = 0;
20  if (dokunuldu) {
21    dokunuldu = false;
22    // Parmak durdukça kesme tekrar tekrar gelir; 300 ms'de bir say
23    // The ISR repeats while the finger stays; count once per 300 ms
24    if (millis() - sonDokunma > 300) {
25      sonDokunma = millis();
26      Serial.printf("Dokunma! deger: %u\n", touchRead(PED));
27    }
28  }
29}

この例ではしきい値を40にしています。待機時に60前後を示すパッドに合っています。そうでない場合は、先ほどの読み取り用スケッチで得た数値に合わせて変更してください。割り込み関数に付けたIRAM_ATTR属性は、関数を高速なメモリに配置します。ESP32の割り込み関数ではこの指定が推奨されています。割り込みを無効にするにはtouchDetachInterrupt(pin)を呼び出します。無印ESP32では、touchInterruptSetThresholdDirection(false)を呼び出して、値がしきい値を上回ったときに割り込みを発生させることもできます。指が離れた瞬間をとらえるのに便利です。

3枚のパッドで作るタッチスライダー

パッドを3枚並べれば、指の位置がわかります。指が2枚のパッドの間にあると両方の値が下がるので、それぞれのパッドの下がり幅から加重平均で位置を計算します。パッドを単純な四角形ではなく、かみ合うジグザグ形や矢じり形に切ると、どの位置でも指が少なくとも2枚のパッドに触れるため、スライダーの動きがずっと滑らかになります。幅1.5 cmの銅箔テープを1〜2 mmのすき間を空けて3本貼るのが、手始めにちょうどよい方法です。

部品ESP32のピンメモ
パッドA(左)GPIO 13(T4)位置0
パッドB(中央)GPIO 14(T6)位置500
パッドC(右)GPIO 33(T8)位置1000
LEDGPIO 26220 Ωの抵抗を付け、短い足をGNDへ
C++ (Arduino IDE)
1// Üç pedli dokunmatik kaydırıcı ile LED parlaklığı / 3-pad touch slider dims an LED
2// Pedler: GPIO 13 (T4), GPIO 14 (T6), GPIO 33 (T8); LED: GPIO 26
3// Pads: GPIO 13 (T4), GPIO 14 (T6), GPIO 33 (T8); LED: GPIO 26
4
5const uint8_t pedler[3] = {T4, T6, T8};
6const uint8_t LED_PIN = 26;
7uint32_t bos[3];                   // her pedin boştaki değeri / idle value of each pad
8int parlaklik = 0;
9
10uint32_t oku(uint8_t pin) {
11  uint32_t t = 0;
12  for (int i = 0; i < 4; i++) t += touchRead(pin);
13  return t / 4;
14}
15
16void setup() {
17  Serial.begin(115200);
18  delay(300);
19  for (int p = 0; p < 3; p++) {
20    uint32_t t = 0;
21    for (int i = 0; i < 32; i++) t += touchRead(pedler[p]);
22    bos[p] = t / 32;
23  }
24}
25
26void loop() {
27  long fark[3];
28  long toplam = 0;
29  for (int p = 0; p < 3; p++) {
30    fark[p] = (long)bos[p] - (long)oku(pedler[p]);   // dokununca değer düşer / value drops on touch
31    if (fark[p] < 0) fark[p] = 0;
32    toplam += fark[p];
33  }
34
35  // Toplam düşüş boştaki değerin %25'ini geçerse parmak var
36  // A finger is present if the total drop exceeds 25% of an idle value
37  if (toplam > (long)bos[1] / 4) {
38    // Ağırlıklı ortalama: ped A = 0, ped B = 500, ped C = 1000
39    // Weighted average: pad A = 0, pad B = 500, pad C = 1000
40    long konum = (fark[1] * 500L + fark[2] * 1000L) / toplam;
41    parlaklik = map(konum, 0, 1000, 0, 255);
42    analogWrite(LED_PIN, parlaklik);
43    Serial.printf("Konum: %ld  Parlaklik: %d\n", konum, parlaklik);
44  }
45  delay(30);
46}

スケッチは起動時に各パッドの待機時の値を保存し、ループのたびに下がり幅を計算します。下がり幅の合計が十分に大きければ指がスライダーに触れていると判断し、0〜1000の範囲で位置を求めます。その値をmap()で0〜255に変換し、analogWrite()でLEDに送ります。analogWrite()はESP32 Arduinoコアの2.xと3.xのどちらでも動作します。PWMのしくみは「PWMとは?」の記事で確認できます。

タッチでディープスリープから復帰する

電池で動かすプロジェクトでは、ESP32をディープスリープにして、誰かがパッドに触れたときだけ起こすことができます。このモードではコアは停止していますが、タッチの測定回路は低消費電力で動き続けます。touchSleepWakeUpEnable(pin, しきい値)関数は、しきい値の設定とタッチによる復帰の有効化を一度に行います。無印ESP32では複数のパッドを復帰要因にできますが、ESP32-S2とS3で使えるパッドは1つだけです。復帰後は、esp_sleep_get_touchpad_wakeup_status()でどのパッドがボードを起こしたかがわかります。ディープスリープの詳細と電流の値は「ESP32のディープスリープ」の記事で解説しています。

C++ (Arduino IDE)
1// Dokunarak deep sleep'ten uyanma / wake from deep sleep by touch
2// GPIO 27 (T7) pedi / GPIO 27 (T7) pad
3
4#if CONFIG_IDF_TARGET_ESP32
5  #define ESIK 40      // ESP32: değer bunun altına inerse uyanır / wakes below this value
6#else
7  #define ESIK 5000    // ESP32-S2/S3: boştaki değere göre artış / rise above the baseline
8#endif
9
10RTC_DATA_ATTR int uyanmaSayisi = 0;   // uykuda korunur / kept during deep sleep
11
12void setup() {
13  Serial.begin(115200);
14  delay(500);
15  uyanmaSayisi++;
16
17  if (esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_TOUCHPAD) {
18    Serial.printf("Dokunmayla uyandi, ped: %d\n", (int)esp_sleep_get_touchpad_wakeup_status());
19  } else {
20    Serial.println("Ilk acilis ya da baska neden / first boot or other cause");
21  }
22  Serial.printf("Uyanma sayisi: %d\n", uyanmaSayisi);
23
24  // Burada ölçüm yap, veri gönder... / take readings, send data here...
25  delay(2000);
26
27  touchSleepWakeUpEnable(T7, ESIK);   // T7 pedini uyandırma kaynağı yap / enable T7 as wake source
28  Serial.println("Uyuyorum / going to sleep");
29  Serial.flush();
30  esp_deep_sleep_start();
31}
32
33void loop() {
34}

ディープスリープ中はRAMの内容が消えるため、復帰後はsetup()から再び実行されます。復帰回数を保持するために、変数の前にRTC_DATA_ATTRを付けました。このような変数は、スリープ中も保持される小さなRTCメモリに保存されます。スリープ中もタッチの測定が続くため、ディープスリープ中の電流はタイマーで復帰する場合より少し大きくなります。電池の持ちを見積もるときは、この点を考慮してください。コード内の#ifブロックにより、同じプログラムをESP32-S2やS3でも正しいしきい値でコンパイルできます。

MicroPythonでESP32のタッチピンを使う

ESP32にMicroPythonを書き込んでいる場合は、machineモジュールのTouchPadクラスで同じことができます。read()メソッドはArduinoのtouchRead()と同じ値を返し、無印ESP32ではやはりタッチすると下がります。復帰にはesp32.wake_on_touch(True)とパッドのconfig(しきい値)メソッドを使います。

MicroPython
1# ESP32 MicroPython dokunmatik pin / ESP32 MicroPython touch pin
2from machine import Pin, TouchPad
3import time
4
5ped = TouchPad(Pin(4))       # GPIO 4 = T0
6led = Pin(2, Pin.OUT)        # kart üstü LED / onboard LED
7
8bos = sum(ped.read() for _ in range(20)) // 20   # dokunulmamış değer / idle value
9esik = bos * 6 // 10
10basili = False
11
12while True:
13    deger = ped.read()
14    if not basili and deger < esik:
15        basili = True
16        led.value(not led.value())   # her dokunuşta LED'i değiştir / toggle on every touch
17        print("dokunuldu", deger)
18    elif basili and deger > bos * 8 // 10:
19        basili = False
20    time.sleep_ms(30)

Raspberry Pi Picoには静電容量式タッチセンサーが内蔵されていません。PicoやArduino Unoでタッチボタンを使いたい場合は、市販のTTP223モジュールがいちばん簡単です。モジュール自体がタッチを検知し、普通のデジタル信号を出力します。

TTP223タッチセンサーモジュール
タッチピンを内蔵していないボードでは、TTP223モジュールがタッチを検知してデジタル出力を返します。

湿気、水、ノイズの問題

静電容量式の検知は、指だけでなく水にも反応します。パッドに付いた水滴や高い湿度は静電容量を増やすため、値が下がってボタンが勝手に反応することがあります。浴室、キッチン、屋外のプロジェクトでは、パッドを水が付きにくい面の裏側に置き、しきい値を少し低めにして、タッチが少なくとも50〜100 ms続くことを条件にしてください。長いワイヤー、近くのリレーやモーター、品質の悪いUSB電源も値をふらつかせます。下の表に、よくある問題とその対策をまとめました。

問題考えられる原因対策
勝手に反応するしきい値が待機時の値に近すぎるしきい値を待機時の値の60%に下げ、ヒステリシスを追加
値がずっとふらつく長いワイヤーや宙に浮いたワイヤー、ノイズの多い電源ワイヤーを短くし、4〜8回の平均を取り、品質のよいUSBケーブルを使う
パソコンから外したら感度が変わったグラウンドの基準が変わった最終的な構成で、電池やACアダプターをつないでキャリブレーション
湿気や水滴で反応する水が静電容量を増やすパッドをカバーの裏に置き、最低タッチ時間を条件にする
値がまったく変わらないピンがあるタッチ非対応のGPIOを使ったピン表で確認。GPIO 34〜39はタッチ非対応
ボードが起動しないGPIO 12につないだパッドとワイヤーが起動を妨げているパッドをGPIO 4、13、27、32、33のいずれかに移す
長く使うプロジェクトでは、パッドのワイヤーを短くしっかり固定し、パッドの周りに2〜3 mmのすき間を空けてGNDのリングを設け、ボードをケースに入れたあとでしきい値を測り直してください。ケースのふた、ワイヤーの通し方、さらには手の位置でさえ、待機時の値が数ポイント変わります。

ESP32-S3やほかのモデルのタッチピン

ESP32-S2とESP32-S3は第2世代のタッチハードウェアを使っていて、無印ESP32とは3つの重要な点で異なります。1つ目は、チャンネルがGPIO 1〜14にあり、14個あることです。T1がGPIO 1、T14がGPIO 14です。2つ目は、値がずっと大きく、タッチすると上がることです。待機時に20,000程度のパッドが、タッチすると40,000を超えることもあります。3つ目は、touchAttachInterruptとtouchSleepWakeUpEnableのしきい値が絶対値ではなく、待機時の値からの増加量であることです。S3では、touchInterruptGetLastStatus(pin)を使って、パッドがまだ押されているかどうかも確認できます。ESP32-C3とESP32-C6には、タッチセンサーがまったくありません。複数のモデル向けにコードを書く場合は、復帰の例のようにCONFIG_IDF_TARGET_ESP32で切り分けてください。

タッチピンを使ったプロジェクトのアイデア

  • デスクライト:木製のカバーの裏に銅箔テープを貼った見えないオン/オフスイッチ。長押しで明るさを調整します。
  • スライダー式の調光器:3枚のパッドのスライダーで、WS2812B LEDテープの明るさと色を変えます。
  • 電池式のドアチャイムやメモ装置:ESP32がディープスリープで待機し、パッドに触れると起きてWi-Fiで通知を送ります。
  • フルーツピアノ:バナナやリンゴにワイヤーをつなぎ、果物ごとに違う音を鳴らすおもちゃです。音はブザーで出せます。
  • 隠し暗証番号パネル:箱の中に隠した4枚のパッドに正しい順番で触れると開くロックです。

ESP32のタッチピンを使えば、数センチのアルミホイルと数行のコードでプロジェクトにタッチ操作を加えられます。BlueGraysアプリには、ESP32でLEDを点滅、ボタンでのLED制御、PWMによるLEDの明るさ調整、ディープスリープなどのプロジェクトがあり、それぞれ回路図とコードをステップごとに確認できます。ボタンをこのガイドのタッチパッドに置き換えて、自分だけのバージョンを作ってみてください。

よくある質問

ESP32にはタッチピンがいくつありますか?

無印ESP32には10個の静電容量式タッチチャンネルがあります。T0〜T9で、GPIO 4、0、2、15、13、12、14、27、33、32です。ESP32-S2とESP32-S3にはGPIO 1〜14に14個のチャンネルがあります。ESP32-C3とC6にはタッチセンサーがありません。

ESP32のtouchReadの値はどのくらいになりますか?

無印ESP32で短いワイヤーを使った場合、待機時はたいてい40〜80、タッチ時は10〜25です。正確な数値はワイヤー、パッドの大きさ、周囲の環境によって変わります。自分の環境で測定し、待機時の値の約60%をしきい値にするのがよい出発点です。

ESP32のタッチのしきい値はどう決めればいいですか?

まずtouchReadでパッドの待機時とタッチ時の値を測ります。無印ESP32では、しきい値をその間、通常は待機時の値の60%に設定します。いちばん確実なのは、起動時に待機時の値を測り、コードでしきい値を計算してヒステリシスを加える方法です。

ESP32のタッチピンでディープスリープから復帰できますか?

はい。touchSleepWakeUpEnable(pin, しきい値)でパッドを復帰要因にしてから、esp_deep_sleep_start()でスリープさせます。パッドに触れるとボードが再起動します。無印ESP32は複数のパッド、ESP32-S2とS3は1つのパッドに対応しています。

ESP32のタッチピンが勝手に反応するのはなぜですか?

多くの場合、しきい値が待機時の値に近すぎるか、パッドのワイヤーが長いか、湿気があります。しきい値を下げ、複数の測定値を平均し、ヒステリシスを加え、ワイヤーを短くしてください。最終的に使う電源でキャリブレーションすることも大切です。

ESP32-S3ではタッチするとtouchReadの値が増えるのはなぜですか?

ESP32-S2とS3は第2世代のタッチハードウェアを使っていて、測定値が静電容量とともに増えます。そのためS3ではタッチすると値が上がり、数万のレベルになります。割り込みと復帰のしきい値も、絶対値ではなく待機時の値からの増加量です。

全プロジェクトを見る
ESP32でLEDを点滅
#103初級

ESP32でLEDを点滅

ESP32のGPIO出力の基本を学びます。デジタルピンからLEDを点灯・消灯させて、点滅させます。Arduino UNOの定番のLED点滅プロジェクトのESP32版です。Arduino環境で使う基本的な点滅コマンドは同じですが、ESP32のピン配置と3.3 VのGPIO電圧レベルはArduino UNOとは異なります。

4.7(37)
100
ESP32でボタンによるLED制御(トグル)
#105初級

ESP32でボタンによるLED制御(トグル)

ボタンを押すたびにLEDの状態が切り替わり、点灯中なら消灯し、消灯中なら点灯します。基本的なトグル動作です。チャタリング対策でボタンの機械的なノイズを除去し、1回の操作で1回だけ切り替わるようにします。

4.6(39)
58
ESP32の内蔵LEDを点滅
#106初級

ESP32の内蔵LEDを点滅

ESP32 DevKit V1に内蔵された青色LEDを点滅させます。外付け部品は不要です!ESP32を購入したら、最初に試すプロジェクトです。GPIO 2が内蔵LEDにつながっています。

4.8(29)
53
ESP32のPWMでLEDをフェード
#110初級

ESP32のPWMでLEDをフェード

LEDの明るさを0から最大へ、最大から0へと滑らかに変化させます。Arduinoと同じようにanalogWrite()でPWMを制御します。ESP32 Arduino Core 3.0+では同じ構文がそのまま使えます。ピンの定義とpinMode、analogWriteだけで実現できます。

4.8(36)
55
ESP32でRGB LEDを制御
#111初級

ESP32でRGB LEDを制御

3個の個別のLEDの代わりに、1個のRGB LEDで無数の色を作ります。Arduinoと同じようにanalogWrite()でR/G/Bの値を調整し、虹色に変化させます。赤と緑を混ぜると黄色になるなど、色の仕組みを実際に確認できます。

4.6(29)
51
ESP32のディープスリープで節電(OLED + RTC RAMカウンター)
#135上級
プレミアム

ESP32のディープスリープで節電(OLED + RTC RAMカウンター)

ESP32のディープスリープモードは、CPUとほとんどの周辺機器を停止し、消費電流を約10 µAまで抑えます。電池で動くIoT機器に欠かせない機能です。このプロジェクトでは、タイマー(15秒)、外部ピン(EXT0、ボタンはGPIO 33)、タッチ(T0/GPIO 4)の3種類の復帰方法を使います。RTC_DATA_ATTRを付けた変数はディープスリープ中も保持され、起動回数、タイマーによる復帰回数、ボタンによる復帰回数を継続して記録できます。復帰するたびにSSD1306 OLEDディスプレイに復帰理由と回数を表示します。

4.3(10)
16
ESP32の調色ライト(可変抵抗3個 + RGB LED + OLED)
#138上級
プレミアム

ESP32の調色ライト(可変抵抗3個 + RGB LED + OLED)

ESP32と3個の可変抵抗で、好みの色を作れるスマート調色ライトです。赤・緑・青の可変抵抗を回すと、カソードコモンのRGB LEDの色がリアルタイムに変わります。SSD1306 OLEDディスプレイには、各色の0~255の値、色の強さを示すバー、#FF8040などのWeb用HEXカラーコードをリアルタイムで表示します。小さなプロ仕様のカラースタジオとして、RGBの色の仕組み、ADCによるアナログ値の読み取り、PWMによる明るさの制御、I2Cディスプレイの表示設計を1つのプロジェクトで学べます。

4.7(6)
10
ESP32スマート照明(PIR + LDR + リレー + OLED)
#141上級
プレミアム

ESP32スマート照明(PIR + LDR + リレー + OLED)

ESP32で廊下やトイレ、食品庫の照明をスマート化します!PIRモーションセンサー、LDR光センサー、リレーモジュールを使い、「暗い場所で動きを検知すると点灯する」定番の仕組みを作ります。周囲が明るければ動きを検知しても点灯しないため、日中の無駄な電力消費を抑えられます。照明は30秒間点灯し、動きが続くとタイマーがリセットされて点灯時間が延びます。SSD1306 OLEDには大きな文字で状態(ON / DAYTIME / WAITING)とカウントダウンを表示します。

4.3(6)
11