ArduinoベースSCARAロボット自作 – ステップバイステップガイド
このチュートリアルでは、ArduinoベースのSCARAロボットの作り方を学びます。ロボット設計から、制御用グラフィカルユーザーインターフェース(GUI)開発まで、全工程を紹介します。 動画または以下の記事をご覧ください。 このロボットは4自由度を持ち、4台のNEMA 17ステッピングモーターで駆動。さらにエンドエフェクター(今回はグリッパー)制御用に小型サーボモーター1台を搭載。頭脳はArduino UNOボードで、CNCシールドと4台のA4988ステッピングドライバーでモーターを制御します。 Processing開発環境でGUIを作成。順運動学と逆運動学の両方で制御可能です。順運動学では各関節角度を手動設定し、エンドエフェクターの最終位置(X、Y、Z値)を画面右側に計算表示。左側のスライダーで各関節角度を設定します。 一方、逆運動学ではエンドエフェクターの目標位置を指定すると、プログラムが自動的に各関節角度を計算してその位置に到達させます。 同じ画面で両方式を同時使用可能。関節角度とエンドエフェクターのX、Y、Z値は連動し、常に画面に表示されます。 自動動作も可能。「Save」ボタンでロボットの各動作/位置を保存。「Run」ボタンで保存された動作を最初から最後までループ実行。移動速度と加速度もGUIから調整可能。 まず3Dモデルを見てみましょう。 このSCARAロボットは3DEXPERIENCE SOLIDWORKSで設計。これが今回の動画スポンサーです。 3DEXPERIENCE SOLIDWORKSは、3DEXPERIENCEプラットフォームを通じてクラウド機能を提供するSOLIDWORKS。すべてクラウド上で動作し、チームメンバーが世界中どこからでも、いつでもデータやモデルにアクセス可能。プラットフォームには便利な生産性・管理アプリも多数含まれます。 例えばProject Plannerでタスク管理、期限設定、進捗管理。3D MarkupアプリでノートPC、タブレット、スマホからモデルの閲覧・探索・メモ記入が可能。 ブラウザ上で動作するクラウドベース3Dモデラー「SOLIDWORKS xDesign」も別途提供。SOLIDWORKSと併用も単独使用も可能。いつでもどこでも、あらゆるデバイスでモデリングできます。 教育コンテンツを支援してくれたSOLIDWORKSに感謝。SOLIDWORKSと3DEXPERIENCEプラットフォームがあなたに合うか知りたい方は以下リンクをご覧ください。 3DEXPERIENCEを無料体験(特別リンク):www.solidworks.com/HTMTryNow 3DEXPERIENCE SOLIDWORKS詳細:www.solidworks.com/HTMLearnMore モデルに戻って設計コンセプトを説明。目標は「ほとんどのパーツを3Dプリント可能にすること」。ここに見えるすべてが、小型3Dプリンターでもプリント可能。GT2プーリーも3Dプリント可能で、パラメトリック設計により歯数変更だけで全寸法が自動更新されます。 第1関節:2段減速で20:1減速比。2本のGT2ベルトはクローズドループ、200mmと300mm。関節は2個のスラストベアリングと1個のラジアルベアリングで構成。 第2関節:同様に16:1減速比。第3関節:単段減速で4:1。関節は中空構造で、モーター配線とマイクロスイッチ配線を通せます。各ベルトにはテンション用アイドラープーリー取り付けスロットあり。 ロボットグリッパーはMG996Rサーボモーター駆動。グリッパーエンドを交換すれば様々な把持サイズに対応可能。Z軸は8mmリードスクリュー駆動。アーム全体は4本のφ10mmスムースロッドとリニアボールベアリングでスライド。ロボット高さはスムースロッド長に依存(今回40cm)。リードスクリューはこの構成で2cm短くするか、Zモーターをスペーサーナットで2cm上げる必要あり。 3DモデルはThangsで検索、ダウンロード、ブラウザ探索可能: Thangsでアセンブリ3Dモデルをダウンロード。 3Dプリント用STLファイル: パーツの3DプリントにCreality CR-10を使用。手頃な価格で優秀な3Dプリンター。前述の通り、パーツは小型3Dプリンター(例:Ender3)でも収まるよう設計。 ほとんどのパーツにPLA+(青)、プーリーとグリッパーに通常PLAを使用。プリント速度60mm/sで全パーツ約120時間。ベースが最大で約32時間。プリント速度を上げればさらに短縮可能。 関連記事:初心者・メーカー向けベスト3Dプリンター【2021年更新版】 すべての3Dプリントパーツ: 補足:すべてのパーツを水平展開 -0.1mm 有効でプリント。これにより寸法精度が向上し、ベアリング、ロッド、ボルトなど機械部品とのフィットが良くなります。 このArduinoベースSCARAロボットの組み立てに必要なコンポーネントリストです。電子部品リストは後述の回路図セクションにあります。 必要なボルトサイズ: ベースから組み立て開始。まず内径35mm、外径47mmのラジアルボールベアリングを圧入。 次に第1スラストベアリング(内径40mm、外径60mm)を挿入。これはプーリーとベースの間に配置されます。 ベース反対側には同サイズのもう1個のスラストベアリングとジョイントカプラーを配置。 プーリーと上部パーツをM4ボルト4本(55mm)で連結。セルフロックナットを使用し、関節がガタなく自由回転するよう適切に締め付け。 中間プーリーを取り付け。このプーリーはジョイントプーリーと300mm GT2ベルトで連動。2個の608ベアリング(上面と下面)と45mm M8ボルト、ワッシャー、セルフロックナットで固定。 この関節用ステッピングモーターを取り付け。中間プーリーと200mmベルトで連動。ベース固定にM3ボルト4本。 ボルト締め付け前にベルトをできるだけ張る。中間プーリーのM8ボルトは頭を下向きに交換してベース内に収まるようにしました。 この時点でベルトテンションを確認。足りなければアイドラープーリーで調整。ここでは35mm M5ボルトとナットでテンションプーリーを自作。 ベルト両側のスロットに取り付け、好きなだけテンション調整可能。両側でテンション調整完了。これで第1関節完成。 この関節用マイクロスイッチを取り付け。スペースが狭いので事前に配線をハンダ付け。M3ボルト20mmとナットで固定。 ジョイントカプラーがスイッチに非常に近いため、片側のみボルト固定、もう片側は短いボルトを接着で対応。十分固定できて正常動作します。 次にZ軸組み立て。ジョイントカプラー上にZ軸底板パーツを固定。 その上にスムースロッド用クランプ4個を固定。スムースロッドを挿入(タイトフィットでジョイントカプラーまで貫通)。クランプでM4ボルト・ナットで締め付け固定。 リードスクリュー用ベアリングを圧入。シンプルなカバーをスライドさせて内部を隠し、見た目をすっきりさせます。 第1アーム組み立て。アームは2パーツをボルト連結。まずリニアベアリング(スムースロッドを通す)を取り付け。かなりタイトフィットで挿入が硬い場合があります。 これはプリンター精度に依存。プリント時に水平展開機能を使い、プリンターに合わせて調整することを推奨。私の場合2個のベアリングが最後まで入らなかったが、実用上問題なし。 アーム2パーツを連結。M5ボルト25mm 4本使用。 第2ステッピングモーター取り付け。ここでパラメトリック設計した20歯GT2プーリーを使用。うまく機能します。リードスクリューナットもここで固定。 第2関節用ベルトとプーリー取り付け。400mmと300mmベルト各1本。手順は第1関節と同じ。 第2、第3関節ではより小さいベアリングを使用。ラジアル:内径30mm/外径42mm、スラスト:内径35mm/外径52mm。 第2ジョイントカプラー取り付け前、六角スロットにM4ボルト20mm 6本を挿入。 これらで第2アームをジョイントに固定。必要ならアイドラープーリーでベルトテンション調整。第2マイクロスイッチ固定でアーム1アセンブリ完成。 第2アームをジョイントカプラーに取り付け。先ほどカプラーに入れたボルトで上部パーツを固定。 ここで関節のバックラッシュをテスト。ベルト由来のバックラッシュは予想していましたが、ジョイントの2パーツ間に予想以上のガタがあることが判明。ボルト穴がボルトよりわずかに大きかったのが原因。 解決策:ボルトと穴のフィットをタイトにする。私の場合4.5mmドリルで穴拡大し、M4からM5ボルトに変更。ただし3Dモデルは穴径3.5mmに修正済みなので、M4ボルトで組み立て可能。第1関節も同様に修正。これでジョイントのガタはほぼ解消、ベルト由来のわずかなバックラッシュのみ残る。 第2アーム組み立て継続。第3関節用ステッピングモーター取り付け。 ここではアーム軽量化のため短いNEMA 17(全長24cm)を使用。 第3関節用ベルトとプーリー取り付け。単段減速で400mmベルト1本のみ。下部パーツを上部パーツに連結する前に、モーターとマイクロスイッチ配線を第2関節を通して接続。 この時点でエンドエフェクター用配線も通す。私の場合ステッピングモーター用4芯ケーブルを流用(グリッパーサーボは3線)。 上部アームのスロットにM4ナットを挿入(下部パーツ固定用)。 合体直前、配線をフックの下に通して可動部と接触しないよう固定。 第2関節から出る配線がプーリーナットに巻き込まれる恐れがあるため、簡易ワイヤーホルダーで配線を退避。 配線をアーム片側にまとめて可動部との接触回避。第1アームカバーを取り付け(スナップフィット)。これでロボットアーム部完成。 このアセンブリ全体をZ軸ロッドに挿入。 Z軸トッププレート(ロッド上端保持用)を準備。まずZ軸マイクロスイッチ取り付け、4個のクランプをプレートに固定。 トッププレート装着前、下部と同様のカバーを挿入してクランプ、ボルト、マイクロスイッチを隠蔽。クランプでロッドに締め付け固定。 リードスクリュー挿入。手元のものは少し長かったので、金属用手ノコで38cmにカット。 第4ステッピングモーター取り付け。モーターとリードスクリュー接続用に5mm-8mmシャフトカプラーを使用。 配線をカバーを通し、ボルト2本でトッププレートにカバー固定。 ケーブルマネジメント。ケーブルスリーブで配線をまとめ、結束バンドも併用。 スリーブに通す前に各配線にマーキングしておくと接続間違い防止になります。 エンドエフェクター製作。どんなエンドエフェクターでも取り付け可能ですが、ここではMG996Rサーボ駆動のシンプルなグリッパーを作成。2本のφ6mmロッド上を両側がスライドする構造。 2つのスライド側をサーボホーン、3Dプリントリンク、M3ボルト・ナットでサーボに連結。グリッパー全体にM3ボルト・ナット使用。ボルト・ナット完全リストはWeb記事参照。スペースが狭く、一部組み立てには忍耐が必要。 この設計の利点:グリッパーエンドを簡単に交換可能。幅広/狭、特定形状など対応可能。M4ボルト・ナットでロボットアームに取り付け。 最後にサーボモーターを先ほど通した配線に接続。 これでSCARAロボットアームの機械的組み立て完了。あとは電子部品接続。 Arduino UNO + CNCシールド + A4988ステッピングドライバー×4を使用。 ロボットに見えても、必要な電子部品はこれだけ。Arduino UNOの代わりにArduino MEGA + RAMPS 3Dプリンターコントローラーボードも使用可能。 Arduino UNO用ケースを3Dプリントし、ベースに簡単装着可能。ステッピングドライバーは1/4ステップ分解能で駆動するため、適切なピンにジャンパー挿入。ステッピングモーターとマイクロスイッチをCNCシールドに接続。 SCARAロボットの回路図と全接続: 必要なコンポーネント: ロボット電源には12V、最低4A以上(推奨6A)の電源が必要。ただしステッピングドライバーの電流制限設定に依存し、最低レベル設定を推奨。 最後にすべての配線をケース内に収め、ドライバーのヒートシンクは露出させたままカバーを装着。 SCARAロボット完成。ベースを何かに固定する必要があります。ここでは20mm厚木材を使用。ロボットベース底面に12個の取り付け穴があるので、ベース図面を印刷して木材に穴あけ。 底面は皿取り加工(フラットヘッドボルト使用で木材表面とフラッシュ)。ベーススロットにM4ナットを入れ、木材ベースをロボットベースに固定。 理想的にはテーブルにボルト固定しますが、ここではクランプで固定。 これでSCARAロボットのハードウェア完全完成。残るは動作確認。 関連記事:スマホ制御DIY Arduinoロボットアーム ロボットの位置・姿勢制御には順運動学と逆運動学の2手法があります。 順運動学:与えられた関節角度からエンドエフェクターの位置・姿勢を求める手法。 逆運動学:エンドエフェクターの目標位置から必要な関節角度を求める手法。ロボティクスではツールを特定座標に移動させたいことが多いため、こちらがより実用的。 逆運動学で目標座標から関節角度を計算。 順/逆運動学の式は三角関数のルールと公式から導かれます。 記事下部にArduinoコードとProcessingコードの両方を掲載。 Processing開発環境でのコード実装例: 順運動学では、ロボット2アームの関節角度θ1、θ2と長さL1、L2からエンドエフェクターのX、Y値を計算。 逆運動学では、目標位置(X、Y座標)から関節角度θ2、θ1を計算。 目標位置がどの象限にあるかにより、これらの「if」文で関節角度を調整。このロボット構成では2リンクで逆運動学を計算。第3角度「phi」はグリッパー姿勢(X軸平行)制御用。 GUIはProcessing IDEのcontrolP5ライブラリで作成。ボタン、スライダー、テキストフィールドなどを簡単に作成可能。 左側スライダーで関節角度制御、テキストフィールドで目標位置入力。GUIでのあらゆる操作でデータをシリアルポート経由でArduinoへ送信。 送信データには関節角度、グリッパー値、速度、加速度、Save/Runボタン押下フラグが含まれます。 すべて1つの長い文字列としてArduinoに到着。まずカンマ区切りで分解し、個別変数に格納。 これらの変数でロボットを制御。例:SAVEボタン押下で現在の関節角度を別配列に保存。 RUNボタン押下で保存ステップ実行、等々。 ステッピングモーター制御にはAccelStepperライブラリを使用。複数ステッピングモーター同時制御に優れますが、ロボット制御では加減速実装に制限があります(スムーズな動作には重要)。 ライブラリで加減速を実装しましたが、理想ほどスムーズではありません。 このArduino SCARAロボットプロジェクトの完全なArduinoコードとProcessingコードは記事末尾に掲載。 Arduinoにコード書き込み、Processingプログラム実行、電源投入でSCARAロボットがホームポジションへ移動開始。 以降、手動操作も自動動作も自由自在。どんなエンドエフェクターも取り付け可能。例えば3Dプリンターホットエンドを付ければ3Dプリンターに、レーザーヘッドならレーザーカッターに。これらも将来の動画で挑戦予定なので、チャンネル登録をお忘れなく。 最後にいくつか補足。ロボットの剛性は期待ほど高くありませんでした。 原因は、Z軸とアーム全体が第1関節のみで支えられているため。全重量と移動時の慣性力がベースの第1関節部に集中し、プラスチック製ベースがわずかにたわみます。ベルトもバックラッシュフリーではないため、これも剛性低下要因。しかし、SCARAロボットの仕組みを学び、自作への自信を得るには十分なプロジェクトだと思います。 質問はコメント欄で、Arduinoプロジェクト集もご覧ください。概要


SCARAロボット 3Dモデル







ロボットパーツの3Dプリント


ロボットの組み立て






























SCARAロボット 回路図




組み立ての仕上げ



SCARAロボットの仕組み


SCARAロボット プログラミング – ArduinoとProcessingコード
// FORWARD KINEMATICS void forwardKinematics() { float theta1F = theta1 * PI / 180; // degrees to radians float theta2F = theta2 * PI / 180; xP = round(L1 * cos(theta1F) + L2 * cos(theta1F + theta2F)); yP = round(L1 * sin(theta1F) + L2 * sin(theta1F + theta2F)); }/ INVERSE KINEMATICS void inverseKinematics(float x, float y) { theta2 = acos((sq(x) + sq(y) - sq(L1) - sq(L2)) / (2 * L1 * L2)); if (x < 0 & y < 0) { theta2 = (-1) * theta2; } theta1 = atan(x / y) - atan((L2 * sin(theta2)) / (L1 + L2 * cos(theta2))); theta2 = (-1) * theta2 * 180 / PI; theta1 = theta1 * 180 / PI; // Angles adjustment depending in which quadrant the final tool coordinate x,y is if (x >= 0 & y >= 0) { // 1st quadrant theta1 = 90 - theta1; } if (x < 0 & y > 0) { // 2nd quadrant theta1 = 90 - theta1; } if (x < 0 & y < 0) { // 3d quadrant theta1 = 270 - theta1; phi = 270 - theta1 - theta2; phi = (-1) * phi; } if (x > 0 & y < 0) { // 4th quadrant theta1 = -90 - theta1; } if (x < 0 & y == 0) { theta1 = 270 + theta1; } // Calculate "phi" angle so gripper is parallel to the X axis phi = 90 + theta1 + theta2; phi = (-1) * phi; // Angle adjustment depending in which quadrant the final tool coordinate x,y is if (x < 0 & y < 0) { // 3d quadrant phi = 270 - theta1 - theta2; } if (abs(phi) > 165) { phi = 180 + phi; } theta1=round(theta1); theta2=round(theta2); phi=round(phi); cp5.getController("j1Slider").setValue(theta1); cp5.getController("j2Slider").setValue(theta2); cp5.getController("j3Slider").setValue(phi); cp5.getController("zSlider").setValue(zP); }
if (gripperValuePrevious != gripperValue) { if (activeIK == false) { // Check whether the inverseKinematics mode is active, Executre Forward kinematics only if inverseKinematics mode is off or false gripperAdd = round(cp5.getController("gripperValue").getValue()); gripperValue=gripperAdd+50; updateData(); println(data); myPort.write(data); } }public void updateData() { data = str(saveStatus) +","+str(runStatus) +","+str(round(cp5.getController("j1Slider").getValue())) +","+str(round(cp5.getController("j2Slider").getValue())) +","+str(round(cp5.getController("j3Slider").getValue())) +","+str(round(cp5.getController("zSlider").getValue())) +","+str(gripperValue) +","+str(speedSlider) +","+str(accelerationSlider); }if (Serial.available()) { content = Serial.readString(); // Read the incomding data from Processing // Extract the data from the string and put into separate integer variables (data[] array) for (int i = 0; i < 10; i++) { int index = content.indexOf(","); // locate the first "," data[i] = atol(content.substring(0, index).c_str()); //Extract the number from start to the "," content = content.substring(index + 1); //Remove the number from the string } /* data[0] - SAVE button status data[1] - RUN button status data[2] - Joint 1 angle data[3] - Joint 2 angle data[4] - Joint 3 angle data[5] - Z position data[6] - Gripper value data[7] - Speed value data[8] - Acceleration value */// If SAVE button is pressed, store the data into the appropriate arrays if (data[0] == 1) { theta1Array[positionsCounter] = data[2] * theta1AngleToSteps; //store the values in steps = angles * angleToSteps variable theta2Array[positionsCounter] = data[3] * theta2AngleToSteps; phiArray[positionsCounter] = data[4] * phiAngleToSteps; zArray[positionsCounter] = data[5] * zDistanceToSteps; gripperArray[positionsCounter] = data[6]; positionsCounter++; }stepper1.moveTo(stepper1Position); stepper2.moveTo(stepper2Position); stepper3.moveTo(stepper3Position); stepper4.moveTo(stepper4Position); while (stepper1.currentPosition() != stepper1Position || stepper2.currentPosition() != stepper2Position || stepper3.currentPosition() != stepper3Position || stepper4.currentPosition() != stepper4Position) { stepper1.run(); stepper2.run(); stepper3.run(); stepper4.run(); }まとめ


製造プロセス
- LEGO Mindstorms EV3用カスタムオブジェクトセンサー構築: DIY光ベース「目」
- Arduino & Raspberry Pi でインターネット制御ビデオストリーミングロボットを構築
- サウロン製作記:Arduino Mega 2560 製セミヒューマノイドロボット完全ガイド
- Arduinoで作る高精度エナジーモニター&データロガー – Dr. Wattsonボード活用
- ArduinoでユニバーサルIRリモコンを自作:ステップバイステップガイド
- LittleArm 2C: 3Dプリント製Arduinoロボットアーム – STEM教育向け耐久設計
- Arduinoと超音波センサーで自動ドアを制御:LCD・ブザー付き完全ガイド
- ArduinoとMPU-6050で作るジェスチャー制御ロボット(自作ハンドジェスチャーRCカー)
- ホワイトペーパー:自動化ポテンシャルを解き放つ─低リスク・高リターンなロボットプロジェクト7ステップ
- 最適なSCARAロボットの選び方:製造業者向け総合ガイド
- 成功するオートメーションロードマップ構築の7ステップ:目的定義からスケールアップまで