Grippers and wrist cameras usually hang off the robot controller's USB hub, while the vision code that needs them runs on a separate PC. The controller's Linux sees the gripper's USB-serial converter; your vision PC does not. This guide closes that gap with serial port forwarding: you identify the controller-side serial device from the controller's kernel log, forward it through the robot vendor's ROS driver as a virtual port, and open it on the PC like any local serial device. It also settles the camera question with numbers instead of folklore: a camera reached through the controller returns frames but no parameter control, so it moves to the PC's own USB bus.
The decision: forward the serial port, keep the camera local
A gripper is a register device. It needs a serial line, a few bytes each way and tens of milliseconds of patience. A camera is a stream device: it needs hundreds of megabits and, for inspection, live control of exposure, focus and white balance. Those two needs pull the wiring in opposite directions, so split them.
Forward the gripper's serial port from the controller to the vision PC through the robot vendor's ROS driver, and leave the camera on the PC's own USB bus with its own high-flex cable. A camera left on the controller's hub can return frames, but the bridge does not carry its control interface, so exposure, focus and white balance stay out of reach — and an exposure drift you cannot correct is a rejected batch waiting to happen. If the robot program needs to know when a frame was grabbed, have the PC answer over a socket: the pattern is in trigger a USB camera capture from a robot controller over a socket.
Control bytes tunnelled, images local: that is the same division of labour behind planning who drives what in a vision system and robot gripper architecture.
What you need
- The robot controller with the USB hub at the wrist, running its own Linux — the gripper's USB-serial converter enumerates there.
- The robot vendor's ROS driver with tool-communication support, on a distribution it supports. ROS Melodic is covered, as are the newer generations the current driver supports.
- The gripper maker's ROS package for the PC side, which opens a plain serial port.
- A vision PC with one free network port for the robot control link plus one per camera and PLC. The vision controllers in the catalog run from 2 to 5+ LAN ports for exactly this split.
- A drag-chain-rated USB 3 cable for the wrist camera run to the PC, and Ethernet for the robot link. The camera and I/O cables range covers both.
Find the gripper's serial device on the controller
- Open a shell on the controller itself over ssh. The hub at the wrist is part of the controller's USB tree, not your PC's.
- List the serial devices the kernel has seen: run
dmesg | grep tty. Two families of lines matter:
[ 3.573559] 00:02: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a 16550A
[ 86.551742] cdc_acm 1-2.3.1:1.2: ttyACM0: USB ACM device
[ 86.552132] cdc_acm 1-2.3.1:1.5: ttyACM1: USB ACM device
- Read the families apart. The ttyS0 line appears seconds after boot and names a 16550A chip at I/O 0x3f8: that is the controller's own console UART, not a peripheral. The same trap exists across industrial Linux boxes, which is why the walkthrough on disabling a controller's own serial ports starts by separating console UARTs from add-on devices. The cdc_acm lines are your hardware: the kernel's cdc_acm driver claimed a USB communications device at USB path 1-2.3.1 and named its two interfaces ttyACM0 and ttyACM1. Those two names are the candidates for the gripper's port.
- Match a name to the gripper. Run
dmesg | grep ttywith the hub unplugged and the cdc_acm lines disappear. Replug the hub alone and both return; replug the gripper alone and one returns. Note the device name and the USB path (1-2.3.1 above): the driver configuration needs the name, and stable naming needs the path.
Free the port and forward it
- Deactivate the controller-side software that also opens that serial device — the gripper maker's on-controller service. Behind the USB converter the tool link is a shared RS-485 bus, and two masters interleave each other's bytes into checksum errors and unanswered frames.
- Configure the driver's tool communication on the PC. The driver documentation page named setup_tool_communication.md lists the parameters; three of them decide the result: the controller-side device (the ttyACM name you noted), the serial parameters (match the gripper — electric grippers of this class commonly run 115200 baud, 8 data bits, no parity, one stop bit), and the name of the local virtual port the driver creates on your PC. With the robot driver connected, it opens the controller-side device over the control Ethernet link and re-exposes it on the PC.
- Point the gripper maker's ROS package at the PC-side virtual port with the same serial parameters. The package cannot tell that the physical converter sits on the controller; it sees a serial device like any other.
Verify the link end to end
- Query before you grip. Send the gripper's identification or status read at the configured parameters and check for a clean reply. A garbage or silent reply is almost always parameters, wiring or a second reader on the line — the same chain as in frame grabber serial port communication fails: fix the chain.
- Run an open-close cycle at low speed and low force with the area clear, then run 100 cycles. A tunnel that drops bytes shows up inside the first few dozen cycles as checksum or timeout errors, never as a gradual drift.
- Log the round-trip time of the status query for a minute and keep the measured value. It is the input your timing budget consumes below.
Keep the wrist camera on the PC's own USB bus
A camera on the controller's hub can usually be made to deliver frames, and for a fixed-configuration camera with locked exposure and fixed focus in unchanging light that can be enough. For an inspection camera it is not: the bridge does not carry the camera's control interface, so exposure, white balance and focus cannot be set from your code. Exposure is the parameter you retune per part, which is exactly what setting camera exposure time through a GenICam API is for. Move the camera to the PC's USB bus, and three details decide the run:
- Use a true USB 3 port and check the negotiated speed. Cameras fall back to USB 2.0 on marginal ports, hubs and cables more often than anyone expects; the fix is mechanical, as in camera enumerates as USB 2.0 on a USB 3.0 port.
- Give the camera room on the bus. Sharing one USB controller with other streaming devices produces timeouts and corrupted frames — the depth camera that times out when other USB devices share one controller is that failure. For several cameras on one PC, budget bandwidth per host controller as in acquiring from multiple USB cameras.
- Mind the cable limit and the moving loop. USB 3 passive cables are specified to 3 m, so a wrist run through a dress pack wants a drag-chain-rated 3 m cable. For longer runs, use an active optical USB cable or make the wrist camera a GigE model, whose cabling runs to 100 m. If the camera reports a red power fault after re-pinning the loop, the wrist camera and gripper wiring fix for red LED power faults covers the power side.
The timing budget, with the arithmetic
For 8N1 framing, every byte costs 10 bits on the wire: 1 start, 8 data, 1 stop.
Worked example at 115200 baud, the common setting for this class of gripper. A 12-byte command out and a 48-byte status frame back give a line time of (12 + 48) × 10 / 115200 = 600 / 115200 = 5.2 ms. Add roughly 2 ms of gripper turnaround (an estimate for this class — your step 10 log replaces it) and about 2 ms for the forwarding round trip across the control link (single-digit milliseconds on a switched 100 Mbit/s LAN). Total: about 9.4 ms per gripper query. Against a 50 ms pick-and-place decision loop (20 Hz), that is 19% of the budget, which is workable. Against an 8 ms servo-synchronous loop (125 Hz), it does not fit: keep force control on the controller and let vision answer at its own rate.
Check the line's capacity the same way: 115200 / 10 = 11520 bytes/s. A 640×480 8-bit frame at 30 fps is 640 × 480 × 30 = 9.2 MB/s of pixels, and 9216000 × 8 / 115200 = 640 times the serial line's bit rate. Images never ride the forwarded port; it is a control channel sized in kilobytes per second, not megabytes.
Common mistakes
- Two masters on the tool bus. Leaving the on-controller gripper service running alongside the tunnel puts two talkers on one RS-485 line; the symptoms are checksum errors and frames that answer only sometimes.
- Chasing ttyS0. The 16550A at I/O 0x3f8 that appears at boot is the controller's console. No peripheral lives there.
- Entering the four serial parameters at only one end. The driver configuration and the gripper package must carry identical settings.
- Trusting the ttyACM0 name across reboots. Pin it by USB path or serial number with a udev rule.
- Sharing the robot control port with image traffic. Keep the driver's link on its own network interface; jitter on that link surfaces as timeout variance in the tunnel.
- Forwarding images through the tunnel. The capacity math above ends that idea in one line.
When forwarding is the wrong tool
- Servo-tight force control. If the gripper must react within the controller's own control cycle, command it from the robot program and keep vision advisory. A 9.4 ms tunnelled query cannot.
- The host is a PLC runtime rather than a Linux PC. The forwarding trick is Linux-side; a PLC instead maps the device locally, as in map a USB serial port to a COM port inside your PLC runtime.
- The controller itself runs your logic. Reading the serial device locally on the controller's Linux can beat forwarding, the same pattern as USB barcode scanner on a Linux controller: serial port in Node-RED.
- Many serial devices across a line. Serial-to-Ethernet gateways forward frames on the same principle; Linux Modbus ASCII/RTU logging with serial port forwarding shows the pattern end to end.
- The robot vendor documents a direct serial path to vision. When one exists, it beats a tunnel; robot serial port integration with vision systems is one documented example.
Parts for this set-up
The host side decides how clean this stays: one network port for the robot driver, one per camera and PLC, and USB 3 headroom. The MV-VC3301H-128G66 provides 5+ LAN ports, 3-4 USB 3 ports, 4 built-in light channels, 8 GB of memory and an Intel Core i3.
- LAN ports
- 5+ LAN ports
- USB 3 ports
- 3-4 USB 3 ports
- Light outputs
- 4 built-in channels
- Memory
- 8 GB
Cells that also drive PoE cameras or heavier models want more headroom: the MV-VC5525-256G70-NN pairs PoE camera ports and 8 built-in light channels with 32 GB of memory and 5+ LAN ports.
- LAN ports
- 5+ LAN ports
- USB 3 ports
- 3-4 USB 3 ports
- PoE
- PoE camera ports
- Light outputs
- 8 built-in channels
Both cable runs out of this article are high-flex, drag-chain rated and 3 m:
The USB 3 run serves the wrist camera on the PC's bus; the GigE run suits a GigE wrist camera or a longer link to a switch.
Before you order
- Count network ports: robot link plus every camera plus PLC. A controller with 5+ LAN ports keeps the robot link on its own interface.
- Note the gripper's serial parameters from its manual before you configure the tunnel, not after the first failed query.
- Reserve one USB 3 port per camera, and confirm the negotiated speed once the camera is mounted on the wrist.
- Rate every cable in the moving loop for drag-chain duty, and stay within 3 m for passive USB 3.
- Agree the ownership change before it happens: on-controller service off, PC node up, operator informed.
Once the port answers on the PC, the rest of the cell is ordinary vision engineering. Pick the host from the vision controllers above, or send the camera and gripper layout through the contact page and we will size the ports and the timing budget with you. The systems how-to collection gathers the neighbouring fixes: USB fallbacks, bandwidth splits and socket triggers.
Questions
Why does ttyACM0 turn into ttyACM1 after I re-plug the hub?
Enumeration order decides the number: the kernel names converters ttyACM0, ttyACM1 in the order their drivers bind, and a different socket, hub port or boot timing changes that order. Pin the name instead of chasing it — a udev rule keyed to the USB path dmesg prints (1-2.3.1 in the example) or to the converter's serial number gives a fixed name such as /dev/gripper across reboots.
Can I forward the gripper port and a second serial tool at the same time?
Yes, one tunnel per device. Each USB serial function enumerates as its own ttyACM device and the driver forwards each separately, so a hub with a gripper and a second tool shows ttyACM0 and ttyACM1. Keep one master per RS-485 bus and budget the line time: two 60-byte transactions at 115200 baud serialize to about 10.4 ms, not 5.2 ms, because the bytes share one line at the controller end.
What serial settings go into the forwarding configuration?
Whatever the gripper documents, set identically at both ends: the controller-side device and line parameters in the driver configuration, and the same parameters in your ROS node. Electric grippers of this class commonly run 115200 baud, 8 data bits, no parity, one stop bit. A mismatch does not raise an error — you get framing garbage or silence — so on a failed first query, check the four parameters before the wiring.
Is any camera usable if it stays on the controller's USB hub?
For frames only. The bridge passes the video stream but not the camera's control interface, so exposure, white balance and focus stay wherever the controller last set them. That is workable for a camera with locked, fixed parameters in unchanging light — a presence check, not a measurement. Anything you expose or focus per part, or any auto-exposure you need to pin, belongs on the vision PC's USB bus where the controls are reachable.
Does this work on ROS 2 as well?
The forwarding lives in the robot vendor's driver, so it works on any ROS generation that driver supports — check the driver's tool-communication documentation rather than the gripper package. Gripper control packages are the thinner end: first-party ROS 2 support has lagged, and where it is missing, community drivers fill the gap. Pick a package that opens a plain serial port, because the forwarded endpoint presents exactly that.



