SCN5 And SCN6 Dyadic System Electric Linear Actuator Device Capabilities
Functions
# initialization
def init(com: int,
device_id: Union[int, List[int]] = 0,
stroke: int = 100,
accel: int = 200,
gain: int = 7,
normal_speed: int = 7800,
home_speed: int = 2000,
move_mode: int = 0,
go_home: int = 0,
go_center: int = 0,
diag: int = 0) -> bool:
"""
Initialize the SCN device.
Parameters:
com (int): Required. COM port number (e.g., 4 for COM4)
id (int or list[int]): Optional. Device ID Range [0-15]
stroke (int): Optional. Stroke length (e.g., 100)
accel (int): Optional. Acceleration value
gain (int): Optional. Control gain
normal_speed (int): Optional. Normal movement speed
home_speed (int): Optional. Speed for homing
move_mode (int): Optional. Movement mode
go_home (int): Optional. If non-zero, go home on init
go_center (int): Optional. If non-zero, go center after home
diag (int): Optional. Dump actuator BANK settings
Returns:
bool: True if initialization succeeded, False otherwise
"""
...
# mandatory ending
def terminate() -> None:
"""Cleanly shuts down the SCN device and releases resources."""
...
# device information
def get_device_info(selector: str, id: int = 0) -> Union[str, int]:
"""
Retrieve information from the SCN device.
Parameters:
selector (str): The info field to query (e.g., 'version', 'name', 'ticks', 'type', 'vendor id', 'product id', 'serial number').
id (int): Optional. Device ID (default is 0).
Returns:
Union[str, int]:: A string or int containing the requested information, -4 in case of wrong selector.
"""
# device motion control
def go_home(id: int = 0) -> bool:
"""
Move the actuator to its home position.
Parameters:
id (int): Optional. Device ID (default is 0).
Returns:
bool: True if the command was successfully issued, False otherwise.
"""
def go_center(id: int = 0) -> bool:
"""
Move the actuator to the center of its stroke range.
Parameters:
id (int): Optional. Device ID (default is 0).
Returns:
bool: True if the command was successfully issued, False otherwise.
"""
def go_position(pos: float, id: int = 0) -> bool:
"""
Move the actuator to an absolute position (in mm). Submit command is optional.
Parameters:
pos (float): Target position in millimeters.
id (int): Optional. Device ID (default is 0).
Returns:
bool: True if the command was successfully issued, False otherwise.
"""
def load_position(pos: float, id: int = 0) -> bool:
"""
Load a target position without immediate execution.
Parameters:
pos (float): Target position in millimeters.
id (int): Optional. Device ID (default is 0).
Returns:
bool: True if the position was successfully loaded, False otherwise.
"""
def clear_position(id: int = 0) -> None:
"""
Clear the currently loaded position.
Parameters:
id (int): Optional. Device ID (default is 0).
"""
def check_scn(id: int = 0) -> bool:
"""
Check if the alarm is set.
Parameters:
id (int): Optional. Device ID (default is 0).
Returns:
bool: True if the actuator is okay, False if the alarm is set.
"""
def submit_check(id: int = 0) -> None:
"""
Submit the current pending commands including homing and check the actuator status.
Parameters:
id (int): Optional. Device ID (default is 0).
"""
def submit(id: int = 0) -> None:
"""
Submit the pending motion command and return immediately.
Parameters:
id (int): Optional. Device ID (default is 0).
"""# utility function to pass parameters to z3scn init()
# include this function below to your script
def z3setup(**kwargs) -> list[int]:
"""
Prepare ordered and validated actuator initialization parameters.
Parameters (all optional except 'com'):
com (int): Required. COM port number (e.g., 4 for COM4).
id (int or list[int]): Optional. Device ID Range [0-15], (default 0).
stroke (int): Optional. Stroke length (default 100, only 50, 150, or 200 are valid; others become 100).
accel (int): Optional. Acceleration value (default 200 - range 70 to 1000).
gain (int): Optional. Control gain (default 7 - range 6 to 10).
normalSpd (int): Optional. Normal movement speed (default 7800 - range 100 to 15000).
homeSpd (int): Optional. Homing speed (default 2000 - range 100 to 5000).
moveMode (int): Optional. Movement mode (default 0).
goHome (int): Optional. Whether to go home on init (default 0).
goCenter (int): Optional. Whether to go center after home (default 0).
diag (int): Optional. Diagnostic flag (default 0).
Returns:
list[int]: A list of parameters ready to be unpacked into the init() function.
Raises:
ValueError: If 'com' is missing or unknown parameters are passed.
Example:
import z3scn as dev
params = z3setup(com=4, stroke=200, accel=385, normalSpd=10000 )
dev.init(*params)
"""
param_order = ["com", "id", "stroke", "accel", "gain", "normalSpd", "homeSpd", "moveMode", "goHome", "goCenter", "diag"]
defaults = {
"id": 0, "stroke": 100, "accel": 200, "gain": 7,
"normalSpd": 7800, "homeSpd": 2000, "moveMode": 0,
"goHome": 0, "goCenter": 0, "diag": 0
}
stroke_valid = {50, 150, 200}
allowed_keys = set(param_order)
for key in kwargs:
if key not in allowed_keys:
raise ValueError(f"Unknown parameter '{key}'. Allowed parameters are: {', '.join(param_order)}")
if "com" not in kwargs:
raise ValueError("Parameter 'com' is required")
stroke = kwargs.get("stroke", 100)
kwargs["stroke"] = stroke if stroke in stroke_valid else 100
args = [kwargs.get(k, defaults.get(k)) for k in param_order]
while len(args) > 1 and args[-1] == defaults.get(param_order[len(args)-1]):
args.pop()
# print(f"[DEBUG] Prepared args: {args}")
return args
Initialization
init(COM [, id=0, stroke=100, accel=200, gain=7, normalSpd=7800, homeSpd=2000,…]) function
Parameters:
com (int): Required. COM port number (e.g., 3 for COM4)
id (int): Optional, default id=0. Range [0–15] (ID can be changed with Dyadic System software tool like MVST.exe)
stroke (int): Optional. Stroke length (e.g., 100)
accel (int): Optional. Acceleration value
gain (int): Optional. Control gain
normalSpd (int): Optional. Normal movement speed
homeSpd (int): Optional. Speed for homing
moveMode (int): Optional. Movement mode
gohome (int): Optional. If non-zero, go home on init
gocenter (int): Optional. If non-zero, go center after home
diag (int): Optinal. If non-zero, print the scn eeprom bank1 and bank0
init() initialize the device extension and open serial com. This function takes one mandatory parameter, the COM port, all other are optional.
in addition to the COM port the default value of parameters are:
id=0, stroke=100, accel=200, gain=7, normalSpd=7800, homeSpd=2000, goHome=0, goCenter=0, diag=0
Example To Initialize the SCN5 or SCN6 device (z3scn device extension)
import z3scn as dev
# init scn with COM4 and default parameters (id=0, stroke=100, accel=200, gain=7, normalSpd=7800, homeSpd=2000)
if dev.init(4):
print("Start Testing...")
# your script here
# end of script
dev.terminate()
Using Multiple SCN Actuators on a Single COM Port
With a special FTDI adapter featuring one USB connection and multiple SCN ports (2, 4, or 6 connectors), it’s possible to control several SCN5/6 actuators through a single COM port. This setup simplifies cabling and reduces the number of required USB ports.
To enable this mode in the z3scn API, simply pass a list of actuator IDs to the init() function. For example:
z3.init(com=3, ids=[0, 1, 3, 7])
This tells the driver to initialize actuators with IDs 0, 1, 3, and 7 on COM3. Each actuator must have a unique ID set beforehand (via manufacturer tools or manual configuration).
dev.init(3, [0, 1, 3, 7])Performance note: For projects requiring fast and highly responsive control, we recommend using no more than 2 actuators per COM port. Beyond that, bus latency may increase, potentially affecting precision or synchronization.
terminate() function
Use terminate() when you no longer need the extension just before quitting or at the end of script.
This function cleanly shuts down the SCN device and releases resources.
# end of script
dev.terminate()get_device_info(selector [, id = 0] ) function
get device information and capabilities (id parameters is optional, default is 0)
import z3scn as scn
# version
# Return version as string
# Example:
z3_vers = scn.get_device_info("version")
# name
# Return name of extension as string
# Example:
z3_name = scn.get_device_info("name")
# type
# Return the class number of the device (see the device type class)
# Example:
class_num = scn.get_device_info("type")
# ticks
# Return number of ticks elapsed since PC startup
# Example:
if scn.get_device_info("ticks") > old_tick:
print("time elapsed!")
# vendor id
# Return the vendor ID of the device
# Example:
vendor_id = scn.get_device_info("vendor id")
# product id
# Return the product ID of the device
# Example:
product_id = scn.get_device_info("product id")
# product serial number
# Return the serail number of the device
# Example:
product_sn = scn.get_device_info("serial number")HIGH LEVEL API (z3scn and z3scnpro device extensions)
The high level API is very easy to use and recommended to get started quickly with SCN5 or SCN6 actuators. This involved more 5 years of R&D to optimize the API and give you a maximum performance with SCN6. All the hard work has been done internally to let you focus on your project in place of dealing with the management of actuators. All high-level functions automatically stop to respond in the event of an incident on the actuator (alarm/error).
go_home([id=0] ) function
preload command to go home position, run submit_check() command to execute the command. It’s recommended to run the go_home() and the go_center() functions after the initialization of your SCN device (id parameters is optional, default is 0).
dev.go_home()
dev.submit_check()go_center([id=0] ) function
preload command to go center position, run submit_check() command to execute the command. It’s recommended to run the go_home() and the go_center() functions after the initialization of your SCN device (id parameters is optional, default is 0).
dev.go_center()
dev.submit_check()go_position(double mm[, int id=0] ) function
move actuator to the position (in millimeter). submit() command is optional but recommended (id parameters is optional, default is 0).
dev.go_position(55)
dev.submit() # optionalload_position(double mm[, int id=0]) function
preload position (in millimeter). must be followed by submit_check() command to move the actuator (id parameters is optional, default is 0).
dev.load_position(75)
dev.submit_check()clear_position([int id=0]) function
clear preloaded position (id parameters is optional, default is 0).
# clear preloaded position of SCN id 0 and 1
dev.clear_position(0)
dev.clear_position(1)
dev.load_position(54, 0)
dev.load_position(54, 1)
dev.submit()submit_check([int id=0]) function
execute all preloaded commands and wait until the target position is reached. It’s recommended to run the submit_check() function after calling go_home() or go_center() or load_position() functions (id parameters is optional, default is 0).
submit([int id=0]) function
execute all preloaded commands return immediately (id parameters is optional, default is 0). Useful to get a maximum performance with go_position() function
check_scn([int id=0]) function
check if an incident has occurred (error or alarm has been set or the servo has been turned off), return 0 if OK (id parameters is optional, default is 0).
pos = 44
dev.go_position(pos)
if dev.check_scn() >0: print("SCN Error! Check Alarm.")z3scn device extension (full example using high-level API)
import z3scn as dev
import time
import math
def z3setup(**kwargs) -> list[int]:
"""
Prepare ordered and validated actuator initialization parameters.
Parameters (all optional except 'com'):
com (int): Required. COM port number (e.g., 3 for COM4).
id (int): Device ID (default 0).
stroke (int): Stroke length (default 100, only 50, 150, or 200 are valid; others become 100).
accel (int): Acceleration value (default 200).
gain (int): Control gain (default 7).
normalSpd (int): Normal movement speed (default 7800).
homeSpd (int): Homing speed (default 2000).
moveMode (int): Movement mode (default 0).
gohome (int): Whether to go home on init (default 0).
gocenter (int): Whether to go center after home (default 0).
diag (int): Diagnostic flag (default 0).
Returns:
list[int]: A list of parameters ready to be unpacked into the init() function.
Raises:
ValueError: If 'com' is missing or unknown parameters are passed.
Example:
params = z3setup(com=4, accel=385)
dev.init(*params)
"""
param_order = ["com", "id", "stroke", "accel", "gain", "normalSpd", "homeSpd", "moveMode", "gohome", "gocenter", "diag"]
defaults = {
"id": 0, "stroke": 100, "accel": 200, "gain": 7,
"normalSpd": 7800, "homeSpd": 2000, "moveMode": 0,
"gohome": 0, "gocenter": 0, "diag": 0
}
stroke_valid = {50, 150, 200}
allowed_keys = set(param_order)
for key in kwargs:
if key not in allowed_keys:
raise ValueError(f"Unknown parameter '{key}'. Allowed parameters are: {', '.join(param_order)}")
if "com" not in kwargs:
raise ValueError("Parameter 'com' is required")
stroke = kwargs.get("stroke", 100)
kwargs["stroke"] = stroke if stroke in stroke_valid else 100
args = [kwargs.get(k, defaults.get(k)) for k in param_order]
while len(args) > 1 and args[-1] == defaults.get(param_order[len(args)-1]):
args.pop()
# print(f"[DEBUG] Prepared args: {args}")
return args
# smooth filter
def smooth_path(start, end, steps):
return [round(start + (end - start) * 0.5 * (1 - math.cos(math.pi * i / steps)), 2)
for i in range(steps + 1)]
def sleep(ms):
time.sleep(ms / 1000.0)
def frange(start, stop, step):
while start < stop:
yield start
start += step
# init scn with COM Port 4 and default parameters (stroke = 100)
if dev.init(*z3setup(com=4)):
print("Start Testing...")
z3vers = dev.get_device_info("version")
print(f"Version: {z3vers}")
# SCN actuator 100mm
max_stroke = 100
pos_center = max_stroke / 2
# go home position
dev.go_home()
dev.submit_check()
sleep(100)
# go center position
if dev.go_center():
dev.submit_check()
sleep(100)
else:
print("error center failed!")
# Params
pause_fast = 0.05 # quick pause between small move
pause_long = 0.1 # long pause 500 ms
repetitions = 2 # cycles
# key pos.
low_rest = 20
low_min = 20
low_max = 40
high_rest = 70
high_min = 70
high_max = 90
for cycle in range(repetitions):
print(f"\n--- Cycle {cycle+1} ---")
# 1. start Position
dev.load_position(low_rest)
dev.submit_check()
sleep(100)
# 2. fast move low position
for _ in range(5):
for move in (low_max, low_min):
dev.go_position(move)
time.sleep(pause_fast)
# 3. Pause
dev.load_position(high_rest)
dev.submit_check()
sleep(500)
# 4. fast move high position
for _ in range(5):
for move in (high_max, high_min):
dev.go_position(move)
time.sleep(pause_fast)
# 5. return and pause
dev.load_position(low_rest)
dev.submit_check()
sleep(500)
# return to center position
dev.go_center()
dev.submit_check()
sleep(100)
# notify device extension
dev.terminate()
print("Test Done!")
else:
print("Initialization failed!")
Example using multi IDs on one COM port:
import z3scn as z3
def test_multi_ids(shared_dict):
if z3.init(9, [0,1]):
z3.clear_position(0)
z3.clear_position(1)
z3.go_home(0)
z3.go_home(1)
z3.submit_check(0)
z3.submit_check(1)
sleep(100)
z3.go_center(0)
z3.go_center(1)
z3.submit_check(0)
z3.submit_check(1)
sleep(100)
z3.load_position(54, 0)
z3.load_position(54, 1)
z3.submit()
sleep(2800)
z3.go_center(0)
z3.go_center(1)
z3.submit_check(0)
z3.submit_check(1)
sleep(100)
else:
print("INIT FAILED")LOW LEVEL API (z3scnpro device extension)
The low level API exposes almost all Dyadic functions and is recommended for expert only. All functions are documented in Dyadic Electric Linear Actuator SCN5 and SCN6 official publication (pdf). A PRO annual subscription to EKSIMRacing foundation is required to get z3scnpro device extension, contact us if you’re interested.
