強化したスイープ
マイクロコントローラのサーボモータ制御の一般的な入門として「スイープ」プログラムを使用します。これはArduino IDEをダウンロードするときに含まれるArduinoプログラミング例の主要部です。プログラムコードは、Arduinoサーボライブラリコマンドの機能を示し、サーボアームをその全範囲にわたってスイープさせるために必要な手順を文書化します。
いくつかの修正といくつかの外部デバイスの追加で、スイープサーボは調整可能な移動制限範囲で調整可能な速度で移動できる、より便利なデバイスになります。鉄道模型のレイアウト上の踏切のしゃ断器や模型飛行機のドア、着陸ギアの精密な動きなどホビーに関連した課題に、多く利用されています。
移動範囲と速度を決定するために使われる手順は、プログラミングとセンサの経験に応じて多くの方法で達成できます。この例では、3つのポテンショメータが標準スイープ回路に追加され、Arduinoコードのいくつかの改良がされます。このデモンストレーションの中心は、Atmega328Pマイクロコントローラー(μC)を使用するARDUINO MINI V5です。図1を参照ください。μCの入出力のすべてが使用されるわけではなく、将来的に追加の周辺機器を含めることができます。
設定
強化スイープ計画では、3個の外付ポテンショメータ入力、ON/OFFタクトスイッチ入力、LEDのセンター位置と動作制限表示器、1個のサーボを駆動する出力を含む、必要なすべての電源および入出力を接続したブレッドボードにμCを取り付けることから始まります。
ブレッドボードの配線レイアウトは図2に示す通りです。
注:Digi-KeyプロトタイプWebページにあるような標準のワイヤジャンパキット は、長さに応じて色分けされているため、ワイヤのルートによって色が変わることがあります。提供されている回路図は、 バルク・スプールからのカスタムカットワイヤを使用した(と思われる:不要)単色の配線を示しています。
必要な部品:
サーボ:180度 (1528-1083-ND), タクトスイッチ (450-1650-ND), ポテンショメータ (3310P-125-103L-ND), Arduino Mini 328 5V (1568-1055-ND). 発光ダイオード - 緑 (160-1130-ND). 発光ダイオード - 赤 (160-1127-ND), コンデンサ (445-8571-ND), Arduino プログラミング用USB/シリアルコンバータ (1050-1021-ND). 抵抗 10k (CF18JT10K0CT-ND).
レイアウトの考察
一般的なサーボは4.8~6.5VDCで動作し、負荷がかかっているときや方向を変えているときに最大3アンペアを消費します。サーボはμCから直接信号を受信しますが、Arduino Miniのオンボード電圧レギュレータはサーボに必要な電流レベルを供給できません。サーボの電源リードは6V電源に直接接続されていることに注意してください。μCにはレギュレータが搭載されているため、同じ6V電源で実行することができます。サーボとμCが別の電源で動作している場合、サーボがμCからの信号を認識するために、共通グラウンドにしなければなりません。この例では、タクトスイッチはμC経由でサーボをスタート/ストップをさせるために使われます。
訳注:
図2)接点を見やすくするため、いくつかのワイヤー経路を誇張して描いています。
コード(教育目的のため詳細に注釈)
/* The potentiometers are used to provide adjustable input on analog pins A0, A1, A2 The analog inputs are used for left and right limits in servo travel as well as servo travel speed. When deactivated, the servo returns to the nearest limit position at maximum speed. An LED on digital pin 8 indicates each crossing of the center servo position. An additional LED on pin 9 indicates the servo has reached the maximum limit. The tactile switch is pulled HIGH via a 10k resistor when not pressed. Pressing the button changes its state to LOW (direct connection to ground). */ /********************************* Configuration ************************************/
#include <Servo.h> //Include the Arduino servo library
Servo wiperServo; //Create a name for the servo/*************************** Declare and initialize variables ****************************/
int pos; int lastPos; //Current position variables
int leftServo; int rightServo; //Desired position variables
int servoSpeed = 2; //Set the initial servo speed/* startAngle variable - The left and right limit potentiometers can be adjusted to add/subtract an adjustable number of degrees between zero and 90 minus the startAngle variable. With the startAngle variable set at 70, the servo will travel 70 degrees from center before the pot adjustment has any effect. If the pot is set to zero, the servo will travel 70 degrees and then reverse direction. If the pot is set to its maximum, the servo will travel the full 90 degrees and then reverse direction. If the startAngle variable is set to 50 as another example, the limit potentiometers will have 40 degrees of adjustment. The higher the variable value, the finer the potentiometer control.
*/
int startAngle = 70;//Designate pin 2 as an interrupt for ON/OFF control using the tactile switch
const byte interruptPin = 2;//Set the system status flag. Also used for ON/OFF control
volatile byte flag = LOW;/**************************** Setup area - Runs one time ****************************/
void setup() {
pinMode(8, OUTPUT); pinMode(9, OUTPUT); //Set digital pins 8 and 9 as outputs//Flash red LED 3 times to indicate uC has entered setup mode.
for (int flash = 0; flash < 3; flash++)
{
digitalWrite(8, HIGH); delay(200); digitalWrite(8, LOW); delay(200);
}//Identify the servo signal digital pin
wiperServo.attach(10);//Identify interrupt pin, function to run on interrupt, HIGH to LOW detection
attachInterrupt(digitalPinToInterrupt(interruptPin), onOff, FALLING);//Read the analog level of uC pin A0, convert the 12bit value to a degree range (0-90),
rightServo = map(analogRead(A0), 0, 1023, 90, 0);//Confine the range of servo travel to the right of center to 0-90.
rightServo = constrain(rightServo, 0, 90);//Run the servo. The delay gives the servo time to reach its destination.
wiperServo.write(rightServo); delay(2000);//Read the analog level of uC pin A1, convert the 12bit value to a degree range (90-180),
leftServo = map(analogRead(A1), 0, 1023, 90, 180);//Confine the range of servo travel to the left of center to 90-180.
leftServo = constrain(leftServo, 90, 180);//Run the servo. The delay gives the servo time to reach its destination.
wiperServo.write(leftServo); delay(2000);//Flash an LED 3 times to indicate end of servo test.
for (int flash = 0; flash < 3; flash++)
{
digitalWrite(8, HIGH); delay(200); digitalWrite(8, LOW); delay(200);
}
//Remember the servo position as a starting point in the main program
lastPos = leftServo;} //End of setup
/************************* Main program - Loops continuously ***********************/
void loop() {
//Get 12bit value from speed potentiometer and map to desired output range
//Lower values of this variable cause higher servo speeds.
servoSpeed = map(analogRead(A2), 0, 1023, 0, 20);//Set range limits for speed - less than 2 will cause servo chatter
servoSpeed = constrain(servoSpeed, 2, 18);//Turn on the green LED if leftServo value is at the center position.
if (analogRead(A1) < 25)
{
leftServo = 90;
digitalWrite(8, HIGH);
delay(25);
}
else
{
leftServo = map(analogRead(A1), 26, 1023, 90 + startAngle, 180);
leftServo = constrain(leftServo, 90, 180);//Turn on the Red LED if leftServo is approaching the maximum position.
if (leftServo >= 175) digitalWrite(9, HIGH);
else digitalWrite(9, LOW);
}//Turn on the green LED if rightServo value is at the center position.
if (analogRead(A0) < 25)
{
rightServo = 90;
digitalWrite(8, HIGH);
delay(25);
}
else
{
rightServo = map(analogRead(A0), 26, 1023, 90 - startAngle, 0);
rightServo = constrain(rightServo, 0, 90);//Turn on the Red LED if rightServo is approaching the maximum position.
if (rightServo <= 5) digitalWrite(9, HIGH);
else digitalWrite(9, LOW);
}//The following responds to a tactile button press (High to Low transition).
if (flag)
{
if (lastPos > rightServo)//Continuous motion loop - from right limit to left limit for (pos = lastPos; pos >= rightServo; pos--)
{
//If the flag changes state (turned OFF), jump out of the loop
if (!flag) break;//Run the servo motion and LED indication function
runServo(servoSpeed);
}if (lastPos < leftServo)
//Continuous motion loop - from left limit to right limit
for (pos = lastPos; pos <= leftServo; pos++)
{
if (!flag) break;
runServo(servoSpeed);
}
}//If the flag, set by the switch, is false (OFF) enter this loop
if (!flag)
{
if (lastPos >= 90)
{
//If the last position is left of center, go to the left limit
wiperServo.write(leftServo);//Remember the current position.
pos = leftServo;
}
else
{
//If the last position is right of center, go to the right limit
wiperServo.write(rightServo);
//Remember the current position
pos = rightServo;
}
}
} //End of main program
カスタム関数
/*********************************** Custom Functions ******************************/ //The following function runs when a falling edge (HIGH to LOW) interrupt occurs (switch press is detected) void onOff() { //Toggle the flag status flag = !flag; }
//The following function runs when servo motion is required
void runServo(int rate)
{
//Send the position value to the servo
wiperServo.write(pos);//Remember the last position for determining which way to go home when flag is false
lastPos = pos;//Turn ON the green LED when at center
if (pos == 90) digitalWrite(8, HIGH);//Turn OFF the servo center indicator when at any angle other then 90
if (pos != 90) digitalWrite(8, LOW);//Stop for a moment when the servo arm reaches a limit before reversing direction.
if (pos == rightServo) delay(100);
if (pos == leftServo) delay(100);//Set the speed by delaying the time between position values
delay(rate);
}
//End of custom functions
要約
サーボモータは、信号を動きに変換する強力で実装しやすいデバイスです。上記のコードは2つの単純な変数 rightServo と leftServo を操作して、サーボモータに単純なスイープ関数以上の多くのことを実行させる方法を示しています。これらの同じ2つの変数を使用して、コードを簡単に変更することでさらに多くの可能性を得ることができます。タクトスイッチは磁気スイッチや論理出力を備えたその他のセンサーなど、HIGHからLOWへの信号を作り出すあらゆる種類のトリガデバイスに置き換えることができます。