自作CNCシリーズ 第2回
はじめに:なぜ「動く」だけではCNCとして不十分なのか
こんにちは。にんじんです🥕
自作CNCで穴あけや刻印の位置が毎回わずかにズレる——その原因は、機械が「自分の現在地」を知らないことにあります。前回(第1回)でArduinoからXYテーブルのステッピングモーターを回すところまでは進みましたが、電源を入れた場所がそのまま「0」になってしまうため、起動のたびに手で位置を合わせ直す必要がありました。
この記事では、自作CNC(Arduino+GRBL)にリミットスイッチを追加し、原点(0, 0)を毎回同じ位置に再現するホーミングの設定方法を解説します。ノイズに強いプルアップ回路の配線、接点のチャタリング対策、Arduino Unoで動作を確認できるテストコード(ZIP配布)まで、実際にハマったポイントを添えてまとめました。
この記事で分かること
- リミットスイッチで「機械原点(0, 0)」を作ると、位置の再現性がどう変わるのか
- ホーミング(原点復帰)でなぜ2回スイッチに当てるのか(慣性の影響を消す仕組み)
- マイクロスイッチの選び方と、プルアップ配線にする理由(ノイズ誤検出対策)
- X軸・Y軸のホーミング動作を確認できるテストコード(
test_code_XY_switch.ino、ZIP配布) - チャタリング・ノイズで止まる・毎回数ミリずれる、といったトラブルの原因と対策
CNCでリミットスイッチが必要な理由と「位置の再現性」
CNC(コンピュータ数値制御)の運用で最も重要なのが「位置の再現性」です。手動での位置合わせや、基準があいまいな状態では次のような問題が起きます。
- 寸法のズレ:穴あけや刻印の位置がわずかにズレるだけで、組み立てパーツとしての実用性が失われる
- 誤差の蓄積:モーターの脱調(ステップ抜け)や電源投入タイミングの差で、位置は少しずつずれていく
- 基準の不在:電源を入れた場所が自動的に「0」になると、起動のたびに手動で位置合わせが必要になる
これを解決するのがリミットスイッチです。物理的なスイッチに軸を接触させることで、「ここが本当の0地点である」という明確な基準(機械原点)を作れます。
ホーミング(原点復帰)の仕組み:なぜリミットスイッチに2回当てるのか
リミットスイッチに接触して軸を止め、原点を確定させる一連の動作を「ホーミング(Homing)」と呼びます。単純に1回ぶつけて終わりではなく、次のステップを踏みます。
- 高速アプローチ:対象の軸をスイッチ方向へ高速で移動させる
- 接触と停止:スイッチに当たった瞬間に停止する
- プルオフ(退避):少しだけ反対方向に引き返し、スイッチをOFFに戻す
- 再接触:1回目よりもかなり遅い速度で、もう一度ゆっくりスイッチに触れる
なぜ2回当てるのか:1回目の高速移動では、機械の慣性(惰性)で停止位置にわずかなバラつきが出ます。2回目に超低速で優しく触れ直すことで慣性の影響を排除し、高い精度で原点座標を特定できます。
マイクロスイッチの選定とプルアップ配線の方法
今回追加するパーツはシンプルで、リミットスイッチ ×2(X軸・Y軸用)だけです。レバーを押すと「カチッ」と明確な音がする一般的なマイクロスイッチが扱いやすくおすすめです。
配線は「プルアップ」方式にする
なぜプルアップなのか:配線が浮いた状態(どこにも繋がっていない状態)だと、ノイズを拾って勝手に「スイッチが押された」と誤検出することがあります。プログラム側で常にHIGH(電圧あり)にしておき、スイッチが押されたときだけLOW(0V)に落とすことで、ノイズに強い確実な検出ができます。Arduinoでは pinMode(pin, INPUT_PULLUP) で内蔵プルアップを有効化します。
A4988のVref調整も忘れずに
モーターを回す前提として、A4988ドライバの電流制限(Vref)調整が必要です。未調整だと動作が不安定になったり発熱が激しくなったりします。
⚡ モーターを回す前に(必読) A4988の電流制限(Vref)調整方法|焼損を防ぐ計算式とテスターでの設定手順 計算式とテスターでの手順でVref調整を解説。CNC・ステッピングモーター記事の共通の前提です。 → 🔧 前回はこちら(第1回) XYテーブルをCNC化!ArduinoとA4988を使ったステッピングモーター制御の基本 Arduino IDEのインストール、A4988の結線、電解コンデンサの入れ方、モーターを回すテストコードまで。 →テストコードによる動作確認とArduino Unoへの書き込み手順
結線が終わったら、テスト用のスケッチを書き込んで動作を確認します。テストコード test_code_XY_switch.ino は、X軸・Y軸を往復させながら、シリアルモニタから g でホーミング開始、s で停止できる内容です。
test_code_XY_switch.ino(Arduino IDEに貼り付けて書き込みます)
// テストコード test_code_XY_SWITCH.ino
#define X_STEP 2
#define X_DIR 5
#define Y_STEP 3
#define Y_DIR 6
#define ENABLE 8
#define X_LIMIT 9
#define Y_LIMIT 10
// ===== 調整パラメータ =====
#define BACKOFF_STEPS 250
#define HOMING_FAST 800
#define HOMING_SLOW 2000
// ===== ホーミング方向 =====
#define X_HOME_DIR HIGH // ← Xだけ逆にした
#define Y_HOME_DIR LOW // Yはそのまま
bool stopFlag = false;
void setup() {
pinMode(X_STEP, OUTPUT);
pinMode(X_DIR, OUTPUT);
pinMode(Y_STEP, OUTPUT);
pinMode(Y_DIR, OUTPUT);
pinMode(ENABLE, OUTPUT);
pinMode(X_LIMIT, INPUT_PULLUP);
pinMode(Y_LIMIT, INPUT_PULLUP);
digitalWrite(ENABLE, LOW);
Serial.begin(115200);
Serial.println("Press 's' to STOP, 'g' to HOME");
}
// ===== 入力チェック =====
void checkInput() {
if (Serial.available()) {
char c = Serial.read();
if (c == 's' || c == 'S') stopFlag = true;
if (c == 'g' || c == 'G') homeXY();
}
}
// ===== 停止処理 =====
void stopAll() {
Serial.println("STOPPED");
digitalWrite(ENABLE, HIGH);
while (1);
}
// ===== 1軸ホーミング =====
void homeAxis(int stepPin, int dirPin, int limitPin, bool homeDir) {
// ① 高速で当たる
digitalWrite(dirPin, homeDir);
while (digitalRead(limitPin) == LOW) {
checkInput();
if (stopFlag) stopAll();
digitalWrite(stepPin, HIGH);
delayMicroseconds(HOMING_FAST);
digitalWrite(stepPin, LOW);
delayMicroseconds(HOMING_FAST);
}
delay(100);
// ② BACKOFF(逆方向)
digitalWrite(dirPin, !homeDir);
for (int i = 0; i < BACKOFF_STEPS; i++) {
digitalWrite(stepPin, HIGH);
delayMicroseconds(HOMING_FAST);
digitalWrite(stepPin, LOW);
delayMicroseconds(HOMING_FAST);
}
delay(200);
// ③ ゆっくり再接触
digitalWrite(dirPin, homeDir);
while (digitalRead(limitPin) == LOW) {
checkInput();
if (stopFlag) stopAll();
digitalWrite(stepPin, HIGH);
delayMicroseconds(HOMING_SLOW);
digitalWrite(stepPin, LOW);
delayMicroseconds(HOMING_SLOW);
}
delay(100);
}
// ===== XYホーミング =====
void homeXY() {
Serial.println("HOMING START");
homeAxis(X_STEP, X_DIR, X_LIMIT, X_HOME_DIR);
homeAxis(Y_STEP, Y_DIR, Y_LIMIT, Y_HOME_DIR);
Serial.println("HOMING DONE");
}
// ===== モーター動作 =====
void moveMotor(int stepPin, int dirPin, bool dir, int steps) {
digitalWrite(dirPin, dir);
for (int i = 0; i < steps; i++) {
checkInput();
if (stopFlag) stopAll();
digitalWrite(stepPin, HIGH);
delayMicroseconds(1000);
digitalWrite(stepPin, LOW);
delayMicroseconds(1000);
}
}
void loop() {
checkInput();
stopFlag = false;
// ===== X軸 =====
moveMotor(X_STEP, X_DIR, LOW, 300);
delay(500);
moveMotor(X_STEP, X_DIR, HIGH, 300);
delay(1000);
// ===== Y軸 =====
moveMotor(Y_STEP, Y_DIR, HIGH, 300);
delay(500);
moveMotor(Y_STEP, Y_DIR, LOW, 300);
delay(2000);
}- Arduino IDEを開く
- 上部のプルダウンでArduinoが接続されているポートを選択
- デフォルトのコードを削除し、テストコードを貼り付け
- 左上の → ボタンをクリックしてArduino Uno R3に書き込み
- 自動でX軸・Y軸の動作が始まります
※ Arduino IDE右上の「シリアルモニタ」を開き、キーボードの S +Enterで動作停止、g +Enterで原点復帰(ホーミング)が開始されます。
動作動画
ホーミングでよくあるトラブルとノイズ対策(チャタリング・脱調・位置ずれ)
実際に動かすと、想定通りに動かないことがあります。代表的なトラブルと原因・対策をまとめました。
| トラブル内容 | 原因と対策 |
|---|---|
| チャタリング | スイッチの接点が細かくバタつく現象。ソフト側で数ミリ秒待つ(デバウンス)か、コンデンサを入れて電気的に平滑化する。 |
| ノイズで勝手に止まる | モーターの配線からノイズを拾っている可能性。配線をツイストするか、シールド線を使うのが効果的。 |
| 位置が毎回数ミリずれる | スイッチの固定が甘い(剛性不足)かもしれない。ネジの緩みやステーのたわみをチェックする。 |
まとめと次回予告:GRBLの導入とCNCjsによるPC制御へ
リミットスイッチが正常に機能すれば、XYテーブルは自分の初期位置を正確に把握できるようになります。これで工作機械としてのハードウェアの土台が整いました。
- [x] モーターの回転動作(第1回)
- [x] 機械原点の確定(今回ここまで完了)
次回・第3回では、このハードウェアをPCの画面から操作できるようにするため、専用ファームウェア「GRBL」の書き込み手順と、操作画面となる「CNCjs」の初期設定を解説します。
次に読む記事
💻 次回はこちら(第3回) ArduinoへGRBLを書き込む手順とCNCjsの使い方|XYテーブルをPC制御 GRBLの書き込み、CNCjsのインストールと接続、ジョグ操作までを解説します。 → 🗺️ シリーズ全体像 ゼロから自作するCNCの全手順ロードマップ|Arduino・GRBL・CNCjsでレーザー刻印機を作る 第1回〜第10回の全工程をまとめたロードマップ。どの順で読めばいいかが分かります。 →よくある質問(FAQ)
Qホーミングでなぜ2回スイッチに当てるのですか?
A1回目は高速で動くため、機械の慣性で停止位置にバラつきが出ます。2回目に超低速でゆっくり触れ直すことで慣性の影響を排除し、原点座標を高い再現性で特定できます。
Qリミットスイッチの配線をプルアップにする理由は?
A配線が浮いた状態だとノイズを拾って誤検出することがあります。常にHIGHにしておき、押されたときだけLOWに落とすことでノイズに強くなります。Arduinoでは pinMode(pin, INPUT_PULLUP) で内蔵プルアップを使います。
Qスイッチはノーマルオープン(NO)とノーマルクローズ(NC)のどちらで配線しますか?
A今回のテストコードは押されたときにLOWになる前提(実質NO+プルアップ)で書いています。NC配線にすると断線を検知できる利点がありますが、GRBL側の $5(limit pins invert)設定と合わせる必要があります。
Qホーミング中にスイッチを通り過ぎて軸がぶつかります。
Aアプローチ速度が速すぎるか、プルオフ量が大きすぎます。テストコードの HOMING_FAST / BACKOFF_STEPS を調整してください。GRBL運用時は $25(homing seek rate)と $27(homing pull-off)で調整します。
Qスイッチに触れていないのに反応してしまいます。
Aモーター配線からのノイズが原因のことが多いです。信号線をツイストする、シールド線を使う、スイッチ端子に0.1μF程度のコンデンサを入れる(ハードウェアデバウンス)などが有効です。
Qこの段階でGRBLを入れないのはなぜですか?
Aまず素のArduinoスケッチで「配線とホーミング動作そのものが正しいか」を切り分けて確認するためです。GRBLの書き込みとCNCjsでのPC制御は第3回で解説します。
自作CNCシリーズ 全10回
- XYテーブルをCNC化!ArduinoとA4988を使ったステッピングモーター制御の基本【自作CNC第1回】
- 自作CNCのリミットスイッチ配線とホーミング設定|プルアップ回路・チャタリング対策【自作CNC第2回】(この記事)
- ArduinoへGRBLを書き込む手順とCNCjsの使い方|XYテーブルをPC制御【自作CNC第3回】
- GRBLの$100キャリブレーションと$110速度制限の解除|CNCjsでステップ数を実測補正【自作CNC第4回】
- CNCシールドでリミットが常時ON(Pn:Z)になる原因|GRBLのD11・D12ピン反転の罠【自作CNC第5回】
- GRBLホーミング失敗「ALARM:8」の原因と解決策!4ステップの動作原理を徹底解説
- CNCjsで「Check Door」エラーが出る原因と解決策!GコードのUTF-8文字コードの罠
- 自作CNC 1064nm赤外線レーザーで金属刻印!GRBL設定変更とLightBurn素材テスト
- 自作CNCのレーザー加工を10倍高速化!アルミフレーム剛性強化と速度検証
- 【設計データ配布】自作CNCレーザー刻印機の全部品リストと2D/3D図面一式
Follow me on X
本ブログの中の人「ニンジン🥕」はXやってます。新着記事はいち早くポストでお知らせしているので、見逃したくない方は @ninjin_py_vba をフォローしてみてください🥕
@ninjin_py_vba をフォローシリーズ記事一覧
電子工作・自動化ツールの製作記録をシリーズごとにまとめています。気になるテーマからお読みください。
-
FILE.01 — IoT
Raspberry Pi Pico W × GASラズパイPico W×GASで自作!「LINEで動く温湿度&スマートリモコン」完全ロードマップ
「外出中のペットの室温が心配…」そんな思いからスタートしたIoT自作プロジェクトの総集編。温湿度監視からエアコン遠隔操作まで、仕組みをゼロから作りたい方のための全5回の開発記録です。
シリーズを読む -
FILE.02 — CNC
Arduino × レーザー刻印CNCCNC自作シリーズ
高精度な加工を目指し、本格的な自作CNC製作に挑戦中。現在は基幹パーツであるオリエンタルモーターの納品を待つ「設計・準備編」を公開。ハードとソフトの両面から、理想のマシンを形にする過程をリアルタイムにお届けします。
シリーズを読む -
FILE.03 — XY軸制御
Raspberry Pi × ステッピングモーターXYテーブルシリーズ
Raspberry Piとステッパモーターを使い、ゼロから2軸制御に挑む記録。OS設定から回路設計、多軸制御のPythonコードまで、躓きやすいポイントを徹底図解。電子工作初心者が「動く感動」を味わうための実戦ガイドです。
シリーズを読む -
FILE.04 — 業務自動化
Python × Excel × CustomTkinter【Python開発記】NINJIN Mail制作記
PythonとExcelを連携させ、実務で即戦力となるメール送信ツールを開発。CustomTkinterによるUI構築や、ミスを防ぐテンプレート活用術など、現場の「痒い所に手が届く」自動化ノウハウを細部まで丁寧に解説します。
シリーズを読む -
FILE.05 — 業務自動化
Python × Excel × GUIアプリ化Invoice Maker(請求書・見積書自動作成)
手作業の請求書作成から卒業!PythonでExcelデータを読み込み一括PDF化する「Invoice_Maker」の作り方を全3回で解説。基本ロジックからGUIアプリ化まで、実務で役立つ自動化ノウハウが満載です。
シリーズを読む




コメント