loading

内部クロック8MHzのArduino(ATmega328P-PU)では、servo.hを使って180度を指定すると、120度ぐらいは向いてくれているのですが、180度へ向いてくれないため、昨日から途方に暮れていたのですが、サーボモータのデータシートを見ていますと、頑張ればPWMを自分でも書けそうなので、データシートを元にサンプルスケッチを作成してみました。

servo.hのソースコードは確認していませんが、(きっと)内部クロック8MHzに対応していないかと思います・・・

内部クロック8MHzのArduinoのスペックは次の通り

  • ATMEGA328P-PU
  • ブートローダ:ATmegaBOOT_168_atmega328_pro_8MHz.hex
  • フューズビット:Low:0xE2, High:0xDA, Ext:0x05

Step 1: データシートからプログラムを作成してみる

いきなり8MHzは難しいので、とりあえず16Mhzから・・・

サーボモータ(SG90)のデータシートを眺めていると、20msecの中で、サーボの角度に応じてパルス幅(dutyCicle)を指定してやればよいみたいなので、16Mhzの場合は以下になります。

  1. digitalWrite( pin, HIGH );// ON
  2. delayMicroseconds( dutyCicle );
  3. digitalWrite( pin, LOW ); // OFF
  4. delayMicroseconds( 20000 - dutyCicle );

次に、パルス幅は0.5msec〜2.4msecとなっていますが、この値をそのまま入れて0度を指定するとモーターが止まりません。

そこで、Arduino 日本語リファレンスのattach(pin)を見ると、サーボの角度のパルス幅を書いてくれているのでそのまま利用します。

【Arduino 日本語リファレンス抜粋】

min (オプション): サーボの角度が0度のときのパルス幅(マイクロ秒)。デフォルトは544

max (オプション): サーボの角度が180度のときのパルス幅(マイクロ秒)。デフォルトは2400

  1. const int posision0 = (500 + 44) ; //0.5msec.(16MHz) ⇒ 0.544msec.(16MHz)
  2. const int posision180 = (2400 + 0) ; //2.4msec.(16MHz)

Step 2: しかし、動かないorz

最初は、次のようなコードを書いてみましたが、サーボモータがピクピクするだけで、ちゃんと回ってくれません。

サーボモータは回ろうとはしているので、何かサーボを回す条件が足りないようです。

const int pmwPin = 8; // PWM制御に8ピンを使用
//マニュアルどおりの秒数だとモータが回りっぱなしなので補正値(44msec)を入れる

const int posision0 = (500 + 44) ; //0.5msec.(16MHz) ⇒ 0.544msec.(16MHz)

const int posision180 = (2400 + 0) ; //2.4msec.(16MHz)

const float oneDeg = (posision180 - posision0) / 180.0;

void setup() {

pinMode( pmwPin, OUTPUT );

}

void loop(){

sg90write(pmwPin, 0 );

delay(1000);

sg90write(pmwPin, 180 );

delay(1000);

}

/*

* SG90 PWM control

*/

int sg90write(int pin, int deg) {

int dutyCicle;

if ( deg >= 0 && deg <= 180 ) {

dutyCicle = posision0 + deg * oneDeg;

digitalWrite( pin, HIGH );// ON

delayMicroseconds( dutyCicle );

digitalWrite( pin, LOW ); // OFF

delayMicroseconds( 20000 - dutyCicle ); //20ms(50Hz)(16Mhz) PWM Period

}

}

Step 3: そういえば、PWM ってPulse Width Modulationですよね

PWM Periodが20msecですと、20msec周期でオンとオフを繰り返えさないといけない・・・ですよね。

で、loopの中身を修正してみました。

unsigned long time = 0;
unsigned long nextTime = 0;

int deg = 0;

void loop() { time = millis();

//2秒間隔で0度と180度を切り替える

if (time >= nextTime) {

if (deg == 180)

  deg = 0;

else

  deg = 180;

  nextTime = time + 2000;

}

sg90write( pmwPin, deg );

}

Step 4: 16MHzで動作したので8MHzで試してみました

8MHzで動作しましたので、サンプルスケッチを置いておきます。

デジタルピン3, 5, 6, 9, 10,11ピン以外のピンでサーボモータを回すことができます。

もちろん、3, 5, 6, 9, 10,11でもサーボモータを回すことができます。

<p>Thanks for sharing your project!</p>

About This Instructable

1,328views

4favorites

Bio: Sanuki udon is one of &quot;Japanese taste&quot;. it is a food made of noodles of popular wheat in Japan. And my soul food. I'm ... More »
More by SANUKI UDON:How to Maek Game of Life Using ATtiny13A and Mini Breadboard. Mini Christmas tree made with ATtiny13a and mini breadboard. How to make Ladder game using ATtiny13a and mini breadboard. 
Add instructable to: