赤道儀モータードライバ マイクロステップ変更で速度制御

以前に報告した、赤道儀用のモータードライバであるが、望遠鏡を東西に移動させるときに恒星時運転から、ステップレートを変えるには、タイマーのレートを変更して行っている。この方法は、20年以上も前に、M6800マイコンでモータードライバを製作したときから採用している実績あるやりかたである。

モータードライバのICがマイコン側からマイクロステップの分割モードを変更できるように配線したので、タイマーレートを一定にして、マイクロステップ分割モードの変更により、ステッピングモーターの速度を変更する方法を試してみた。

再度、必要とされるパルスレートを検討してみると、
  ・平均恒星時   86146秒
  ・メインウォームギア歯数 500
  ・サブウォームギア歯数 30
  ・Motor Step数 200
として、ステップモーターを ドライバIC A4988のMAX マイクロステップ 1/16で駆動するものとすると、
  500×30×200×16 ÷ 86146 = 557.19 Hz
すなわち、周期 1.7947msのパルスとなる。

このレートで運転して、微動のコマンドの時には、マイクロステップレートを1/8に設定すれば、倍速で動作し、早送りのときには、ステップレートを1/1にすることにより、16倍のスピードでモーターを駆動することができる。

この方法の良いところは、恒星時運転を動作の細かな 1/16マイクロステップで動作させることができることだ。また、FF時にはより強いパワーでMOTORを回すことができる。設定レートが限られてしまうが、タイマーセッティングと併用すれば、希望の速度で駆動することができるが、実際にはそんなに必要ないと思う。

変更した回路図は以下のとおり。
IOポートの接続がきれいな並びでないのは、配線変更の容易さを優先したため。あと、SLEEP端子は、Pullupとした。

イメージ 1

これにあわせて変更した Arduino のスケッチ(プログラム)は以下のとおり。
簡単に解説すると、
・setup()
 タイマーやIOポート割付、初期設定を行っている
・loop()
 KeyPadの状態を読み込んで、Keyに対応した、移動方向、スピードの設定を行っている。スピードは、モータードライバのMS1~MS3を設定することで行う。
・ISR(timer1Event)
 タイマー割り込み処理ルーチンで、Stepパルスの発生、タイマーの再設定を行っている。ルーチンのTOPでパルスを出力するように変更した。

//****************************************************************
#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 MS1 4          // Port D D4   Output         
#define MS2 5          // Port D D5   Output
#define MS3 3          // Port D D3   Output
#define Step 6         // Port D D6   Output
#define Direction 7    // Port D D7   Output

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

  StepState = 0;                // Set Step Pulse LOW
  digitalWrite(MS1,HIGH);       // Microstep Rate = 1/16
  digitalWrite(MS2,HIGH);
  digitalWrite(MS3,HIGH);
  digitalWrite(Reset,LOW);      // Rest Motor Driver
  digitalWrite(Reset,HIGH);
 
  // Base Step Drive Clock
  // Main worm gear teeth = 500 , Sub worm gear teeth = 30 , Step Step = 200 , Micro Step Rate = 16
  // Sidereal = 86146 sec
  // Pulse rate = 500 x 30 x 200 x 16 / 86146 = 557.19 Hz ( 1.7947 msec )
  // For 50% Duty  897 usec
  BaseRate = 897;
  startTimer1(BaseRate); // Set timer 7.178 msec interval
}

void loop()
{ // Sens Key Pad and Set Data
  ReadKey = PINB;                  // Read Key Pad data
  ReadKey = ReadKey & B0011100;    // Mask anather bit

  switch(ReadKey){
    case B00001100:                // Go West Guide
     digitalWrite(MS1,LOW);        // Microstep Rate = 1/8
     digitalWrite(MS2,HIGH);
     digitalWrite(MS3,HIGH);
     digitalWrite(Direction,HIGH);
    break;

    case B00010100:                // Go East Guide
     digitalWrite(MS1,LOW);        // Microstep Rate = 1/8
     digitalWrite(MS2,HIGH);
     digitalWrite(MS3,HIGH);
     digitalWrite(Direction,LOW);
    break;

    case B00001000:                // Go FF West
     digitalWrite(MS1,LOW);        // Microstep Rate = 1/1
     digitalWrite(MS2,LOW);
     digitalWrite(MS3,LOW);
     digitalWrite(Direction,HIGH);
    break;

    case B00010000:                // Go FF East
     digitalWrite(MS1,LOW);        // Microstep Rate = 1/1
     digitalWrite(MS2,LOW);
     digitalWrite(MS3,LOW);
     digitalWrite(Direction,LOW);
    break;

   default:                        // Normal West
     digitalWrite(MS1,HIGH);       // Microstep Rate = 1/16
     digitalWrite(MS2,HIGH);
     digitalWrite(MS3,HIGH);
     digitalWrite(Direction,HIGH);
   }
}

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

    digitalWrite(Step, StepState);    // Set Step Pulse
    startTimer1(BaseRate);            // Restart Timer
    resetTimer1();
    StepState ^= 1;      // Toggle Step's state For Step Drive Pulse
}