前に戻る

※ 最低限のメモのようなもので、資料としてちゃんと整えておりません。あくまで参考までに。。

GPTに「M5stickCPlus2でQYF-740を使いたい」とプロンプトを投げた程度です。

QYF-740 は「5V駆動の小型バイブレーションモータ+ドライバ(MOSFET)」の3ピンモジュールなので、M5StickC Plus2からはGPIO 1本だけで直接ON/OFF・PWM制御できます。外付けトランジスタをもう1段足す必要は基本ありません。


1. 前提スペック(ざっくり)

QYF-740 の典型仕様はこんな感じです:

  • 動作電圧:3.0–5.3 V(定格 5 V)
  • 定格電流:最大 60 mA
  • 起動電流:最大 90 mA
  • ピン:
    • VCC … 電源+(3.3–5 V)
    • GND … GND
    • IN / CTRL / S … 制御入力(HIGHでON、LOWでOFF、PWMで強さ制御)

M5StickC Plus2 の外部ピン側には 5V 出力と GPIO が生えています:

  • 5V … USB給電時は 5 V 出力
  • GND … 共通グランド
  • GPIO … G26 / G32 / G33 あたりが使いやすい

2. 配線(1個だけ動かす最小構成)

M5StickC Plus2 ⇔ QYF-740

  • QYF-740 VCC → M5StickC Plus2 の 5V
  • QYF-740 GND → M5StickC Plus2 の GND
  • QYF-740 IN → M5StickC Plus2 の GPIO26(例)

※GPIOは 26 でなく 32/33 でもOK(PWM出せるピンなら)。
※USB給電前提なら 5V 1個・2個程度のモータは余裕ですが、たくさんぶら下げると電流が怪しくなります。

ノイズ対策(やっておいた方がいい)

  • QYF-740 の VCC–GND 間に 100µF程度の電解コンデンサ + 0.1µF セラミック を近くに入れておくと、電源リセット・画面チラつきがだいぶ減ります。

3. M5StickC Plus2 用サンプルコード(Arduino)

3-1. ON/OFF だけの超シンプル版

#include <M5StickCPlus2.h>

const int MOTOR_PIN = 26;  // QYF-740 の IN に接続

void setup() {
  auto cfg = M5.config();
  M5.begin(cfg);

  pinMode(MOTOR_PIN, OUTPUT);
}

void loop() {
  // 1秒振動
  digitalWrite(MOTOR_PIN, HIGH);
  delay(1000);

  // 1秒停止
  digitalWrite(MOTOR_PIN, LOW);
  delay(1000);
}

3-2. PWM で「強さフェード」する例(LEDC)

ESP32なので、analogWrite() ではなく LEDC をちゃんと使う版です。

#include <M5StickCPlus2.h>

const int MOTOR_PIN = 26;   // QYF-740 IN
const int PWM_FREQ  = 1000; // 1kHz くらいでOK
const int PWM_RES   = 8;    // 0-255 の 8bit

void setup() {
  auto cfg = M5.config();
  M5.begin(cfg);

  // ESP32 3.x 系の PWM 初期化
  ledcAttach(MOTOR_PIN, PWM_FREQ, PWM_RES);
}

void loop() {
  // 弱 → 強へフェード
  for (int duty = 0; duty <= 255; duty += 5) {
    ledcWrite(MOTOR_PIN, duty); // ピン番号を指定
    delay(30);
  }

  // 強 → 弱へフェード
  for (int duty = 255; duty >= 0; duty -= 5) {
    ledcWrite(MOTOR_PIN, duty);
    delay(30);
  }

  delay(500);
}

このコードだと、「心拍っぽい」ゆるいフェード振動が作れるので、ウェアラブルHCI系にはそのまま使えます。


4. ありがちなハマりポイント

ここは若干ハードモードで注意点を並べておきます:

  1. モータを GPIO 直結しない
    QYF-740「モジュール」を使わず、ただのモータ単体を直で GPIO に刺すのはアウト。
    • GPIO は 20 mA 程度まで
    • モータ起動電流は 90 mA クラス
      → 瞬殺まではいかなくても、寿命を無駄に削ります。Arduino Forum
  2. 電圧とロジックレベルの勘違い
    • VCC は 5 V 給電
    • IN は 3.3 V ロジック HIGH で十分
      「5V駆動だから IN も 5V 必須」と思ってレベルシフタを挟む必要は基本なし。
  3. バッテリ駆動時の余裕
    • M5StickC Plus2 の内蔵バッテリ 200mAh。モータをガン振動させると体感でかなり減りが早くなる
    • 長時間 or 複数モータなら、外部 5V バッテリパック+共通GNDを真面目に検討した方がいいです。docs.m5stack.com
  4. 複数QYF-740をぶら下げるなら設計をちゃんとする
    3個以上並べるなら
    • 5Vラインの総電流(起動時 90mA × 個数)
    • 配線の太さ
    • デカップリングコンデンサ
      をちゃんと見ないと、M5がリセット連発したりします。

M5のマイクと連動させてみる

マイクの音量をざっくり取って、その平均振幅を PWM のデューティにマップすれば OK。

とりあえず「小さい音は振動 0、そこそこ以上の音でだんだん強く振動」っていうサンプル書くね。

#include <M5StickCPlus2.h>

const int MOTOR_PIN = 26;    // 振動モータ
const int PWM_FREQ  = 1000;
const int PWM_RES   = 8;

const int LED_PIN   = 19;    // 本体内蔵の赤LED(G19)

// マイクデータ
const size_t MIC_BUF_LEN = 256;
int16_t micBuf[MIC_BUF_LEN];

// 音量→出力マッピング
const float VOLUME_THRESHOLD = 500.0f;   // これ以下は無視
const float VOLUME_MAX       = 4000.0f;  // これ以上は最大として扱う

void setup() {
  auto cfg = M5.config();
  M5.begin(cfg);

  // 振動モータ PWM 設定
  ledcAttach(MOTOR_PIN, PWM_FREQ, PWM_RES);

  // スピーカー無効化 & マイク有効化
  M5.Speaker.end();
  M5.Mic.begin();

  // 内蔵LED設定
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);   // 消灯スタート

  // 画面
  M5.Display.setRotation(1);
  M5.Display.setTextSize(2);
  M5.Display.fillScreen(BLACK);
  M5.Display.setCursor(0, 0);
  M5.Display.println("Mic -> Vib + LED");
}

void loop() {
  M5.update();

  if (!M5.Mic.isEnabled()) {
    ledcWrite(MOTOR_PIN, 0);
    digitalWrite(LED_PIN, LOW);
    return;
  }

  // マイクデータ取得
  if (M5.Mic.record(micBuf, MIC_BUF_LEN, 16000)) {

    long sumAbs = 0;
    for (size_t i = 0; i < MIC_BUF_LEN; ++i) {
      sumAbs += abs(micBuf[i]);
    }
    float avgAmp = (float)sumAbs / MIC_BUF_LEN;

    // 振動デューティ計算
    int duty = 0;

    if (avgAmp > VOLUME_THRESHOLD) {
      float x = avgAmp - VOLUME_THRESHOLD;
      if (x > VOLUME_MAX) x = VOLUME_MAX;
      float norm = x / VOLUME_MAX;  // 0〜1
      duty = (int)(norm * 255);
    } else {
      duty = 0;
    }

    // 振動モータ
    ledcWrite(MOTOR_PIN, duty);

    // ★ LED:音が一定以上なら点灯、無音なら消灯
    if (duty == 0) {
      digitalWrite(LED_PIN, LOW);   // 消灯
    } else {
      digitalWrite(LED_PIN, HIGH);  // 点灯
    }

    // デバッグ表示
    M5.Display.fillRect(0, 20, 240, 20, BLACK);
    M5.Display.setCursor(0, 20);
    M5.Display.print("amp:");
    M5.Display.print((int)avgAmp);
    M5.Display.print(" duty:");
    M5.Display.print(duty);
  }
}


調整ポイント

  • VOLUME_THRESHOLD
    • 小さくすると「小さな音でもすぐ震える」
    • 大きくすると「結構うるさくないと動かない」
  • VOLUME_MAX
    • ここを変えると「どのくらいの音で最大振動になるか」が変わる

まずはこのまま動かしてみて、
画面に出てる amp:(平均振幅)を見ながら VOLUME_THRESHOLD を自分の環境向けに合わせる感じで。

もし M5.Mic 周りでコンパイルエラー出たら、そのエラーメッセージ丸ごと貼ってくれれば、そこの修正もやる。

完成

近くで声を出したりすればリアルタイムに振動に変換してくれます。

あとは髪留めなどに装着すれば、髪の毛で音を感じる新しいユーザインタフェース「Ontenna」のプロトタイプですね

https://ontenna.jp/