google-site-verification: google3bd66dd162ef54c7.html
fc2ブログ

Arduinoを使ってDVDのスピンドルモーターを高速回転

◆まえがき
Arduinoを使ってモーターを回す実験のたぶん最終回になると思います。前回はDVDのスピンドルモーターを低速回転させましたが、今回は思いっきり高速で回転させてみます。

◆回路図
ずっと同じ回路なのですが、再度掲載しておきます。
回路図
NANOをUSB電源で動かす場合は、VINに繋がっている線を外します。
同時にモーターの2つのコイルに通電しているので、2Aくらいの容量の電源が必要になります。

◆外観
DVDのスピンドルモーターをArduinoで廻す

◆プログラム
ちょっと長いですが、見える形で掲載しておきます。
// 誘導モーターの実験(外側回転子)20230106_DVDmotorHighSpeedDriveCharange
// 三相矩形波駆動。6ポジション励磁, 1回転=36パルス
// 2023/1/6 ラジオペンチ http://radiopench.blog96.fc2.com/

#define PERIOD_MIN  42.0      // 最速周期(x10usの値) 42=0.42ms、1回転36パルスなので60/(0.42ms*36)=3968rpm
#define PERIOD_MAX  1000.0    // 開始時周期(x10usの値)
#define ACC_RATE    0.998     // 加速レート(1パルス毎の周期の変化率)

float periodF;
int   period;

void setup() {
  Serial.begin(115200);
  pinMode( 9, OUTPUT);  // R相
  pinMode(10, OUTPUT);  // S
  pinMode(11, OUTPUT);  // T
  pinMode(13, OUTPUT);
}

void loop() {
  periodF = PERIOD_MAX;

  for (int n = 0; n < 50 * 36; n++) {   // 正転加速
    stepDrive(1, period);
    acc();
  }
  digitalWrite(13, HIGH);               // 最高速運転中表示ON
  for (int n = 0; n < 150 * 36; n++) {  // 高速運転
    stepDrive(1, period);
  }
  digitalWrite(13, LOW);                // 最高速運転中表示OFF

  for (int n = 0; n < 44 * 36; n++) {   // 減速
    stepDrive(1, period);
    deAcc();
  }

  stepDrive(0, period);        // モーター電源OFFして待機
  delay(1000);

  periodF = PERIOD_MAX;
  for (int n = 0; n < 50 * 36; n++) {   // 逆転加速
    stepDrive(-1, period);
    acc();
  }
  digitalWrite(13, HIGH);               // 定速運転中表示
  for (int n = 0; n < 150 * 36; n++) {  // 高速運転
    stepDrive(-1, period);
  }
  digitalWrite(13, LOW);                // 定速運転中表示

  for (int n = 0; n < 44 * 36; n++) {   // 減速
    stepDrive(-1, period);
    deAcc();
  }
  stepDrive(0, period);      // モーター電源OFFして待機
  delay(1000);
}

void acc() {                       // 加速
  if (periodF > PERIOD_MIN) {
    periodF = periodF * ACC_RATE;  // パルス間隔を短縮
    period = periodF;              // タイマー設定用に整数化
  }
}

void deAcc() {                     // 減速
  if (periodF < PERIOD_MAX) {
    periodF = periodF / ACC_RATE;  // パルス間隔を延長
    period = periodF;
  }
}

void stepDrive(int mode, int t) { // mode 1=CW, 0=OFF, -1=CCW、t=待機時間(10usステップ)
  static long phaseN = 1;         // 位相カウンタ
  if (mode != 0) {                // 停止指示で無く、
    if (mode > 0) {               // CW指定なら、
      phaseN++;                   // 位相を一つ進め
      if (phaseN == 7) {          // 1回転していたら、
        phaseN = 1;               // 先頭に戻す
      }
    } else if (mode < 0)  {       // CCW指定なら、      
      phaseN--;                   // 位相を一つ戻し
      if (phaseN == 0) {          // 1回転していたら、
        phaseN = 6;               // 先頭に戻す
      }
    }
    switch (phaseN) {                 // 位相番号に合わせコイルを励磁
      case 1:
        PORTB |= _BV(1);              // HIGH D9
        PORTB &= (~_BV(2) & ~_BV(3)); // LOW  D10, D11
        break;
      case 2:
        PORTB |= (_BV(1) | _BV(2));   // HIGH D9, D10
        PORTB &= ~_BV(3);             // LOW  D11
        break;
      case 3:
        PORTB |= _BV(2) ;             // HIGH D10
        PORTB &= (~_BV(1) & ~_BV(3)); // LOW  D9, D11
        break;
      case 4:
        PORTB |= (_BV(2) | _BV(3)) ;  // HIGH D10, D11
        PORTB &= ~_BV(1);             // LOW  D9
        break;
      case 5:
        PORTB |= _BV(3) ;             // HIGH D11
        PORTB &= (~_BV(1) & ~_BV(2)); // LOW  D9, D10
        break;
      case 6:
        PORTB |= (_BV(1) | _BV(3)) ;  // HIGH D9, D11
        PORTB &= ~_BV(2);             // LOW  D10
        break;
    }
    for (int n = 0; n < t; n++) {     // 10μ刻みの時間待つ
      delayMicroseconds(10);          // 実際には4μ刻みの値になるが気にしないことにする
    }
  }
  else {                              // 停止指示なら
    PORTB &= (~_BV(1) & ~_BV(2) & ~_BV(3)); // コイル励磁OFF(全ピンLow)
//    Serial.println("Moter pow OFF");
  }
}
出来るだけスイッチング速度を上げたいので digitalWriteは使わずPORTBレジスタを直接操作しています。

いきなり最大速度で廻すことは出来ないので、定率で加速/減速するようになっています。丁寧にやるならS字カーブで制御した方が良いのですが、そこまで手が回りません。

発熱量を出来るだけ減らすため、停止時にはコイルの励磁を切っていますが、これによりホールディングトルクが無くなっています。ホールドしたい場合はモーター電源OFFの行をコメントアウトします。なお、こんな小技では無く、低速時はコイルの通電角を狭くして消費電流を減らす制御を行った良いのですがそこまで出来ませんでした。

◆動いている様子
オシロに表示しているのはコイルへの通電指定パルスです。(停止時OFF機能は切っています)

◆まとめ
DVDのスピンドルモーターを最高で約4000rpmで廻すことが出来ました。PM同期モーターとして動いているのでパルスモーターと同じで、ぴったりと同じ角度で停止させることが出来ます。パルスモーターは(たぶん)こんな高速では回らないと思います。

DVDのスピンドルモーターをいろいろいじってきました。本来はホールセンサーを使ったDCブラシレスモーターなのですが、ホールセンサーを使わないでマイコンからコイルの通電を制御する、つまりオープン制御で動かしても結構まともに動くことが判りました。ちょっとしたメカを動かすのに便利だと思います。

もちろんホールセンサーを使ってローターの位置を把握した制御を行った方が効率は良くなりますが、急に難易度が高くなるので簡単ではありません。
関連記事

コメントの投稿

管理者にだけ表示を許可する

カレンダー
05 | 2023/06 | 07
- - - - 1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 -
プロフィール

ラジオペンチ

Author:ラジオペンチ
電子工作を中心としたブログです。たまに近所(東京都稲城市)の話題など。60過ぎて視力や器用さの衰えを感じつつ日々挑戦!
コメントを入れる時にメールアドレスの記入は不要です。なお、非公開コメントは受け付けていません。
記事の内容のご利用は読者の自己責任でお願いします。

記事が気に入ったらクリックを!
最新記事
カテゴリ
最新コメント
リンク
FC2カウンター
検索フォーム
月別アーカイブ
RSSリンクの表示
QRコード
QRコード