11 サーボモーターを動かしてみよう

ロボットを構成するサーボモーター



 サーボモーターは、PWM(パルス幅変調)の信号指令により指定角度位置に移動するデバイスです。あるパルス幅(停止点、例えば1ms)より狭ければ正回転、広ければ逆回転するのがサーボモーターです。
下記の図で、1msと書かれている幅(Duty Cycle)が角度情報になります。SG90の資料はこちら
BrainPadの上部に出力ピンがあります。左側がサーボモーター用で右側がDCモーター用です。 ピンのすぐ上部左側に~と印字されているところが信号線で、ここで用いるSG90の場合はオレンジの色です。-がグラウンド(接地)で茶色の線、真ん中の+は電源で赤の線になります。接続を間違えないでください。


 この指令の値は各サーボモーターによって異なります。従って、BrainPad.csには取りあえずの数値が入っているだけで、そのまま使っても正しく動作するとは限りません。以下の部分をソースファイルから探してください。

BrainPad.csのこの部分を探す
       public static void SetPosition(int position) {
            if (position < 0 || position > 180) throw new ArgumentOutOfRangeException("degrees", "degrees must be between 0 and 180.");

            Stop();

            output.Period = 20000;
            output.Duration = (uint)(1000.0 + ((position / 180.0) * 1000.0));

            Start();
        }


ここで用いるSG90の場合は、Duty Cycleが0.5~2.4msですので、正確には
500.0 + ((position / 180.0) * 1900.0)
この式の単位はμ秒です。
となりますが、個体差もあるので、実際に測定するのが良いでしょう。取りあえずそれらしく動かすだけならば、この式を用いてください。
以上の作業を行った上で、以下のサンプルプログラムを動かしてください。ただし、本当に180度動くかどうかはサーボモーターの仕様で決まります。

プログラム
void main()
{
    BrainPad.Display.Clear();
    int step = 5;
    BrainPad.ServoMotor.SetPosition(0);
    BrainPad.ServoMotor.Start();
    while (true)
    {
        for (int i = 0; i < 180; i += step)
        {
            BrainPad.ServoMotor.SetPosition(i);
            CPU.delay(30);
        }
        for (int i = 180; i > 0; i -= step)
        {
            BrainPad.ServoMotor.SetPosition(i);
            CPU.delay(30);
        }
    }
}
 1 
 2 
 3 関係ないが、ディスプレイを消去
 4 5度ずつ移動させる予定
 5 サーボモーターの初期位置(移動はしない)
 6 サーボモーター動作開始
 7 永久ループ
 8 
 9 0度からstep(5度)刻みで180度まで移動する予定
10 
11 サーボモーターを移動させる
12 推定移動時間
13 
14 逆方向に回転させる
15 
16 
17 
18 
19 
20 


サーボモーターを光量メーターにする

CdSで測定した光量をサーボモーターで指示させてみます。
暗くすると左に回るようにします。

光量メータ
        void main()
        {
            BrainPad.Display.Clear();
            BrainPad.ServoMotor.SetPosition(0);
            BrainPad.ServoMotor.Start();
            while (true)
            {
                int light = (int)((1-BrainPad.LightSensor.ReadLightLevel()) * 180);
                BrainPad.ServoMotor.SetPosition(light);
                CPU.delay(100);
            }
        }
 1 
 2 
 3 ディスプレイ消去
 4 ゼロの位置に設定
 5 サーボ始動
 6 永久ループ
 7 
 8 光量測定値を角度にする
 9 サーボモーターに動作指令
10 100ms待つ
11 
12 


拡張コネクタにサーボモーターをつなぐ
 BrainPadではボードの上部のピンの一つしか利用できません。ここでは、サーボモーターを複数利用できるように別のServoMotorクラスを利用します。
接続は、下図の拡張コネクタのところのPWMと書いてあるところが利用できます。しかし、ほかのデバイスとの兼ね合いで必ずしも使えるとは限りません。ここでは、E9の場所のPWM6を用います。
従ってサーボモーターの信号(オレンジ)はE6、+電源(赤)はE15、-(黒)はE16に接続します。
下図はBrainPadに印刷されている文字とは異なりますが、回路的にはこのようになっています。



拡張サーボモーターを光量メーターにする
ここで用いるSG90の場合は、0.5msが最小パルス幅、2.4msが最大パルス幅であるから、設定は以下のようにします。単位はμsです。
ServoMotor(CPU.E9, 500u, 2400u);

拡張サーボ光量メーター
        void main()
        {
            BrainPad.Display.Clear();
            BoeBotLib.ServoMotor sv = new BoeBotLib.ServoMotor(CPU.E9, 500u, 2400u);
            sv.Start();
            while (true)
            {
                int light = (int)((1 - BrainPad.LightSensor.ReadLightLevel()) * 180);
                sv.SetPosition(light);
                CPU.delay(100);
            }
        }
 1 
 2 
 3 ディスプレイ消去
 4 サーボモーターの設定、E9から信号が出る
 5 サーボモーター動作開始
 6 永久ループ
 7 
 8 光量測定値を角度にする
 9 角度位置に行かせる
10 時間待ち
11 
12 


サーボモーターを回転させる

基本的にサーボモーターの目的から言って回転するはずはありません。しかし、位置検出をさせないなどの改造を行えば、それは可能になります。
 このように改造したモータの特性は以下のグラフのような特性になります。

大体のスピードの直線性を利用するプログラムを作ってみます。それには、特性グラフの肩に当たる最低及び最大のスピードのパルス幅と停止位置のパルス幅を求める必要がありますが、ここでは、停止位置のみ正確に求め、後は体感的に設定してみます。本当は測定装置で求めるべきです。これらの値はサーボモーターによって異なります。

以下のプログラムは、パルス幅が900μsから1000μsの間にあるはずとあたりをつけています。実際にはこの間にあるとは限りませんので、この値を変更する必要があります。


停止位置を求めるプログラム
        private void main()
        {
            uint step = 5;
            BoeBotLib.ServoMotor sv = new BoeBotLib.ServoMotor(CPU.E9);
            sv.Start();
            while (true)
            {
                for (uint i = 900; i <= 1000; i += step)
                {
                    sv.SetSpeed(i);
                    Debug.Print(i + " ");
                    CPU.delay(500);
                }
                for (uint i = 1000; i >= 900; i -= step)
                {
                    sv.SetSpeed(i);
                    Debug.Print(i.ToString());
                    CPU.delay(500);
                }
            }
        }
 1 
 2 
 3 カウント幅
 4 E9のPWMを用いる
 5 PWM開始
 6 永久ループ
 7 
 8 900μsから1000μsまで
 9 
10 パルス幅の変更
11 VisualStudio側に表示
12 500ms待つ
13 
14 1000μsから900μsまで
15 
16  パルス幅の変更
17 VisualStudio側に表示
18 500ms待つ
19 
20 
21 




VisualStudioの右下の出力の部分に表示されます。サーボモーターが止まった時に表示されている数字が停止するパルス幅です。

ここでは、正回転を920μs、停止点950μs、逆回転を980μsとしていますが、各モーターによって異なっても不思議はありません。各自チェックしてください。正回転、逆回転は正確である必要はありません。move()メソッドの引数の単位はパーセントです。100は正回転で最速、-100は逆回転で最速となります。

正逆回転スピードチェック
        private void main()
        {
            BrainPad.Display.Clear();
            int step = 5;
            BoeBotLib.ServoMotor sv = new BoeBotLib.ServoMotor(CPU.E9, 920u, 950u, 980u);
            sv.Start();
            while (true)
            {
                for (int i = -100; i <= 100; i += step)
                {
                    sv.move(i);
                    CPU.delay(500);
                }
                for (int i = 100; i >= -100; i -= step)
                {
                    sv.move(i);
                    CPU.delay(500);
                }
            }
        }
 1 
 2 
 3 
 4 5%ずつスピードを変化させる
 5 拡張コネクタのE9にサーボモーターを繋げる
 6 +方向100%スピードの幅920μ秒、停止950μ秒
 7 -方向100%スピードの幅980μ秒で、信号スタート
 8 
 9 -100%のスピードから+100%のスピードで回転予定
10 
11 指定のスピードで回転させる
12 
13 
14 逆シーケンス
15 
16 
17 
18 
19 
20