ESP32でスピーカーとサーボモーターを交互に動かす

以前ESP32を利用した際、スピーカーとサーボモーターを一つのプログラムで動かすのに手こずったので記事にしておきます。

環境

ESP32-DevKitC-32D(WiFi使用, Bluetooth不使用)

AE-MICAMP(マイクアンプ。入力機器として使用)

SG92R(サーボモーター)

PT08-Z185R(圧電スピーカー)

プログラム

サーボモーターとスピーカー以外についての記述は一部省略しています。

#include <WiFi.h>
#include <time.h>
#include "esp_system.h"

#define BEAT 500
#define BUZZER_PIN 17
#define SERVO_PIN 16
#define PWM_BITWIDTH 10
int MIKE_PIN = A0;

//音の定義(省略)

void playmusic(){
   ledcWriteTone(1,C4);
   vTaskDelay(BEAT);
   ledcWriteTone(1,D4);
   vTaskDelay(BEAT);
   //省略
   ledcWrite(1,0); //stop
}

int min2 = 26;  // (26/1024)*20ms ≒ 0.5 ms  (-90°)
int max2 = 75; // (123/1024)*20ms ≒ 2.4 ms (+90°)
int n = min2;
int sensorValue = 0;

int deg2pw(int deg){
   double ms = ((double) deg - 90.0) * 0.95 / 90.0 + 1.45;
   return (int) (ms / 20.0 * pow(2, PWM_BITWIDTH));
}

void setup() {
 Serial.begin(9600);
 delay(100);
 
 //servo
 ledcSetup(0, 50, 10);  // 0ch 50 Hz 10bit resolution
 ledcAttachPin(SERVO_PIN, 0); // 16pin, 0ch
 
 //buzzer
 ledcAttachPin(BUZZER_PIN,1); //1ch
 ledcWrite(0, max2);
}

void loop() {
 sensorValue = analogRead(MIKE_PIN) - 1931;//マイク感度調整
 
 //corは閾値
 if(abs(sensorValue) > cor){
   ledcWrite(0, max2);
   delay(500);

   for(int i = max2; i > min2; i--){
     ledcWrite(0, i);
     delay(10);
   }
   
   ledcSetup(1,12000, 8);
   playmusic();

   ledcSetup(0, 50, 10);
 }
 delay(1);
}

動作と方法

void setup() {
 Serial.begin(9600);
 delay(100);
 
 //servo
 ledcSetup(0, 50, 10);  // 0ch 50 Hz 10bit resolution
 ledcAttachPin(SERVO_PIN, 0); // 16pin, 0ch
 
 //buzzer
 ledcAttachPin(BUZZER_PIN,1); //1ch
 ledcWrite(0, max2);
}

まず、setupでサーボとスピーカーのセットアップを行ないます。サーボは0ch、スピーカーは1chです。

void loop() {
 sensorValue = analogRead(MIKE_PIN) - 1931;//マイク感度調整
 
 //corは閾値
 if(abs(sensorValue) > cor){
   ledcWrite(0, max2);
   delay(500);

   for(int i = max2; i > min2; i--){
     ledcWrite(0, i);
     delay(10);
   }
   
   ledcSetup(1,12000, 8);
   playmusic();

   ledcSetup(0, 50, 10);
 }
 delay(1);
}

閾値を超えると、まずサーボをmax2の位置にしてから徐々にmin2まで動かします。次に、スピーカーをplaymusic()で定義した音で鳴らします。

このサーボ→スピーカー、スピーカー→サーボに切り替えるタイミングで、改めてledcSetupを行なっています。理由は分かりませんが、これによって出力を切り替えることが出来ました(これを入れないと、スピーカーまたはサーボがそのままledcWriteで動作する)。

最後に

今回は交互に動作させるということで書きましたが、これは同時に動作させる事の妥協案であるという裏話があります。

現在実験ができる機材を持ち合わせていないため、これについては今後の課題としておきます。