M5Stack Core2のタッチパネル研究

概要

タッチパネルまわりのフィードバックや、動作確認をしてみました。ボタンは何らかのフィードバックがないと、やっぱり使いにくいと思います。

公式スケッチ例

  • https://github.com/m5stack/M5Core2/blob/master/examples/Basics/touch/touch.ino

上記がスケッチ例になります。ちょっと微妙なので、これを改造してみました。

スケッチ

#include <M5Core2.h>

void setup() {
  M5.begin(true, true, true, true);   // Core2初期化

  M5.Lcd.fillScreen(WHITE);           // 画面初期化
  M5.Lcd.setTextColor(BLACK, WHITE);
  M5.Lcd.setTextSize(2);
  M5.Lcd.setCursor(10, 10);
  M5.Lcd.printf("DISPLAY Test!");
}

void loop() {
  static bool touch = false;
  static uint16_t color = BLACK;      // 描画色
  static uint16_t colorOld = BLACK;   // ボタンフィードバック用
  TouchPoint_t pos = M5.Touch.getPressPoint();
  if (pos.x != -1) {
    // 描画
    M5.Lcd.fillCircle(pos.x, pos.y, 8, color);

    if (!touch) {
      // タッチ中は緑色LEDを消す
      touch = true;
      M5.Axp.SetLed(false);
    }
    if (pos.y > 240) {
      // Yが240以上はボタンのエリア
      uint16_t colorNew;
      if (pos.x < 109) {
        colorNew = RED;
        M5.Lcd.setTextColor(colorNew, WHITE);
      } else if (pos.x > 218) {
        colorNew = BLUE;
        M5.Lcd.setTextColor(colorNew, WHITE);
      } else if (pos.x >= 109 && pos.x <= 218) {
        colorNew = GREEN;
        M5.Lcd.setTextColor(colorNew, WHITE);
      }

      if (colorNew != colorOld) {
        // ボタンを押した場合には75ミリ秒振動モーターを動かす
        color = colorNew;
        colorOld = color;
        M5.Axp.SetLDOEnable(3, true);
        delay(75);
        M5.Axp.SetLDOEnable(3, false);
      }
    }

    // 画面にタッチした座標を表示
    M5.Lcd.setCursor(10, 10);
    M5.Lcd.printf("DISPLAY Test!");
    M5.Lcd.setCursor(0, 26);
    M5.Lcd.printf(" X:%3d\n Y:%3d", pos.x, pos.y);
  } else {
    if (touch) {
      // タッチが離れたら緑色LEDを点ける
      touch = false;
      colorOld = BLACK;
      M5.Axp.SetLed(true);
    }
  }

  delay(1);
}

結構短いスケッチですが、画面にタッチした座標とボタンの処理が入っています。

上記みたいに描画もしているので、タッチパネルの精度もわかると思います。

タッチのフィードバック(色)

画面に触れているかどうかは、手前にある緑色LEDで行っています。タッチしたら消して、離したら点けていますが、反対でもいいと思います。このへんは好みですね。他の用途に緑色LEDを利用する場合には利用できないと思いますが、用途がない場合には、とりあえずフィードバックに使ってもいいと思います。

M5.Axp.SetLed(true);   // 点ける
M5.Axp.SetLed(false);  // 消す

制御はAxpクラスにあります。

ボタンのフィードバック(触感)

こちらは触感フィードバックとして、振動モーターを動かしています。

        M5.Axp.SetLDOEnable(3, true);
        delay(75);
        M5.Axp.SetLDOEnable(3, false);

こちらもAxpクラスにあるLCO出力でON、OFFします。本当は電圧調整もできますがON、OFFだけで十分だと思います。50ミリ秒だとちょっと短い感じがするのと、オモリがある位置によってちょっと物足りない振動の場合がありました。継続時間は好みがでると思います。

また、delay()で止めているので、他の処理ができなくなるので本当はあまり良くありません。Beepなどのようにupdate()の中で処理したほうがいいかもしれませんが、そうすると継続時間がばらつきます。タスク化してもAxpクラスなのでI2Cをマルチタスクから同時に呼び出すとハングアップするので、排他処理が必要になります。

なかなか面倒なので、処理的に問題なければdelay()が一番楽だと思います。

音声フィードバック

M5Stack Core2はスピーカーを内蔵しているので、音を鳴らすことも可能です。ただし圧電ブザーなどではなく、I2Sでデータを転送する必要があるのでブザー音を鳴らすのでも結構手間が必要です。

音声ファイルを内蔵するか、自分でsine()関数などで波形データを作る必要があります。今回はちょっとパスしていますがATOM Echoのときに研究したので、今後検証していきたいと思います。

タッチの精度

タッチペンとかを使ってみるとわかりやすいのですが、同じ場所で触っているつもりでも座標はぶれます。指の太さがあるので一定のエリアで接地しますが、接地しているエリアの中心ではなく、そのなかでランダムに場所がずれるような感じでした。

追従は悪くないですので、文字入力とかには十分使えると思います。

まとめ

ボタン周りの処理はちょっと面倒ですね。インターフェイス的にはボタンの上、画面の一番下にボタンの機能を書いたほうがわかりやすいですが、だったらボタンエリアいらないんじゃないってことになりかねない(笑)

コメント