Arduinoを使う4軸ウィンチ(1)

4つのモーターで水平昇降

4軸のステッピングモーターで昇降できるウィンチを作ることにしました。
なぜ普通のブラシモーターを使わないかというとステッピングモーターってトルクが強く、静止時にギアがなくても保持していることができて、比較的ゆっくり回せるからです。
巷には3Dプリンターのおかげで出回っています。
こんな感じで作ります。
Arduinoで細かい制御をして、Raspberry Piからのコマンドで動くことにします。

と、ん?

こういうボードはどっかで見たよな。

あ、あれだ。

CNCマシン用のボード。
とくにArduinoに乗っけるピンが完備したボードを”シールド”と呼ぶ風習があります・
このボードはCNCマシンのキットに使われていて、GRBLというオープンソースで駆動します。
何年か前にさんざんいじってたヤツ。
とてもポピュラーで、ボードは激安で売られています。

とりあえず4個モーターがついたキットを購入。モーターは4401タイプなのだそうだ。
ボードのバージョンは無印のV3.0です。

ボードチューニング

4401は12Vで200カウントで一回転する。最大電流は1.7Aです。
モータードライブモジュールはA4988という最大で2A程度がドライブできます。Arduino Uno R3もコネクターは12Vまでサポートしているので電源は12Vで決まりです。
ドローン基盤から取れるということですね。どうするかは未定だけど。

A4988ボードはのっかっている極小のボリュームで最大出力電流をコントロールできます。
GNDとボリュームの中心にテスターをあて、電圧を測ります。もっとも右にまわして1.5Vくらいのはずです。
最大にすると結構発熱するので、4401モーターを使っている限りにおいては、中間(0.7Vくらい?)にしておいたほうがいいと思います。
MS0, MS1, MS2はドライブの精度をあげる場合に設定しますが、今回は回転数で数えるくらいの精度でいいので全部LOWにします。

なお、すべてのロジックは5V仕様となります。
ドローン系(Raspberry PI)は3.3V仕様ですから、接続時に5V-3.3Vのレベルコンバーターを挟む必要がありますが、以下のようにUSBインターフェースを使えば、そんな悩みはないです。

GRBL使っていた時にはArduinoとコントローラーのボードのピン配列なんか考えずに、言われたとおり繋いでいればよかったんですが、自分でコード書くならばそうもいきません。

とはいってもシールドのピンレイアウトは比較的どうでもいいです。
大事なものはこれ。

ここEnable, Direction, Stepが重要なピンです。

しかし!ここにはX,Y,ZしかなくAドライブについてはポートがありません!
それはこの動画(https://www.youtube.com/watch?v=UZcyh9qgwyQにあるとおり、

とジャンパーすればXドライブと同じようにAドライブは動くのです。
Aドライブはあくまでもフォロワーとして動くのですね。

なお、モーターケーブルの差し込みはこのとおり。

モーターテスト

ボードに12V電源を繋いで、

Arduinoプログラムでのピンの定義


const int stepXPin = 2; //X-軸 ステップ
const int stepYPin = 3; //Y.軸 ステップ
const int stepZPin = 4; //Z.軸 ステップ

const int dirXPin = 5; // X-軸 方向 1-CW 0-CCW
const int dirYPin = 6; // Y-軸 方向
const int dirZPin = 7; // z-軸 方向

const int enPin=8; // スピンドル エネイブル

とりあえずX軸用モーターが回るプログラム


const int stepXPin = 2; //X-軸 ステップ
const int stepYPin = 3; //Y.軸 ステップ
const int stepZPin = 4; //Z.軸 ステップ

const int dirXPin = 5; // X-軸 方向 1-CW 0-CCW
const int dirYPin = 6; // Y-軸 方向
const int dirZPin = 7; // z-軸 方向

const int enPin=8; // スピンドル エネイブル

const int stepsPerRev=200; // 200カウントで1回転
int pulseWidthMicros = 100;  // microseconds パルス幅
int millisBtwnSteps = 1000;  // 動作待ち時間

boolean direction = HIGH;

void setup() {
  Serial.begin(9600);

  pinMode(stepXPin, OUTPUT);
  pinMode(stepYPin, OUTPUT);
  pinMode(stepZPin, OUTPUT);
  
  pinMode(dirXPin, OUTPUT);
  pinMode(dirYPin, OUTPUT);
  pinMode(dirZPin, OUTPUT);
  
  pinMode(enPin, OUTPUT);
  digitalWrite(enPin, LOW);

  Serial.println("End of Initialization");
}


void loop() {
 // directionのロジックはわかりやすくするためダサダサです。
  if (direction == HIGH){
    digitalWrite(dirXPin, HIGH); // CW
    direction = LOW;
  } else {
    digitalWrite(dirXPin, LOW);
    direction = HIGH;
    
  }
  delay(100);

  for (int i = 0; i < stepsPerRev; i++) {
      digitalWrite(stepXPin, HIGH);
      delayMicroseconds(pulseWidthMicros);
      digitalWrite(stepXPin, LOW);
      delayMicroseconds(millisBtwnSteps);
  }

  delay(1000);
  
}

高度化させるためにいろいろなステッピングモーターコントロールプログラムを調べました。
困ったことにオープンソースの3DプリンターやCNCはモーターを一時点でひとつしか動かさないようで、stepperdriverやAccelStepperといったライブラリーは連続してモーターを回せない(360度回すと一瞬止まる)し動きがカクカク、同時に複数のモーターを動かせないようです。(なにか方法があるかもしれません。)

単なる昇降なので、自前でコードを書くほうがわかりやすく安心です。
単体ドライブのコードとの違いはdelayです。delaymaicrosecondsで待つと、モーター4台が同時に回りません。おかしな動きをします。
上の方法を拡張した次をみてください。


/*
 * X,Y,Z stepper Motor test
 * A Stepper should be controlled by jumper pins.
 * by Tsukasa Takao 2023
 */

const int stepXPin = 2; //X-軸 ステップ
const int stepYPin = 3; //Y.軸 ステップ
const int stepZPin = 4; //Z.軸 ステップ

const int dirXPin = 5; // X-軸 方向 1-CW 0-CCW
const int dirYPin = 6; // Y-軸 方向
const int dirZPin = 7; // z-軸 方向

const int enPin=8; // スピンドル エネイブル

const int stepsPerRev=200; // 200カウントで1回転
int pulseWidth = 3;  // ミリで十分。microsecondsは駄目


void setup() {
  Serial.begin(9600);

  pinMode(stepXPin, OUTPUT);
  pinMode(stepYPin, OUTPUT);
  pinMode(stepZPin, OUTPUT);
  
  pinMode(dirXPin, OUTPUT);
  pinMode(dirYPin, OUTPUT);
  pinMode(dirZPin, OUTPUT);

  pinMode(enPin, OUTPUT);
  digitalWrite(enPin, LOW);
  Serial.println("End of Initialization");
}

void rotate(int count){
  Serial.println("Start Rotation");
  for (int i = 0; i < stepsPerRev*count; i++) {
      digitalWrite(stepXPin, HIGH);
      digitalWrite(stepYPin, HIGH);
      digitalWrite(stepZPin, HIGH);
      delay(pulseWidth);
      digitalWrite(stepXPin, LOW);
      digitalWrite(stepYPin, LOW);
      digitalWrite(stepZPin, LOW);
      delay(pulseWidth);    
  }
   Serial.println("End Rotation");
}

void moveDown(){
   digitalWrite(dirXPin, HIGH);
   digitalWrite(dirYPin, LOW);
   digitalWrite(dirZPin, HIGH);
   rotate(10);
}

void moveUp(){
   digitalWrite(dirXPin, LOW);
   digitalWrite(dirYPin, HIGH);
   digitalWrite(dirZPin, LOW);
   rotate(10);
}

void loop() {
  moveDown();
  delay(1000);
  moveUp();
  delay(1000);
}

いろいろ調べても同時にステッピングモーターを回したい人はあまりいないらしく、おかしな動きも自己解決するしかありませんでした。

*長いので続きは次の投稿