
大家好我最近在做一个机械臂末端夹爪相关的实验核心内容是用飞特Feetech舵机作为夹爪的驱动单元配合达妙Damiao夹爪的机械结构实现一个带力反馈的夹取 Demo。踩了不少通信、供电和力控标定的坑今天把完整思路和可复现的流程整理出来。这篇文章适合三类读者正在做机器人夹爪、仿生手或力控相关毕设/竞赛项目的同学。手里有飞特舵机想低成本实现“夹持力感知”的开发者。想把“电流反馈”变成“力反馈”的嵌入式与机器人爱好者。读完这篇文章你将掌握飞特串行总线舵机的基本控制方法。如何读取舵机电流/负载值并换算成夹持力。达妙夹爪的通信控制思路。一套可落地的力反馈夹取 Demo 算法与代码框架。常见坑点接线错误、供电不足、电流突变、控制震荡等排查方式。1. 背景与核心概念1.1 什么是力反馈 Demo力反馈并不是一个神秘概念。在机器人夹爪场景里我们希望夹爪在抓取易碎物品鸡蛋、纸杯、玻璃瓶时既能夹稳又不会夹碎。传统开环夹爪只有两个状态打开、闭合。夹爪碰到物体后继续加大电流可能直接把物体压坏。力反馈 Demo 的核心是把夹持力变成可测量、可闭环控制的物理量。常见的力检测方案有三种方案传感器精度成本实现难度专用力矩传感器六维力/关节力矩传感器高高高薄膜压力传感器柔性压阻薄膜中低中电机电流估算驱动器电流采样中低最低低对于入门 Demo 和教学演示用舵机电流估算力矩是最快捷的方案。飞特舵机支持读取电流和负载状态这让低成本力反馈成为可能。1.2 飞特舵机解决什么问题飞特Feetech是国产串行总线舵机品牌常见型号包括 SC 系列、STS 系列等。相比普通 PWM 舵机飞特串行总线舵机有几个关键优势只需一根总线TTL 或 RS485就能串联多个舵机。支持位置、速度、扭矩控制。可以读取舵机内部电压、温度、电流、负载等状态。舵机转动遇到阻力时电流会上升这个特性可以用来估算外力。在夹爪 Demo 中我们主要利用它的电流读取能力和位置控制能力。1.3 达妙夹爪在系统中的角色达妙Damiao在机器人圈更出名的是关节模组但它的夹爪结构件也经常出现在机器人末端方案里。达妙夹爪的优势在于结构刚性好、传动精度高、手指可替换。和飞特舵机配合时可以有两种形态形态一电动夹爪本体。夹爪自带电机驱动和控制板飞特舵机作为外部辅助力觉输入用于模拟人手转动或者外部干扰。形态二机械夹爪结构件。夹爪本身不带电机我们把飞特舵机作为唯一的驱动源通过连杆带动夹爪手指开合。本文的 Demo 逻辑兼容以上两种形态。核心控制思想是由舵机输出夹持动作通过电流检测反馈力的大小再根据力反馈结果调节夹爪的目标位置或目标电流。1.4 为什么需要用电流代替真实力传感器真实力传感器很贵而且标定复杂。电流估算力矩的原理是直流电机的输出力矩与电枢电流近似成正比即[ T K_t \times I ]其中( T ) 是电机输出力矩。( K_t ) 是电机力矩常数。( I ) 是电机电流。舵机内部是减速电机。当外部负载变大时电机为了维持位置或速度需要输出更大扭矩从而电流随之上升。所以电流值可以作为力矩的间接表示。用飞特舵机自带的状态读取指令可以比较方便地拿到这个值。1.5 Demo 的整体目标本 Demo 要模拟一个“防碎夹取”场景给夹爪一个初始夹持角度。夹爪逐步闭合。舵机电流随着夹持力增大而上升。当电流达到设定阈值时说明已经夹紧。控制器停止继续增加夹持力进入保持状态。如果物体打滑或位置改变舵机电流出现波动系统重新微调夹持力。下面我们来看这套系统的完整设计方案。2. 总体架构与方案设计2.1 系统框图先用一个 ASCII 简图说明整体结构------------------ | 上位机 / 主控 | | (Python/STM32) | ----------------- | | 串口/RS485 ------------------ | | --------v--------- -----v---------- | 飞特串行总线舵机 | | 达妙夹爪 | | (驱动 力传感) | | (执行终端) | ------------------ ----------------主控是整个系统的决策中心发送位置指令给飞特舵机让舵机驱动夹爪闭合。周期读取舵机电流值。根据电流值计算夹持力估计值。如果力超过安全阈值停止夹紧进入保持。夹爪的最终位置可以通过夹爪自带的角度反馈或舵机的位置读数获得。2.2 控制链路设计整个 Demo 采用一个简单的闭环控制目标夹持力/阈值 | v [力控制器] - [舵机目标位置] - [夹爪机械结构] ^ | | v ---------- [电流采样] ---- [电机负载]也可以理解为接触物体前位置控制模式低速闭合。 接触物体后力阈值判断电流到达阈值就停止。 保持阶段位置环保持同时监控电流波动。2.3 力反馈的三种实现层次为了满足不同读者手里的硬件条件我列三个层次层次一阈值保护模式最简单舵机匀速闭合实时采集电流。当电流超过阈值立即停止。这个模式不需要精确力值只需要知道“力大了”。层次二电流闭环控制模式给定期望电流等效期望夹持力用 PID 调节舵机位置或夹爪电流环让实际电流稳定在期望值附近。这种方式适合需要精确控力的场景。层次三力/位混合控制夹爪先快速接近物体接触后平滑切换为力控制。这是工业夹爪的常见做法但在 Demo 阶段可以用前两个层次先跑通。本文主要介绍层次二因为它是理解力反馈的核心。3. 硬件准备与通信环境3.1 硬件清单硬件说明飞特舵机建议使用支持串行总线、可读电流的型号如 STS 系列或 SCS 系列达妙夹爪根据实际情况选择带驱动模块或纯机械结构版本主控板STM32 或 ESP32也可以直接用 PC 串口调试USB 转串口模块支持 TTL 或 RS485取决于舵机类型直流电源舵机供电建议 6V-7.4V电流余量至少 3A 以上杜邦线/接线端子注意线径电流较大时不要用太细的线被测物体建议用易碎或易变形物体例如鸡蛋、纸杯、海绵万用表排查供电和通信问题3.2 飞特舵机通信接口飞特串行总线舵机一般有两种物理接口TTL 接口半双工串口电平为 3.3V/5V适合短距离。RS485 接口差分信号抗干扰能力强适合长距离和多个舵机串联。连接时要注意TTL 舵机的 TX/RX 交叉连接。RS485 舵机需要 A/B 线对应连接。舵机总线是多机共线每个舵机需要设置不同的 ID。主控与舵机通信一般使用飞特官方的串口协议。帧格式如下帧头(0xFF 0xFF) ID 长度 指令 参数 校验和读取舵机角度、电流、电压的指令示例读取位置指令 0x02寄存器地址根据型号各不相同。读取电流/负载需要查询对应型号的寄存器地址表。这里特别强调不同型号的飞特舵机寄存器地址不一定相同通信波特率也要匹配。入门时需要先下载对应型号的说明书本文的示例代码需要根据实际型号修改参数。3.3 达妙夹爪通信接口达妙夹爪/关节模组通常支持CAN 总线通信。串口通信。不同产品差别很大本文不直接绑定某一个协议。建议先使用官方上位机或者官方 Demo 把夹爪转起来验证通信链路正常再接入自己的控制逻辑。3.4 供电注意事项供电是舵机项目最常见的坑点。舵机启动瞬间电流很大USB 口带不动多个舵机。电源功率不足会导致舵机复位、通信失败、电压跌落。控制板与舵机最好分开供电共地即可。如果舵机长时间堵转发热严重要设置电流保护阈值。建议供电顺序给主控板上电。确认主控串口正常。给舵机供电。测试舵机是否可以正常转动。4. 飞特舵机与达妙夹爪基础调试4.1 准备工作先安装 Python 串口库pip install pyserial然后用一个简单的串口工具或者 Python 脚本测试通信。4.2 飞特舵机通信测试以下是一个简化的 Python 串口收发框架。注意飞特舵机有官方 SDK但为了理解原理这里演示手动组包的基本思路import serial import time # 初始化串口 ser serial.Serial( portCOM10, # Windows 示例 baudrate1000000, # 根据舵机实际波特率修改 timeout0.1 ) def checksum(packet): 飞特协议校验和对 ID 到数据位求和取低八位取反 s sum(packet[2:]) 0xFF return (~s) 0xFF def read_servo_state(servo_id, reg_addr, length): 读取舵机寄存器 servo_id: 舵机 ID reg_addr: 寄存器地址 length: 读取字节长度 # 构建读指令包 packet [0xFF, 0xFF, servo_id, 0x04, 0x02, reg_addr, length] packet.append(checksum(packet)) ser.write(bytearray(packet)) time.sleep(0.02) response ser.read(64) return response def write_servo_angle(servo_id, angle, speed100): 写舵机角度 # 角度范围按实际型号转换多数舵机 0-1000 对应 0-360 度或 0-270 度 pos_raw int(angle / 270.0 * 1000) # 以 270 度舵机为例 # 构建写指令包 packet [ 0xFF, 0xFF, servo_id, 0x07, 0x03, 0x2A, # 位置寄存器地址按型号修改 pos_raw 0xFF, (pos_raw 8) 0xFF, speed 0xFF, (speed 8) 0xFF, ] packet.append(checksum(packet)) ser.write(bytearray(packet)) time.sleep(0.1)代码里的注释特别提示寄存器地址和角度范围必须查对应型号的手册。4.3 读取电流/负载值飞特舵机中的“负载/电流”寄存器通常能反映舵机受力程度。读取思路如下def read_load(servo_id): # 以某个型号负载寄存器地址为 0x38 为例仅示意 LOAD_REG 0x38 resp read_servo_state(servo_id, LOAD_REG, 2) if len(resp) 8: low resp[5] high resp[6] load_raw (high 8) | low direction (load_raw 10) 0x01 load_value load_raw 0x3FF # 如果 direction 为 1表示反向负载 if direction: load_value -load_value return load_value return None这个值不是标准的“克”或“牛”而是比例值。它和真实力矩之间存在近似线性关系后面需要标定。4.4 达妙夹爪控制思路如果夹爪本身带驱动板一般支持以下控制模式位置模式设置目标开合量。速度模式设置开合速度。电流/力矩模式设置最大力矩。在力反馈 Demo 中最理想的是“位置模式 电流限制”。这样可以在夹持到物体后通过限制电流来限制夹持力。如果你的夹爪只有位置模式那也没关系我们可以通过控制舵机的输出来间接控力。5. 力反馈算法与核心 Demo 实现5.1 控制目标我们希望夹持力 F 可控。由于缺少直接力传感器我们建立[ F \approx K \times I_{load} ]其中( I_{load} ) 是舵机负载电流/负载比例值。( K ) 是标定系数。实际操作时我们经常不需要把负载值换算成物理单位而是直接以“负载阈值”作为控制目标。例如空载时舵机负载比例值为 20。夹到纸杯时负载比例值达到 80。夹到金属块时负载比例值达到 400。那我们可以把安全阈值设为 100 或 150。5.2 增量式 PID 力控思路在夹爪接近物体后我们希望实际负载值 (Actual) 跟踪目标负载值 (Target)。使用增量式 PID[ e_k Target - Actual_k ][ \Delta U_k K_p (e_k - e_{k-1}) K_i e_k K_d (e_k - 2e_{k-1} e_{k-2}) ][ U_k U_{k-1} \Delta U_k ]其中 (U_k) 对应舵机的目标角度增量。为了简化 Demo也可以使用“阈值 保持”控制即if load_value threshold: angle step # 继续夹 else: angle - 2 # 略微回退或保持这种策略实现简单适合演示。5.3 完整 Demo 代码框架下面是一个简化但完整可运行的 Python 脚本框架。它实现了以下逻辑初始化串口。让夹爪打开到最大位置。以低速逐渐闭合夹爪。每次闭合后读取舵机负载值。当负载值超过阈值时停止闭合。尝试保持一小段时间如果负载下降则继续夹紧。最后控制夹爪打开结束 Demo。# -*- coding: utf-8 -*- 飞特舵机 达妙夹爪 力反馈防碎夹取 Demo 注意 1. 串口号、波特率、寄存器地址需要根据实际设备修改。 2. 舵机角度范围和夹爪开合方向需要根据机械结构确认。 3. demo 仅为教学演示不代表工业级控制逻辑。 import serial import time # ------------------ 串口配置 ------------------ SERIAL_PORT COM10 BAUDRATE 1000000 SERVO_ID 1 # ------------------ 控制参数 ------------------ OPEN_ANGLE 60 # 夹爪打开角度根据实际机械结构调整 CLOSE_ANGLE 10 # 最大闭合角度防止机械限位 STEP_DEGREE 0.5 # 每次微调角度 LOAD_THRESHOLD 120 # 负载阈值越大表示夹持力越大 # ------------------ 工具函数 ------------------ ser serial.Serial(SERIAL_PORT, BAUDRATE, timeout0.1) def checksum(packet): s sum(packet[2:]) 0xFF return (~s) 0xFF def read_load_value(): 读取舵机负载值。 注意寄存器地址按实际舵机型号修改下述为占位示例。 reg_addr 0x38 # 占位寄存器地址 packet [0xFF, 0xFF, SERVO_ID, 0x04, 0x02, reg_addr, 0x02] packet.append(checksum(packet)) ser.write(bytearray(packet)) time.sleep(0.01) resp ser.read(32) if len(resp) 8: return None low resp[5] high resp[6] raw (high 8) | low load raw 0x3FF direction (raw 10) 0x01 if direction: load -load return load def write_angle(angle): 写舵机角度。 角度值根据实际舵机范围和寄存器地址调整此处为占位实现。 pos_raw int(angle / 270.0 * 1000) pos_raw max(0, min(1000, pos_raw)) # 位置寄存器地址示例按型号修改 reg_addr 0x2A speed 50 packet [ 0xFF, 0xFF, SERVO_ID, 0x07, 0x03, reg_addr, pos_raw 0xFF, (pos_raw 8) 0xFF, speed 0xFF, (speed 8) 0xFF, ] packet.append(checksum(packet)) ser.write(bytearray(packet)) time.sleep(0.02) def set_damiao_close(percent): 达妙夹爪闭合指令封装。 percent 0-100 表示开合程度。 具体指令格式需要根据官方协议替换。 # TODO: 根据达妙夹爪官方通信协议实现 pass def set_damiao_open(): 达妙夹爪打开指令封装。 pass # ------------------ 主逻辑 ------------------ def main(): print( 力反馈夹取 Demo 启动 ) # 1. 打开夹爪 print(步骤1: 夹爪打开) write_angle(OPEN_ANGLE) set_damiao_open() time.sleep(1) # 2. 开始夹紧 print(步骤2: 开始夹紧逐步增加夹持力) current_angle OPEN_ANGLE while current_angle CLOSE_ANGLE: # 读取当前负载 load read_load_value() if load is None: print(读取负载失败检查串口/舵机接线) break print(f当前角度: {current_angle:.1f}, 负载值: {load}) # 超过阈值停止夹紧 if abs(load) LOAD_THRESHOLD: print(检测到夹持力达到阈值停止夹紧) break # 继续微调 current_angle - STEP_DEGREE write_angle(current_angle) time.sleep(0.05) # 3. 保持夹持 2 秒 print(步骤3: 保持夹持状态) time.sleep(2) # 4. 打开夹爪 print(步骤4: 释放物体) write_angle(OPEN_ANGLE) set_damiao_open() time.sleep(1) print( Demo 结束 ) if __name__ __main__: try: main() except KeyboardInterrupt: print(用户中断) finally: ser.close()这段代码的核心逻辑并不复杂。实际项目中还存在几个问题负载值可能有负号负号表示方向判断阈值时要用绝对值。舵机从运动到停止会有惯性角度微调后需要等待一小段时间再采样。负载值有噪声可以加一个简单的滑动滤波。5.4 加入滑动滤波为了让负载值更稳定可以定义如下滤波函数class MovingAverageFilter: def __init__(self, window_size5): self.window [] self.window_size window_size def update(self, value): self.window.append(value) if len(self.window) self.window_size: self.window.pop(0) return sum(self.window) / len(self.window) filter_ MovingAverageFilter(5) load_filtered filter_.update(load_raw)滤波窗口太小则效果不明显太大会导致响应迟钝。建议从 5 到 10 开始调。5.5 带 PID 的恒力夹持如果希望夹持力恒定在一个目标值可以使用简单 PIDclass IncrementalPID: def __init__(self, kp, ki, kd): self.kp kp self.ki ki self.kd kd self.prev_error 0 self.prev_prev_error 0 self.output 0 def update(self, target, current): error target - current delta ( self.kp * (error - self.prev_error) self.ki * error self.kd * (error - 2 * self.prev_error self.prev_prev_error) ) self.output delta self.prev_prev_error self.prev_error self.prev_error error return self.output在主循环中pid IncrementalPID(kp0.3, ki0.02, kd0.05) target_load 100 angle_offset 0 while True: load read_load_value() if load is None: continue angle_offset pid.update(target_load, abs(load)) current_angle OPEN_ANGLE angle_offset current_angle max(CLOSE_ANGLE, min(OPEN_ANGLE, current_angle)) write_angle(current_angle) time.sleep(0.02)PID 的三个参数需要观察实际响应来调(K_p) 太大会震荡。(K_i) 太大会超调。(K_d) 太大会放大噪声。6. 负载值与夹持力标定6.1 为什么需要标定舵机的负载值是一个相对值。同一个舵机在不同供电电压、不同减速比下负载值对应的实际力矩也不一样。我们可以通过简单砝码法来标定。6.2 砝码法标定流程在舵机输出轴上一次装好夹爪结构保持舵机水平让舵机处于空载状态读取负载值 (L_0)。在夹爪手指上挂一个已知质量的砝码 (m)记录负载值 (L_1)。换不同质量砝码记录多组数据。估算夹持力[ F m \times g ]如果砝码挂在夹爪指尖需要考虑杠杆比例。假设舵机轴到施力点的力臂为 (L_r)砝码悬挂点到舵机轴距离为 (L_f)则指尖等效负载力为[ F_{fingertip} \frac{m \times g \times L_f}{L_r} ]这个值通常只是一个参考值不需要特别精确。6.3 数据记录与拟合把采集到的多组数据放入表格序号砝码质量(g)负载值理论力(N)10200250450.493100720.984150981.47然后用最小二乘法拟合[ F a \times Load b ]Python 中可以用numpy.polyfit实现import numpy as np # 数据示例 load_values [20, 45, 72, 98] force_values [0, 0.49, 0.98, 1.47] k, b np.polyfit(load_values, force_values, 1) print(f拟合公式: F {k:.4f} * Load {b:.4f})有了这个公式后面的负载阈值就能换算成实际夹持力。7. 常见问题与排查实操过程中最容易遇到下面这些问题问题现象常见原因解决思路舵机完全不转动供电不足、接线错、舵机 ID 错误检查电源电流余量确认总线接线单独只接一个舵机测试串口读到乱码波特率不匹配确认舵机实际波特率尝试 9600 / 115200 / 1M舵机转动时主控重启电源功率不够瞬间电流拉低电压舵机与控制板分开供电共地负载值一直为 0读错了寄存器地址查阅舵机说明书确认电流/负载寄存器地址负载值波动很大没加滤波、供电不稳、舵机振动增加滑动滤波检查电源稳定性采样后延时夹爪夹不紧物体掉落负载阈值设得太低提高阈值或者增加夹持后保持阶段的微调夹爪夹碎物体负载阈值太高或步进太大降低阈值减小每次角度步进增加位置保持时间舵机发热严重长时间堵转设置堵转保护阈值不要让舵机长期处于极限负载达妙夹爪不响应通信类型/协议不匹配先跑官方上位机 Demo确认通信正常后再接入主控排查顺序建议先单独用官方工具控制飞特舵机。再单独用官方工具控制达妙夹爪。两端都正常后再用自己的协议解析代码。最后再把力反馈控制逻辑加进去。这样可以有效缩小问题范围。8. 工程建议与安全边界8.1 机械结构方面夹爪手指与舵机之间的连接件建议留出限位结构防止舵机堵转过位。如果夹持力要求较大不要直接使用舵机输出轴承受径向载荷最好加轴承支撑。3D 打印件要注意受力方向层纹方向容易断裂。8.2 控制逻辑方面不要把电流阈值设成固定值因为供电电压变化会影响同样的负载值。负载值读取要加滤波但滤波不能太强否则夹爪撞到硬物时来不及响应。启动阶段先执行一次“找零位”或“开环归位”避免每次上电角度不一致。8.3 安全边界特别提醒舵机驱动夹爪的力矩足以夹伤手指测试时手指严禁伸入夹爪开口区域。夹取带电物体时要确保绝缘。不要让舵机长时间堵转否则轻则发热、重则烧毁驱动。如果夹爪是生产设备的一部分负载阈值必须经过反复测试并保留安全余量。8.4 日志与数据记录建议在 Demo 中加入数据记录功能方便后期分析with open(force_demo_log.csv, w, encodingutf-8) as f: f.write(time_ms,angle,load_raw,load_filtered\n) start time.time() while running: now int((time.time() - start) * 1000) f.write(f{now},{current_angle},{load_raw},{load_filtered}\n) time.sleep(0.01)记录的数据不仅可以用来调 PID还能做成曲线图直观展示力反馈效果。8.5 从 Demo 走向真实项目如果后续要做一个稳定的力反馈夹爪建议使用真正的力矩传感器或薄膜压力传感器。使用电流环响应更快的伺服驱动而不是普通舵机。增加控制器到执行器的加速度前馈。在软件上加入防抖、力超调保护、通信看门狗。9. 总结本文围绕“飞特舵机 达妙夹爪 力反馈”组合展开完整的流程是明确力反馈设计目标。理解飞特舵机的电流/负载读取原理。设计主控控制链路与通信架构。通过串口调试舵机和夹爪。用负载阈值或增量式 PID 实现力控。做负载-力标定。排查常见问题补充安全防护。本次 Demo 最核心的一句话是在没有力传感器的情况下舵机电流就是最便宜的力传感器。你只需要把电流值读准、滤波、判断阈值就能轻松实现夹持力保护。如果你打算继续深入推荐按下面路线学习直流电机模型与电流环控制原理。串行总线舵机通信协议。达妙关节模组的 CAN FD 通信与官方 SDK。阻抗控制与导纳控制。力/位混合控制在夹爪中的应用。如果本文对你有帮助可以收藏备用。后续我会补充更多关于夹爪力控标定和 PID 参数整定的实战内容欢迎在评论区交流你的调试经验。