以前の記事、「Arduinoと市販のロボットアームでロボット制御の基本を学ぼう」では、超音波センサーで検出した物体に向かってロボットアームを伸ばす実験を行いました。
超音波センサーの精度もあり、緻密な制御は難しかったはずです。今回は、より正確にロボットアームを制御するために可変抵抗器(ポテンショメータ)を使用します。
可変抵抗器の回転に合わせて、ロボットアームの可動部分が動作するイメージです。
また本記事では、複数のサーボモータを、それぞれの可変抵抗器から独立して制御できるようにします。
目次
1. 可変抵抗器の動作
可変抵抗器は、英語では「potentiometer: ポテンショメータ」と呼ばれます。本来、ポテンショメータとは、回転角や移動量を調整するデバイスの総称ですが、そのデバイスの内部で可変抵抗器が使用されていることから、英語では「可変抵抗器=ポテンショメータ」と呼ばれるようになったようです。
日本語では、可変抵抗器の中でも、特に回転角や移動量を調整する用途に使用されるものを「ポテンショメータ」と呼びます。デバイスは同じものです。本記事では、混乱を避けるために「可変抵抗器」と呼び方を統一します。
可変抵抗器の機能はシンプルです。本体から伸びるシャフトの回転量に合わせて端子間の抵抗値が変化します。実際の電子機器では、この抵抗値の変化をボリュームの調整やライトの調光などに使用します。
一般的な可変抵抗器では、1番・2番・3番のピンを備えた3本のものが使われます。シャフトを回すことで「1番と2番」、「2番と3番」の端子間の抵抗値が変わります。
1番-2番の抵抗値が増えれば、その分2番-3番の抵抗値が減る関係です。
(端子名は製品によって異なる場合があるので、データーシートで確認してください。)
1番-2番の間にある抵抗と2番-3番の間にある抵抗は、2番の部分でつながっているイメージです。そこで、例えば「電源(+)・1番-2番・2番-3番・電源(-)」の回路を考えると、2番 の端子の電圧は、抵抗の分圧の計算で求めることができます。
電源の電圧を5Vとした場合、可変抵抗器のシャフトを回転させると、2番の電圧が0Vから5Vまで徐々に変化します。
今回の電子工作も、この仕組みを利用します。
この可変抵抗器の2番の電圧の変化を、Arduinoボードのアナログ入力ピンで測定します。
アナログ入力ピンから読み取った信号(0Vから5Vの間の電圧)は、ArduinoのA/D変換(「ADコンバータ」とも呼ばれます)を使って、0〜1023の整数値(1024段階)に変換され、スケッチへ送られます。
2. 準備
それでは、可変抵抗器を使ったサーボモータの制御を試してみましょう。
本記事では次のものを使用します。
Arduino Uno
可変抵抗器・ノブ
Arduino IDE
ロボットアーム
サーボモータを組み合わせて自作します。MeArmなどのキットも使用できます。
準備するものは、以前の記事、「Arduinoと市販のロボットアームでロボット制御の基本を学ぼう」と、ほぼ同じです。
違いは、超音波センサーを可変抵抗器に変更した点のみです。
可変抵抗器のシャフトには、ノブやスライダーなど、利用する機器に合った部品を取り付けることができます。
今回はノブを使用します。ノブは単に「つまみ」と呼ばれることがあります。
可変抵抗器のシャフト径に合う製品を選べば、特殊なものを除いて、どこのメーカーのものも利用できます。お好みで用意してください。
上記に加えて、USBケーブルが必要です。
本記事で使用した、ロボットアームのキットには、サーボモータが同梱されていました。サーボモータは別売りの場合があるので注意してください。
ホビー用のサーボモータであれば、どの製品も制御方法に大きな違いはありません。
ただし、シャフトの回転角に制限がない「連続回転サーボモータ」は、使用目的が異なるため今回は使用できません。
3. スケッチ全体
作成するスケッチは以下の通りです。
#include <Servo.h> Servo myservo1; // create servo object to control a servo Servo myservo2; // create servo object to control a servo int potpinA0 = 0; // Assign analog pin to potentiometer int potpinA1 = 1; // Assign analog pin to potentiometer int val0 = 0; // Variable to read value from potentiometer, starts at 0 int val1 = 0; // Variable to read value from potentiometer, starts at 0 void setup() { myservo1.attach(9); // attaches the servo on pin 9 to the servo object myservo2.attach(10); // attaches the servo on pin 10 to the servo object Serial.begin(9600); // This will allow you to read how far away your sensor is later } void loop() { val0 = analogRead(potpinA0); // Reads potentiometer value (between 0 and 1023) val0 = map(val0, 0, 1023, 110, 150); // Scale value to volume (value between 0 and 50) val1 = analogRead(potpinA1); // Reads potentiometer value (between 0 and 1023) val1 = map(val1, 0, 1023, 50, 170); // Scale value to volume (value between 0 and 50) Serial.print("Pin 1: "); Serial.print(val0); // Print dial/volume position Serial.print(", Pin 2: "); Serial.print(val1); // Print dial/volume position Serial.println(); myservo1.write(val0); // Sets servo 1 according to the scaled value delay(15); // Waits for the servo to get there myservo2.write(val1); // Sets servo 2 according to the scaled value delay(15); // Waits for the servo to get there }
4. 可変抵抗器をAD変換で読み取る
スケッチの大部分は、以前の記事、「Arduinoと市販のロボットアームでロボット制御の基本を学ぼう」で紹介したものと、ほぼ同じです。
ここでは、ArduinoのA/D変換を使って可変抵抗器の値を読み込む方法を中心に解説します。
スケッチの先頭部分で変数の定義と初期化を行っています。
int potpinA0 = 0; // Assign analog pin to potentiometer int val0 = 0; // Variable to read value from potentiometer, starts at 0
定義と初期化はsetup()関数の前に書く必要があります。
1行目の変数potpinA0は、可変抵抗器を接続したアナログ入力ピンの番号です。今回はArduinoボードのA0ピンに接続してあるので、変数を0で初期化します。
2行目の変数val0は、A0ピンから読み取った整数値を格納します。最小値を意味する0で初期化しておきます。
次は、実際にアナログ入力ピン(ここではA0ピン)からA/D変換した可変抵抗器の値を読み取る部分です。
val0 = analogRead(potpinA0); // Reads potentiometer value (between 0 and 1023) val0 = map(val0, 0, 1023, 110, 150); // Scale value to volume (value between 0 and 50)
1行目は、アナログ入力ピンから可変抵抗器の値を読み取り、変数val0に格納します。格納される値は、0〜1023の間の整数値です。
この値をサーボモータに回転角として指定するのですが、一般的なサーボモータの回転角は大きくても180度程度です。また、今回のロボットアームの動作などは、もう少し範囲が狭いのが普通です。使用したロボットアームの適当な動作角は、110〜150度の範囲でした。
そこで、2行目のmap()関数を使用して、0〜1023の値を、110〜150の範囲に収まるように調整します。
map()関数を使用することで、ここでは、val0の値が0の時(可変抵抗器の最小)は110に、1023の時(最大)は150のように変換し、その間の値は同じ比率で変換します。
map()関数の詳細は公式マニュアルを(英語)参照してください。
ロボットアームの最適な動作角は、実際に動作させながら調整したほうが良いでしょう。
Serial.print("Pin 1: "); Serial.print(val0); // Print dial/volume position Serial.print(", Pin 2: "); Serial.print(val1); // Print dial/volume position Serial.println();
Serial.で始まる行は、Arduinoボードが読み取った可変抵抗器の値(map()関数で調整された値)を、シリアルポートを通して送信します。このデータはArduino IDEのシリアルモニタで確認できます。
このシリアルモニタを使ったデバッグは、さまざまな状況で有用なテクニックです。
myservo1.write(val0); // Sets servo 1 according to the scaled value delay(15); // Waits for the servo to get there
最後に、write()関数で、サーボモータに回転角を指示します。
2行目のdelay()関数は、プログラムの実行を一時的に停止して、サーボモータの動作が完了するのを待つためのものです。
上記のスケッチには、可変抵抗器の値を読み取り、サーボモータに指示するソースコードが2組含まれます。これらは完全に独立して動作します。
もし、ロボットアームに2個所以上の可動部分があっても、同様に、可変抵抗器の読み取りとサーボモータへ指示を出す部分のソースコードを追加するだけです。
追加後はロボットアームの可動部分に合わせて、map()関数で回転角を調整することを忘れないでください。
5. 配線
サーボモータを使った電子工作を進める際は、配線する前にスケッチの作成を終え、Arduinoボードに転送しておくことをお勧めします。
それでは、パソコンにつながるUSBケーブルを一旦取り外して配線します。ブレッドボードを使うと便利です。
- 可変抵抗器の1番を、ArduinoボードのGNDピンに接続します。
- 可変抵抗器の2番を、ArduinoボードのA0ピンに接続します。
- 可変抵抗器の3番を、Arduinoボードの5Vピンに接続します。
可変抵抗器を2個以上使用する場合は、上記の手順を繰り返します。ただしA0ピンではなくA1ピンを使用してください。以降は空いているアナログ入力ピンを順次割り当ててください。
次はサーボモータの接続です。
- サーボモータのグランド線を、ArduinoボードのGNDピンに接続します。
- サーボモータの信号線を、Arduinoボードの9番ピンに接続します。
- サーボモータの電源線を、Arduinoボードの5Vピンに接続します。
サーボモータを2個以上使用する場合は、上記の手順を繰り返します。ただし9番ピンではなく10番ピンを使用し、以降は空いているデジタル入出力ピンを順次割り当ててください。
全ての配線が終わったら、Arduinoボードを再びパソコンに接続します。
可変抵抗器のノブを回すと、回転量に応じて、サーボモータが動作するはずです。サーボモータが複数接続されている場合は、それぞれに対応する可変抵抗器で独立して制御できます。
6. まとめ
全てのArduinoボードにはアナログ入力ピンが搭載されていますが、「何に使うのだろう?」と思う方は多いのではないでしょうか?
今回の電子工作のように、アナログ入力ピンに可変抵抗器を取り付けることで、サーボモータを正確に操作できるようになります。
Arduinoからホビー用のサーボモータを制御すること自体はそれほど難しくありません。慣れてくればプログラムでダイナミックに動作させることも夢ではないでしょう。
実用的な電子機器になると、今回の可変抵抗器を使用したサーボモータの制御のような、手動での操作方法がメンテナンス作業などの際に必要となります。簡単ですが、応用しやすい回路なので、しっかりとマスターしましょう。