こんにちは、「メカのりまき」です。
この記事では、Arduinoでサーボモータ(SG90)を動かす方法について、説明したいと思います。
この記事は「Arduino IDE」の基本的な使い方を、理解していることを前提とした記事となっています。
「Arduino IDE」の使い方は以下のリンク先の記事で説明していますので、「Arduino IDE」の使い方が分からない方は、以下のリンク先の記事を是非ご覧になってください。
目次
本記事で使用するもの
本記事で私が使用した物は以下の通りです。
- 「Arduino IDE2.0.4」をインストールしたPC(Windows11)
- USBケーブル
- Arduino Uno R3(ELEGOO UNO R3でも可)
- サーボモータ(SG90)
- ジャンパーワイヤー
「Arduino Uno R3」の互換ボードであれば、「ELEGOO UNO R3」以外のボードでも、本記事と同様な手順で動作可能だと思われますが、動作検証はしていないので、その点はご了承ください。
以下のリンクのスターターキットを購入した場合、上記で述べた使用するものは、PC以外すべて入手することができます。
Arduinoをまだ購入していないという方やArduinoで動かすことができるたくさんのパーツが欲しいという方は、購入を検討してみてください。
サーボモータの説明
サーボモータ(SG90)は指令した角度になるように、軸を回転させることが出来るモータで以下の写真のような見た目をしています。
通常のモータの場合、電流を流すと、常に軸が回転し続けますが、サーボモータは、軸の角度を認識するための部品と角度を制御するための基盤がセットになっており、指令を与えることで、軸の角度を制御することができます。
サーボモータ(SG90)に接続するための線は3本あり、茶色の線を「電源のマイナス(GND)」、赤色の線を「電源のプラス」、オレンジ色の線を「指令するためのピン」に接続します。
上記の茶色の線と赤色の線はモータや制御基板を動かすための電力供給などに使用され、オレンジ色の線は、角度の指令をするために使用されます。
サーボモータ(SG90)の軸の角度は、オレンジ色の線の先が、周期20[ms]の中で、どれだけ「HIGH」になっていたかで決まります。
ここで、軸の角度は「HIGH」となっている時間が、0.5[ms]の時「-90度」、1.45[ms]の時「0度」、2.4[ms]の時、「90度」になります。
上記のように、一定の周期の中で「HIGH」となっている時間を変更するような信号を使い、物を制御することを、「PWM制御」と呼びます。
少し前の記事でLEDの明るさを調節したのも「PWM制御」で、周期が約2[ms]の中で「HIGH」の割合を変化させる「PWM制御」でした。
今回は、周期20[ms]の中で、「HIGH」の長さを0.5~2.4[ms]で変化させる「PWM制御」ということになります。
サーボモータ(SG90)の説明は以上となります。
上記の情報やサーボモータ(SG90)の詳細は、以下のリンク先のデータシートに記述されていますので、気になる方は確認してみてください。
Arduinoとサーボモータ
上記で説明したように、サーボモータを動かすためには、電力の供給と角度の指令が必要になります。
ここでは、Arduinoとそれらの関係について、順番に説明したいと思います。
電力の供給
サーボモータ(SG90)に大きな負荷をかけず単体で動かす場合、茶色の線と赤色の線を、それぞれ「Arduino」の「GNDピン」、「5Vピン」に接続することによって電力の供給を行うことができます。
ここで、「Arduino Uno」の5Vピンはそれほど大きな電流を流すことができないため、サーボモータの種類によっては、電力が足りず動作しないことがあります。
その場合、電池や電圧を安定化させる部品など、別途電源が必要になるので、注意してください。
また、サーボモータ(SG90)であっても、大きな負荷がかかる場合(重いものを素早く動かしたい場合)や、複数のモータやセンサを同時に扱おうとした場合は、その分大きな電流が必要となるため、別途電源が必要となる場合があるので、注意してください。
基本的にモータを扱う場合は、外部の電源を利用することをお勧めしますが、今回の記事では、サーボモータ(SG90)単体を、負荷をかけずに動かすため、茶色の線と赤色の線を、それぞれ「Arduino Uno R3」の「GNDピン」、「5Vピン」に接続します。
角度の指令
サーボモータ(SG90)の軸の角度は、オレンジ色の線の先が、周期20[ms]の中で、どれだけ「HIGH」にしている時間があるかによって決まると上記で説明しました。
つまり、オレンジ色の線を出力ピンと接続した後に「digitalWrite()」と「delayMicroseconds()」を使って、出力ピンの「HIGH」と「LOW」を切り替えれば角度の指令を行うことができるということになります。
サーボモータを試す
では、上記で説明した理論をもとに、サーボモータを動かしていただこうと思います。
スケッチを書き込む
まず、以下のスケッチを書き込んでください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
//サーボモータに指令を与えるピンを指定する変数 int servo_pin=2; //パルス幅を指定する変数(500~2400) int pulse_HIGH=800; void setup() { //サーボモータに指令を与えるピンを出力ピンに設定 pinMode(servo_pin,OUTPUT); } void loop() { //20[ms]のPWM信号を出力し、サーボモータに指令を与える digitalWrite(servo_pin,HIGH); delayMicroseconds(pulse_HIGH); digitalWrite(servo_pin,LOW); delayMicroseconds(20000-pulse_HIGH); } |
動作の確認
次は、以下のように、Arduinoとサーボモータを接続してください。
Arduinoに電源が入っている場合、繋いだ瞬間に軸が動き出すので注意してください。
サーボモータの接続が完了すると軸が動き、ある角度で止まります。
ここで、接続前の角度が、スケッチで指令した角度と偶然一致していた場合は、動かずに止まります。
動作が確認できなかった場合は、USBケーブルを抜くことで、Arduinoの電源をオフにした後、軸を手動で適当な角度に回転させ、その後もう一度USBケーブルを差し、Arduinoの電源をオンにします。
すると、サーボモータの軸は、手動で動かす前の角度に向かって回転し止まります。
上記のことを行っても軸が動かない場合は、Arduinoの電源をオフにし、Arduinoの接続とスケッチが間違えていないか、確認をしてください。
スケッチの解説
スケッチ全体の流れは以下のようになります。
処理はとても単純で、5行目で「pulse_HIGH」という変数を宣言してパルス幅を指定し、16~19行目で、指定したパルス幅の時間「HIGH」となり、周期が20[ms]になるような信号を出力しています。
サーボモータの軸の角度は、信号の「HIGH」となっている時間によって変化するため、5行目の文の値を変更すれば、角度を変更することが出来ます。
試しにスケッチの5行目の文
5 |
int pulse_HIGH=800; |
の数値「800」を、以下のように「2000」に変更して、もう一度スケッチを書き込んでください。
このとき、スケッチの書き込みが完了すると軸が動き出すので注意してください。
5 |
int pulse_HIGH=2000; |
スケッチの書き込みが完了すると、軸が別の角度に向かって動き出し、ある角度で止まります。
上記のスケッチの弱点
上記のスケッチには、良くない点が2つあります。
1つ目はサーボモータの角度とパルス幅の関係が、分かりづらいという点です。
上記のスケッチでは、パルス幅を指定することで、サーボの角度を制御しているため、動かしたい角度が決まっている場合、その角度になるようなパルス幅を計算する必要があります。
2つ目は、サーボモータを動かす以外の処理を同時に行うのが難しいという点です。
サーボモータの角度を一定に保つためには、常に信号を一定の間隔で送り続ける必要があります。
しかし、上記のスケッチに他の処理を追加した場合、信号を送る間隔が、追加した処理の分だけ延びてしまいます。
別の処理を行いつつ、一定の間隔で、信号を送り続けたい場合は、割り込み処理を利用したり、時間を測定し、間隔を調整したりするなどの工夫が必要になります。
上記のスケッチを自分で修正し、問題点を解決しても良いのですが、Arduinoには「ライブラリ」というものが存在し、それにより、センサやモータなどを簡単に扱うことができます。
ライブラリの説明
通常、センサやモータをArduinoで動かす場合は、変数の宣言、計算の処理、ピンを制御するための処理など、スケッチをすべて自分の手で記述しなくてはなりません。
しかし、「ライブラリ」には、センサやモータなどを動かすためのコードがまとめられており、Arduinoで読み込むことにより、スケッチをすべて自分の手で記述しなくても、センサやモータなどを簡単に扱うことができるようになります。
ライブラリでサーボモータを制御する
ここでは、「Arduino IDE」に初めから付属している「Servoライブラリ」で、「ライブラリ」の使い方を学びつつ、サーボモータの制御を行っていただこうと思います。
スケッチを書き込む
まずは、以下のスケッチを書き込んで、動作の確認を行ってください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
//ライブラリの読み込み #include <Servo.h> //Servoというクラス型の変数を用意 Servo myservo; //サーボモータに指令を与えるピンを指定する変数 int servo_pin=2; void setup() { //サーボの初期設定 myservo.attach(servo_pin,500,2400); } void loop() { //0度の位置に回転 myservo.write(0); delay(2000); //90度の位置に回転 myservo.write(90); delay(2000); //180度の位置に回転 myservo.write(180); delay(2000); } |
スケッチが正しければ、以下の動画のように、サーボモータが動きます。
アームの位置は取り付け方によって異なりますが、反時計回りに2回、90度の回転を行った後、元の位置に戻るような動きが確認できるはずです。
スケッチの解説
まず、スケッチの2行目で、以下のような文が記述されています。
2 |
#include <Servo.h> |
これが、「Servoライブラリ」を読み込むための文であり、「Servo.h」と書かれている部分を変更すれば、他のライブラリを読み込むことができます。
続いて、5行目では以下のような文が記述されています。
5 |
Servo myservo; |
上記の文により、Servoというクラス型の変数が用意され、「Servoライブラリ」内にあるサーボモータを動かすための関数などを使用することができるようになります。
「myservo」の部分は変数の名前であり、アルファベット、数字、アンダーバー( _ )を使って好きな名前を自分で付けることができます。
以上の2つの文が、ライブラリ内の関数などを使用するための基本的な準備となります。
まずは、これらの準備について、もう少し分かりやすいように説明したいと思います。
少し前の記事で、変数宣言はデータを格納するための箱を用意するという風にイメージをすると少し分かりやすくなると説明しました。
クラス型の変数の場合は、箱の集合体を用意するという風にイメージすると分かりやすくなります。
そして、この箱の中には、センサやモータなどを動かすための変数や関数が入っており、後からそれらのデータを出し入れすることができます。
ここで、クラス型の変数を宣言したとき、箱の構成や中に入っている変数や関数が、すでに決められていることに注目してください。
実は、クラス型の変数はあるデータを基に、作られたものであり、そのデータこそが「ライブラリ」です。
「ライブラリ」はクラス型の変数を作るための設計図とイメージすると少し分かりやすくなります。
つまり、上記のスケッチの2行目と5行目では、Servoというクラス型の変数を作るための設計図を読み込んだ後、Servoというクラス型の変数を作成したということになります。
ライブラリ内の関数などを使用するための基本的な準備の説明は以上となります。
続いて、サーボライブラリ内の関数を使って、サーボを動かす文について、説明したいと思います。
スケッチの8行目で
8 |
int servo_pin=2; |
により、サーボモータに指令を与えるピンを指定して、13行目の
13 |
myservo.attach(servo_pin,500,2400); |
で、サーボモータの初期設定を行っています。
ここで、13行目では、5行目で宣言した変数「myservo」の中にある「attach()」という関数を使用しています。
上記のように、クラス型の変数の中にある関数を利用したい場合は、変数の名前の後に、ドット( . )を入力し、続けて使いたい関数を記述します。
「attach()」はサーボモータの初期設定を行う関数で、指令を与えるピン番号、指令で使用するパルス幅の最小と最大を[μs]単位で記述します。
今回のスケッチでは、パルス幅の最小と最大をそれぞれ、データシートに記載されていた、500[μs](0.5[ms])、2400[μs](2.4[ms])に設定しています。
また、出力ピンの設定を行う際には、「pinMode()」を使用していましたが、この「attach()」で指定したピンは関数の中で、出力ピンとして設定されるため、改めて「pinMode()」で出力ピンに設定する必要はありません。
最後に、「void loop()」内では、「delay()」で間を空けながら、以下のような文が繰り返されています。
19 |
myservo.write(0); |
この「write()」はサーボモータの角度を指定する関数であり、( )内に0~180の値を記述します。
ここで注意しなくてはならないのは、指定する値は0~180になるという点です。
「write()」は0という値をパルスの最小幅に、180という値をパルスの最大幅に割り当てます。
つまり、今回の場合は、以下の図のように角度が割り当てられるため、マイナスの値は扱いません。
また、360度軸が回転するようなものなど、サーボモータの種類によっては、扱い方が異なる場合があるため、どのような信号に対して、どう動くのかを先に確認しておくことをお勧めします。
Servoライブラリの注意点
「Arduino Uno R3」の場合、「Servoライブラリ」を使用している間は、9番ピンと10番ピンのPWMを使用することができません。
どのピンのPWMが使えなくなるかは、Arduinoボードに使われている、マイコンチップの種類によって変わります。
例えば、「Arduino Nano」の場合は、「Arduino Uno R3」と同じ「ATmega328P」というマイコンチップが使われているため、9番と10番ピンのPWMが使用できなくなりますが、「Arduino Mega 2560 R3」の場合は、「ATmega2560」というマイコンチップが使われているため、44、45、46番ピンのPWMが使用できなくなります。(「ATmega2560」の場合、サーボモータの数が12個増えるごとに、使えなくなるPWMピンの数が増えていきます)
また、「Servoライブラリ」は割り込み処理を利用して、サーボモータを制御しているため、「pulseIn関数」などの処理を邪魔する可能性があるので注意が必要となります。
Arduinoでサーボモータ(SG90)を動かす方法についての説明は以上となります。
今回の記事では、「Servoライブラリ」の一部を使ってサーボモータを動かす方法を説明しました。
「Arduino IDE」に付属しているライブラリの情報は、Arduinoの公式ホームページで確認することができます。
また、Arduinoの公式ホームページは英語で記述されていますが、それらの情報を日本語に直してまとめてくれているサイトも存在するので、分からないことがあった場合は、まず、それらを活用して、情報を集めると良いと思います。
それでも、欲しい情報が得られない場合や情報が本当か疑わしい場合は、ソースコードを見て確認するという方法がありますが、それについては、後日別の記事で説明したいと思います。
次回の記事では、ライブラリの説明をするときにも出てきた、関数を自分で作成する方法について説明したいと思います。
本記事はここまでです。ご清覧ありがとうございました。
広告
楽天モーションウィジェットとGoogleアドセンス広告です。
気になる商品がございましたら、チェックをしてみてください。