ArduinoでDVDドライブのステッピングモーターを回す(スイッチでキャリブレーションする)

DVDドライブのモーターの回路は↓で紹介しています。 blog.takumus.com ステッピングモーター制御ライブラリSuteppaについては↓です。 blog.takumus.com

 DVDドライブのモーターがSuteppaを使って回せる!という事は紹介しました。そこで今回はもっと実用的なデモを行います。

私が手に入れたDVDドライブの仕様

 キャリブレーションの前に、まず私の手元にあるDVDドライブの仕様を調べましょう。以下のようになっています。
f:id:takumus:20161016124250p:plain  センサー部分が上下に動くように、軸がネジ状になっています。また、一番下に一番端に来たことを調べるためのスイッチが付いていました。
 一番下から上まで大体488ステップ(1-2相励磁で)必要なことも分かりました。ではこの仕組みをそのまま利用してセンサーを上下させてみたいと思います。

キャリブレーションする

 ステッピングモーターが現在の角度を把握できない(ロータリーエンコーダーなしで)という事はご存知だと思います。そんなステッピングモーターを制御するにはまず初期角度を設定する必要があります。こういった処理をキャリブレーションと言います
 今回は、とりあえず最大まで回してスイッチに触れたらそこをhomeとする。みたいなキャリブレーションを行いたいと思います。

スイッチへの食い込み?

 注意しなければならないことがあります。既にスイッチに深く食い込んでしまった状態でキャリブレーションを行うと、キャリブレーション開始と同時にその地点がhomeになります。モーターの力とスピードでスイッチを押した時と、元々押されたスイッチとで、homeにずれが生じます。

スイッチへの食い込み対策

 それを解決する方法として思いついたのが、まずスイッチ方向へゆっくり近づくのは同じですが、スイッチを押したら少し逆回転させ、再びスイッチを探す。というものです。確実にスイッチをモーターの力とスピードで押す。こうすることで正確なキャリブレーションが行えます。

スイッチへの食い込み対策の利点

 この方法を取る利点はもう一つあります。キャリブレーションは正確に行うため、基本低速で行うべきなのです。しかし、バーがスイッチから遠かった場合、スイッチに到達するまでとても時間がかかります。そこで今回の方法のように2度スイッチを押すことで、1度目のキャリブレーションを高速化し、スイッチを押したら2度目はその場所から少し戻り、ゆっくりキャリブレーションをするという事が出来ます。

ソース

gist.github.com

動画

 右側にスイッチがあります。一度右端に行って、ちょこっと戻る動作が確認できると思います。これがキャリブレーションです。その後は、紙で作った矢印とマーカーの位置から、正確に動いていることが分かると思います。
 Arduinoをリセットしてキャリブレーションからやり直させる。というのを何度か行っています。 www.youtube.com

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;

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

ステッピングモーター制御ライブラリを作りたい(その5)「脱調防止できるのか実験!」

その1はこちらです。

 前回のDVDのステッピングモーターで脱調防止実験を行います。実験は現在開発中のライブラリを用いて行いますが、すいません!前回、ライブラリの説明も次回行うと言いましたが、ボリュームがたっぷりになってしまうので、ライブラリの説明自体は今回は省略させてもらいます。が一応貼っておきます。
github.com

回路

前回同様です。

ソース

 実験用ソースは一応貼りますが、ライブラリの解説がないと分かりにくいので、今回はソースの説明はしません。次回ライブラリの解説をするときにこのソースの解説も行う予定です。長いので最後に貼ります。

いざ実験

まず、このお手本をご覧ください。

2000マイクロ秒 通常モード(お手本)

YouTube


 このお手本は、ライブラリによる脱調防止機能をオフにして撮影しています。ステップとステップの時間は2000マイクロ秒です。この時点では脱調防止機能オフでも正確な位置決めが出来ています。これと同じ動きを少し早くしてやってもらいます。

1300マイクロ秒 通常モード

YouTube


 こちらは1300マイクロ秒にしたバージョンですが、途中で脱調していることが分かると思います。お手本と同じ動きをしているつもりなのですが、脱調しているためぐちゃぐちゃになっています。

ここからが本番です

 通常モードでは1300マイクロ秒で脱調してしまいました。ここからは脱調を防止したライブラリを使用したスムーズモードでの実験となります。

1300マイクロ秒 スムーズモード

YouTube


 どうでしょうか。通常モードでは脱調してしまった1300マイクロ秒を難なく突破です。スムーズモードは動画ではわかりにくいですが加減速をしています。最高速度はしっかりと1300マイクロ秒に達しています。

スムーズモードについての詳しい説明は、その2で行っています。S字加速を使用した方式ですので是非ご覧ください。

950マイクロ秒 スムーズモード

YouTube


 どこまでいけるかと思い下げていくと、950が限界のようです。ですが、スムーズモードだとここまで高速に動けることが分かります。

おまけ

 スムーズモードが動画だと分かりにくいので、加減速をより強調した設定にして動かしてみました。この動画だと加減速がはっきりわかると思います。

YouTube


次回

ライブラリの説明とソースコードの説明を行います。

ソース

gist.github.com

その6(最後)はこちらです。