2,000 USD
Free shipping.
It will be shipped approximately 2-4 weeks after your payment.
Customs duties, import taxes, and fees are the responsibility of the buyer.
The CR Hand is a truly human-sized robotic hand with 6 degrees of freedom. The distance from the wrist mounting surface to the fingertips is only 172 mm. All motors and the control box are integrated into this compact design, making it ready to operate as soon as you connect a USB cable and power supply. By utilizing high-precision FDM 3D printing, we have achieved an affordable price. It is ideal for educational and research purposes.
<Main Features>
<Specifications>
Weight: 326g
Voltage: 6V
Max Motor Force: 18N(Per Finger)
Control Board: Pololu Micro Maestro 6-Channel USB Servo Controller
<Contents List>
CR Hand main unit
6V power adapter
USB 2.0 cable (mini-B type)
Mounting flange (ISO 9409-1-50-4-M6 for collaborative robots, compatible with UniversalRobot, Techman, etc.)
Screws: M3L8 x4, M6L10 x4
<Approximate dimensions / Wrist mounting dimensions>
<Fingertip mounting dimensions>
<Mounting Flange>
You can download the 3D data from this link.
For quotes, orders, or any other inquiries, please contact us at admin@curious-robotics.com
The following is technical information.
<How to use>
1. Download Driver and Software
Please download Pololu’s driver and Maestro Control Center to your PC.
2. Cable Connection
Connect the hand to your PC using the included USB cable. Also, connect the included 6V power adapter to the hand and plug it into a power outlet.
3. Launch the Software
Start the Maestro Control Center that you downloaded in step 1.
(i)From the dropdown list, select the connected board (displayed as a number such as #XXXXXXXX).
(ii)Check Enable for all Servos #0–5.
(iii)Drag the sliders left and right to confirm that all six motors operate correctly.
Maestro Control Center is a tool that allows you to operate and configure the robotic hand intuitively. Its main features are as follows:
Real-Time Control: Each motor can be controlled individually, and you can adjust motor positions simply by dragging sliders.
Cross-Platform Support: Compatible with both Windows and Linux.
Script Creation and Execution: Using the built-in script editor, you can create and edit simple scripts and run them directly. This enables automation and customization of movements.
Motion Recording and Playback: Motor movements can be recorded as sequences and replayed. This makes it easy to create and edit complex motion patterns.
With these features, you can intuitively and efficiently configure and control the CR Hand.
4. Operation from Programs
The built-in control board, Pololu Micro Maestro 6-Channel USB Servo Controller, supports serial communication. By using a programming language such as Python to communicate via serial, you can operate the CR Hand.
Below are sample programs in Python and Processing. In both cases, please change the port number in the program accordingly.
You can check the port number in Device Manager under "Pololu Micro Maestro 6-Servo Controller Port." In the example below, it is COM22.
Below is a sample program in Python. When executed, a window like the one shown below will open. You can operate the hand by clicking each button.
# cr_hand_button_controller.py
# Usage:
# python cr_hand_buttons.py
# python cr_hand_buttons.py --port COM1 --baud 9600
import sys
import argparse
import time
from typing import List, Dict
try:
import serial
from serial.tools import list_ports
except ImportError:
print("ERROR: This script requires pyserial. Install with: pip install pyserial")
sys.exit(1)
import tkinter as tk
from tkinter import ttk
# ---- Servo scenarios (Ch0..Ch5) ----
SCENARIOS: Dict[str, List[int]] = {
"Open": [4000, 4000, 4000, 4000, 4000, 4000],
"Pinch_open": [8000, 7000, 4000, 8000, 8000, 8000],
"Pinch_close": [8000, 7000, 6000, 8000, 8000, 8000],
"Grasp_open": [8000, 4000, 4000, 4000, 4000, 4000],
"Grasp_close": [8000, 6000, 8000, 8000, 8000, 8000],
"Key_Pinch_open": [4000, 4000, 8000, 8000, 8000, 8000],
"Key_Pinch_close": [4000, 8000, 8000, 8000, 8000, 8000],
}
NUM_CHANNELS = 6 # Ch0..Ch5
class MaestroController:
"""
Pololu Micro Maestro (Command Port) minimal controller.
Sends 'Set Target' (0x84) commands in quarter-microseconds.
"""
def __init__(self, port: str, baud: int = 9600, timeout: float = 1.0):
self.port_name = port
self.baud = baud
self.timeout = timeout
self.ser: serial.Serial | None = None
def open(self):
self.ser = serial.Serial(self.port_name, self.baud, timeout=self.timeout)
time.sleep(0.1)
print(f"[INFO] Connected to {self.port_name} @ {self.baud}bps")
def close(self):
if self.ser and self.ser.is_open:
self.ser.close()
print("[INFO] Serial port closed.")
def set_servo_position(self, channel: int, target: int):
if not (0 <= channel < 24):
raise ValueError("Channel out of range.")
if not (0 <= target <= 16383):
raise ValueError("Target out of range (0..16383).")
cmd = bytes([0x84, channel & 0xFF, target & 0x7F, (target >> 7) & 0x7F])
us = target * 0.25
print(f"[TX] Ch{channel}: {cmd[0]:#04x} {cmd[1]:#04x} {cmd[2]:#04x} {cmd[3]:#04x} "
f"| Target={target} ({us:.2f} µs)")
assert self.ser is not None and self.ser.is_open, "Serial port is not open."
self.ser.write(cmd)
def set_all(self, positions: List[int]):
if len(positions) < NUM_CHANNELS:
raise ValueError(f"positions must have {NUM_CHANNELS} values.")
for ch in range(NUM_CHANNELS):
self.set_servo_position(ch, positions[ch])
def list_available_ports() -> List[str]:
try:
return [p.device for p in list_ports.comports()]
except Exception:
return []
def build_ui(ctrl: MaestroController):
root = tk.Tk()
root.title("CR Hand Button Panel")
# simple spacing
root.geometry("420x260")
root.resizable(False, False)
container = ttk.Frame(root, padding=12)
container.pack(fill="both", expand=True)
title = ttk.Label(container, text="CR Hand Controller", font=("Segoe UI", 14, "bold"))
title.grid(row=0, column=0, columnspan=3, sticky="w")
hint = ttk.Label(container, text="Click a button below to send positions.")
hint.grid(row=1, column=0, columnspan=3, sticky="w", pady=(0, 8))
status = tk.StringVar(value="Ready.")
status_lbl = ttk.Label(container, textvariable=status)
status_lbl.grid(row=99, column=0, columnspan=3, sticky="w", pady=(10, 0))
# Button callback
def send(name: str):
try:
positions = SCENARIOS[name]
ctrl.set_all(positions)
status.set(f"Sent: {name} {positions}")
except Exception as e:
status.set(f"Error: {e}")
print(f"[ERROR] {e}", file=sys.stderr)
# Make 7 buttons in a tidy grid (3x3-ish)
names = list(SCENARIOS.keys())
for i, name in enumerate(names):
r, c = divmod(i, 3)
btn = ttk.Button(container, text=name, command=lambda n=name: send(n), width=16)
btn.grid(row=2 + r, column=c, padx=6, pady=6, sticky="nsew")
# Stretch columns a bit
for c in range(3):
container.grid_columnconfigure(c, weight=1)
# Initialize to "Open" like Processing setup()
try:
ctrl.set_all(SCENARIOS["Open"])
status.set(f"Initialized: Open {SCENARIOS['Open']}")
except Exception as e:
status.set(f"Init error: {e}")
print(f"[ERROR] {e}", file=sys.stderr)
# Cleanly close serial on window close
def on_close():
try:
ctrl.close()
finally:
root.destroy()
root.protocol("WM_DELETE_WINDOW", on_close)
return root
def main():
ports = list_available_ports()
default_port = "COM1" if "COM1" in ports or not ports else ports[0]
parser = argparse.ArgumentParser(description="CR Hand button controller (Python + Tkinter + pyserial)")
parser.add_argument("--port", default=default_port, help=f"Serial port (default: {default_port})")
parser.add_argument("--baud", type=int, default=9600, help="Baud rate (default: 9600)")
args = parser.parse_args()
if ports:
print("[INFO] Available serial ports:")
for p in ports:
print(f" - {p}")
else:
print("[WARN] No serial ports found by pyserial.")
ctrl = MaestroController(args.port, args.baud)
try:
ctrl.open()
except Exception as e:
print(f"[FATAL] Could not open {args.port}: {e}")
sys.exit(1)
app = build_ui(ctrl)
app.mainloop()
if __name__ == "__main__":
main()
Below is an example of operating the hand’s poses using Processing with keyboard input. Copy and paste the sample program into Processing’s text editor, change the port number to the actual one, and then click Run. When executed, a window will open. While this window is active, entering 1–7 on the keyboard will make the hand assume the pose corresponding to each number.
import processing.serial.*;
// Serial object
Serial myPort;
// Define servo positions to be set when each key ('1' to '7') is pressed
// Index: 0-6 corresponds to Ch0-Ch5
// Example: scenarios[0] represents the servo positions when key '1' is pressed
int[][] scenarios = {
{4000, 4000, 4000, 4000, 4000, 4000}, // '1' Open
{8000, 7000, 4000, 8000, 8000, 8000}, // '2' Pinch_open
{8000, 7000, 6000, 8000, 8000, 8000}, // '3' Pinch_close
{8000, 4000, 4000, 4000, 4000, 4000}, // '4' Grasp_open
{8000, 6000, 8000, 8000, 8000, 8000}, // '5' Grasp_close
{4000, 4000, 8000, 8000, 8000, 8000}, // '6' Thumb_pinch_open
{4000, 8000, 8000, 8000, 8000, 8000} // '7' Thumb_pinch_close
};
void setup() {
size(400, 200);
// Display available serial ports (for debugging)
println(Serial.list());
// Connect to the Maestro Command Port (change the port name as needed)
myPort = new Serial(this, "COM4", 9600);
println("Connected to COM4");
// Set the initial state, for example, to the position for key '1'
setAllServos(scenarios[0]);
}
void draw() {
// No processing required
}
// Called when a key is pressed
void keyPressed() {
// Check if the key is between '1' and '7'
if (key >= '1' && key <= '7') {
int index = key - '1'; // Calculate: '1' corresponds to 0, '2' to 1, and so on
if (index >= 0 && index < scenarios.length) {
// Set the servo positions defined in scenarios[index]
setAllServos(scenarios[index]);
}
}
}
// Function to set positions for all servos (Ch0 to Ch5)
void setAllServos(int[] positions) {
for (int ch = 0; ch < 6; ch++) {
setServoPosition(ch, positions[ch]);
}
}
// Function to set a servo position
void setServoPosition(int channel, int target) {
byte[] command = new byte[4];
command[0] = (byte)0x84; // Servo position setting command (0x84)
command[1] = (byte)channel;
command[2] = (byte)(target & 0x7F); // Lower 7 bits
command[3] = (byte)((target >> 7) & 0x7F); // Upper 7 bits
println("Sending command to Ch" + channel + ": "
+ hex(command[0]) + " "
+ hex(command[1]) + " "
+ hex(command[2]) + " "
+ hex(command[3]));
println("Target: " + target + " (" + (target * 0.25) + "µs)");
myPort.write(command);
}
This concludes the basic usage instructions. If you have any questions, please contact us at admin@curious-robotics.com