方言を話すおしゃべり猫型ロボット『ミーア』をリリースしました(こちらをクリック)

【モーター】サーボモーター vs DCモーター:音比較

dc vs servo
この記事は約10分で読めます。

現在、方言を話すおしゃべり猫型ロボット「ミーア」を開発中。

https://mia-cat.com

今までは、SG90サーボモーターで、ミーアちゃんの口を動かしていたが、結構うるさくて、喋る音声に干渉してしまうのではという懸念が生じたので、DCモーターも作成して比較することに

DCモーターの要件を確認

以前に、勉強用としてFreenoveのESP-WROVER用スターターキットを購入しており、DCモーターに関してはサンプルコード付きで、必要な部品とともに記載されていたので、そちらを参照して作成していく。

https://rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=kazu098-22&language=ja_JP&o=9&p=8&l=as4&m=amazon&f=ifr&ref=as_ss_li_til&asins=B09BC5B4H6&linkId=b1c0a836499da43bf0a1cbf8010ceb14

L293Dモータードライバーで検証

とりあえず、下記のサンプルコードを貼り付けて、配線もサンプルに記載の通りに実施して検証

C++
/**********************************************************************
  Filename    : Control_Motor_by_L293D
  Description : Use PWM to control the direction and speed of the motor.
  Auther      : www.freenove.com
  Modification: 2020/07/11
**********************************************************************/
int in1Pin = 12;      // Define L293D channel 1 pin
int in2Pin = 14;      // Define L293D channel 2 pin
int enable1Pin = 13;  // Define L293D enable 1 pin
int channel = 0;

boolean rotationDir;  // Define a variable to save the motor's rotation direction
int rotationSpeed;    // Define a variable to save the motor rotation speed

void setup() {
  // Initialize the pin into an output mode:
  pinMode(in1Pin, OUTPUT);
  pinMode(in2Pin, OUTPUT);
  pinMode(enable1Pin, OUTPUT);
  
  ledcSetup(channel,1000,11);         //Set PWM to 11 bits, range is 0-2047
  ledcAttachPin(enable1Pin,channel);
}

void loop() {
  int potenVal = analogRead(A0);      // Convert the voltage of rotary potentiometer into digital
  //Compare the number with value 2048, 
  //if more than 2048, clockwise rotates, otherwise, counter clockwise rotates
  rotationSpeed = potenVal - 2048;
  if (potenVal > 2048)
    rotationDir = true;
  else
    rotationDir = false;
  // Calculate the motor speed
  rotationSpeed = abs(potenVal - 2048);
  //Control the steering and speed of the motor
  driveMotor(rotationDir, constrain(rotationSpeed,0,2048));
}

void driveMotor(boolean dir, int spd) {
  // Control motor rotation direction
  if (dir) {
    digitalWrite(in1Pin, HIGH);
    digitalWrite(in2Pin, LOW);
  }
  else {
    digitalWrite(in1Pin, LOW);
    digitalWrite(in2Pin, HIGH);
  }
  // Control motor rotation speed
  ledcWrite(channel, spd);
}

これだけだと、回転数を揃えているわけではないのと、実際にギアをつけてラックを動かしてみた時での検証ではないので、なんとも言えない。

というわけで、ギアの作成に取り掛かる。

https://www.hackster.io/Arnov_Sharma_makes/l293d-with-esp32-wemos-lolin-d32-v2-hacked-edition-ea2086

DCモーターに接続するギアを3Dプリンターで作成

サーボモーターに関しては、以前にサーボ本体から突き出たギヤに装着するギアを作成していたので、同様にして、dcモーターのシャフトに接続するギアを作成していく。

おそらく、先人の方々がすでに3dプリンターで作成していて、STLファイルもアップロードしているだろうと思うので、リサーチ

こちらの記事に、シャフトに取り付けるギアのSTLファイルがあった。

ただ、シャフトの直径が2.3mmに対してのギアであり、今手元にあるギアは1.5mm程度なので大きすぎるかなと思うが、FDM方式で印刷すると0.3mm程度は膨張するので、一旦このデータで試すことに。

https://www.instructables.com/3d-Printed-Gearbox-for-Small-Dc-Motors/

AnkerMakeにSTLデータ放り込んで、スライスしてプリント

サイズが全然合わなかったので、自作することに。

dcモーターは、おそらく、マブチモーターのFA-130 で、シャフトの直径が20mmなので、FDMで印刷した時に0.3mmくらい膨張することを考慮して、23mmの穴で作成した。

しかし、実際にankermakeの標準速度で印刷すると、23mmの穴の中に若干のフィラメントのたまりが見られたせいでシャフトが入らず。今回はシャフトにハマるギアをプロトで作成してサーボモーターと比較するだけなので、少し穴を大きくして調整したところ25mmの穴でちょうどハマる感じになった。

実際にdcモーターにギアを取り付けた図がこちら

サーボモーターと異なり、シャフトに長さがあるので、その部分も含めてギアを取り付けると、ギアと垂直方向にもある程度固定される点は良い。

サーボモーターで下記のように直接ギアを取り付けた場合、ギアの軸方向の固定がないので、別途固定しないと、ラック・ピニオン機構で直線運動を試みた時に、ギアがサーボモーターからギアの軸方向に外れてしまうことが今までにあった。

上下に3回転するコード作成

最終的には、ネコちゃんが喋っている間だけ上下に下唇が移動するように、dcモーターを上下に回転させる必要があるが、仮置きで上下に3回転するコードを作成。

サーボモーターと異なり、回転角度を制御できないので、回転する時間を調整する必要がある(下記コードではとりあえず0.5秒としている)。

回転速度は、startMortor()関数内のanalogWrite関数の第2引数(モーターのPWM信号のデューティサイクル)で0-255の間で設定。

今回は、回転速度は固定で良いので、第2引数に直書きで数字を入れ込む

C++
#include <Arduino.h>

#define MOTOR_PIN1 12  
#define MOTOR_PIN2 14  
#define SPEED_PIN 13   
#define BUTTON_PIN 15  

bool isMoving = false;
bool lastButtonState = LOW;
int moveCount = 0;  
bool direction = true;  
unsigned long lastUpdate;
unsigned long moveDuration = 500;

void stopMotor() {
  isMoving = false;
  digitalWrite(MOTOR_PIN1, LOW);
  digitalWrite(MOTOR_PIN2, LOW);
  analogWrite(SPEED_PIN, 0);
}

void startMotor() {
  isMoving = true;
  if (direction) {
    digitalWrite(MOTOR_PIN1, HIGH);
    digitalWrite(MOTOR_PIN2, LOW);
  } else {
    digitalWrite(MOTOR_PIN1, LOW);
    digitalWrite(MOTOR_PIN2, HIGH);
  }
  analogWrite(SPEED_PIN, 255);
  lastUpdate = millis();
}

void setup() {
  Serial.begin(115200);
  pinMode(MOTOR_PIN1, OUTPUT);
  pinMode(MOTOR_PIN2, OUTPUT);
  pinMode(SPEED_PIN, OUTPUT);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  stopMotor();
}

void loop() {
  bool currentButtonState = digitalRead(BUTTON_PIN);

  if (lastButtonState == HIGH && currentButtonState == LOW) {
    if (!isMoving) {
      startMotor();
    }
    delay(50);  
  }

  if (isMoving) {
    if (millis() - lastUpdate > moveDuration) {
      direction = !direction;
      moveCount++;
      if (moveCount >= 6) {
        stopMotor();
        moveCount = 0;
      } else {
        startMotor();
      }
    }
  }

  lastButtonState = currentButtonState;
}

C字クランプ作成

髪留めゴムを上下運動中に保持するために、ラックのギアと接する部分と対側にC字クランプを作成。

正面から見た時に、保持している部分が見えてしまって口として違和感がないかが懸念だったが、実際に作成してみるとほとんど気にならない。プラスして、幅2mm程度のC字クランプでもゴムの保持力が想像以上に強かったので、何回も上下に移動させても外れなさそうな点が良かった。

ラックピニオン単体では動くが、ゴムをつけると動かない

duty cycle 168に設定したところ、ラックアンドピニオン機構単体では十分動いた。

下唇に相当する、髪留めゴムをつけただけでも問題なく動いた。

しかし、唇の片方を穴に通して奥行方向に固定すると、モーターの駆動力が足りずに動かなくなる。。ラック•ピニオンをグリス塗って摩擦を減らすは一つだけど、他どうしよう?

サーボは回転角度をまだ小さく設定しているが、設定した角度範囲では、紐をつけた状態でもピニオン機構に追随して動いているので、サーボの方が駆動力が大きいのか?

音に関しては、まだサーボの方でゴムつけて動かせていないので、正確な比較検証はできていないが、最大スピード(duty cycle 255)で動かしたとしてもdcモーターの方が、サーボより静音な感じ。なので、できれば、DCモーターに切り替えたいところ。

コメント

タイトルとURLをコピーしました