Arduinoを使ってDVDのスピンドルモーターを高速回転
◆まえがき
Arduinoを使ってモーターを回す実験のたぶん最終回になると思います。前回はDVDのスピンドルモーターを低速回転させましたが、今回は思いっきり高速で回転させてみます。
◆回路図
ずっと同じ回路なのですが、再度掲載しておきます。
NANOをUSB電源で動かす場合は、VINに繋がっている線を外します。
同時にモーターの2つのコイルに通電しているので、2Aくらいの容量の電源が必要になります。
◆外観
◆プログラム
ちょっと長いですが、見える形で掲載しておきます。
// 誘導モーターの実験(外側回転子)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の行をコメントアウトします。なお、こんな小技では無く、低速時はコイルの通電角を狭くして消費電流を減らす制御を行った良いのですがそこまで出来ませんでした。
◆動いている様子
Arduino使ってDVDのスピンドルモーターを回してみた。
— ラジオペンチ (@radiopench1) January 3, 2023
最高24000rpmで回してるんだけど、PM同期モーターなので位相ズレは無くてぴったり元の位置に戻ってる。
1回転36パルスだけどステッピングモーターとして使えそう。 pic.twitter.com/sobSCaR5WE
オシロに表示しているのはコイルへの通電指定パルスです。(停止時OFF機能は切っています)
◆まとめ
DVDのスピンドルモーターを最高で約4000rpmで廻すことが出来ました。PM同期モーターとして動いているのでパルスモーターと同じで、ぴったりと同じ角度で停止させることが出来ます。パルスモーターは(たぶん)こんな高速では回らないと思います。
DVDのスピンドルモーターをいろいろいじってきました。本来はホールセンサーを使ったDCブラシレスモーターなのですが、ホールセンサーを使わないでマイコンからコイルの通電を制御する、つまりオープン制御で動かしても結構まともに動くことが判りました。ちょっとしたメカを動かすのに便利だと思います。
もちろんホールセンサーを使ってローターの位置を把握した制御を行った方が効率は良くなりますが、急に難易度が高くなるので簡単ではありません。
- 関連記事
-
- DVDのスピンドルモーターを低速回転させる-続編
- Arduinoを使ってDVDのスピンドルモーターを高速回転
- Arduinoを使ってDVDのスピンドルモーターを低速回転
- セルシンの受信機を作ってみるも失敗
- 外側に回転子を持つ誘導モーターを動かす