DIYスタンドアローン・スティックフォーカーサー

DIY Focuser

この国(国名は敢えて非公開)の隔離措置のお陰で、最初の3泊は隔離ホテルの部屋から全くでることを許されません。その後5日間は外は自由に移動できますが、オフィスビルとレストランには入れません。毎日コンビニ飯です。朝はホテルが朝食を部屋まで運んでくれます。明日の夜まで・・・涙

仕事は色々あって忙しいのですが、夜は飲みにもいけず暇過ぎです。

今日は以前から構想をねっていたものをCADデザインとコーディングすることにしました。

以前いろいろなタイプのフォーカーサーを作りました。Stellermate(KStars&Ekos、INDI)でコントロールすることを前提に製作しました。その後ASiairに移行したので全部使えなくなってしまいました。それに余程寒くない限り手動で合わせた方がトラブルが少ないです。ただし手動でピントを合わせると手ブレなのかピンぼけなのか、手ブレが収まるまでちょっと待たなければなりません。そこで、スタンドアローンで動作するフォカーサーを作ることにしました。可動部は以前作ったスティックフォーカーサーを使います。ファームウェアを入れ替えればMoonlite互換INDI対応フォーカーサーに戻せます。

鏡筒へのセットはこんな感じです。

28BJY-48ステッパーを使っています。都合よくモーター軸がオフセットされているので、フォーカーサー本体を回転させることでタイミングベルトのテンションを調整することが簡単にできます。

最初にピントをあわせる方法を、ボタンにするか、可変抵抗にするか悩みましたが、最終的にジョイスティックにしました。一番安いし簡単に作れそうなので。2軸の可変抵抗に合わせてスイッチも使えるので最高です。

9Vのリチャージャブルバッテリーで電源供給します。あっ、メインスイッチが必要だな〜、どこに付けようか?

2軸の可変抵抗のうちY軸のみ使ってピント合わせをします。X軸は今の所使いません。レバーを奥に倒すと遠景、手前に倒すと近景にピントが合います。レバーの傾きに合わせて微動から高速まで動作スピードが変化します。レバーを押すとスイッチとなります。

  1. シングルクリック: ピント合わせ動作のオン/オフ切り替え
  2. ダブルクリック: プリセット位置に移動
  3. トリプルクリック: プリセット位置を保存(ピントが合った位置を保存)
  4. クワッドクリック: 初期位置(0)へ戻る。※使用を終えたら、常に0に戻して電源を落とす仕様

オフまたは初期位置に戻ってから30秒後に省エネモード(モーターへの電源供給をストップ)に移行します。シングルクリックでアクティブに戻ります。

とここまで書きましたが、まだ頭の中の構想の状態です。帰国したら実際作ってみて動作確認する予定です。費用は多分1500円位でできるんじゃないかな?はんだ付けも10ヶ所くらいです。

久しぶりにコード書いた・・・

// FocusControler with Joystick
// Copyright (C) 2022 by Kenichi Aihara and licensed under
// GNU GPL v3.0, https://www.gnu.org/licenses/gpl.html

#include <AccelStepper.h>
#include <EEPROM.h>
#include <JC_Button.h>          // https://github.com/Kuantronic/JC_Button

// Arduino Button Library
// https://github.com/JChristensen/JC_Button
// Copyright (C) 2018 by Jack Christensen and licensed under
// GNU GPL v3.0, https://www.gnu.org/licenses/gpl.html

#define HALFSTEP 8

#define motorPin1  2    // IN1 on ULN2003 ==> Blue   on 28BYJ-48
#define motorPin2  3    // IN2 on ULN2004 ==> Pink   on 28BYJ-48
#define motorPin3  4    // IN3 on ULN2003 ==> Yellow on 28BYJ-48
#define motorPin4  5    // IN4 on ULN2003 ==> Orange on 28BYJ-48

// NOTE: The sequence 1-3-2-4 is required for proper sequencing of 28BYJ-48
AccelStepper stepper1(HALFSTEP, motorPin1, motorPin3, motorPin2, motorPin4);

// Define our analog pot input pin
#define  X_PIN A0
#define  Y_PIN A1
#define  SW_PIN 10

Button myBtn(SW_PIN);       // define the button

// Define our maximum and minimum speed in steps per second (scale pot to these)
#define  MAX_SPEED 1000
#define  MIN_SPEED 0.1
int a = 0;
int value;
int X_POS ;            // X軸方向の読み取り値の変数を整数型に
int Y_POS ;            // Y軸方向の読み取り値の変数を整数型に
int SW_POS ;           // センタースイッチの読み取り値の変数を整数型に
float OFFSET = 0.05 ;  // センター付近のオフセット値を5%に設定
int DUTY ;             // ディーティ比用変数
int SLPF ;             // スリープの準備
unsigned long slp_t, prev, curr, interval;
int EN = 1 ;
int to_slp = 30000;   //スリープまでの時間(ms)

void setup() {

  Serial.begin(115200);             // 115200バンドレートでシリアル通信の開始
  myBtn.begin();                  //initialize the button object

  stepper1.setMaxSpeed(10000.0);

  // Set up the three button inputs, with pullups
  pinMode(X_PIN, INPUT);          // A0ピンを入力に(省略可)
  pinMode(Y_PIN, INPUT);          // A1ピンを入力に(省略可)
  // pinMode(SW_PIN, INPUT_PULLUP);  // D10ピンをプルアップして入力に

  stepper1.enableOutputs();       // Enable Stepper

  prev = 0 ;                      //前回アナログ数値読み込み時間
  interval = 1000 ;               //アナログ数値読み込み間隔(ms)

}

void loop() {
  static float current_speed = 0.0;         // Holds current motor speed in steps/second

  uint8_t numOfPresses = myBtn.multiPressRead();

  switch (numOfPresses) {
    case 1:
      Serial.println("single press!");
      if (EN == 1) {
        EN = 0;                       //ストップサイン
        SLPF = 1;                         //スリープ準備
        slp_t = millis();                 //スリープタイマーセット
        Serial.print(EN);
        Serial.println("-Stop");
      } else {
        EN = 1;                       //ムーブサイン
        SLPF = 0;                         //スリープ準備解除
        stepper1.enableOutputs();         //モーターをアクティブに
        Serial.println(EN);
        Serial.println("-Move");
      }
      break;
    case 2:
      Serial.println("double press!");
      stepper1.moveTo(0);                 //初期位置まで戻る
      stepper1.setSpeed(2000);
      stepper1.setAcceleration(200);
      while (stepper1.distanceToGo() != 0)
        stepper1.run();
      EN = 0;
      SLPF = 1;                         //スリープ準備
      slp_t = millis();                //スリープタイマーセット
      break;
    case 3:
      Serial.println("triple press!");
      value = EEPROM.read(a);
      stepper1.moveTo(value);                 //プリセット位置まで戻る
      stepper1.setSpeed(2000);
      stepper1.setAcceleration(200);
      while (stepper1.distanceToGo() != 0)
        stepper1.run();
      break;
    case 4:
      Serial.println("quadruple press!");
      EEPROM.write(a, stepper1.currentPosition());       //プリセット位置をセット
    default:
      // do nothing
      // for no press and presses over 4 in fast succession
      break;
  }

  if ((curr - prev) >= interval) {      //設定したインターバルを経過したら読込み
    prev = curr;                        //タイマーリセット
    X_POS = analogRead(X_PIN);          //X_PINを0-1023の範囲で読込み
    Y_POS = analogRead(Y_PIN);          //Y_PINを0-1023の範囲で読込み
  }

  // X軸方向のセンター(512)の前後OFFSET分はストップ
  //if ((X_POS > 512 - 512 * OFFSET) && (X_POS < 512 + 512 * OFFSET)) {
  //  ;
  //}

  // Y軸方向のセンター(512)の前後OFFSET分はストップ
  if ((Y_POS > 512 - 512 * OFFSET) && (Y_POS < 512 + 512 * OFFSET)) {
    ;
  }
 /* コメントアウト
  // スティックを左に倒したときの動作
  if (X_POS <= 512 - 512 * OFFSET) {
    DUTY = map(X_POS, 512 - 512 * OFFSET, 0, 0, -255); // デューティー比を0~-255の範囲に調整
    ;
  }
  // スティックを右に倒したときの動作
  else if (X_POS >= 512 + 512 * OFFSET) {
    DUTY = map(X_POS, 512 + 512 * OFFSET, 1023, 0, 255); // デューティー比を0~255の範囲に調整
    ;
  }
  */コメントアウトここまで

  // スティックを上に倒したときの動作
  if (Y_POS <= 512 - 512 * OFFSET) {
    DUTY = map(Y_POS, 512 - 512 * OFFSET, 0, 0, 255); // デューティー比を0~255の範囲に調整
  }
  // スティックを下に倒したときの動作
  else if (Y_POS >= 512 + 512 * OFFSET) {
    DUTY = map(Y_POS, 512 + 512 * OFFSET, 1023, 0, -255); // デューティー比を0~-255の範囲に調整
  }

  current_speed = EN * DUTY * 4;                    //回転方向、スピードを決定
  stepper1.setSpeed(current_speed);                 //スピードをアップデート
  if (stepper1.currentPosition() == 0) {            //モーターポジションが0になったら
    stepper1.stop();                                //モーターをストップ
  } else {
    stepper1.runSpeed();                            //モーターを一定スピードで回転
  }

  if (SLPF != 1)
    slp_t = curr;                                   //スリープ準備になるまでslp_tを現時刻にUpdate
  else if ((curr - slp_t) >= to_slp)                //経過時間の判定
    stepper1.disableOutputs();                      //モータースリープ
}

関連記事

特集記事

コメント

    • Gyoenastaader
    • 2022.09.10 2:34am

    Great example of how to make a DIY focuser. I recommend including a RJ11 port on both the remote and unit so you can disconnect the two.

    • KEN
      • KEN
      • 2022.09.10 2:49am

      I was thinking the same thing, too!

  1. i*matと申します。どうぞよろしくお願いします。
    クルリと回して、テンション調節・・・
    工具も不要で、その場で手樽に。スゴくスマートなアイディアですね。
    レンズの光軸調整等にも応用できそう!

    • KEN
      • KEN
      • 2022.09.11 6:56pm

      i*matさん、こんにちは!

      工作してばかりなので、そろそろ観測や撮影の腕をあげなければ・・・・

      今後ともよろしくお願いします!

    • Nick
    • 2023.02.12 3:56am

    Awesome project. Where can we find the STL files for the joystick case?

  2. Hello. A good project, but the source code needs to be refined. The source code did not work immediately. After finishing the code, it started working. Added to the code the dead zone for the joystick, because it does not always return to zero:
    //deadzone
    if (current_speed > -160 && current_speed < 160) {
    current_speed = 0;
    stepper1.setSpeed(current_speed); //スピードをアップデート
    } else {
    stepper1.setSpeed(current_speed); //スピードをアップデート
    stepper1.runSpeed();
    }

TOP
WP2Social Auto Publish Powered By : XYZScripts.com