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

DVDのスピンドルモーターを低速回転させる-続編

◆まえがき
以前DVDのスピンドルモーターを低速回転させましたが、回転速度に少しムラがあるのが気になっていました。

セルシンを作った時も回転ムラの問題があったのですが、この時のモーターは3相(3ポール)のコイルに対して磁石は1対。つまり1回転の中で磁気的にロックされるポジションは1つしか無いので、まあ仕方ないかなという感じでした。

一方で、このDVDのモーターは1回転で磁気的にロックされる位置が6箇所あります。つまり、もっと滑らかに回転出来るはずなのに、目に見えるような回転ムラが発生するが残念でした。

回転ムラを減らすには、マスダンパーを付けるなどのメカニカルな対策が考えられますが、電気的な駆動条件の調節で対策出来ればそれに越したことはありません。

そんなことで、駆動力と回転速度を運転中に変更出来るようにして、その効果を確認してみました。

◆回路図
回路図
VR1とVR2でモーター電流と回転速度を運転中に変更出来るようにしました。

モーター電源は最大1.5Aくらい流れるので別ルートから供給しています。回路図に示していませんが、Arduino NANOの電源はUSB電源など別系統から供給する必要があります。パワーを上げないならモーター電源をNANOの+5Vから取る手もありますが、その場合はボードの電流供給能力に注意する必要があります。
・外観
ブレッドボード

◆プログラム
Arduino UNO/NANOで使うことを想定したスケッチです。
// DVDスピンドルモーターの3相アナログ駆動テスト
// 可変抵抗で駆動パワー、回転速度を指定可能にした
// 20230427_3PhaseMotorDrive

int ax;          // モーターの角度

void setup() {
  pinMode(8, OUTPUT);          // 動作速度測定用
  pinMode(7, INPUT_PULLUP);    // 回転方向設定(HIGH or LOW)
  Serial.begin(115200);
  ax = 0;                      // 角度設定変数(0-360度で指定)
  angle(ax);                   // ホームポジションに移動 
  delay(1000);
}

void loop() {
  if (digitalRead(7) == HIGH) {  // 回転方向スイッチがOFFなら
    ax ++;                       // CW
    if (ax > 360) {
      ax = 0;
    }
  } else {                       // OFFなら
    ax --;                       // CCW
    if (ax < 0) {
      ax = 360;
    }
  }
  angle(ax);                     // 指定角度に回転
}

void angle(int a) {                     // 指定された位相でコイルを駆動.位相は度の値で指定
  int r, s, t;
  float pow_r, pow_s, pow_t;
  float magPow;
  int  rotInt;                          // インターバル

  magPow = 120.0 * analogRead(A0) / 1024.0;             // 磁界の強さ設定 (130us)
  rotInt = 500 * (1.0 - analogRead(A1) / 1024.0) - 30;  // 回転速度決定、値は0.1usステップ、-30はオフセット補正(130us)
  if (rotInt < 0) {                                     // 負の値になった時の後始末
    rotInt = 0;
  }

  pow_r = cos(PI * a / 180.0);          // 位相に相当するパワーを設定(175us)
  pow_s = cos(PI * (a + 120 ) / 180.0); // 位相 +120度            (175us)
  pow_t = cos(PI * (a - 120 ) / 180.0); // 位相 -120度            (175us)
  r = (pow_r * magPow) + 125;           // 振幅125±magPowでスイング(255近傍は怪しいので避ける)
  s = (pow_s * magPow) + 125;
  t = (pow_t * magPow) + 125;
  analogWrite( 9, r);                   // アナログ(PWM)出力
  analogWrite(10, s);
  analogWrite(11, t);
  delay100us(rotInt);                   // 指定時間待機して回転速度を調整
  Serial.print(magPow); Serial.print(", "); Serial.print(rotInt); Serial.print(", ");
  Serial.print(r); Serial.print(", "); Serial.print(s); Serial.print(", "); Serial.println(t);
}

void delay100us(int t) {           // 引数*100μs 待機
  // delayMicroseconds は16383us以上の値が設定出来ないのでこの関数を使う
  for (int i = 0; i < t; i++) {    // 指定回数
    delayMicroseconds(100);        // 100us待機
  }
}
PWMで三相のパワーを調整してモーターを駆動するようになっています。

37, 38行目のAnalogReadで可変抵抗の値を読み、励磁パワーと回転速度を設定しています。

回転速度は1回転当たり4.7秒から1分45秒の範囲で変更可能になっています。

angle( ) の関数内でモーターのコイルの励磁条件を設定しており、コメント内に書き込んである(130us)などの数字はその行の実行時間です。cosの値を計算するのに175us掛かっているのがこの関数の実行時間の足を引っ張っています。ここをテーブル参照方式などに変更すれば、処理時間を短く出来て最高回転速度をもっと上げることが出来るはずです。

◆動作テスト
全体
ターンテーブルに載せる物を変えたりしてテスト。

パワーを調節することで、(目で見る限りは)回転ムラを感じない駆動条件に設定することが出来ました。なお、パワーを下げ過ぎるとスリップして回転停止。パワーを必要以上に上げると回転ムラが発生し、またモーターが加熱します。

・動画(ツイッター)
回転数を調整している様子です。

◆HDDのスピンドルモーターを回す
面白いので、同じ回路を使って壊れたHDDのスピンドルモーターを回してみました。コイルはY結線になっていてピンは4本出ているので、中点以外の3ピンに接続します。(中点はピン間の抵抗を測定すれば判ります)

HDDのスピンドル

HDD
流軸のスピンドルを低速で廻したのでは本来の性能は出ませんが、それでもそのあたりに転がっている軸受けよりは精度が高いと思います。

◆まとめ
駆動パワーを調整することで回転ムラを目立たなくすることが出来ました。作品をデモする時などにあれば便利かも知れません。

こういうエレメカ物は対策の効果が目で見て判るので、いじっていて楽しいですね。

電源の時差測定結果のオフセット拡大とその対策

◆まえがき
電源周波数モニタ(50Hz)の時差測定結果にオフセットが目立つようになってきたので、原因の調査と対策を行いました。

◆時差測定結果の状況
2022年の8月の終わり頃からGPSの1PPSパルスを基準とした時差測定を開始しました。快調に動いていると思っていたのですが、最近の時差の平均値が+2秒付近になっていて負の値になることはめったに無くなっていました。本来ならゼロを中心に正負に振れていて欲しいのでちょっと残念な状況です。

時差の値がゼロの状態は電力会社の中の人にしか判らないので、相対的な変化が判ればとりあえずは良いのですが、それでも徐々に値が上にずれていくのはやっぱりまずいです。

・時差の測定値の変化
過去4か月の時差の変化
グラフがギザギザしているのは電源の需給状況を反映していて、矢印で示すような大きなピークは周波数の変動の時間が長かったことを表わしています。

測定開始から10月中旬あたりまでは、ばらつきの中心はほぼ一定で、10月10日時点の分析では、平均値は+0.5Hz付近にありました。

10月23日以降は中心値が僅かに右上がりの傾向に変わっていて、直近では+2Hzも中心値が上にズレていることが判ります。140日で平均値が1.5秒増加していますが、これを周波数の精度に換算すると 4E-8 の誤差に過ぎません。でもGPSがこんなにズレていることは考えられないし、東京電力の実力がこの程度である訳は無いので、うちの測定系に何か問題がありそうです。

◆調査
GPSモジュールの位置を変えたりしていると、1PPSの確認LEDが激しく点滅することがありました。このGPSモジュールは衛星をロストしたらすぐに判る様に、1PPS信号を8PPSで出力するように設定しています。つまり、衛星をロストしていたようです。簡単にロストすることは無いと思っていたのですが、たまたま衛星の位置が悪かった?あるいは感度劣化があるのかも知れません。

8PPSで信号が出るとソフト側は無視するようになっているので時差変化無しと見なす、つまり同じ時差の値が報告されるはずです。だったら値が変化しなかった回数をカウントしてグラフで確認してみました。

・変化ゼロの回数の変化
ゼロ発生回数の累積


普通に測定していても時差の値が変化しない場合もあるので右上がりのグラフになります。ただ赤矢印のタイミングで明らかに変化が認められます。つまりこのタイミングで衛星をロストしていた可能性があります。

10月半ばから異常が始まっていることから思い当たるのが、窓に付いている虫よけ網のアルミサッシの位置です。気温が下がったことで窓の開け方が変わり、防虫ネットの位置変わったためにGPSのアンテナの視界を遮るようになった可能性がありそうです。

細かい話になりますが、8PPSで信号が来るとソフトで異常を検出して測定を行わない仕掛けになっています。つまりそれだけでは時差が増えたり減ったりはしないはずです。ただその切り替えのタイミングでは不正確な1PPS信号が出来てしまうので、その影響を受けてプラス側に誤差が出易くなるメカニズムが存在しているのだと推定しています。

◆対策
GPSモジュールの取り付け状態
GPSモジュールを窓に貼り付ける位置を少し内側に移動しました。そのままではモジュールのケースにぶつかって窓が全開出来なくなるので、ケースを薄型の物に作り直しました。なおここは普段はカーテンの影になるので目立たない位置です。

・網戸の枠の干渉
網戸の枠が干渉
この位置に網戸が来るとGPSアンテナを遮っちゃうのですが、そういう使い方はしないので気にしないことにしました。

◆測定系をリセット
リセット実施
対策が出来たので測定系をリセットしました。リセット直前の前の時差は+1.66秒だったのがゼロになりました。つまり、2023年1月10日 9:30の時点で測定結果には-1.66秒のオフセットがかかったことになります。

なお、リセットは商用電源とUTCの時差が少ない時に行った方が測定結果のオフセットが小さくなって好都合です。実は、休日明けの火曜日の朝の8時から10時はこれまでの経験からUTCに対する商用電源の時差が少ないことが判っているので、このタイミングを狙ってリセットを行いました。

・リセット後
電源周波数モニタ
本体に表示されている時差の値もゼロになりましたが、すぐに値は変化します。

◆まとめ
完全な対策にはなっていない可能性があるのですが、とりあえずこの状態で様子を見たいと思います。

予備として屋外にアンテナを設置出来るタイプのGPSモジュールを入手しておこうと思います。ただ、数年ぶりにAliExpressでGPSモジュールを探すとずいぶん値段が高くなっていて、「外れでも良いから買っちゃえー」なんて気楽に注文出せない値段になっていました。だんだん遊び難い世の中になってきて困ったものです。

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コード