赤道儀モータードライバの詳細

前回の、古い赤道儀用のモータードライバの詳細である。
このような需要がどの程度あるのか分からないが、自作するひとの参考まで。

回路は以下のとおり。
イメージ 1

Arduino Uno互換ボード(Aitendoの「びんぼうでいいの」を使用)にA4988マクロステップMOTOR DRIVER基板を接続しただけのものである。あと、E/W方向、スピードコントロールのスイッチを接続。
A4988基板の/RESET、/SLEEP端子も接続してあるが、天文用途では、ほぼ必要ないため、Pull Upでも良いと思う。最初、この端子は内部で Pull Up されていると思い、開放にしておいたところ、誤動作したため、Arduinoに接続した。
マイクロステップのレートを設定する MS1~MS3は使用するレートをソフトで変更しないのなら、希望するところで、H/Lを設定するかDIP SWを使うことも有りだろう。

電源は、手持ちの18V2Aのものを使用した。秋葉原には、ノートPC用の15~20Vの電源が大量に安価に出回っているので、それを利用するのも手である。
Arduino の電源もこれから供給するようにする。電圧が高すぎるので、抵抗を入れて10V程度にドロップさせている。
PCとArduinoをUSBケーブルで接続したときに、PC側からも5V電源が供給されて具合が悪いので、プログラミング・デバッグのときには、+5VラインをカットしたUSBケーブルを使用する。

Arduino 用のプログラム(スケッチというらしい)は以下のとおり。本体は全部で100行くらいの簡単なものである。マイクロ秒のタイミングが必要なため、Timer1というライブラリを使用する。以下、プログラムの簡単な説明。

・setup()
変数の定義、I/Oポートやタイマーの初期設定を行って、タイマーを起動する。
初期値は、前回計算した恒星時運転 69.65Hz で、50% Duty パルスとなるように、7128 μsecごとのタイマー割り込みをセットする。
モーターのマイクロステップレートは、MS1=H、MS2=L、MS3=Lでハーフステップ 1-2相励磁モードである。

・loop()
くりかえしの動作が行われるセクション。
E/W、スピードのスイッチが接続されているポートを読み込み、それらの状態によって、駆動パルスのレート、方向を設定する。E/Wキーのときには、恒星時の2倍、FFキーと同時に押されたときには、10倍の値となるようにしてある。この値が適当かどうか、実際の望遠鏡で確認する予定。

・ISR(timer1Event)
timer1がカウントアップしたときに、割り込みが発生して、ここのプロシージャーが実行され、モーター駆動タイミングパルス、方向信号を発生させる。
再度 timer1へ書き込むとき値 Rate は、loop()でキーの状態によって設定されており、そのタイミングで運転パルスを発生させることができる。
このアルゴリズムは、PICで作ったモータードライバでも採用しており実績のあるものなのだが、処理を次の割り込みまでに終わらなければならないので、あまり早いスピードでは動作させることができない。実験では、50倍速までOKであった。

今日、散歩しているときの思いついたのだが、スピードを変更するのに、パルスレートを変更するのでなく、マイクロステップレートを変更するのが良いかも知れない。このようにすることにより、恒星時運転では、滑らかな運転、高速時にはパワーのある運転に自動的に変わる、ということが期待できそうだ。

#include <Timer1.h>
//******************************************************************
// ATmega168, ATmega328:
// - Using Timer 1 disables PWM (analogWrite) on pins 9 and 10
//******************************************************************
// Pin 13 has a LED connected on most Arduino boards
#define LED 13
#define West 12        // Port B D12  Input
#define East 11        // Port B D11  Input
#define FF 10          // Port B D10  Input
#define Reset 2        // Port D D2   Output
#define Sleep 3        // Port D D3   Output
#define MS1 4          // Port D D7   Output          
#define MS2 5          // Port D D6   Output
#define Step 6         // Port D D5   Output
#define Direction 7    // Port D D4   Output

byte StepState,ReadKey;
boolean Dir;
int EastKey,WestKey,FFKey;
long Rate,BaseRate;
void setup()
{
  pinMode(LED, OUTPUT);
  pinMode(Step,OUTPUT);
  pinMode(Direction,OUTPUT);
  pinMode(MS1,OUTPUT);
  pinMode(MS2,OUTPUT);
  pinMode(Reset,OUTPUT);
  pinMode(Sleep,OUTPUT);
  pinMode(West,INPUT_PULLUP);
  pinMode(East,INPUT_PULLUP);
  pinMode(FF,INPUT_PULLUP);
 
  StepState = 0;
  // Disable Arduino's default millisecond counter (from now on, millis(), micros(),
  // delay() and delayMicroseconds() will not work)

  disableMillis();

  // Prepare Timer1 to send notifications every 7.18msec
  //
  // Base Step Drive Clock
  // Main worm gear teeth=500,Sub worm gear teeth=30,Step Step =200,Micro Step Rate=2
  // Sidereal = 86146 sec
  // Pulse rate = 500 x 30 x 200 x 2 / 86146 = 69.65 Hz
  // For 50% Duty 7.18 msec
  BaseRate = 7128;
  startTimer1(BaseRate); // Set timer 7.178 msec interval
 
  digitalWrite(MS1,HIGH);
  digitalWrite(MS2,LOW);
  digitalWrite(Sleep,HIGH);
  digitalWrite(Reset,LOW);
  digitalWrite(Reset,HIGH);
}

void loop()
{
  ReadKey = PINB;
  ReadKey = ReadKey & B0011100;     //

  switch(ReadKey){
    case B00001100:      // Go West
     Rate = BaseRate / 2;
     Dir = HIGH;
    break;

    case B00010100:      // Go East
     Rate = BaseRate / 2;
     Dir = LOW;
    break;

    case B00001000:      // Go FF West
     Rate = BaseRate / 10;
     Dir = HIGH;  
    break;

    case B00010000:      // Go FF East
     Rate = BaseRate / 10;
     Dir = LOW;  
    break;

   default:
     Rate = BaseRate;
     Dir = HIGH;
   }
}

// Timer Inerrupt Handler
ISR(timer1Event)
{// Reset Timer1 (resetTimer1 should be the first operation for better timer precision)

    startTimer1(Rate);
    resetTimer1();
    digitalWrite(Direction,Dir);
    // Toggle Step's state For Step Drive Pulse
    StepState ^= 1;
    digitalWrite(Step, StepState);
}