MAKIINASDK

GuidesDrive an actuator

Drive a single actuator

Talk to one MAKIINA drive over CAN without a server: find it, read its state, move it, tune it and stream its state at a high rate.

makiina.actuator talks straight to one MAKIINA drive over a USB CAN adapter, with no robot server in between. Use it when you build your own machine around MAKIINA actuators, for bench tests, or to look at one drive closely. This guide goes from finding the drive to smooth, tuned motion.

All values are in SI units at the output shaft: radians, rad/s, amperes, N m, and degrees Celsius. Only one program can hold the adapter, so close the Robot Console's session first.

Find the drive

Every drive answers on its own CAN id. Sweep the adapter to list them:

Python
from makiina.actuator import list_channels
from makiina.calibration.discovery import discover_bus

list_channels()                                      # your adapters
for board in discover_bus("candle", "207137C04845500F2:0"):
    print(board.id, board.version, board.part, board.label)
# 1454 (2, 5) right_arm J1

The sweep only reads: it asks every possible id for its position and notes which ones answer, then asks each drive what it is. It takes about a second. The Robot Console's On this PC page shows the same ids on each board of an arm.

Connect

Python
from makiina.actuator import Actuator

act = Actuator(1454, interface="candle", channel="207137C04845500F2:0")

Several Actuator objects can share one adapter. In a script, prefer the with form so the bus is released however the script ends:

Python
with Actuator(1454, interface="candle", channel="207137C04845500F2:0") as act:
    print(act.get_states())

With exactly one adapter plugged in you can leave out interface and channel.

Read its state

Python
frame = act.get_states()
frame.position          # rad, multi-turn
frame.velocity          # rad/s
frame.current           # A, the torque-producing current
frame.torque            # N m, an estimate (NaN on classic CAN frames)
frame.temperature       # degrees C (NaN on classic CAN frames)

Set the limits

Python
act.max_current = 3.0       # A: the safety knob; weak enough to stop by hand
act.max_velocity = 20.0     # rad/s while it tracks a position target
act.output_ramp = 1000.0    # lower is a softer start
act.set_position_mode()

With a low current limit the drive cannot hurt you or itself. Raise it only when you need the torque.

Move it

Python
act.target_pos = act.current_pos + 1.0      # one radian from where it is

The drive runs to the target at up to max_velocity and holds it. For a smooth back and forth, stream targets on a cosine, so the velocity is zero at both ends of the stroke:

Python
import math, time

center = act.current_pos
t0 = time.time()
while time.time() - t0 < 12:
    phase = (time.time() - t0) / 4.0 * 2 * math.pi            # 4 s per cycle
    act.target_pos = center + 3.0 * (1 - math.cos(phase)) / 2   # 3 rad stroke
    time.sleep(0.01)
act.target_pos = center

Interrupt it whenever you like; the drive holds the last target it got.

Choose a control mode

ModeSet it withThen command
positionset_position_mode()target_pos, rad
velocityset_velocity_mode()target_velocity, rad/s
currentset_current_mode()target_current, A
torqueset_torque_mode()target_torque, N m
freeset_free_mode(True)nothing: the shaft turns by hand, with cogging compensation

Tune it

Gains are properties; set them and read them back from the drive:

Python
act.kp_angle = 20.0                         # position stiffness
act.configure_adaptive_vpid(enabled=True, p_min=0.1, p_max=0.4,
                            i_min=0.2, i_max=0.6,
                            vel_min_rad_s=0.0, vel_max_rad_s=30.0)
act.position_filter_amount = 0.06           # light smoothing of targets

act.kp_angle                                # 20.0, read from the drive
act.read_settings(["kp_angle", "max_current"])
act.read_settings()                         # every setting, as a dict

Every read is one round trip on the bus, so read when you want to look, not inside a control loop. Reading settings needs firmware 2.04 or later. Tune the joints live explains what the gains do.

Stream state at a high rate

Asking for the state costs a round trip each time. In broadcast mode the drive sends its state on its own, at the rate you choose:

Python
act.start_broadcast(500.0)                          # frames per second
frame = act.get_next_broadcast_frame(timeout_s=0.1) # every frame, in order
act.get_latest_velocity()                           # the newest value, no waiting
act.stop_broadcast()

Use get_next_broadcast_frame() to record every frame, and the latest readers in a control loop that only needs the newest value. A robot uses the same mechanism at 60 Hz per drive.

Let go

Python
act.stop_broadcast()
act.set_free_mode(True)     # optional: let the shaft turn freely
act.close()

close() releases the bus and sends nothing to the drive: while powered, it keeps holding its last target unless you put it in free mode first.

Go further

makiina.actuator.protocol documents the CAN wire format, if you want to talk to the drive from your own stack. The full list of functions and properties is in the makiina.actuator reference.