Arduinoでサーボモーターを複数同時に動かす、メカを雑に作るならタミヤのユニバーサルアーム&ユニバーサルプレート【動画解説】

電動のつまようじディスペンサーを買ったよ。
手をかざすとパカッとふたが開いて、両手でつまようじを差し出してくれる。
この愉快な動きを、ずっと見ていたい気持ちになるね。
今日は、ずっと見ていられるようにするよ。

動画の技術解説、9本目です。

www.youtube.com

www.nicovideo.jp

今回のトピックはこんな感じ。

爪楊枝ディスペンサーについて

動画中に登場する爪楊枝ディスペンサーはこれです。

早く受け取りたかったのでAmazonで買いましたが、Aliexpressで買った方が安いです。(値段は執筆時。以下も同様)


Smart Sensor Toothpick Dispenser,Automatic Sensor Toothpicks DispenserTooth Pick Container Organizador Kitchen Accessories

ニコニコ動画の方で「障碍のある人用かな?」というコメントがありましたが、というよりも、コロナの時期に非接触で爪楊枝を取りだすための機器として大量生産されたっぽいです。

動きがかわいいので気になった人はぜひ買ってみてください。

注意点としては、付属する中国製の爪楊枝は少し細いため、日本の爪楊枝だと差し出された瞬間にポロッと落ちてしまうらしいです。試してないけどAmazonのレビューに書いてありました。
その場合、手のパーツの樹脂部品の溝を少し削って広げてやるとうまくホールドできるのではと思います。

使用部品の紹介

タミヤの棒、タミヤの板

アームに使っている板と棒ですが、正式名称をユニバーサルアーム、ユニバーサルプレートといいます。

動画を見ていただくとわかると思いますが、構造やリンク機構がサクサク作れてかなり便利です。メカをサクッと作りたいときはかなり重宝します。

また組むときだけでなくバラすのも楽なので、試行錯誤しつつ作るのにも向いてます。今回のように、ちゃんと計算して設計しないで作りながら直していくようなやり方には最適です。

ラック&ピニオンセットなどこれらと組み合わせられる部品のシリーズもいろいろあるので、調べてみると面白いと思います。

サーボモーター

このあいだのネコ自作でもサーボモーターを使いましたが、今度は違う機種のサーボを使っています。深い理由はなくて、家にいっぱいあるから…。

1(アームの根元)これ

DSpower 21g Metal Gear mini servo 4.2KG 17g Servo for 1:18 1:16 rc car slash E-Revo 144001 C24 D12 MN99S MN86 RC Airplane robot

2(アームの上の方)はこれ

DSpower SG90 MG90S 9g 12g Mini Micro Servo Motor Metal gear Servo for 450 Helicoper SCX24 RC Car WLtoys axial trx Airplane

3(フタ)はこれ
GWSサーボ MICRO/STD/F(フタバ): 制御部品・駆動部品 秋月電子通商-電子部品・ネット通販

1と2は最近試しに買ってみたやつで、あんまりおすすめではないです。動かすと逆起電力(モーターの動き始めに普段と逆向きの電流が発生する現象)が発生してマイコンが誤動作したので、電源にダイオードを噛ませる必要がありました。
3のGWSのやつは使いやすいサーボです。
サーボモーターの機種についてはここにいろんな機種のレビューとおすすめが書いてあるので見てみてください。
nomolk.hatenablog.com

また、一応負荷の高そうな1のほうによりトルクの強いものを使ったのですが、ちょっと足りなかったみたいで、動画中でアームがめちゃくちゃプルプルしているのはそのせいです。

ブレッドボード用電源モジュール

ブレッドボードについているこれですが

電源モジュールです。これをブレッドボードに挿してACアダプタをつなぐといい感じに5Vや3.3Vの電源を作ってくれます。ACアダプタは6.5V~12Vのが使えるみたいです。

これがけっこうよくて、

丸を付けた部分のジャンパブロックを挿し変えると、出力電圧を5Vと3.3Vで切り替えできます。ブレッドボードの左右に別電圧の電源を作れるので便利。

また矢印の先にあるボタンが電源ボタンになっていて、いちいち抜き差ししなくても電源を遮断できるのも地味に便利です。
今回は5Vしか使ってませんが電源ボタンが欲しかったので使いました。

サーボモーターを複数動かすやり方

回路的にはこんな感じにしています。
※電源がDCプラグの絵になってますが、上で書いた電源モジュールに読み替えてください。5V設定で使用。

動画の回路では面倒だったのでコンデンサ1個にサーボ3つをつないでいますが、本当は図のように分けた方がいいと思います。

Arduinoの電源はブレッドボードからVinピン経由で供給しているので、USBは繋ぎません。Vinからの電源供給には本当は7V以上が必要なのですが、5Vでもわりと動きます。(※安定動作させたい場合はこうしないでArduinoとサーボを別電源にしましょう)

あとVinからの電源供給中はArduinoにUSBをつながない方がいいと思います。壊れるかも。(プログラム書き換え時はブレッドボード側の電源スイッチをOFF!)

プログラム的には、普通に

#include <Servo.h>

Servo servo1;
Servo servo2;
Servo servo3;

void setup() {
  servo1.attach(5);
  servo2.attach(6);
  servo3.attach(9);
}

void loop() {
  servo1.attach(50);
  servo2.attach(80);
  servo3.attach(20);
  delay(15);
}

こんな感じで3つサーボを定義してやれば動きます。

動くのですが、上記のコードだと、サーボ1がギュインと動く→サーボ2がギュインと動く→サーボ3がギュインと動く……っていう感じで同時に動いてくれないんですよね。
動画でいうと「マジで人の話を聞く気がない奴」がこの状態です。

改善のため3つのサーボを同時にゆっくり動かしたかったので、こんな関数を作って制御しています。

void moveServos(int pos1, int pos2, int pos3, int duration) {
  int steps = 50;
  int delayMs = duration / steps;
  int start1 = sm1pos;
  int start2 = sm2pos;
  int start3 = sm3pos;

  float step1 = (pos1 - start1) / float(steps);
  float step2 = (pos2 - start2) / float(steps);
  float step3 = (pos3 - start3) / float(steps);

  for (int i = 0; i <= steps; i++) {
    sm1.write(start1 + step1 * i);
    sm2.write(start2 + step2 * i);
    sm3.write(start3 + step3 * i);
    delay(delayMs);
  }

  sm1pos = pos1;
  sm2pos = pos2;
  sm3pos = pos3;
}

1~3つ目の引数が3つのサーボそれぞれの移動先角度、4つ目が動かすのにかける時間です。
この関数を使って、3つのサーボを指定の角度に向けて同時にゆっくり動かしています。

ちなみに別のやりかたとして、3台も動かすのであればサーボドライバを使う

という手もありそうです。この部品の詳細は今度使ったときに詳しく書こうと思います。

実際のプログラム

というわけで実際に使ったコード全体も貼っておきます。

#include <Servo.h>

Servo sm1;
Servo sm2;
Servo sm3;
int sm1pos = 60;
int sm2pos = 180;
int sm3pos = 160;

int sm1pin = 5;
int sm2pin = 6;
int sm3pin = 9;
int pos = 0;

void moveServos(int pos1, int pos2, int pos3, int duration) {
  int steps = 50;
  int delayMs = duration / steps;
  int start1 = sm1pos;
  int start2 = sm2pos;
  int start3 = sm3pos;

  float step1 = (pos1 - start1) / float(steps);
  float step2 = (pos2 - start2) / float(steps);
  float step3 = (pos3 - start3) / float(steps);

  for (int i = 0; i <= steps; i++) {
    sm1.write(start1 + step1 * i);
    sm2.write(start2 + step2 * i);
    sm3.write(start3 + step3 * i);
    delay(delayMs);
  }

  sm1pos = pos1;
  sm2pos = pos2;
  sm3pos = pos3;
}

void setup() {
  sm1.attach(sm1pin, 544, 2500);
  sm2.attach(sm2pin, 544, 2500);
  sm3.attach(sm3pin, 544, 2400);
  moveServos(sm1pos, sm2pos, sm3pos, 3000);
  delay(3000);
}

void loop() {
  //爪楊枝を出す
  moveServos(80, 180, 160, 1000);
  delay(500);

  //すくう準備
  moveServos(100, 125, 160, 1000);
  delay(500);

  //すくう
  moveServos(85, 85, 160, 1000);

  //アーム起こす
  moveServos(80, 60, 160, 500);
  
  //運ぶ
  //moveServos(30, 90, 60, 500);
  moveServos(80, 90, 160, 500);
  
  //投入口を開く
  moveServos(80, 90, 60, 500);

  //捨てる
  moveServos(80, 180, 60, 500);

  //投入口を閉じる
  moveServos(80, 180, 160, 500);

  //アーム一回退避
  moveServos(30, 180, 160, 500);
  delay(1000);
}

こんな感じです。

sm1.attach(sm1pin, 544, 2500);
↑これが気になるかもしれませんが、これはサーボのパルス幅の設定です。要は角度指定のための信号の設定です。

デフォルトだと544~2400になるのですが、DSpowerのサーボは544~2500なので、設定変更しています。
やらなくても角度が指定と微妙にずれる程度なので、わからない場合は気にしなくても大丈夫です。

以上、技術解説でした。

www.youtube.com

高評価とチャンネル登録してもいいからね。
またね。