HDriveETH Python SDK
Control Henschel Robotics HDrive17-ETH servo drives from Python. No PLC required.
Features
- Simple API —
motor.move_to(90)and you're done - Zero dependencies — uses only the Python standard library
- Real-time telemetry — live position, velocity, and torque via UDP
- Thread-safe — send commands from any thread
- Context manager — automatic connect/disconnect with
withstatement - Object read/write — read and write drive configuration objects over TCP
- Firmware version check — refuses to connect to outdated firmware (< v266)
Installation
pip install hdrive-eth
Or install from source:
git clone https://github.com/henschel-robotics/python-hdrive17-eth.git
cd python-hdrive17-eth
pip install .
For development (editable install):
pip install -e .
Quickstart
from hdrive_eth import HDriveETH
import time
with HDriveETH("192.168.122.102") as motor:
# Move to 90 degrees
motor.move_to(90)
# Read telemetry
time.sleep(1)
frame = motor.telemetry
if frame:
print(f"Position: {frame.position}, Velocity: {frame.velocity}")
# Motor is automatically stopped and disconnected when leaving the 'with' block
API Reference
Connect
from hdrive_eth import HDriveETH
# Recommended: use a context manager (auto-connect and auto-disconnect)
with HDriveETH("192.168.122.102") as motor:
motor.move_to(90)
# The motor is stopped (mode=0) and the connection is closed automatically.
On connection the driver will:
- Open a TCP socket to the drive
- Read the firmware version (
m3s0) and refuse to connect if < 266 - Discover the UDP telemetry port (
m4s17) - Configure telemetry: check UDP enabled (
m4s19), autosend (m4s34), set binary TX ticket (m4s22=3,TX_BinaryTicket; value2is the smaller debug binary ticket, not this layout) - Start the UDP telemetry receiver
Position Control
# Move to absolute position in degrees
motor.move_to(position=90)
# With custom speed, torque, acceleration, deceleration
motor.move_to(position=90, speed=500, torque=500, acc=3000, decc=3000)
Velocity Control
# Constant speed
motor.set_speed(speed=500)
# With torque limit
motor.set_speed(speed=500, torque=300)
Torque Control
# Direct torque setpoint in milli-newton-metres (mNm; firmware demandedTorque)
motor.set_torque(torque=200)
Stop
# Stop the motor (sets mode to 0)
motor.stop()
Read / Write Objects
# Read a drive object (e.g. firmware version m3s0)
version = motor.read_object(index=3, subindex=0)
print(f"Firmware version: {version}")
# Read a CAN slave object over the same TCP command socket
slave_voltage = motor.read_slave_object(slot=0, index=0, subindex=6)
print(f"Slave voltage: {slave_voltage}")
# Or use the HTTP slave-object gateway explicitly
slave_voltage_http = motor.read_slave_object(
slot=0,
index=0,
subindex=6,
transport="http",
timeout=3.0,
)
print(f"Slave voltage (HTTP): {slave_voltage_http}")
# Write a drive object (e.g. select BinaryTicket telemetry — m4s22 = 3)
motor.write_object(index=4, subindex=22, value=3)
For the existing HTTP slave-object gateway (getData.cgi?slvobj=...), use
HDriveETH.read_slvobj(...) / HDriveETH.write_slvobj(...). The unified instance
API defaults to transport="tcp" and also accepts transport="http" for reads.
Telemetry
# Read the latest telemetry frame
frame = motor.telemetry
if frame:
print(f"Position: {frame.position}")
print(f"Velocity: {frame.velocity}")
print(f"Time: {frame.time_us} µs")
print(f"Temperature: {frame.temperature}")
print(f"Motor mode: {frame.motor_mode}")
# Register a callback for every frame
def on_frame(frame):
print(f"pos={frame.position} vel={frame.velocity}")
motor.on_telemetry(on_frame)
Alternate TX layouts match TicketManager::TX_Ticket (see hdrive_eth.TXTicket): Binary CAN (29×int32), Binary CAN full (49×int32, positions/speeds/torques/modes/states per axis), debug (15×int32). Example:
from hdrive_eth import HDriveETH, TXTicket, BinaryCanFullTelemetryFrame
motor = HDriveETH(
"192.168.122.102",
telemetry_ticket=TXTicket.BINARY_CAN_FULL,
telemetry_format="binary_can_full", # optional: reject other UDP sizes
)
t = motor.telemetry
if isinstance(t, BinaryCanFullTelemetryFrame):
print(t.master_torque, t.slave_torques)
With telemetry_format="auto" (default), the parser selects the layout from the UDP payload length.
Raw Command
from hdrive_eth import HDriveETH, Mode
# Full control over all parameters
motor.send_raw(
position=90,
speed=500,
torque=200,
mode=Mode.POSITION_CONTROL,
acc=5000,
decc=5000,
)
Control Modes
| Constant | Value | Description |
|---|---|---|
Mode.TORQUE_CONTROL |
0x80 (128) | Profile torque / current (AXIS_STATE_MOTORMODE_CURRENT) |
Mode.POSITION_CONTROL |
0x81 (129) | Profile position (AXIS_STATE_MOTORMODE_POSITION) |
Mode.VELOCITY_CONTROL |
0x82 (130) | Profile speed (AXIS_STATE_MOTORMODE_SPEED) |
Mode.DISABLE |
0x00 | Stop (AXIS_STATE_MOTORMODE_STOP) |
Telemetry Frame Fields
With TXTicket.BINARY (default), each UDP packet has 33 int32 values (~1 kHz):
| Index | Field | Description |
|---|---|---|
| 0 | time_us |
System time in microseconds |
| 1 | position |
Actual position (degrees) |
| 2 | velocity |
Actual velocity |
| 9 | temperature |
Motor temperature |
| 10 | motor_mode |
Current motor mode |
| 11 | motor_voltage |
Supply voltage |
| 12 | demanded_speed |
Demanded speed |
| 13 | demanded_position |
Demanded position |
| 19 | software_version |
Firmware version |
| 23–30 | slave_positions |
CAN slave positions (list of 8) |
See hdrive_eth/telemetry.py for the full list of all 33 fields.
Network Configuration
| Parameter | Default | Description |
|---|---|---|
| IP address | 192.168.122.102 |
HDrive default IP |
| TCP port | 1000 |
Command port (auto-discovered from m4s16) |
| UDP port | 1001 |
Telemetry port (auto-discovered from m4s17) |
# Custom IP (ports are auto-discovered from the drive)
motor = HDriveETH("192.168.1.50")
Examples
See the examples/ folder:
basic_control.py— Connect, move, print telemetryvelocity_mode.py— Constant speed controltorque_mode.py— Torque controlread_object.py— Read a single object via raw TCP
Requirements
- Python 3.8+
- HDrive17-ETH firmware version 266 or newer
- No external dependencies
License
MIT — see LICENSE for details.
Support
Metadata
Release files for hdrive-eth 0.1.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| hdrive_eth-0.1.4.tar.gz | 32.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| hdrive_eth-0.1.4-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 53.5 kB
Release files / hdrive_eth-0.1.4.tar.gz
| Download URL | hdrive_eth-0.1.4.tar.gz |
|---|---|
| Size | 32.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3f72cf307d6a6e3d118e9647805a6b6d84ae865bc1e903bb72afbdaa7e3514df
|
|
BLAKE2b-256 checksum How to use checksums |
153997257f391c998876636b18487086751b8a3d662cdb38bece957b02001238
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.8
|
Release files / hdrive_eth-0.1.4-py3-none-any.whl
| Download URL | hdrive_eth-0.1.4-py3-none-any.whl |
|---|---|
| Size | 21.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1f00c8e8995ad01a10e8fc97f2c973b79aed4c0c4e95b13c85fa570213b18b8c
|
|
BLAKE2b-256 checksum How to use checksums |
1b842743bfa61321090290e1f9c31b899734d259398ca5e0dfcd697314bf16bd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.8
|