亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Manufacturing Technology >> 制造工艺

进阶遥控夹爪机器人:精密抓取 DIY 指南

组件与物料

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
.750" 8-32 尼龙隔离柱 × 2
.500" 6-32 螺丝含螺母 × 8
.3125" 6-32 螺丝 × 8

应用与在线服务

Arduino IDE

项目背景

几个月前儿子想要一台遥控机器人,列了清单后我们精简为可落地方案。最终成品如下:

底盘可自制或选用其他 4WD 封闭式底盘。

步骤 1:所需软件

步骤 2:硬件 BOM 详细清单

零件可从 eBay、Sparkfun、Adafruit、ServoCity 采购。

步骤 3:底盘组装

按说明书或视频组装底盘。控制器安装板置于中间孔位,预留前后空间。重要:后续步骤前请先拆下 4 个车轮,避免装配时损坏电机。

步骤 4:夹爪组装

按视频教程组装夹爪。

步骤 5:安装夹爪 - 第一阶段

用料:90° 支架、轻量舵机轮毂、4 颗 .3125" 螺丝。

进阶遥控夹爪机器人:精密抓取 DIY 指南
进阶遥控夹爪机器人:精密抓取 DIY 指南
进阶遥控夹爪机器人:精密抓取 DIY 指南
进阶遥控夹爪机器人:精密抓取 DIY 指南
进阶遥控夹爪机器人:精密抓取 DIY 指南
进阶遥控夹爪机器人:精密抓取 DIY 指南

步骤 6:安装夹爪 - 第二阶段

进阶遥控夹爪机器人:精密抓取 DIY 指南
进阶遥控夹爪机器人:精密抓取 DIY 指南
进阶遥控夹爪机器人:精密抓取 DIY 指南
进阶遥控夹爪机器人:精密抓取 DIY 指南
进阶遥控夹爪机器人:精密抓取 DIY 指南

步骤 7:安装电子模块

进阶遥控夹爪机器人:精密抓取 DIY 指南
进阶遥控夹爪机器人:精密抓取 DIY 指南
进阶遥控夹爪机器人:精密抓取 DIY 指南

步骤 8:电机接线

车头朝外,左侧电机:两根黑线接 Motor A 第 1 端子,两根红线接第 2 端子;右侧电机同理接 Motor B。

舵机接线:

步骤 9:蓝牙模块接线

步骤 10:供电连接

步骤 11:配置 HC-05/HC-06 蓝牙模块

在电脑 OS 蓝牙设置中配对,记下分配的串口设备名/编号。Windows/Linux/Mac 均可,Linux 推荐 blueman。

步骤 12:烧录 Arduino 代码

  1. 安装 Arduino IDE
  2. 安装 L9110 驱动库:解压 L9110Driver.zip 到 libraries 文件夹,或用 IDE “添加 .ZIP 库”
  3. 打开 blue_t_slave.ino,选板 Uno,选端口,上传

步骤 13:运行 Python 上位机控制程序

  1. 解压 rover.py 到任意目录
  2. 终端进入目录,运行 python rover.py
  3. 弹出 GUI 窗口,输入蓝牙串口号点击“Connect”
  4. 连接成功后控件启用,即可操控

控制说明

键盘控制:

前进/后退为持续指令,直到发新指令或停止。转向为定时动作,延时后自动停车。滑块范围 0-180:Y 轴 0=最高 180=最低;X 轴 0=全合 180=全开。需点击“Set”或按对应键生效。“Disconnect”按钮会停车并复位夹爪。

进阶遥控夹爪机器人:精密抓取 DIY 指南

代码

Python 上位机 GUI (rover.py)

#!/usr/bin/env python
# Linux/BSD/Mac 可 chmod +x 直接执行
###########
# Rover Control App
# Written by Scott Beasley - 2015
# Free to use or modify. Enjoy.
###########
import sys, serial, time
from Tkinter import *
import tkFont, 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)
        Label(self.f1, text="Comm Port: ").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.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)
        Label(self.f3, text="Last action: ").pack(side=LEFT)
        Label(self.f3, text=" ", textvariable=self.message).pack(side=RIGHT)
        self.f3.grid(row=3, column=0, pady=8)
    def CtrlButtonsState(self, bstate):
        for btn in [self.leftforwardButton, self.leftButton, self.rightforwardButton, self.rightButton,
                    self.upButton, self.leftdownButton, self.downButton, self.rightdownButton,
                    self.haltButton, self.disconnectButton]:
            btn.config(state=bstate)
        for s in [self.grip_horz, self.grip_vert, self.grip_horz_set, self.grip_vert_set]:
            s.config(state=bstate)
    def ConnCtrlsState(self, bstate):
        self.connectButton.config(state=bstate)
        self.comm_entry.config(state=bstate)
    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:
            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")
    def TurnLeft45(self, event=None): self.send_cmd('q', "Left45")
    def TurnRight(self, event=None): self.send_cmd('s', "Right")
    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!")
    def GripperX(self, event=None):
        grp_change = ('>', chr(self.grip_horz.get()), chr(255))
        self.send_cmd(grp_change, "Gripper X")
    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)

def main():
    root = Tk(); root.geometry("450x350"); root.wm_title("Rover Control Center (RCC)")
    App(master=root).mainloop()

if __name__ == '__main__': main()

Arduino 端代码 (blue_t_slave.ino)

/* Bluetooth Rover - Scott Beasley 2015 */
#include <L9110Driver.h>
#include <Servo.h>

#define SERVO_Y 2
#define SERVO_CLAW 7
#define pinAIN1 5; #define pinAIN2 6
#define pinBIN1 3; #define pinBIN2 11

#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, 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 '>': val = Serial.read(); grip_servo.write(constrain(val, 64, 179)); break;
    case '^': 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 = 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 驱动库

GitHub: https://github.com/jscottb/L9110Driver

自定义零件与外壳

4wdgripperbt2.fzz (Fritzing 设计文件)

原理图

进阶遥控夹爪机器人:精密抓取 DIY 指南

4wdgripperbt2.fzz

制造工艺

  1. 多位置温度传感器系统,助力智能家居集成
  2. 862D+ 电烙铁 DIY 智能温控器:精准可靠,低成本替代方案
  3. MotionSense:基于 Arduino 与 ESP8266 的智能入侵检测系统
  4. 3D 打印机防火卫士:智能传感器安全系统
  5. Arduino 简易排斥式磁悬浮:电路与 DIY 指南
  6. 高性能 Arduino 气象气球数据记录器
  7. ArduFarmBot 第二部分:构建远程 IoT 控制站
  8. 进阶微控制器实验平台:ESP32、Arduino、PIC 与多传感器模块集成
  9. DIY 视觉暂留 (POV) 球体:Arduino Mega 驱动的 LED 光绘艺术
  10. CoroFence 热成像检测器:Panasonic GridEye + PIR + IoT 集成
  11. 云监控:实时资产管理的远程控制系统
  12. 现代工业远程生产控制的5大核心优势