読者です 読者をやめる 読者になる 読者になる

Arduinoでステッピングモーターを制御するライブラリ「Suteppa」

このライブラリ開発記録のその1はこちらです。

 ライブラリの改良等をしていたため少し書くのが遅くなりましたが、公開できるレベルにはなったので公開したいと思います。

github.com

Suteppaとは

 Suteppaは、Arduinoでのステッピングモーターの制御を助けるためのライブラリです。注意して頂きたいのは、このライブラリ自体にステッピングモーターを回転させる機能は無いという事です。少しややこしいですが、実際にモーターを回すコードを貼ります。

「1回転→1秒→逆に1回転→1秒」を繰り返すソース

gist.github.com

解説

void step(int d)
{
    static const int hs[8] = {省略};
    static int i;
    i += d;
    if(i > 7) i = 0;
    if(i < 0) i = 7;
    byte b = hs[i];
    digitalWrite(IN1, bitRead(b, 0));
    digitalWrite(IN2, bitRead(b, 1));
    digitalWrite(IN3, bitRead(b, 2));
    digitalWrite(IN4, bitRead(b, 3));
}

 stepという関数がありますが、これは1-2相励磁でステップさせるために用意した関数です。この関数をSuteppaのinitに渡しています。Suteppaは渡されたstepを使って回転させます。このような設計にした理由は、1-2相励磁以外のいろいろな方法に対応する為です。ほかの励磁方法や、またマイクロステップをさせたい場合もあると思います。そういった場合に備えてステップを刻む関数は自分で作って渡してもらう事にしました。
 引数のint dですが、これはステップ方向を示しています。Suteppaがstepを呼ぶとき、dには-11が入ります。dによって回転方向が変わるような設計にしてください。

s.init(4096, step);

 ここでSuteppaをinitしています。一回転のステップ数と、上で説明したstep用関数を渡しています。1回転のステップ数は用途によっては必要ですが、分からない場合や、DVDのモーターのような回転せずスライドするタイプの場合等は0でも良いです。これが必要になるケースは後ほど説明しますが、基本的に0で良いと考えてください。

//100ステップを加減速に使い, 開始速度は2000us
s.beginSmooth(100, 2000);
//通常速度は700us
s.setSpeed(700);

 beginSmoothメソッドは加減速をスムーズに行うための設定用メソッドです。ここでは、加減速に最大100ステップ(合わせて200ステップ)を使い、開始速度は2000usという設定にしています。
 setSpeedで通常の速度を設定します。つまり今回の場合、100ステップかけて2000usから700usまで加速し、100ステップかけて700usから2000usまで減速します。

※usが小さい方が早く、大きい方が遅く回るので注意です。

//4096ステップ回転
s.rotate(Suteppa::RELATIVE, 4096);
delay(1000);

//0ステップへ戻る
s.rotate(Suteppa::ABSOLUTE, 0);
delay(1000);

 rotateメソッドは第1引数で回転モードを、第2引数にはステップを指定ます。ステップは負にすれば逆回転します。
 Suteppa::RELATIVEは相対ステップで、Suteppa::ABSOLUTEは絶対ステップで回転させます。よって今回の場合、現在の位置から、4096ステップ回し、その後0ステップに戻る。という事になります。  第3引数を含めた詳しいrotateの解説は下で行います。以上でデモのソースコードの解説を終わります。

rotateメソッドとtick

 rotate(int mode, long step, bool sync)

Suteppa::RELATIVE

 相対ステップです。現在の位置から相対的にステップします。

Suteppa::ABSOLUTE

 絶対ステップです。デフォルト位置からのステップへ移動します。

Suteppa::ABSOLUTE_SKIP

 同じく絶対ステップですが、最短で移動します。たとえば、一回転360ステップのモーターの場合、270ステップ地点から、0ステップへ移動するためには、+90ステップするか、-270ステップするかの2通りがあります。このモードでは、+90して最短で移動します。注意すべきはここでステップは0になります。360にはなりません。

tick

 rotateメソッドのsyncは省略できます。デフォルトではtrueです。ただ、このままだとモーターが1台しか制御できないという問題点があります。以下がその例です。s1s2の2台のモーターを制御します。

Suteppa s1;
Suteppa s2;
//初期化省略
s1.rotate(Suteppa:ABSOLUTE, 100);
s2.rotate(Suteppa:ABSOLUTE, 100);
Serial.println("ok");

 しかし、これだとs1の回転が完了した後にs2が回転します。同時には回転しません。rotateメソッドが処理を止めてしまうのです。
 この問題を解決すべく、tickで回転を行うという方法を用意しました。

s1.rotate(Suteppa:ABSOLUTE, 100, false);
s2.rotate(Suteppa:ABSOLUTE, 100, false);
while(s1.tick() || s2.tick()){}
Serial.println("ok");

 こうするとs1s2が同時に回ります。tickはモーターを回すためのメソッドで、回転中はtrueを返し、完了すればfalseを返します。回転完了後にtickを呼び続けても平気です。それ以上回転することはありません。
 ソースを見ればわかりますが、rotateメソッドはsyncがtrueだった場合最後にwhile(tick()){}をしています。tickを呼ぶ周期は可能な限り短い方が良いです。最低でも50usごとには呼んでほしいです。それ以上だとスムーズな加減速が出来なくなります。

スピードとスムーズモード

 最初のサンプルコードでも使っていますが、スムーズモードがこのライブラリの特徴です。加減速を調整することで脱調を防ぐことが出来ます。またステッピングモーターを確実に最高速度で回すことが出来ます。

setSpeed(通常速度us);
beginSmooth(ステップ数, 開始速度us);

 開始速度usから通常速度usまでステップ数分のステップでスムージングします。

スムーズモードの有効化と無効化

s.setSpeed(900);
s.beginSmooth(100, 2000);
s.rotate(Suteppa::RELATIVE, 1024);
s.endSmooth();
s.rotate(Suteppa::RELATIVE, -1024);

 スムーズモードはbeginSmoothメソッドで有効化します。endSmoothメソッドを呼ぶことでスムーズモードを解除できます。上記の場合、1024ステップをスムーズモード(2000usから900usまでを100ステップでスムーズに変化)で移動し、スムーズを無効化したのち1024ステップ戻ります。

脱調する場合

 脱調は、急な加速や減速が原因なので、脱調する場合はステップ数を増やすか、開始速度usを下げます(数値を上げます)。ただし開始速度us通常速度usの差が開きすぎるのも良くありません。その分ステップ数を増やせばよいですが、そこらへんは調整してください。基本的にステッピングモーターが始動できる速度を開始速度usに当てはめるのが良いでしょう。

デフォルトスムーズ

 頻繁にスムーズモードを有効化したり無効化する場合、いちいち値をセットするのは面倒です。そこでsetDefaultSmoothを用意しました。

s.setDefaultSmooth(ステップ数, 開始速度us);
//色々省略
s.beginSmooth();
s.rotate(省略);
s.endSmooth();
s.rotate(省略);
s.beginSmooth();
s.rotate(省略);
s.endSmooth();

 一度defautSmoothをセットすればbeginSmoothするだけでスムーズモードを有効化できます。

基準点のセット

 setHomeメソッドを用意しました。このメソッドを呼んだ位置が0ステップとしてセットされます。キャリブレーションを行う時に使えます。例えば以下のように。

s.rotate(Suteppa::RELATIVE, -9999, false);
while(s.tick()){
    if(digitalRead(SW) == 1){
        break;
    }
}
s.setHome();
s.rotate(Suteppa::ABSOLUTE, 1024);

 先頭につけたスイッチ(SW)を押すまでマイナスへ回り続けます。tickごとにdigitalRead(SW)で先頭スイッチが押されたかを確認します。押されたらwhileを抜けて回転を中止。その位置をhomeにセット。その後1024絶対ステップで回す。という流れです。キャリブレーションも簡単に実装できますね。キャリブレーションのデモは別記事で詳しく書く予定です。

おまけ

static const int RELATIVE = 0;
static const int ABSOLUTE = 1;
static const int ABSOLUTE_SKIP = 2;

こうなっているので、長くて面倒な場合は数字でも良いです。