🎵

M5StickC Plus2でブザーとサーボを併用する際の注意事項

2025/01/15に公開

結論

M5StickC Plus2でブザーとサーボを併用する際は、PWMのチャンネルが競合するため、調整が必要。

はじめに

こんにちは!
ユカイ工学エンジニアの宮﨑です。

普段はサーバ寄りの開発をしているのですが、たまにプロトタイプ開発でM5stackシリーズを使ったりします。
今回は、開発で詰まった点があったので、共有します。

環境

  • デバイス
    • M5StickC Plus2
  • サーボ
    • K-POWER MM0090
  • ライブラリ
    • m5stack/M5StickCPlus2@^1.0.2
    • madhephaestus/ESP32Servo@^3.0.5

配線・ピンアサイン

GROVEポートのG33を信号線として利用しています。
電源、GNDもGROVEポートのものを利用しています。
実際はGROVEコネクター付コードを付けて、サーボと接続しています。

症状

  1. ブザーを鳴らすとブザーに合わせて、サーボが動いてしまう。
  2. ブザーを鳴らした後は、サーボが動かなくなる。
  3. 再起動するとサーボは動くようになる。

アプローチ

ハード起因?

色々あって、ハードウェアを取ったりつけたりしたので、線がくっついたのか?と思ったのですが、問題なさそうでした。

ソフト起因?

疑ったのはPWMチャンネルの競合でした。
そこで、それぞれのライブラリの使用PWMチャンネルについて調べてみました。

ブザーに使用されているPWMチャンネルはデフォルトが0

Tone.cpp
static uint8_t _channel = 0;

ソース

ESP32Servoで使用しているPWMチャンネルもデフォルトが0

ESP32PWM.h
int ESP32PWM::pwmChannel = 0

ソース

よって、2つのライブラリでPWMのチャンネルが競合してしまい、動作不良を起こしていたようです!

なお、toneの方はchannelが固定されてそうなので、変更できそうにありませんでした。

https://github.com/espressif/arduino-esp32/blob/1f038677eb2eaf5e9ca6b6074486803c15468bed/cores/esp32/Tone.cpp#L123-L135

また、一方のPWMServoも関数内でインクリメントされていたので、変更できそうにありませんでした。

対応

ledc関数を使って、自作のtone関数を作成しました。

void customTone(int frequency, int duration) {
  int channel = 15;                  // PWM チャンネル(0~15が使用可能)
  int pin = GPIO_NUM_2;              // スピーカーを接続するピン
  ledcSetup(channel, frequency, 8);  // チャンネル、周波数、解像度
  ledcAttachPin(pin, channel);       // ピンにチャンネルを割り当て
  ledcWriteTone(channel, frequency); // トーン開始
  delay(duration);                   // 指定した期間トーンを鳴らし続ける
  ledcWrite(channel, 0);             // トーンを停止
}

これで無事、ブザーとサーボを併用することができるようになりました。

おわりに

エッジ系だとハードのことも気にしながらプログラミングしなければならないので大変ですね。
その分、動いた時の達成感は大きいです。

ユカイ工学テックブログ

Discussion