Tinkercad Circuits で Arduino 入門8~RCサーボモータ~


概要

第8回目です。今回は RCサーボモータ(あーるしーさーぼもーた) について扱います。

「RCサーボモータ」について、はじめて見聞きする方は、まず、YouTubeの動画 を適当に $2$ ~ $3$ 本程みていただくと、以降の説明が分かりやすいと思います。

RCサーボモータ

RCサーボモータとは「回転角度を指定できる機構とマイコンを内蔵したモータ」のことで、小型ヒューマノイドロボットの関節などに利用されています。このため、ロボット用サーボと呼ばれることもあります。

普通のDCモータとの違いはクルクル回転するわけではなく、外部からパルスで指定した角度まで回転して、その位置を保持するという点です。また、最大動作角も180°程度(1回転しない)ということも大きな特徴的になります。

もともとは、RC(Radio Control)という名前のとおり、ラジコンカーのステアリング制御(進行方向を決める車輪のハンドル制御)、ラジコン飛行機の翼角度制御などに使われていました。

なお、一般にサーボモータといった場合は、産業用ロボットに使用される「ACサーボモータ」を指します。ACサーボは基本的に専用アンプ(ドライバ)を通して駆動させるもので、ここで紹介する方法では制御・駆動できません(RCサーボとACサーボは基本的に別物と考えてください)。

構造

RCサーボは、ケースボックスのなかに「DCモータ」「歯車(ギア)減速機」「ポテンショメータ(角度センサ)」「制御マイコン」などが収められています。これらがシステムとして機能して、外部から指定した角度まで回転して、それを保持するように動作します。

ギアが内蔵されているため、トルクは非常に大きいです。写真の S03T 2BB は、トルクが $7.4\, \mathrm{kgf}\cdot \mathrm{cm}$ です。ホーン の先端(回転軸から$2\mathrm{cm}$の位置)に $2.0\mathrm{L}$ のペットボトル を取付けても余裕で持ち上げることができます。

スペック

RCサーボのスペックとしては、トルク動作電圧動作角動作速度価格 などに注意してください。

トルクは、$\mathrm{kgf}\cdot \mathrm{cm}$ の単位で表記されます。トルクとは、回転させる力の大きさで「回転軸(出力軸)から力が加わる点までの距離」に「力」を乗じたものになります。

たとえば、次のように回転軸から $1.5\mathrm{cm}$ のところに、$4.0\mathrm{kg}$ の負荷を取り付けた場合、$1.5\times 4.0 = 6.0\, \mathrm{kgf}\cdot \mathrm{cm}$ の負荷トルクがかかります。このとき、RCサーボモータの出力トルクが、$6.0 \,\mathrm{kgf}\cdot \mathrm{cm}$ よりも大きければ、負荷を上に引き上げることができます。

動作電圧は、小型のものでは $5.0\mathrm{V}$ 前後のものがあります。Arduinoのロジックレベルと同じなので使いやすいです。$4.8\mathrm{V}$ という表記のものを見かけますが、実用上、$5.0\mathrm{V}$ 電源で使用して問題ありません。なお、電圧は $5.0\mathrm{V}$ ですが、駆動時・高負荷時には大きな電流を必要とします。そのため、外部電源できれば電池・バッテリーの使用が望ましいです。

動作角(最大動作角度)は、ロボット用のものであれば、$\pm\,90$°($180$°)の製品がメジャーです。ラジコン用では$\pm\,60$° の製品もあるので注意します。また、$360$°の連続回転が可能なローテーションサーボという商品もあります(回転角度でなく回転速度と方向が制御できるようです)。

価格は、性能により大幅に変わってきます。低トルクの安いものは数百円から、高トルクのものは1万円以上のものまであります。

動作速度は、$60$°を回転させるために必要な時間として表記されます。例えば $0.1\,\mathrm{sec}/60\mathrm{deg}$ のように表記されます(度=degree)。内部に減速機があるので、トルクを求めると速度が犠牲になります。基本的にサーボモータ自体には速度の制御機能はありません(ゆっくり回転させたい場合は、小刻みに目標値(角度)を与えます)。

制御方法

回転させたい角度を指定するためにはPWM信号(パルス)を使います(シリアル通信で制御するタイプの製品もあります)。一般には、$10$~$20\mathrm{ms}$ の周期で、パルス幅を $1$~$2\mathrm{ms}$ 程度の範囲で変化させることで角度を指定します。

一般的なRCサーボモータでは、パルス幅の $1$~$2\mathrm{ms}$ の変化に対して、サーボホーンが約 $180$° 回転します。

ところで、周期が $10 \mathrm{ms}$ ということは、周波数 $100\mathrm{Hz}$ です。第5回 で学習しましたが、analogWrite(...) による PWM出力の周波数は基本的に固定で、5番と6番ポートは $970\mathrm{Hz}$ 、その他は $490\mathrm{Hz}$ でした。ということで、analogWrite(...) を使ったPWM信号で、RCサーボモータを制御することはできません。

制御には、専用のライブラリを使用します。

回路の構成

次のように回路を接続します。RCサーボモータは、動くときに大きな電流を必要とするので、それに対応できるように外部電源を準備します(Arduinoの $5\mathrm{V}$ 単位では電流容量が大きくないので使用しません)。回路はとてもシンプルです。

外部電源のGNDArduinoのGND を接続することを忘れないでください。

ここでは、デジタル12番ポートを制御信号を出力するためのポートとして使用しましたが、12番以外でもOKです。

ロジックの構成

まずは、ブロックを使ってロジックを構成してみましょう。

シミュレーションを開始するとモータが回転することが分かります。しっかりと観察すると、可動域(動作角度範囲)が$180$度よりも少し狭いことがわかります。このように、可動域は、データシートを参照したり、実際に実験をしたりして確認する必要があります。

  • 回路例はこちら(TinkerCadに移動します)。

ここで、次のことを試してみて下ください。

  • 2秒を待機」を「0.5秒を待機」にしてシミュレーションを実行
  • 角度の指定を「マイナス」や「270」にしてシミュレーションを実行
  • Arduinoと外部電源の GND を接続せずにシミュレーションを実行
    (サーボモータのGND(接地)を外部電源のGNDだけと接続)
    (サーボモータのGND(接地)をArduinoのGNDだけと接続)

また、次のようにオシロスコープを接続して、制御信号(PWM信号)の変化を観測してみるのも面白いです。

コードの確認

エディタのモードをテキストに切り替えて、コードを確認してみましょう。

次のようなコードになっています。

サーボモータの制御.ino
#include <Servo.h>

Servo servo_12;

void setup()
{
  servo_12.attach(12);
}

void loop()
{
  servo_12.write(180);
  delay(2000); // Wait for 500 millisecond(s)
  servo_12.write(0);
  delay(2000); // Wait for 500 millisecond(s)
}

コードでは、まず最初に #include <Servo.h> により、サーボモータを制御するためのライブラリの読み込みを行なっています。

  • 中級者向け補足:このライブラリを使用すると、デジタル入出力ピンの $9$ と $10$ からの PWM出力 が機能が無効になります。詳細はリファレンス参照。

コードの編集

ところで、次のように「setup関数」と「loop関数」の位置を変えると、どうなるでしょうか?

サーボモータの制御(setupとloopの位置を逆転).ino
#include <Servo.h>

Servo servo;

void loop()
{
  servo.write(180);
  delay(2000); // Wait for 500 millisecond(s)
  servo.write(0);
  delay(2000); // Wait for 500 millisecond(s)
}

void setup()
{
  servo.attach(12);
}

実際に書き換えて、そのあとシミュレーションを開始してみましょう。・・・結果、何ら問題なく動きますね。

では、次は #include <Servo.h>Servo servo; の位置を入れ替えてシミュレーションを開始してみてください。今度は、エラーが発生しますね。

プログラムを効果的に理解・勉強するためにはなぜ、その文(命令)が必要なのか(=その文が抜けると何が問題なのか」や「その文(命令)は、その位置にある必要があるのか、それとも順序を入れ替え可能なのか」といったことを意識しながら読み書きすることです。そして、自分の考えが正しいかを手間を惜しまずに、試すことです。

また「(結果に影響を与えずに)書き換え可能なところはどこか?」を考えることも勉強になります。たとえば、servo_12 というのは単なる変数名なので、次のように servo に変えても何ら問題ありません(ただし、4カ所すべてをかえてください)。

サーボモータの制御2.ino
#include <Servo.h>

Servo servo;

void setup()
{
  servo.attach(12);
}

void loop()
{
  servo.write(180);
  delay(2000); // Wait for 500 millisecond(s)
  servo.write(0);
  delay(2000); // Wait for 500 millisecond(s)
}

さらに、次のように書き換えることもできます。

サーボモータの制御3.ino
#include <Servo.h>
int dTime;
Servo servo;

void setup(){
  dTime = 2000;
  servo.attach(12);
}

void loop(){
  servo.write(180);
  delay(dTime);
  servo.write(0);
  delay(dTime);
}

このように同じ処理をするプログラムでも、ほぼ無限通りの書き方ができるということを意識してください(どんなコードが良い/悪い、というのは状況によって変わり、一概にはいえません)。

複数のサーボモータの制御

リファレンス によれば、最大で $12$ 個のRCサーボが同時に利用できるようです。以下は、2個のサーボモータを同時に使用しています。

実際に、2個のサーボモータを配置・配線して動かしてみてください。

  • 回路例はこちら(TinkerCadに移動します)。

制御用ボード(RCサーボコントローラ)

実践において、複数のRCサーボを制御する場合は、専用の制御ボード「RCサーボコントローラ」を利用したほうが便利で確実です。ArduinoからRCサーボコントローラに対しては SPI や シリアル通信 で簡単な命令を送り、RCサーボコントローラでは、それを受け取って PWM信号 を生成・出力します。

おまけ:手動操縦のロボットアーム

ここまでに学習した知識・技術を組み合わせて、アナログスティック/ジョイスティック(内部回路は可変抵抗・ポテンショメータと同じ)とRCサーボモータを組み合わせて、手動操縦ができる簡単なロボットアームをつくることができます。

アナログスティックの操作量をアナログ入力 analogRead(...) で取り込み、その量を処理して、サーボモータ角度出力 servo.write(...) とします。

ただし「サーボモータ角度 $\propto$ アナログスティックの現在の入力量」でロジックをつくると、スティックから指を離したときにアームも最初位置に戻ってしまいます。「サーボモータ角度 $\propto$ アナログスティックの過去の入力量の累積(積分)」でロジックを構成するようにしないといけません。

おまけ:消毒用アルコールの自動プッシュ装置

コロナウィルスの影響で、いろいろな場所に消毒用アルコールが設置されています。このなかで、既存の手動プッシュ式のボトルを取り付け、手をかざすとセンサーが反応し、電動機構が動いてポンプをプッシュしてくれるものがあります(ボトルに手を触れることなく手指の消毒が可能)。

このシステムの自作することを考えてみましょう。

RCサーボモータは強力なので、特別な機構なしでポンプのプッシュが可能とします。あとは、どうやって「手がかざれたことを検出するか」「どんなセンサを使用するか」「センサから出力される信号で、サーボモータを駆動させるためには、どのようなロジックが必要か?」を具体的に考えてみてください。

また、可能であれば、TinkerCad Circuit で模擬的なシステムをつくってみましょう。