2026-07-16 15:24:40 +08:00
2026-07-16 15:24:40 +08:00
2026-07-16 15:24:40 +08:00
2024-12-09 21:04:49 +08:00
2026-07-16 15:24:40 +08:00
2026-07-16 15:24:40 +08:00
2026-07-16 15:24:40 +08:00
2026-07-16 15:24:40 +08:00
2026-07-16 15:24:40 +08:00
2026-07-16 15:24:40 +08:00
2026-07-16 15:24:40 +08:00
2026-07-16 15:24:40 +08:00
2026-07-16 15:24:40 +08:00
2026-07-16 15:24:40 +08:00
2026-07-16 15:24:40 +08:00
2026-07-16 15:24:40 +08:00
2026-07-16 15:24:40 +08:00
2026-07-16 15:24:40 +08:00
2024-12-11 11:11:50 +08:00
2026-07-16 15:24:40 +08:00
2026-07-16 15:24:40 +08:00
2026-07-16 15:24:40 +08:00
2026-07-16 15:24:40 +08:00
2026-07-16 15:24:40 +08:00

触觉传感器与执行器控制系统 —— 使用手册

项目概述

本项目提供了一套完整的触觉传感器数据采集与执行器(舵机、直线电机)控制系统,包含底层 I2C 通信驱动、传感器数据解析、多指数据采集、串口执行器控制、手柄/键盘遥控以及数据记录等功能模块。

系统架构

┌──────────────────────────────────────────────────────┐
│                   应用层 (Application)                 │
│  demo_auto_grasp.py  test_dof_control.py             │
│  gamepad_remote.py   gamepad_remote_new_pcb.py        │
│  keyboard_remote_new_pcb.py  data_logger.py            │
│  grasp_network_model.py                                │
├──────────────────────────────────────────────────────┤
│                 数据采集层 (DAQ Layer)                  │
│  cap_read.py  tactile_sensor_daq.py                   │
├──────────────────────────────────────────────────────┤
│                 驱动抽象层 (Driver Layer)               │
│  class_finger.py  class_sensorcmd.py  sensorPara.py   │
│  class_ch341.py   serial_robot_driver.py               │
├──────────────────────────────────────────────────────┤
│                 硬件层 (Hardware)                       │
│  CH341 (USB-I2C)    STM32F103 (Serial)                │
│  触觉传感器          舵机 / 直线电机                    │
└──────────────────────────────────────────────────────┘

目录

  1. 环境准备
  2. 模块说明
  3. 快速开始
  4. 底层驱动详解
  5. 数据采集模块
  6. 执行器控制
  7. 遥控模块
  8. 数据记录
  9. 神经网络模型
  10. STM32 固件
  11. 硬件接线
  12. 常见问题

1. 环境准备

重要:请严格按照以下顺序操作,先安装驱动,再安装 Python 依赖。

1.1 CH341 驱动安装(必须首先完成)

CH341 是 USB 转 I2C 芯片,用于与触觉传感器通信。使用本项目前,必须先安装此驱动,否则传感器无法被电脑识别。

Windows

  1. 在项目根目录下找到压缩包 CH341驱动先卸载再安装.zip,将其解压。
  2. 如果之前安装过其它版本的 CH341 驱动,请先卸载
  3. 运行解压后的 CH341PAR.exe,按照提示完成安装。
  4. 安装完成后,将传感器通过 CH341 转接板连接电脑 USB系统会自动识别设备。

驱动安装后,项目代码会自动加载 lib/ch341/CH341DLLA64.DLL,无需额外配置。

Linux

  1. lib/ch341/libch347.so 放置到系统库路径或项目目录下。

  2. 配置 udev 规则(将 john 替换为你的用户名):

# 将用户添加到 dialout 组
sudo usermod -a -G dialout john

# 创建 udev 规则文件
sudo bash -c 'echo "SUBSYSTEM==\"usbmisc\", ATTRS{idVendor}==\"1a86\", ATTRS{idProduct}==\"5512\", MODE=\"0666\", GROUP=\"dialout\"" > /etc/udev/rules.d/ch341.rules'

# 重载规则
sudo udevadm control --reload-rules
sudo udevadm trigger
  1. 重新插拔 CH341 设备,或重启计算机使 udev 规则生效。

1.2 Python 依赖

推荐使用 Python 3.8 及以上版本。安装依赖:

pip install pyserial numpy pygame keyboard torch

各模块依赖说明:

模块 依赖
底层驱动 (class_ch341, class_sensorcmd, class_finger) 无额外依赖
数据采集 (cap_read, tactile_sensor_daq) numpy
串口执行器 (serial_robot_driver) pyserial
手柄遥控 (gamepad_remote, gamepad_remote_new_pcb) pyserial, pygame
键盘遥控 (keyboard_remote_new_pcb) pyserial, keyboard, numpy
数据记录 (data_logger) numpy
神经网络 (grasp_network_model) torch (PyTorch)

说明: 如果仅使用传感器数据读取功能cap_read、tactile_sensor_daq只需安装 numpy。执行器控制、遥控、神经网络等模块可按需安装对应依赖。


2. 模块说明

2.1 文件清单

文件名 功能说明
class_ch341.py CH341 USB-I2C 底层驱动,封装 I2C 读写、速度设置、INT 引脚控制
class_sensorcmd.py 传感器 I2C 命令协议,封装所有传感器配置与读取命令
class_finger.py 传感器(手指)数据解析,包含电容/力数据读取与协议解析
sensorPara.py 传感器参数定义(通道数、力单元数、数据格式等)
cap_read.py 基础电容读取入口,支持单指/多指数据采集与实时可视化
tactile_sensor_daq.py 多指触觉传感器数据采集模块(线程安全,支持去皮)
serial_robot_driver.py 串口执行器驱动,控制舵机和直线电机
stm32f103_drv8870_servo_main.c STM32F103 下位机固件源码
demo_auto_grasp.py 演示程序:触觉反馈自动抓取任务
gamepad_remote.py 游戏手柄遥控程序
gamepad_remote_new_pcb.py 新 PCB 版手柄遥控(支持 ACK 协议和自检)
keyboard_remote_new_pcb.py 新 PCB 版键盘遥控(支持力反馈与压力计算)
test_dof_control.py 自由度独立控制测试
data_logger.py CSV 数据记录器
grasp_network_model.py 条件抓取网络模型Conditional MLP
接线说明.txt 硬件接线参考
新PCB控制实施方案.md 新 PCB 控制系统实施方案
CH341驱动先卸载再安装.zip CH341 驱动程序压缩包,使用前必须先解压安装
传感器iic地址和转接板位置定义.png I2C 地址与接口位置对照图

3. 快速开始

3.1 仅读取单个传感器数据

python cap_read.py

运行前可在 cap_read.py 中修改传感器连接数量:

DEF_MAX_FINGER_NUM = 1  # 需要连接的手指数量最大5个

输出数据包括:

  • capChannelDat:电容通道原始值
  • nf[i]:第 i 个单元的法向力
  • tf[i]:第 i 个单元的切向力
  • tfDir[i]:第 i 个单元的切向力方向
  • sProxCapData:自电容接近值
  • mProxCapData:互电容接近值

3.2 读取多个传感器数据100Hz

from tactile_sensor_daq import TactileSensorDAQ

sensor = TactileSensorDAQ()
sensor.start()

# 等待传感器连接稳定
import time
time.sleep(3)
sensor.tare()  # 去皮

while True:
    data = sensor.get_data()  # 获取 12 维力数据
    print(data)
    time.sleep(0.1)

3.3 控制执行器(串口)

from serial_robot_driver import RobotDriver

robot = RobotDriver(port='COM9')
robot.motor_open()      # 直线电机张开
robot.motor_close()     # 直线电机闭合
robot.motor_stop()      # 停止
robot.set_servo(1, 90)  # 舵机1转到90度
robot.set_config(0)     # 构型0初始位
robot.close()

3.4 命令行快速测试

# 测试通信
python gamepad_remote_new_pcb.py --port COM9 --cmd PING

# 硬件自检
python gamepad_remote_new_pcb.py --port COM9 --test

# 手柄遥控
python gamepad_remote_new_pcb.py --port COM9

# 键盘遥控
python keyboard_remote_new_pcb.py --port COM9

4. 底层驱动详解

4.1 class_ch341.py —— CH341 I2C 通信驱动

封装 CH341 USB-I2C 转换芯片的操作。

主要接口:

from class_ch341 import ClassCh341

ch341 = ClassCh341()

# 初始化并打开设备
ch341.init()                          # 加载 DLL/SO 库
ch341.open()                          # 打开 USB 设备

# 设置 I2C 速度
ch341.set_speed(ch341.IIC_SPEED_400)  # 20/100/400/750 kHz

# I2C 读写
ch341.write(addr, data_list)          # 向从机地址写入数据列表
ch341.read(addr, data_list)           # 从从机地址读取数据到列表

# 连接检查
ch341.connectCheck()                  # 返回 True/False

# 断开
ch341.disconnect()

4.2 class_sensorcmd.py —— 传感器命令协议

封装与触觉传感器 MCU 的 I2C 命令协议。

主要接口:

from class_sensorcmd import ClassSensorCmd

snsCmd = ClassSensorCmd(ch341)

# 地址管理
snsCmd.getAddr(addr)             # 读取传感器 I2C 地址
snsCmd.setAddr(old_addr, new)    # 设置新地址

# 传感器配置
snsCmd.setSensorSendType(addr, 0)      # 设置数据发送类型为原始值
snsCmd.setSensorCapOffset(addr, offset) # 设置电容采集时序偏移

# 读取数据
snsCmd.getSensorCapData(addr, buf)     # 读取电容数据
snsCmd.getSensorProjectIdex(addr)      # 读取项目编号

# 同步
snsCmd.setSensorSync(addr)             # 多传感器同步

4.3 sensorPara.py —— 传感器参数定义

定义了传感器项目的参数结构和具体参数值。

from sensorPara import finger_params, FingerParamTS, DynamicYddsU16Ts

# finger_params 包含所有支持的传感器类型
# 目前支持:
#   - 项目2: "通用手指", 8通道, 1个三维力单元
#   - 项目17: "两指-大包", 16通道, 2个三维力单元

如需添加新的传感器型号,在 sensorPara.py 中追加 FingerParamTS 条目即可。

4.4 class_finger.py —— 传感器数据解析

管理单个传感器(手指)的连接状态和数据读取。

from class_finger import ClassFinger, capData

finger = ClassFinger(pca_idx=2, ch341=ch341)

# 检查传感器连接
if finger.checkSensor():
    print("Sensor connected")

# 读取数据
finger.capRead()

# 访问数据
finger.readData.channelCapData  # 电容通道原始值
finger.readData.nf[i]           # 第i个单元的法向力
finger.readData.tf[i]           # 第i个单元的切向力
finger.readData.tfDir[i]        # 第i个单元的切向力方向
finger.readData.sProxCapData    # 自电容接近值
finger.readData.mProxCapData    # 互电容接近值

5. 数据采集模块

5.1 cap_read.py —— 基础电容读取

最简单直接的传感器数据读取入口。内部维护 CH341 连接状态机,定时轮询读取电容数据,并通过 TCP Socket 发送到 VOFA+ 等调试工具进行实时可视化。

配置参数:

DEF_MAX_FINGER_NUM = 1   # 连接手指数量 (1-5)
DEF_GET_CAP_MS = 30      # 读取间隔 (ms)
DEF_CDC_SYNC_MS = 1000   # 电容同步间隔 (ms),多传感器时使用

运行:

python cap_read.py

数据通过 Socket 发送到 127.0.0.1:1347VOFA+ 默认端口)。

5.2 tactile_sensor_daq.py —— 多指触觉传感器 DAQ

线程安全的传感器数据采集模块,支持 3 个手指、12 维力数据输出含去皮tare功能。

from tactile_sensor_daq import TactileSensorDAQ

sensor = TactileSensorDAQ()
sensor.start()        # 启动后台采集线程
sensor.tare()         # 去皮:将当前读数归零
data = sensor.get_data()  # 获取 12 维 numpy 数组 [F0_U1_Fn, F0_U1_Ft, F0_U2_Fn, ...]
sensor.stop()         # 停止采集

数据格式12 维 float32

索引 含义
0-1 手指0-单元1: 法向力(Fn), 切向力(Ft)
2-3 手指0-单元2: 法向力(Fn), 切向力(Ft)
4-5 手指1-单元1: 法向力(Fn), 切向力(Ft)
6-7 手指1-单元2: 法向力(Fn), 切向力(Ft)
8-9 手指2-单元1: 法向力(Fn), 切向力(Ft)
10-11 手指2-单元2: 法向力(Fn), 切向力(Ft)

配置参数:

DEF_MAX_FINGER_NUM = 3     # 传感器数量
SAMPLE_RATE_MS = 10        # 采样间隔 (ms),默认 100Hz

6. 执行器控制

6.1 serial_robot_driver.py —— 串口执行器驱动

通过串口USB-TTL向 STM32 下位机发送 ASCII 命令,控制直线电机和舵机。

from serial_robot_driver import RobotDriver

robot = RobotDriver(port='COM9', baud=115200)

# 直线电机控制
robot.motor_open()    # 张开
robot.motor_close()   # 闭合
robot.motor_stop()    # 停止

# 舵机控制
robot.set_servo(1, 90)   # 舵机1转到90度
robot.set_servo(2, 120)  # 舵机2转到120度

# 构型切换(组合动作)
robot.set_config(0)   # 初始构型: S1=90, S2=90
robot.set_config(1)   # 错位构型: S1=30, S2=150
robot.set_config(2)   # 对握构型: S1=120, S2=60

robot.close()

6.2 串口通信协议

上位机向 STM32 发送 ASCII 命令(以 \r\n 结尾STM32 回复 OK:ERR: 确认。

命令 功能 回复
PING 通信测试 OK:PONG
M:OPEN 直线电机张开 OK:M:OPEN
M:CLOSE 直线电机闭合 OK:M:CLOSE
M:STOP 直线电机停止 OK:M:STOP
S1:<angle> 舵机1角度(0-180) OK:S1
S2:<angle> 舵机2角度(0-180) OK:S2
CFG:<mode> 构型切换(0/1/2) OK:CFG

6.3 gamepad_remote_new_pcb.py —— 新 PCB 版执行器驱动

相比 serial_robot_driver.py,增加了 ACK 确认、命令行参数、自检等功能。

# 单条命令
python gamepad_remote_new_pcb.py --port COM9 --cmd PING
python gamepad_remote_new_pcb.py --port COM9 --cmd S1:90

# 硬件自检
python gamepad_remote_new_pcb.py --port COM9 --test

# 不等待 ACK (适用于简单固件)
python gamepad_remote_new_pcb.py --port COM9 --no-ack

7. 遥控模块

7.1 gamepad_remote.py —— 手柄遥控

使用 Xbox/兼容游戏手柄远程控制执行器。

按键映射:

按键 功能
A 构型0初始
B 构型1错位
X 构型2对握
LB 长按 直线电机张开
RB 长按 直线电机闭合
松开 LB/RB 电机停止
BACK 急停切换
START 退出

运行:

python gamepad_remote.py

默认连接 COM9可在代码中修改 port 变量。

7.2 keyboard_remote_new_pcb.py —— 键盘遥控

使用键盘远程控制执行器,同时读取触觉传感器数据,支持力反馈自动抓取。

按键映射:

按键 功能
q 构型0初始
w 构型1错位
e 构型2对握
← 长按 直线电机闭合
→ 长按 直线电机张开
空格 急停/恢复
Esc 退出

主要功能:

  • 按下闭合键持续闭合,松开自动停止并打印执行时间
  • 实时显示接触压力KPa
  • 支持急停保护和构型切换

运行:

python keyboard_remote_new_pcb.py --port COM9
python keyboard_remote_new_pcb.py --port COM9 --test          # 自检模式
python keyboard_remote_new_pcb.py --port COM9 --contact-area-mm2 240  # 自定义接触面积

8. 数据记录

data_logger.py —— CSV 数据记录器

将触觉传感器数据记录为 CSV 文件,自动创建 data/ 目录并以时间戳命名。

from data_logger import DataLogger

logger = DataLogger(filename_prefix="experiment_01")

# 记录一行数据
# sensor_data: 12维触觉数据
# config_id: 构型ID (0/1/2)
# label_vector: 标签 [x, y, theta]
logger.log(sensor_data=sensor.get_data(), config_id=1, label_vector=[0.0, 5.5, -2.0])

CSV 格式:

Timestamp Config_ID F0_U1_Fn F0_U1_Ft ... Label_X Label_Y Label_Theta

9. 神经网络模型

grasp_network_model.py —— 条件抓取网络 (CondGraspNet)

一个条件 MLP 网络,输入 12 维触觉数据 + 3 维构型编码,输出 3 维偏差预测 [ΔX, ΔY, Δθ]。

网络结构:

Input(15) → FC(64)+BN+ReLU → FC(128)+BN+ReLU → FC(64)+ReLU → Output(3)

使用示例:

from grasp_network_model import CondGraspNet
import torch

model = CondGraspNet()
tactile_data = torch.randn(8, 12)    # Batch=8, 12维触觉
config_ids = torch.tensor([0,0,1,1,2,2,0,2])  # 构型ID
predictions = model(tactile_data, config_ids)  # [8, 3] 输出

单元测试:

python grasp_network_model.py

10. STM32 固件

stm32f103_drv8870_servo_main.c

STM32F103C8T6 下位机固件,负责接收上位机串口命令并控制硬件。

硬件映射:

功能 STM32引脚 说明
USART1 TX PA9 连接 USB-TTL RXD
USART1 RX PA10 连接 USB-TTL TXD
直线电机 IN1 PB12 连接 DRV8870 IN1
直线电机 IN2 PB13 连接 DRV8870 IN2
舵机1 PWM PB11 TIM2_CH4, 50Hz
舵机2 PWM PB10 TIM2_CH3, 50Hz

CubeMX 配置要点:

  • TIM2: Prescaler=71, Counter Period=19999, 产生 50Hz PWM
  • USART1: 115200 8N1
  • 需开启 TIM2 重映射AFIO Remap

集成方法:

stm32f103_drv8870_servo_main.c 中的用户代码集成到 CubeMX 生成的工程:

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_USART1_UART_Init();
    MX_TIM2_Init();

    app_init();     // 初始化舵机和电机

    while (1) {
        app_loop(); // 主循环:处理串口命令 + 看门狗
    }
}

安全特性:

  • 1 秒无指令自动停止直线电机(通信丢失保护)
  • 命令超长自动拒绝

调试顺序

  1. 仅给 PCB/STM32 上电(不接电机和舵机)
  2. python gamepad_remote_new_pcb.py --port COM9 --cmd PING → 应返回 OK:PONG
  3. 用示波器测舵机 PWM 信号:
    • S1:0 → PB11 约 0.5ms 高电平
    • S1:90 → PB11 约 1.5ms 高电平
    • S1:180 → PB11 约 2.5ms 高电平
  4. 测直线电机控制引脚:
    • M:OPEN → PB12=高, PB13=低
    • M:CLOSE → PB12=低, PB13=高
    • M:STOP → PB12=低, PB13=低
  5. 信号确认正确后,接舵机独立 5V 电源
  6. 最后接直线电机电源和负载

11. 硬件接线

11.1 传感器接线CH341 USB-I2C

传感器通过 I2C 转接板连接,转接板通过 CH341 芯片与 PC 的 USB 连接。

I2C 地址与转接板接口位置为固定对应关系,详见 传感器iic地址和转接板位置定义.png

11.2 执行器接线USB-TTL + STM32

USB-TTL         STM32F103C8T6
  3.3V    →     3.3V
  GND     →     GND
  TXD     →     PA10 (RXD)
  RXD     →     PA9  (TXD)

STM32           外设
  PB12    →     DRV8870 IN1
  PB13    →     DRV8870 IN2
  PB11    →     舵机1 信号线 (A0绿)
  PB10    →     舵机2 信号线 (A1橙)
  GND     →     舵机 GND
  GND     →     直线电机 GND

详见 接线说明.txt

11.3 供电注意事项

  • MG996R 舵机不可由 STM32 板载 5V 供电,需使用独立 5V 3A 以上电源
  • 舵机电源 GND、直线电机电源 GND、STM32 GND 必须共地
  • DRV8870 的 VM 电压须匹配直线电机额定电压
  • 直线电机首次测试建议只点动 0.5s,防止方向相反或机械顶死
  • 如果 M:OPEN 和 M:CLOSE 方向相反,可在固件中交换 PB12/PB13 输出逻辑,或交换电机两线

12. 常见问题

Q: 运行 cap_read.py 提示 "ch341加载失败"

A: 检查 lib/ch341/ 目录下是否有对应平台的库文件:

  • Windows: CH341DLLA64.DLL
  • Linux: libch347.so

并确保已安装 CH341 驱动程序。

Q: 传感器无法连接?

A:

  1. 确认传感器已上电 3 秒以上再运行程序
  2. 检查 I2C 地址是否与转接板接口匹配
  3. 运行后查看终端输出,程序会自动尝试匹配地址

Q: 手柄遥控无法识别手柄?

A:

  1. 确保手柄已通过蓝牙/USB 连接并被系统识别
  2. Windows 下可在"控制面板→设备和打印机"中验证
  3. 确保安装了 pygame 库

Q: 串口命令无响应?

A:

  1. 确认 COM 口号正确Windows 在设备管理器中查看)
  2. 确认波特率为 115200
  3. --cmd PING 测试基本通信
  4. 检查 USB-TTL 的 TXD/RXD 是否交叉连接

Q: 如何修改采样频率?

A: 修改对应文件中的配置参数:

  • cap_read.py: DEF_GET_CAP_MS
  • tactile_sensor_daq.py: SAMPLE_RATE_MS

Q: 如何支持更多传感器型号?

A: 在 sensorPara.pyfinger_params 列表中追加 FingerParamTS 参数定义。传感器会自动根据项目编号匹配对应参数。


项目文件结构

HandControl/
├── class_ch341.py              # CH341 I2C 底层驱动
├── class_sensorcmd.py           # 传感器 I2C 命令协议
├── class_finger.py              # 传感器数据解析
├── sensorPara.py                # 传感器参数定义
├── cap_read.py                  # 基础电容读取入口
├── tactile_sensor_daq.py        # 多指触觉传感器 DAQ
├── serial_robot_driver.py       # 串口执行器驱动
├── gamepad_remote.py            # 手柄遥控
├── gamepad_remote_new_pcb.py    # 新 PCB 手柄遥控
├── keyboard_remote_new_pcb.py   # 新 PCB 键盘遥控
├── demo_auto_grasp.py           # 演示:自动抓取任务
├── test_dof_control.py          # 自由度独立控制测试
├── data_logger.py               # CSV 数据记录器
├── grasp_network_model.py       # 抓取预测神经网络
├── stm32f103_drv8870_servo_main.c  # STM32 固件
├── lib/ch341/                   # CH341 驱动库
│   ├── CH341DLLA64.DLL
│   ├── CH341DLLA64.LIB
│   ├── ch341_lib.h
│   └── libch347.so
├── 接线说明.txt                  # 硬件接线参考
├── 新PCB控制实施方案.md           # 控制系统实施方案
├── 传感器iic地址和转接板位置定义.png  # I2C 地址图
└── README.md                    # 本文件
Description
No description provided
Readme 2 MiB
Languages
Python 84.3%
C 15.7%