【Banggoodクーポン情報】Fatshark HDO2 / Skyzone SKY03O / UZ65 / US65 PRO / Mobula6 HD クーポン追加!

【Arduino入門編⑧】サーボモーターを動かしてみる。PWM制御についていの解説です!

Arduinoを使い電子工作を楽しむなら何かしら動くものを作りたくなりますよね。
動かすとなるとやはりモーターがまず思い浮かびます。
今回はモーターの一種である、サーボモーターをArduinoを使って動かしてみたいと思います。

サーボモーターは主に回転する角度や速度を制御出来るもので2足歩行や4足歩行ロボット、アームの関節部分やラジコンのステアリングなどでも使われ、Arduinoを使った電子工作では欠かせないパーツだと思います。

サーボモーターの制御にはPWM(Pulse Width Modulation)というパルス幅変調という制御方法が使われています。
PWMという用語はこれまでアナログ出力の時にも度々出てきましたが、あらためてPWMの概要についてもご紹介したいと思います。
一定周期内のHIGHの時間(パルス幅)を変えることによる制御方法となります。

しかしArduinoにはサーボモーターを動かすための標準ライブラリとしてServoライブラリというものが存在します。
実際にはこのServoライブラリを使うことによりあまりPWMの事は意識することなく比較的簡単にサーボモーターを動かす事が出来ます。

今回、少し回り道をしながらPWM制御について詳しく見ていきながら理解を深め、実際にServoライブラリを使ったサーボモーターの動かし方をご紹介したいと思います。

【Arduino】サーボモーターを動かしてみる!

今回の目標

サーボモーターを動かす(制御する)にはPWM(Pulse Width Modulation)というパルス幅変調方式が使われます。
PWMに関してはこれまでアナログ出力(analogWrite関数)を使いデューティー比を指定する事によりLEDの明るさ調整などをやってきました。
サーボモーターも同様にこのPWMを使って制御されています。
パルス1周期の中にあるHIGHの時間の割合(パルス幅やデューティー比)を変える事により回転角度を指定して動かしています。
サーボモーターを制御するにあたり、このPWMやパルス幅の話は非常に重要となってきます。

しかし実際のところArduinoにはServoライブラリという便利なライブラリが標準で用意されています。
PWM制御についてあまり意識しなくてもその部分の計算(処理)をライブラリが代わりにやってくれるのでサーボモーターに関しては比較的簡単に動かす事が出来ます。

しかしこれからArduinoを勉強していく上でPWMの話は切ってもきれない重要な項目となり、今回のサーボモーターの制御について言えば角度を指定するよりパルス幅を指定して動かした方がなめらか?に動かせたりもします。

そのあたりのことも踏まえ今回はPWMについて詳しく見ていきながら理解を深め、その上でServoライブラリを使って簡単にサーボモーターを動かせるようになりたいと思います。

サーボモーターとは?

電子工作やラジコン飛行機、ホビーロボットなどに使われている回転角度や速度を指定して制御出来るモーターの事をサーボモーターと呼びます。
このような独特な形状をしたモーターとなります。

内部の構造は、「DCモーター」「制御回路」「ポテンショメーター」の3つから構成されています。

Arduinoから入力されたパルス(PWM信号)を制御回路が受け取りモーターを回転させます。
そしてモーターはポテンショメーターと直結されていてどのくらいモーターが回転したかを読み取り、その情報を制御回路にリターンして指定角度までモーターを動かしその角度を維持したまま止まるという構造となっています。

サーボモーターの制御の仕組み

サーボモーターには3つの端子があり、それぞれVcc(赤ワイヤー)・GND(黒ワイヤー)・信号線(オレンジワイヤー)となっています。

今回SG90と呼ばれるホビーユースでよく使われる非常にポピュラーなサーボモーターを使ってご説明していきます。
駆動電圧は約5V(3.3~6V)となっています。

VccとGND線はサーボモーター内部のDCモーターを駆動するための電源となり、信号線にはArduinoから送られてくるPWM信号を受け取るのに利用されています。
信号線に送られてきたPWMパルスをサーボモーター内部の制御回路が受け取りモーターを回して指定角度まで動かすという事ですね。

PWM(Pulse Width Modulation)制御とは?

サーボモーターの信号線には、パルス変調方式というPWM(Pulse Width Modulation)信号が入力されます。
このPWMとはパルス(HIGHとLOWの信号)なのですが、そのパルスの周期の中にあるHIGHの時間を変化させて制御する方式となります。

この1周期の中にあるHIGHの時間の割合デューティー比やその幅パルス幅を指定する事によりサーボモーターを特定の位置まで動かすというものになります。

具体的に見ていきましょう。
まずは今回使っているサーボモーターSG90のデータシートを確認してみましょう。
非常にメジャーなサーボモーターなので検索すればすぐ出てくると思いますが、秋月電子通商さんのサイトにあったものを引用させてもらいます。

参考 SG90データシート秋月電子通商

PWM信号の周期が20ms(周波数に直すと1/0.02=50Hz)となっています。
つまり1秒間に50回の信号をサーボモーターに送るという事ですが、この周期の中にどれくらいHIGHしている時間があるのかでサーボモーターが動く角度を指定しています。
このような制御方法の事をPWM(Pulse Width Modulation)と呼びます。
HIGHしている時間、つまりパルス幅を変えて制御するということですね。

それではさらにデータシートのデューティーサイクルを見てみると0.5~2.4msと記載されています。
つまりこれは、周期(20ms)のパルスの中にHIGHの時間を0.5msにしてあげるとサーボモーターは最低角度の0度に動き、そして2.4msの幅にすると最大角度の180度にサーボモーターが動くという事になります。
では90度回転させたい場合は・・・真ん中の1.45msという事になりますね。

このように周期内のHIGHの時間を変えていくことにより任意の角度にサーボモーターを動かす事が出来るという事になります。

まとめるとこのようになります。

パルス幅(ms)回転角度
0.5ms0度
1.45ms90度
2.4ms180度

実際には使用するサーボモーターにより周期(周波数)やパルス幅が異なるようです。

デジタル出力でPWM信号を生成し直接サーボモーターを制御してみる

PWM制御について理解出来たでしょうか?
それではサーボモーターを制御するためのPWM信号を作りサーボモーターを動かしてみましょう。

実際には後述するServoライブラリを使うことによりこれからやろうとしているパルス信号の生成など面倒な作業をしなくてもサーボモーターを動かす事が出来ます。
しかしこちらでは、PWMを理解する上で役立つと思いますので少し遠回りをしてやっていきたいと思います。

それではPWM信号を出力するスケッチを考えてみましょう。
これまでやってきたデジタル出力(digitalWrite関数)と一定時間停止させる(delay関数)を使い少し工夫すればPWM信号を作り出す事が出来ます。

まずはArduinoとサーボモーターの接続です。
今回使っているサーボモーターSG90の動作電圧は約5V(最大6V)となっているのでVccとGNDは直接Arduinoから取り、信号線はデジタルピンD7を使いました。

電源に関しては、今回Arduinoから直接取っています。
サーボモーターを動かすには比較的大きな電力を要しますが、SG90のような小型サーボモーターなら数台なら直接取ることも出来ますが注意が必要です。
複数台同時に制御する場合は、サーボモーターの駆動用にArduinoとは別の電源を用意するのが望ましくなります。(最後の項目でやってみます)

そしてスケッチはこちらとなります。

スケッチを解説

まずはサーボモーターに送る信号線をデジタルピン7とし、PULSE_WIDTHという変数にパルス幅を入れています。
初期値は1450μs(1.45ms)としており、サーボモーターが90度の位置まで回転させようとしています。

先述のようにSG90の周期は20msとなり、パルス幅を0.5〜2.4ms(500~2400μs)の範囲で変えることにより0〜180度までの角度で回転させる事が出来ます。

上記スケッチでは、digitalWrite関数を使いHIGHの信号を出しmicroseconds関数で指定時間(マイクロ秒)停止させそのHIGH状態を維持してLOWに戻す動作をさせています。
これがパルス幅になります。(1450μsの時間HIGH状態にしその後LOWに落としています)

そして最後のdelay関数で20ms止まる動作をさせ、これを繰り返すため周期が20msで出力するということになります。

microseconds(μs) 関数
プログラムを指定時間停止させます。
単位はマイクロ秒となります。
delay(ms)関数はミリ秒停止させますが、さらに短いマイクロ秒単位で扱えます。

実際に動かしてみる

それでは実際にスケッチを動かしてみてください。
サーボモーターが90度の位置まで回転し止まります。

そしてPULSE_WIDTH変数の数字(パルス幅になります)を500に変えると0度の位置、2400に変えると180度の位置まで回転する事が確認できます。
あとはこの範囲内で数値をいろいろ変えてサーボモーターの動作を試してみて下さい!

PWM制御信号を作り問題なくサーボモーターを動かす事ができましたね。
これでサーボモーターの動作原理やPWMによる制御方法が理解出来たかと思います。

しかしArduinoにはServoライブラリというものが標準で用意されており、このように自分でPWM信号を作り出さなくても比較的簡単にサーボモーターを動かす事が出来ます。

先ほどやったようなパルスを発生させる計算(処理)をServoライブラリが代わりにやってくれるという事です。
パルス幅の計算は先程のように切りのいい0度や90度などは簡単に計算出来ますが、78度や98度・・・となってくるとなかなか面倒な作業となります。
また動かす角度で指定できないので直感的ではありませんよね!

これらをServoライブラリを使うことによりライブラリ用に用意された関数を使い直接サーボモーターを動かす角度(0〜180度)を指定して動かす事が出来るようになります。
こちらの方が直感的で分かりやすいですよね!

Servoライブラリを使ってサーボモーターを動かす

本来ここから説明してもよかったのですが、PWM制御について理解を深めるために少し遠回りをしてきました。
そしてここからが本題となります。
実際にPWM信号を生成しサーボモーターを動かす事でPWMについて理解が深まったと思います。

しかしこの方法ではサーボモーターを複数台制御する場合、パルスを発生させるタイミングがズレたりといろいろと問題が出てきます。
そこでArduinoにはサーボモーターを制御する事が出来る便利な専用ライブラリが用意されているのでこれを使ってみたいと思います。

先程やったPWMパルス生成部分をこのServoライブラリが処理してくれるので、回転角度を指定するだけで動かす事ができ直感的にサーボモーターを動かすことが出来ます。(パルス幅の指定もできます)

それではやっていきましょう。
まずはServoライブラリのインクルードからやっていきます。

Servoライブラリのインクルード

Arduino IDEのライブラリに関してはこれまでご紹介した事がないので少し簡単にご説明しておきます。

まずライブラリとは何か?
簡単に言うと、Arduinoで使う(接続する)LCDディスプレイや7セグメントLED、センサーやシリアル通信などその特定の部分の制御や処理だけを専用でやってくれるプログラムみたいなものとなります。

先程PWM信号を作りサーボモーターを動かしましたが、例えば85°に動かしたい時にパルス幅を考え実際にPWM信号を出力しようと考えるとその計算は少し手間がかかります。
このような特定の処理(計算など)を専用でやってくれるのがライブラリとなります。

今回使うServoライブラリではPWM信号生成部分などをライブラリ側が代わりにやってくれるので、角度を指定するだけでサーボモーターを動かす事が出来るようになります。
便利な機能ですね!

それではライブラリを使える状態にしてみましょう。
ライブラリを使うにはまずそのライブラリをスケッチ内にインクルードする必要があります。

試しに[ファイル]⇒[新規ファイル]から何も書かれていない新規のスケッチを作り試してみましょう。
新規スケッチが作成できたら[スケッチ]から[ライブラリをインクルード]へ進むとライブラリの一覧が表示されます。
こちらにないものをインストールして使う事も出来ますが、今回使うServoライブラリはArduino IDEに標準で搭載されているライブラリとなるので一覧に表示されていると思います。
一覧から【Servo】を選択します。

そうするとスケッチ先頭に、#include <Servo.h>と入ります。
これでServoライブラリのインクルードは完了でライブラリを使える状態になりました。
あとはこのライブラリが持つ関数を使ってサーボモーターを制御していく形となります。

スケッチ解説

それではServoライブラリを使って実際に動かしてみましょう。
サーボモーターの接続は先程と同じです。
デジタルピンD7に信号線を繋ぎ、電源はArduinoから5VとGNDを取っています。

簡単なスケッチを用意しました。
サーボモーターが0度→90度→180度と順に回転しこれを繰り返すスケッチとなります。

Servoライブラリで使う関数(コマンド)がいくつか出てきたのでスケッチを解説していきます。

まずはスケッチ内で使うサーボモーターの名前を宣言します。
ここではmyservoという名前に割り当てています。

Servo [サーボ名];
Servo型の変数を作る

 

(記述例)
Servo myservo;
myservoがServo型の変数となります。

次にサーボモーターの使用するピンを指定するのがattach(pin)関数です。
上記でmyservoというサーボで使う変数を宣言したので、attach(pin)関数を使い使用するピン(D0~D13ピン・A0~A5ピンが使えます)を指定します。

attach(pin);

サーボ変数をピンに割り当てる。
指定ピンをサーボ制御用に割り当てる。

 

[構文]
myservo.attach(pin);
myservo.attach(pin, min, max);

 

myservo:Servo型の変数
pin:サーボを割り当てる(接続する)ピン番号
min(オプション):サーボの角度が0度の時のパルス幅(マイクロ秒)
max(オプション):サーボの角度が180度の時のパルス幅(マイクロ秒)

 

※minはデフォルトで544、maxは2400に設定されているので省略も可能です!

そして実際にサーボモーターを動かすのがwrite(angle)関数となりangle部分を角度(0から180の数字)で回転角度を指定します。

write(angle);

指定した角度(angle)にサーボシャフトを動かします。

 

[構文]
myservo.write(angle);
myservo:Servo型の変数
angle:角度の指定(0~180)

どうでしょうか?
Servoライブラリを使うと冒頭に出てきたようにPWMについて意識しなくても角度を指定するだけで比較的簡単にサーボモーターを動かす事が出来たと思います。
ライブラリって便利ですね!

あとはピン番号を変え他の端子でも動作するか確認してみて下さい。
実際に1台ずつ試してみましたが、デジタルピン(D0~D13)、アナログピン(A0~A5)全てのピンで動作する事が確認できました。
それではServoライブラリを使った一連の流れを見てから、複数台のサーボモーターも同時に動かしてみましょう。

Servoライブラリを使った一連の流れ

手順① ライブラリ(ヘッダーファイル)の読み込み
#include  <Servo.h>
手順② スケッチ内で使用するサーボの名前を宣言
ライブラリの読み込み後スケッチ内で使用するサーボモーターの名前(任意)を宣言
Servo myservo;
手順③ サーボが使用するピンを指定する
myservo.attach(7,500,2400);
※パルス幅の最小値・最大値は省略可
手順④ サーボを動かす角度を指定する
myservo.write(90);

Servoライブラリを使い複数台のサーボモーターを動かす!

1台動かす事が出来れば、あとは同じ要領でサーボの数を増やしていくだけです。
Servoライブラリを使ってデジタルピン(D0~D13)・アナログピン(A0~A5)全てのGPIOピンでサーボモーターが動くことが確認出来たのであとは台数を増やしていくだけです。(Arduino UNOでは一度に扱える数は12台までとなります!)
4台のサーボモーターを同時に動かしてみましょう。

サーボモーター駆動用に別電源を用意

Arduinoからの電源供給でサーボモーターを動かす場合、Arduinoから取り出せる電力では足りなくなる場合が出てきます。

今回使っているArduino UNOでは1つのGPIOピン(アナログ・デジタル共に)からは大体20mA(最大40mA以上流すと壊れる可能性があります)となっています。
サーボモーターは駆動に比較的大きな電力を必要とするためArduinoからの電力供給が不足し誤動作や破損につながります。
これはサーボモーターに限らずDCモーターやステッピングモーターなどの駆動には別電源を用意した方がよさそうです。

今回はサーボモーターの数が4台に増えたのでその駆動用の電源を別で用意しました。
ブレッドボードに挿せるタイプのものでACアダプタやUSBから簡単に5Vや3.3Vの電源が取れるこちらのボードを使用しました。(後述のELEGOOのArduinoスターターキットには付属しています)
1台持っていると便利ですよ!
また電池ボックスを使い乾電池を4本(eneloop1.2V×4)で繋いでもいいかと思います。

接続図はこちらとなります。
単にサーボモーターの数が増えただけなので接続は簡単ですが、サーボモーターの駆動用に別電源を取っているのでGND端子だけはArduino側と共通として下さい。

注意
間違ってもVcc(5V)はArduino側に繋がないように!

接続ができたらこちらのスケッチを動かしてみましょう。
4つのサーボが0度→90度→180度と動くのが確認できます。

Servoライブラリ用関数の使い方が理解でき複数台のサーボモーターを同時に動かせるようになれば今回の目標は達成です!

単純にサーボモーターを4台動かしただけですが、個別で上手く制御できれば簡単なロボットも作れます。
こちらはM5StickCで動かしているPuppyCというロボット君ですが、Arduinoを使って4台のサーボモーターを個別で制御して動かしていて今回やった内容で出来てしまいます。
おもしろいですよね!

【M5StickC】これからはじめる電子工作。M5StickCからはじめてみるのはオススメです!

パルス幅を指定して動かすことも出来ます

少し長くなっていますが、折角なのでServoライブラリを使ってこれまでの角度指定ではなくパルス幅を指定して動かす方法もご紹介しておきます。

角度を指定して動かす場合write(angle)関数を使いましたが、writeMicroseconds(μs)関数を使えばパルス幅を指定して動かすことが出来ます。

writeMicroseconds(μs);

パルス幅(マイクロ秒)を指定してサーボを回転させる。

 

[構文]
myservo.writeMicroseconds(μs);
myservo:Servo型の変数
μs:パルス幅をマイクロ秒単位で指定。

write関数の角度指定では0~180度の180段階で指定できますが、パルス幅で指定する場合SG90では500~2400マイクロ秒の1900段階で指定できます。

かなり細かく指定できるという事は滑らかな動きになり無駄なトルクもなくなる?ので音も静かになるようですが・・・実際に試してみて下さい!(サーボの性能にもよりますが!)

こちらに角度指定とパルス幅指定で動かすスケッチを作ってみました。
0~180度までは角度を指定するwrite()関数で動かし、折り返しの180~0度まではwriteMicroseconds(μs)関数を使いパルス幅を指定して動かしています。
動作スピードはどちらも同じとなるように調整しています。

接続は冒頭でやった接続と同じです。(D7に信号線を繋いでいます)

動作音や動きを比べてみるとどうでしょう?

Servoライブラリを使ってサーボを動かすには角度指定以外にもパルス幅でも指定できるという事が分かれば十分今回の目標は達成です!

Servoライブラリを使う時の注意点

便利なServoライブラリですが、このライブラリを使う時の注意点(仕様)について少しご説明しておきます。

Servoライブラリを使えば、デジタルピン(D0~D13)・アナログピン(A0~A5)までのピンを使いサーボモーターを動かす事が出来ます。
しかし今回使っているArduino UNOでは同時に扱えるのは12台までとなるようです。

またServoライブラリ使用中は、デジタルピンD9とD10番ピンでのanalogWrite関数によるPWM出力が出来なくなるので、この点注意が必要となってきます。

今回使ったパーツ

Arduino UNO

Arduinoはオープンソースのハードウェアなので正規品以外にも互換品が多数メーカーから販売されています。
互換品でも正規品と比べて特に問題なく使用でき数百円程度で購入が可能なのでArduino学習用としていいですね!

Arduino スターターキット

これからArduino学習を進めていくにあたりArduino UNO(互換品)やブレッドボード、ジャンパーピンなどがセットになったスターターキットが販売されています。

私はGeekcreit製のスターターキットを使っていますが、ELEGOO製のものは国内Amazonなどでも購入可能で人気があるようです。(セット内容はほぼ同じです!)

そしてELEGOOのサイトからスターターキット用サンプルスケッチのダウンロードも可能です。(Geekcreitのキットでも使えます)

参考 チュートリアルダウンロードELEGOO

基本的にこれからこのセットで出来るものから紹介していこうと考えていますが、かなり多くのことが出来ます。
電子工作を始めるにはまずブレッドボードやジャンパーピン、メインとなるArduino UNOやサーボ、LEDなどの基本的なパーツがないと実際に動かすことが出来ませんが、個々にパーツを購入して回路を組んでとなるとかなりの手間がかかります。

スターターキットがあればArduinoの初歩的なことはかなりの数こなすことが出来るのでオススメです!
そこからスキルアップに伴い個別でセンサーなど必要なものを増やしていくのがいいと思います。

今回使ったSG90やブレッドボード用の電源ユニットはELEGOO製Arduinoスターターキットには含まれています。

SG90 サーボモーター

ラジコンや小型ロボットなどホビーユースで使われるサーボモーターとして非常にポピュラーなものとなります。
国内でも数百円程度で手に入るのでArduino学習用として手元にあるといろいろと試せます。

ブレッドボード用電源ユニット

ブレッドボードに取り付ける事が出来る電源ユニットとなります。
ACアダプターやUSBから5Vまたは3.3Vの電源が取れる便利なユニットです。
電子工作をやるにはこの手のアイテムは必須、1台は持っておきたいものです。
上記、ELEGOO製Arduinoスターターキットには付属しています。

今回使った関数(コマンド)まとめ

#include <Servo.h>

サーボライブラリをインクルードする

Servo [サーボ名];
Servo型の変数を作る

(記述例)
Servo myservo;
myservoがServo型の変数となります。

attach(pin);

サーボ変数をピンに割り当てる。
指定ピンをサーボ制御用に割り当てる。

 

[構文]
myservo.attach(pin);
myservo.attach(pin, min, max);

 

myservo:Servo型の変数
pin:サーボを割り当てる(接続する)ピン番号
min(オプション):サーボの角度が0度の時のパルス幅(マイクロ秒)
max(オプション):サーボの角度が180度の時のパルス幅(マイクロ秒)

 

※minはデフォルトで544、maxは2400に設定されているので省略も可能です!

write(angle);

指定した角度(angle)にサーボシャフトを動かします。

 

[構文]
myservo.write(angle);
myservo:Servo型の変数
angle:角度の指定(0~180)

writeMicroseconds(μs);

パルス幅(マイクロ秒)を指定してサーボを回転させる。

 

[構文]
myservo.writeMicroseconds(μs);
myservo:Servo型の変数
μs:パルス幅をマイクロ秒単位で指定。

今回のポイント

  • サーボモーターはPWMで制御されている!
  • PWMは周期内にあるHIGHの時間(パルス幅)により制御する!
  • Arduinoにはサーボモーターの制御に使えるライブラリが用意されている!
  • Servoライブラリを使うと角度指定で直感的にサーボモーターを動かす事ができる!
  • Servoライブラリ使用時は、D9・D10番ピンでanalogWrite(PWM)が使えなくなるので注意が必要!

最後に!

今回、PWMによるサーボモーターの制御方法を見ていきました。
Servoライブラリを使用するとPWM制御についてあまり意識する事なく角度指定で制御出来るので直感的で使いやすくなります。

PWM制御について理解でき、そしてServoライブラリを使ってサーボを自由に動かせるようになれれば今回の目標は達成ということです。

今回は少し長くなりましたので、このあたりで・・・。

コメントを残す