Ir al contenido

Gripper

Gripper del manipulador: dos pinzas con cremallera, piñón central y motor

El gripper es la pinza en el extremo del manipulador. Abre y cierra sus dos dedos a la posición en milímetros que pide el operador, y se detiene solo si algo le impide seguir.

Dos pinzas impresas en 3D con mecanismo de piñón y cremallera, movidas por un motor con encoder y reductor. Lo controla un ESP32-C3 SuperMini con un driver de motor TB6612FNG. A diferencia de las otras dos placas del robot, este controlador no tiene PCB dedicada: va cableado a mano.

Componentes
ParámetroValorUnidadNotas
MicrocontroladorESP32-C3 SuperMini—
Driver de motorTB6612FNG—dual, solo canal A usado
MotorPololu—encoder de cuadratura, reductor 100:1
Recorrido total80mm
Resolución357,1counts/mm28 570 counts en los 80 mm de recorrido
Comunicación con NUCUSB-CDC115 200 baud (COM5)

El piñón central engrana con las cremalleras internas de ambas pinzas, que se desplazan en sentidos opuestos: abren o cierran de forma sincronizada.

El firmware convierte la posición pedida en cuentas del encoder y lleva el motor hasta ella con un perfil de velocidad suave. El encoder es la única retroalimentación de posición: si deja de cambiar durante 500 ms con el motor activo, el firmware asume un obstáculo y detiene el motor.

  1. NUCPython 3.12
  2. USB-CDC · COM5NUC → Controlador del gripper: m <mm>Controlador del gripper → NUC: GRIPPER_STATE
  3. Controlador del gripperESP32-C3 + TB6612FNG
  4. PWM 20 kHzGripper → Controlador del gripper: encoder A / B
  5. Grippermotor con encoder

La NUC publica el estado que recibe como gripper_state, en el puerto 5001 de ZeroMQ.

La geometría de las pinzas lleva refuerzos internos tipo costilla: rigidez sin peso.

Vista superior del gripper con el piñón central del mecanismo
El piñón central entre las dos pinzas, con las guías internas del mecanismo.
Vista inclinada del gripper montado en el último eslabón
Nervaduras de refuerzo de las pinzas y unión atornillada al último eslabón.

Sin PCB, el cableado es lo único que fija el montaje. Estos son los pines que usa el firmware.

Conexiones entre ESP32-C3, TB6612FNG y el encoder
SeñalGPIODestinoFunción
ENC_AGPIO3Encoder del motorCanal A de cuadratura, por interrupción
ENC_BGPIO4Encoder del motorCanal B de cuadratura, por interrupción
STBYGPIO5TB6612FNGStandby: en bajo, el driver queda inhibido
AIN1GPIO6TB6612FNGDirección del canal A
AIN2GPIO7TB6612FNGDirección del canal A
PWMAGPIO10TB6612FNGPWM del canal A, 20 kHz

MicroPython sobre el ESP32-C3.

El firmware decodifica el encoder por interrupciones, con una tabla de transición phase-correct que da resolución de ±1 count. La lectura del contador es atómica: se envuelve en disable_irq/enable_irq para que la interrupción no la modifique a media lectura.

1. mm_to_count(mm) — convierte mm a counts de encoder
2. Si |target − current| ≤ 35 counts: ya está en posición, freno + stop
3. Bucle de control cada 8 ms: perfil de velocidad con boost inicial
de 12 ms, 30 % de recorrido en aceleración, 55 % en desaceleración
4. Detección de stall: si el encoder no cambió en 500 ms, detiene con
freno activo y guarda la posición del evento

El perfil de velocidad usa la función smoothstep01(x) = x²(3 − 2x) para suavizar las transiciones. Sin ella, los escalones de aceleración provocan saltos mecánicos en el mecanismo de piñón y cremallera.

Parámetros de control, leídos del firmware
ParámetroValorUnidadNotas
Frecuencia PWM20kHzPor encima del rango audible
Periodo del lazo8ms
Tolerancia de posición35counts≈ 0,1 mm
Umbral de stall500ms sin cambio de encoder
Duty de crucero50%
Duty mínimo10%Por debajo, el motor no vence la fricción
Boost de arranque40 % durante 12msRompe la inercia inicial
Tramo de aceleración30% del recorrido
Tramo de desaceleración55% del recorrido

Ninguno bloquea: el firmware sigue atendiendo el puerto mientras el motor se mueve.

ComandoDescripción
m <mm>Ir a posición absoluta
o <mm> / c <mm>Abrir / cerrar delta mm desde la posición actual
to / tcIr a completamente abierto / cerrado
s / bStop suave / freno activo inmediato
sc / soGuardar posición actual como cerrado / abierto
save / loadGuardar / cargar calibración desde JSON

Publica una línea de estado cada 250 ms y tras cada comando:

GRIPPER_STATE mm=40.000 count=-14285 target_mm=40.000 target_count=-14285 busy=0 calibrated=1 open_count=-28570 closed_count=0
  1. Mover manualmente (o con pulsos po/pc) a la posición abierta máxima → so guarda OPEN_COUNT.
  2. Mover a la posición cerrada máxima → sc guarda CLOSED_COUNT.

Los valores se guardan en gripper_state.json con escritura atómica (archivo temporal + rename), para que un corte a media escritura no corrompa el archivo. Si no existe o está corrupto, el gripper arranca sin calibrar y bloquea los comandos de posición hasta recalibrar.

La calibración del gripper construido sirve de referencia de orden de magnitud, pero no se puede copiar: depende del montaje de cada mecanismo.

{ "closed_count": 0, "open_count": -28570 }

El signo negativo es la convención de sentido del encoder: abrir cuenta hacia abajo desde el cero de cerrado. De ahí sale la resolución de 357,1 counts/mm.

El script hace lo mismo que la NUC por COM5: pide el estado con p y manda posiciones con m <mm>, esperando a que cada movimiento termine.

  1. Conecta el USB-C del ESP32-C3 a la PC y busca su puerto COM.
  2. Instala la dependencia: pip install pyserial.
  3. Corre la prueba:
Ventana de terminal
python prueba_gripper.py --puerto COM5
python prueba_gripper.py --puerto COM5 --mover --posiciones 60 20 40
python prueba_gripper.py --puerto COM5 --consola

La primera línea muestra la posición, busy y calibrado. Si no está calibrado, los comandos de posición están bloqueados: calibra primero con so y sc desde --consola.