著者:Ben Roloff、最終更新日:2019年1月22日
はじめに
DCサーボモータは、簡単に駆動できるように作られており、今ではただドロップインするだけで使える装置です。追加の回路を必要とする通常のDCモータとは異なります。DCモータにHブリッジ回路を内蔵し、さらにフィードバックループも搭載しています。これにより、連続運転が簡単に運転できるDCモータ、または任意の角度に移動できる位置決めモータにすることができます。単純なサーボモータの良いところは、通常、3本の配線が付属していることです。1本は電源、1本はグランド、3本目は信号です。角度、方向、および速度の制御は、単純なPWM(パルス幅変調)信号で実行されます。そのため、手軽に始められるモータとなっています。
サーボモータ
サーボモータで最初に見るべきものはデータシートです。データシートには、より多くのデータが記載されているものもありますが、最も重要なのはPWM信号に関する情報です。多くのサーボモータのPWM信号は、周期21.5ms、デューティサイクル7%程度です。つまり、約1.5msの間オン、20msの間オフということです。これは通常、サーボモータの90度位置または停止位置にあたります。オンの時間を 1.5msより長くすると、サーボが 180度に近づく、つまり時計回りに動くようになります。逆に1.5msより短くすると、反対方向の、0度に向かって反時計回りに動きます。その両極端は、通常2.25msと0.75ms程度です。 この値はサーボモータによって異なります。 もう1つの重要なポイントは、コードを書いた後、それがどの程度正確にms値に対応しているかをテストする必要があり、正しいゼロ点(停止位置)を得るために調整する必要があるかもしれないことです。
ソフトウェア
Arduino
ほとんどのマイクロコントローラには、PWM信号を生成できるように設定されたタイマが搭載されています。Arduinoを使用している場合、こちらに示すように、ArduinoのIDEを使用して必要な信号を作成するのは非常に簡単です。Arduinoにはサーボライブラリが内蔵されており、サンプルプログラムもいくつか用意されているので、すぐに使い始めることができます。ほとんどのマイクロコントローラは、そのような非常に簡単な設定はありませんが、一般的にPWM信号は非常に短い簡単なコードです。
SCTimer
LPC 812は、カウンタとPWM信号にSCTimerを使用しています。LPC 812を使い始めるには、こちらをご覧ください。このタイマは、異なるステートを使用できることを考えると、他のものより少し優れています。このタイマのもう1つの良いところは、32ビットタイマを使うことも、16ビットタイマを2つ使うこともできることです。信号を発生させるためにマッチとイベントを使用します。これにより、簡単に好きな信号を作ることができ、入力に応じたプリセットの変化を持たせることができます。コードにあるように、イベントとマッチを設定することが大きなポイントですが、それが終われば簡単に使うことができます。マッチの値を変更したい場合は、reload変数を使用することを確認してください。下のオシロスコープの写真で、目的のPWM信号の出力されているのが確認できます。
Servo_Init()
#define Count_ms 0.001*SystemCoreClock // global variable for getting a ms value from the System Clock
void Servo_Init()
{
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<8); // enable the clock for the SCT
LPC_SYSCON->PRESETCTRL |= (1<<8); // disable reset
LPC_SWM->PINASSIGN6 = 0x6ffffff; // assign SCT output 0 to pin 6
LPC_IOCON->PIO0_6 |= (1<<5); // this enables hysteresis
LPC_SCT->CONFIG |= 1; // use one 32 bit timer
LPC_SCT->CONFIG |= (1<<17); // autolimit with match 0
LPC_SCT->REGMODE_L = (0); // this makes all the match registers match and not capture registers
LPC_SCT->MATCH[0].U = 21.5*Count_ms; // set limit at off time of 20 ms and desired duty cycle of 1.5 ms
LPC_SCT->MATCHREL[0].U = LPC_SCT->MATCH[0].U; // load the reload value
LPC_SCT->EVENT[0].CTRL |= 0; // set event 0 to match 0
LPC_SCT->EVENT[0].CTRL |= (1<<12); // set event 0 to trigger on match
LPC_SCT->EVENT[0].STATE |= 0x1; // event 0 operates in state 0
LPC_SCT->MATCH[1].U = 20*Count_ms; // set match 1 to the off time of 20 ms
LPC_SCT->MATCHREL[1].U = LPC_SCT->MATCH[1].U; // load reload value
LPC_SCT->EVENT[1].CTRL |= 1; //set event 1 to match 1
LPC_SCT->EVENT[1].CTRL |= (1<<12); // set event 1 to trigger on match
LPC_SCT->EVENT[1].STATE |= 0x1; // event 1 operates in state 0
LPC_SCT->OUT[0].SET |= (1<<1); // output is set at event 1
LPC_SCT->OUT[0].CLR |= (1<<0); // output is cleared at event 0
LPC_SCT->CTRL_U &=~(1<<2); // turn off halt bit
}
Main()
Servo_Init(); // initialize the SCT pwm
while(1) {
for(i = 0; i < 300000; i++); // random delay
LPC_SCT->CTRL_U |= (1<<2); // turn on halt bit
LPC_SCT->MATCHREL[0].U = 20.75*Count_ms; // change reload of limit
LPC_SCT->CTRL_U &=~(1<<2); // turn off halt bit
for(i = 0; i < 300000; i++); // random delay
LPC_SCT->CTRL_U |= (1<<2); // turn on halt bit
LPC_SCT->MATCHREL[0].U = 22.25*Count_ms; // change reload of limit
LPC_SCT->CTRL_U &=~(1<<2); // turn off halt bit
for(i = 0; i < 300000; i++); // random delay
LPC_SCT->CTRL_U |= (1<<2); // turn on halt bit
LPC_SCT->MATCHREL[0].U = 21.5*Count_ms; // change reload limit
LPC_SCT->CTRL_U &=~(1<<2); // turn off halt bit
}
TMR
ほかによく見かけるのは、PWM信号のTMRタイマです。これは基本的なタイマです。PWM信号の生成には、通常、周期とデューティサイクルを設定します。このPWM信号のスタイルについては、こちらを参照してください。この例では、周期とデューティサイクルを変更する必要があります。
TMR用のPWMコード
//This code was borrowed from http://www.eewiki.net/display/microcontroller/Getting+Started+with+NXP%27s+LPC11XX+Cortex-M0+ARM+Microcontrollers
//Author: Justin Clack
#include "LPC11xx.h"
int main(void) {
//Set up 16 bit timer for PWM operation
LPC_IOCON->PIO0_8 = (LPC_IOCON->PIO0_8 & ~(0x3FF)) | 0x2; //set up pin for PWM use (sec 7.4.23)
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<7); //enable clock signal to 16 bit timer0 (sec 3.5.14)
LPC_TMR16B0->PR = 0x0; //set prescaler max value, not used here (sec 18.7.4)
LPC_TMR16B0->MCR = 0x10; //set for reset on counter match (sec 18.7.6)
LPC_TMR16B0->EMR |= 0x20; //set pin 27 to 1 on match (sec 18.7.10)
LPC_TMR16B0->CCR = 0; //set to timer mode (sec 18.7.11)
LPC_TMR16B0->PWMC = 0x1; //set channel zero to PWM mode (sec 18.7.12)
LPC_TMR16B0->MR1 = 0x32; //set value for period (sec 18.7.7)
LPC_TMR16B0->MR0 = 0xC; //set value for duty cycle (sec 18.7.7)
LPC_TMR16B0->TCR |= 0x3; //enable and reset counter (sec 18.7.2)
LPC_TMR16B0->TCR &= ~(0x2); //clear reset bit (sec 18.7.2)
while(1){ //infinite loop
}
return 0 ;
}
力ずくの方法
GPIOピンを使ってダミーのものを作り、自分でタイミングをとることができます。しかし、これは力ずくのやり方で、正確性に欠け、多くの欠点があります。信号が他のコードから分離して実行されていないため、他の関数呼び出しやコードによってタイマが変更されてしまいます。つまり、そのすべてを考慮しなければならないか、あるいはこのコードが実行するのはこれだけである可能性があり、あまり有用ではないのです。オシロスコープ出力で、PWM信号が作れることがわかりますが、正しい信号にするためには、少し作業が必要です。
GPIO_PWM_Init()
void delay_ms(int x)
{
int i;
for(i = 0; i < (x*1000); i++); // random delay to get as close as possible to a ms
return;
}
delay_msソースを展開
Main() ソースを展開
結論
サーボモータは、かなり簡単に動かすことができます。おそらく、最も動作させやすい電気モータでしょう。必要なのはPWM信号だけです。PWM信号の生成は、ほとんどのマイクロコントローラでかなり一般的に行われています。このC言語コードは普遍的なものではありませんが、少なくともあなたのマイクロコントローラの第一歩としては良いものになるはずです。サーボモータを動かすのはロケット科学のように難しいものではなく、簡単に使えるように設計されています。
Useful Links
LPC 812 User Manual
AN11538_SCTimer_PWM_Cookbook v5.0.pdf (1.8 MB)