高度なリモートコントロールグリッパーロボット: 精密ハンドリング向け
必要な部品と材料
| Runt Rover Half-pint シャーシ | × | 1 | |
![]() |
Arduino UNO | × | 1 |
| V5 シールド | × | 1 | |
![]() |
メス-メス ジャンパーワイヤー | × | 1 |
| L9110S モータードライバー | × | 1 | |
| 90° シングルアングルチャンネルブラケット (585424) | × | 1 | |
| 軽量サーボハブ (Futaba用) | × | 1 | |
| スタンダードグリッパーキット A (637094) | × | 1 | |
| MG995 サーボ | × | 1 | |
| スタンダードサーボプレート | × | 1 | |
| 90° シングルアングルチャンネルブラケット | × | 1 | |
| 5スロット AA電池ホルダー | × | 1 | |
| AA充電池 (NiMH) | × | 5 | |
| 0.750" 8-32 ナイロンスペーサー | × | 2 | |
| 0.500" 6-32 ネジ (ナット付き) | × | 8 | |
| 0.3125" 6-32 ネジ | × | 8 |
アプリとオンラインサービス
![]() |
Arduino IDE |
このプロジェクトについて
数ヶ月前、息子からリモートコントロールロボットを作ってほしいと頼まれました。彼の希望リストから実現可能な項目に絞り込み、以下のロボットを作りました...
- UNOとV5センサーシールドをスナップ結合
- 結合したボードをボット中央のクリップホルダーに配置
- 両面テープでモータードライバーを左内壁、Bluetoothアダプターを右内壁に固定
このプロジェクトでは独自シャーシを作るか、他の適切な4WDシャーシを選択できます。選択は自由です。
ステップ1: 必要なソフトウェア
以下をダウンロードしてください:
- Arduino IDE
- Python 2.7 (tkinter付きフルインストール)
- pySerialライブラリ
- L9110Sモーターコントローラーライブラリ (添付の.zip、このステップのファイル参照)
- ロボットコード (下記または添付.zip、このステップのファイル参照)
- Pythonリモートコントロールアプリケーション (このステップのファイル参照)
ステップ2: ハードウェア部品表
- Runt Rover Half-pintシャーシまたは適切な4WD密閉型代替品
- Arduino Unoまたは類似ボード (USBケーブル付き)
- V5センサーシールド
- L9110Sモータードライバー (安価なので予備も含め複数推奨)
- MG995サーボまたは同等品 ×2
- HC-05またはHC-06 Bluetoothアダプター ×1
- スタンダードサーボプレート B ×1
- 90°ブラケット ×1
- シングルブラケット ×2
- 軽量サーボハブ (525125 Futaba用) ×1
- スタンダードグリッパーキット A ×1
- メス-メス ジャンパーワイヤー
- 単3充電池 (NiMH) 5本と充電器
- 両面テープと小型結束バンド
- 単3 5スロット電池ボックス (充電池オプションの場合)
- 6V NiMHまたは7.4V Li-ion電池パックと充電器
- 1.250" 6-32 ネジ ×2
- 0.750" 8-32 ナイロンスペーサー ×2
- 0.500" 6-32 ネジ (ナット付き) ×8
- 0.3125" 6-32 ネジ ×8
多くの部品はeBayやSparkfun、Adafruit、ServoCityなどから直接入手可能です。
すべての購入、収集、ダウンロードが完了したらビルドを開始します。
ステップ3: 組み立て - シャーシ
シャーシ付属の説明書または動画に従って組み立てます。完成したらコントローラー用プレートをボットの中央の穴に取り付けます。これにより前後にスペースが確保されます。
注意: これ以上進める前に、モーター破損防止のため全4輪を取り外してください。
ステップ4: グリッパーの組み立て
この動画 の手順に従ってグリッパーを組み立てます。
ステップ5: グリッパー取り付け - ステップ1
90°ブラケット、軽量サーボハブ、0.3125"ネジ4本を使用します:
- サーボハブをブラケットの片側に配置し、0.3125"ネジで固定 (写真参照)、一旦置く
- 2本の短いネジにナットを取り付け締め付け
- 2つのシングルブラケット、1.250"ネジ、0.500"ネジ (ナット付き) 2本、ナイロンスペーサー2個、サーボプレートBを用意
- 1つのシングルブラケットをHalf-pintボット内側に配置し、1.250"ネジを左側の穴 (内側から)、0.500"ネジを右側に通す。すべてのネジ頭はボット内側に
- 2つ目のシングルブラケットをボット外側のネジにはめる
- ナイロンスペーサーを長いネジ (1.250") に通し、サーボプレートを長いネジにネジ止め
- サーボプレートへのネジを適切なサイズの六角レンチまたはドライバーで締め付け
写真を参考にしてください。






ステップ6: グリッパー取り付け - ステップ2
- 残りのサーボをサーボブラケットに背骨を上にして配置し、0.3125"ネジ4本で固定
- サーボハブ付き90°ブラケットにグリッパーを取り付け。0.500"ネジ4本を使用し、ブラケットとグリッパーの間に8-32ナット2個をスペーサーとして挟む。さらにナットで固定 (ネジを逆にした場合はブラケット下側にナット)
- グリッパーアセンブリをサーボに載せ、サーボ付属のネジでしっかり固定
完了後、2本のサーボワイヤーをフラットブラケットの穴を通してボット内側に通します。





ステップ7: 電子部品の取り付け
- UNOとV5センサーシールドをスナップ結合
- 結合したボードをボット中央のクリップホルダーに配置
- 両面テープでモータードライバーを左内壁、Bluetoothアダプターを右内壁に固定



ステップ8: 配線 - モーター
- A-1A (モータードライバー) → ピン5 (センサーシールド)
- A-1B → ピン6
- B-1A → ピン3
- B-1B → ピン11
ロボットの前方を自分から離した状態で、左側の配線:
- 左側の黒色ワイヤー2本 → モーターAの第1出力ネジ端子
- 左側の赤色ワイヤー2本 → モーターAの第2出力ネジ端子
右側の配線:
- 右側の黒色ワイヤー2本 → モーターBの第1出力ネジ端子
- 右側の赤色ワイヤー2本 → モーターBの第2出力ネジ端子
サーボ:
- Yサーボワイヤー → センサーシールド ピンライン2 (白/橙色が信号線)
- X (グリッパー) サーボワイヤー → センサーシールド ピンライン7 (白/橙色が信号線)
ステップ9: Bluetoothモジュールの配線
- Bluetooth Tx → センサーシールド ピン0
- Bluetooth Rx → センサーシールド ピン1
ステップ10: 電源追加
5本の単3電池 (または他の6Vパック) の電源リードをセンサーシールドの電源ネジ端子に接続:
- 赤 → Vcc
- 黒 → GND
- V5センサーシールドのジャンパーがジャンパーピンに装着済みか確認
- L9110SドライバーのGNDピン → センサーシールドのGNDピン
- モーター用電池 (6Vまたは7.2V) のプラス線 → L9110SのVccピン
- モーター用電池のマイナス (GND) 線 → モーターシールドのGNDピン
ステップ11: HC-05/HC-06 Bluetoothモジュールの設定
PCのOS「コントロール」または「システム」パネルのBluetoothデバイス設定、またはGoogleで検索して設定してください。
OS別Bluetooth設定情報:
- Windows
- Linux (筆者はLinux Mintでbluemanを使用、ディストリビューションによる)
- Mac
割り当てられたシリアルポートデバイス名または番号をメモしてください。
ステップ12: コードのアップロード
配線を再確認したら、コードをアップロードします。Arduinoサイト の手順に従ってArduino IDEをインストールしてください。
IDEインストール後、L9110モータードライバーライブラリをインストールします。ステップ1の L9110Driver.zip をダウンロードし、Arduinoライブラリフォルダに解凍するか、ライブラリ追加手順 に従ってください。
IDEとライブラリの準備ができたら、ステップ1の blue_t_slave.zip からロボットコードをArduino IDEに読み込みます。これらのファイルはこのステップにも含まれています。
PCとArduinoをUSBケーブルで接続。ツール→ボードメニューでUnoを選択 (別ボードの場合はそれを選択)。ツール→ポートメニューでCOMポートを選択。アップロードボタンをクリック。うまくいけばコードが書き込まれます。失敗した場合はIDEのヘルプ を参照してください。
ステップ13: Pythonコントロールアプリケーションの実行
このステップのzipファイルをダウンロードし、実行したい場所に解凍します。コマンドシェル (ターミナル、cmd.exe等) を開き、解凍したディレクトリに移動。python rover.py と入力すると、画像のようなウィンドウがポップアップします。表示されない場合はPythonエラー (ライブラリ不足等) を確認し修正してください。Pythonサイト が参考になるかもしれません。
アプリが起動したら準備完了です。
ボットの電源を入れ、アダプターのCOMポートを入力して「Connect」ボタンをクリック。数秒後に他のコントロールが有効になり、Connectボタンが無効化されれば接続成功です。Bluetoothアダプターに接続できない場合はGoogleで解決策を探してください!
コントロールアプリはシンプルで、マウスまたはキーボード操作に対応しています。
キーボード操作:
- 矢印キー: 前進、後退、左90°旋回、右90°旋回
- a: 左45°旋回
- s: 右45°旋回
- h: 停止
- y: グリッパーY軸設定
- u: グリッパー開閉設定
- c: グリッパーホーム位置
前進/後退コマンドは持続的 (新しい方向コマンドまたは停止コマンドまで継続)。90°/45°旋回は一時的 (遅延後に停止)。
グリッパースライダーは自動実行されません。対応する「Set」ボタンまたはキーを押して実行します。
スライダー範囲: 0〜180
- グリッパーY軸: 0=最上、180=最下
- グリッパー開閉: 0=全閉、180=全開
「Disconnect」ボタンでプログラム終了。ボット停止とグリッパーホーム復帰コマンドが送信されます。

コード
PythonドライバーGUI Python
#!/usr/bin/env python
# Linux、BSD、Mac OSXでは chmod +x で実行可能に
###########
# Rover control app
# Written by Scott Beasley - 2015
# Free to use or modify. Enjoy.
###########
import sys
import serial
import time
from Tkinter import *
import tkFont
import tkMessageBox
# アプリケーション用ウィンドウ作成
class App(Frame):
def createWidgets(self):
self.connected = False
self.message = StringVar()
helv6 = tkFont.Font(family='Helvetica', size=6, weight='normal')
self.frame = Frame(self.master)
self.frame.pack()
# 接続フレーム
self.f1 = Frame(self.frame)
self.l1 = Label(self.f1, text="Comm Port: ")
self.l1.pack(side=LEFT)
self.comm_entry = Entry(self.f1, bd=5, name="comm_entry")
self.comm_entry.pack(side=LEFT)
self.connectButton = Button(self.f1, text="Connect", command=self.SerialConnect, name="b_connect")
self.connectButton.pack(side=LEFT)
self.disconnectButton = Button(self.f1, text="Disconnect", command=self.SerialDisconnect, name="b_disconnect")
self.disconnectButton.pack(side=RIGHT)
self.f1.grid(row=0, column=0)
# グラウンドコントロールフレーム
self.f2 = LabelFrame(self.frame, bd=3, relief="groove", text="Ground Control")
# グリッパーY軸スライダー
self.g_vert_fm = Frame(self.f2)
self.grip_vert = Scale(self.g_vert_fm, from_=0, to=180)
self.grip_vert.grid(row=0, column=0, rowspan=4, sticky=W)
self.grip_vert_set = Button(self.g_vert_fm, text="Set", command=self.GripperY, name="b_grip_vert_set", width=1, height=2, font=helv6)
self.grip_vert_set.grid(row=5, column=0, sticky=W)
self.master.bind("", self.GripperY)
self.g_vert_fm.grid(row=0, column=0, rowspan=4, sticky=W)
# 方向ボタン
self.leftforwardButton = Button(self.f2, text="\\", command=self.TurnLeft45, name="b_left_forward")
self.leftforwardButton.grid(row=0, column=1)
self.master.bind("", self.TurnLeft45)
self.leftButton = Button(self.f2, text="<", command=self.TurnLeft, name="b_left")
self.leftButton.grid(row=1, column=1)
self.master.bind("", self.TurnLeft)
self.rightforwardButton = Button(self.f2, text="/", command=self.TurnRight45, name="b_right_forward")
self.rightforwardButton.grid(row=0, column=3)
self.master.bind("", self.TurnRight45)
self.haltButton = Button(self.f2, text="Halt!", command=self.Halt, name="b_halt")
self.haltButton.grid(row=1, column=2)
self.master.bind("", self.Halt)
self.rightButton = Button(self.f2, text=">", command=self.TurnRight, name="b_right")
self.rightButton.grid(row=1, column=3)
self.master.bind("", self.TurnRight)
self.upButton = Button(self.f2, text="^", command=self.Forward, name="b_forward")
self.upButton.grid(row=0, column=2)
self.master.bind("", self.Forward)
self.leftdownButton = Button(self.f2, text="/", command=self.TurnRight45, name="b_left_down")
self.leftdownButton.grid(row=2, column=1)
self.downButton = Button(self.f2, text="V", command=self.Reverse, name="b_reverse")
self.downButton.grid(row=2, column=2)
self.master.bind("", self.Reverse)
self.f2.grid(row=1, column=0, pady=25)
self.rightdownButton = Button(self.f2, text="\\", command=self.TurnLeft45, name="b_right_down")
self.rightdownButton.grid(row=2, column=3)
# グリッパーX軸スライダー
self.g_horz_fm = Frame(self.f2)
self.grip_horz = Scale(self.g_horz_fm, from_=0, to=180, orient=HORIZONTAL)
self.grip_horz.grid(row=0, column=0, columnspan=7, sticky=E)
self.grip_horz_set = Button(self.g_horz_fm, text="Set", command=self.GripperX, name="b_grip_horz_set", width=1, height=2, font=helv6)
self.grip_horz_set.grid(row=0, column=8)
self.master.bind("", self.GripperX)
self.g_horz_fm.grid(row=4, column=0, columnspan=7, sticky=E)
self.master.bind("", self.GripperHome)
# ステータスバー
self.f3 = Frame(self.frame)
self.l2 = Label(self.f3, text="Last action: ")
self.l2.pack(side=LEFT)
self.l3 = Label(self.f3, text=" ", textvariable=self.message)
self.l3.pack(side=RIGHT)
self.f3.grid(row=3, column=0, pady=8)
# ボット制御ボタンの状態設定
def CtrlButtonsState(self, bstate):
self.leftforwardButton.config(state=bstate)
self.leftButton.config(state=bstate)
self.rightforwardButton.config(state=bstate)
self.rightButton.config(state=bstate)
self.upButton.config(state=bstate)
self.leftdownButton.config(state=bstate)
self.downButton.config(state=bstate)
self.rightdownButton.config(state=bstate)
self.haltButton.config(state=bstate)
self.disconnectButton.config(state=bstate)
self.grip_horz.config(state=bstate)
self.grip_vert.config(state=bstate)
self.grip_horz_set.config(state=bstate)
self.grip_vert_set.config(state=bstate)
# COMポートエントリーの状態設定
def ConnCtrlsState(self, bstate):
self.connectButton.config(state=bstate)
self.comm_entry.config(state=bstate)
# COMポートに接続
def SerialConnect(self):
try:
self.ser = serial.Serial(self.comm_entry.get(), 9600)
except IOError:
tkMessageBox.showerror("Invalid comm port", "Comm port not found.")
return
self.ConnCtrlsState(DISABLED)
self.CtrlButtonsState(NORMAL)
self.message.set("SerialConnect")
self.connected = True
time.sleep(3)
# ボットから切断
def SerialDisconnect(self):
try:
self.send_cmd('h', "Halt!")
time.sleep(1)
self.ser.close()
except IOError:
print("Could not close port...")
self.message.set("SerialDisconnect")
self.ConnCtrlsState(NORMAL)
self.CtrlButtonsState(DISABLED)
self.connected = False
time.sleep(2)
# コマンド送信
def send_cmd(self, action, msg):
if self.connected == True:
for val in action:
self.ser.write(val)
self.ser.flush()
self.message.set(msg)
# 左旋回
def TurnLeft(self, event=None):
self.send_cmd('a', "Left")
# 左45°旋回
def TurnLeft45(self, event=None):
self.send_cmd('q', "Left45")
# 右旋回
def TurnRight(self, event=None):
self.send_cmd('s', "Right")
# 右45°旋回
def TurnRight45(self, event=None):
self.send_cmd('e', "Right45")
# 前進
def Forward(self, event=None):
self.send_cmd('w', "Up")
# 後退
def Reverse(self, event=None):
self.send_cmd('z', "Down")
# 停止
def Halt(self, event=None):
self.send_cmd('h', "Halt!")
# グリッパーX設定
def GripperX(self, event=None):
grp_change = ('>', chr(self.grip_horz.get()), chr(255))
self.send_cmd(grp_change, "Gripper X")
# グリッパーY設定
def GripperY(self, event=None):
grp_change = ('^', chr(self.grip_vert.get()), chr(255))
self.send_cmd(grp_change, "Gripper Y")
# グリッパーホーム
def GripperHome(self, event=None):
self.send_cmd(('c', chr(255)), "Gripper Home")
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack()
self.createWidgets()
self.CtrlButtonsState(DISABLED)
# GUI起動
def main():
root = Tk()
root.geometry("450x350")
root.wm_title("Rover Control Center (RCC)")
app = App(master=root)
app.mainloop()
if __name__ == '__main__':
main()
ローバーコード Arduino
/* Bluetooth Rover. Goal in life... Follows your commands sent magically though the air! Or from USB :)
Written by Scott Beasley - 2015
Free to use or modify. Enjoy. */
/* L9110Sライブラリを使用。L9110S Hブリッジで動作。
ダウンロード: https://github.com/jscottb/L9110Driver
または https://github.com からzipをクローンし、アーカイブ名から '-master' を削除してライブラリ追加 */
#include
#include
#define SERVO_Y 2 // グリッパーYサーボピン
#define SERVO_CLAW 7 // グリッパークローサーボピン
#define pinAIN1 5 // I1インターフェース
#define pinAIN2 6 // I2インターフェース
#define pinBIN1 3 // I3インターフェース
#define pinBIN2 11 // I4インターフェース
// 速度定義
#define MAXFORWARDSPEED 225 // 前進最大速度
#define MAXBACKWARDSPEED 225 // 後退最大速度
#define TOPSPEED 255 // カーペット等での旋回補助用
// 各種遅延時間
#define TURNDELAY 475
#define TURNDELAY45 235
#define BACKUPDELAY 400
#define SERVOMOVEDELAY 200
#define SERVOSEARCHDELAY 85
// グローバル領域
L9110_Motor motor_left(pinAIN1, pinAIN2); // 左モーターオブジェクト
L9110_Motor motor_right(pinBIN1, pinBIN2); // 右モーターオブジェクト
Servo grip_y_servo; // グリッパーY軸サーボ
Servo grip_servo; // グリッパークローサーボ
void setup() {
Serial.begin(9600);
grip_y_servo.attach(SERVO_Y);
grip_y_servo.write(90);
grip_servo.attach(SERVO_CLAW);
grip_servo.write(90);
delay(500);
}
void loop() {
byte command = 0, val = 0;
if (Serial.available() > 0) {
command = Serial.read();
}
switch (command) {
case 'w': go_forward(); break;
case 'z': go_backward(); break;
case 'a': go_left(); delay(TURNDELAY); halt(); break;
case 's': go_right(); delay(TURNDELAY); halt(); break;
case 'q': go_left(); delay(TURNDELAY45); halt(); break;
case 'e': go_right(); delay(TURNDELAY45); halt(); break;
case 'h': halt(); break;
case '>': // グリッパーX移動
val = Serial.read();
grip_servo.write(constrain(val, 64, 179));
break;
case '^': // グリッパーY移動
val = Serial.read();
grip_y_servo.write(constrain(val, 53, 179));
break;
case 'c': // グリッパーホーム
grip_y_servo.write(90);
grip_servo.write(90);
break;
case 255: // グリッパーコマンド後のフラッシュ
Serial.flush();
break;
}
Serial.flush();
delay(125);
}
void go_forward() {
ramp_it(MAXFORWARDSPEED, FORWARD, FORWARD);
motor_left.setSpeed(MAXFORWARDSPEED);
motor_right.setSpeed(MAXFORWARDSPEED);
motor_left.run(FORWARD|RELEASE);
motor_right.run(FORWARD|RELEASE);
}
void go_backward() {
ramp_it(MAXBACKWARDSPEED, BACKWARD, BACKWARD);
motor_left.setSpeed(MAXBACKWARDSPEED);
motor_right.setSpeed(MAXBACKWARDSPEED);
motor_left.run(BACKWARD|RELEASE);
motor_right.run(BACKWARD|RELEASE);
}
void go_left() {
ramp_it(TOPSPEED, BACKWARD, FORWARD);
motor_left.setSpeed(TOPSPEED);
motor_right.setSpeed(TOPSPEED);
motor_left.run(BACKWARD|RELEASE);
motor_right.run(FORWARD|RELEASE);
}
void go_right() {
ramp_it(TOPSPEED, FORWARD, BACKWARD);
motor_left.setSpeed(TOPSPEED);
motor_right.setSpeed(TOPSPEED);
motor_left.run(FORWARD|RELEASE);
motor_right.run(BACKWARD|RELEASE);
}
void halt() {
motor_left.setSpeed(0);
motor_right.setSpeed(0);
motor_left.run(BRAKE);
motor_right.run(BRAKE);
}
void ramp_it(uint8_t speed, uint8_t lf_dir, uint8_t rt_dir) {
uint8_t ramp_val = 0, step_val = 0;
step_val = abs(speed / 4);
if (!speed) step_val = -step_val;
for (uint8_t i = 0; i < 4; i++) {
ramp_val += step_val;
motor_left.setSpeed(ramp_val);
motor_right.setSpeed(ramp_val);
motor_left.run(lf_dir|RELEASE);
motor_right.run(rt_dir|RELEASE);
delay(25);
}
}
L9110ドライバー
Arduino用L9110モータードライバー: GitHub
カスタムパーツとエンクロージャ
4wdgripperbt2.fzz
回路図
4wdgripperbt2.fzz
製造プロセス
- スマートホーム連携向けマルチポジション温度センサーシステム
- 862D+はんだごて用DIY温度コントローラー:精度と信頼性を両立
- MotionSense: ArduinoとESP8266で作るスマート侵入検知システム
- 3Dプリンター火災予防:スマートセンサーセーフティシステム
- Arduinoで作る斥力式磁気浮上装置: シンプル回路とDIYガイド
- 高性能 Arduino 気象観測気球データロガーの製作ガイド
- ArduFarmBot Part 2:リモートIoT制御ステーションの構築
- 高度なマイクロコントローラー実験:ESP32、Arduino、PIC、センサーモジュール
- CoroFenceサーマルディテクター:Grid-EYE & PIRセンサー搭載IoT体温監視
- クラウド監視:リアルタイム資産管理のためのリモート制御システム
- モダン産業におけるリモート生産制御の5つの主要メリット


