SV660N + MS1 from Scratch: EtherCAT, ROS 2, and a Smooth First Spin

17 minute read

Published:

Complete desk path from a fresh Ubuntu machine plus an Inovance SV660N drive and MS1 motor to a smooth first spin. Everything needed to succeed is in this post—commands, wiring, panel reading, and the mistakes that cost days on this desk.

What you will achieve

StepTarget
Idle busPanel _28ry, ethercat slavesPREOP
Enabled CSPPanel _88rn, 0x6041 ≈ 0x1637, 0x6061 = 8
MotionSoft CSP stream; shaft turns smoothly (no stair-steps / E6200)
StopCtrl+C → PREOP, 0x603F = 0, no EE081

Keep Sync0 / ros2_control at 100 Hz (10 ms). Do not “upgrade” to 1 ms until you understand Write-cycle budget.

Hardware this guide assumes

RoleExact model (this desk)
DriveSV660NS2R8I
MotorMS1H4-40B30CBA334R (brake variant — last digit family 4)
EncoderAbsolute, 23-bit8388608 counts / rev
BusDedicated Ethernet NIC → IgH master → drive EtherCAT IN
HostUbuntu 24.04, PREEMPT_RT kernel, ROS 2 Jazzy
SoftwareStacker codes/ros2_ws with Inovance YAML + mode:=csp\|csv\|pp (not bare upstream ICube alone)

Software path used below:

# Desk machine often uses /work/stacker — elsewhere clone/checkout as ~/stacker
export STACKER=/work/stacker   # or: export STACKER=$HOME/stacker
export WS=$STACKER/codes/ros2_ws

Safety

  • Mount the motor horizontal, bare shaft clear. Keep hands/tools away once enabled.
  • If STO / E-stop is wired, know how to cut power.
  • After E6200 / E6400: stop motion, cool ≥ 30–60 s, reset once. Do not spam H0d.01.
  • Prefer Ctrl+C on the launch terminal. Avoid kill -9 on ros2_control_node while the drive is in OP + enabled (latches EE081).
  • Desk brake unlock = external 24 V always on is OK for a horizontal axis. For a vertical axis you need timed BK via relay / drive DO so the shaft does not drop when disabled.

1. Bill of materials (beyond PC)

ItemNotes
SV660N drive + mains cableRated for motor; PE connected
MS1 motor + power + encoder cablesUse brake power cable if motor has BK leads
EtherCAT patch cableMaster NIC → drive CN3 (IN)
Dedicated Ethernet NICPrefer a second NIC so LAN and EtherCAT are not the same port
24 VDC PSU for holding brakeSee next subsection — mandatory on this motor

Holding brake electrical (do not skip)

This MS1 is a brake motor. BK+/BK− unpowered = shaft mechanically locked. Commanding CSP/CSV/PP against a locked brake looks like “stairs,” huge torque (0x6077), then E6200. Desk confirmation: after 24 V on the brake, CSP / CSV / PP all spin smoothly.

Spec (MS1H4-40B30CB-A33*R)Value
Supply24 VDC ±10%
Exciting current0.32 A
Rated power7.6 W
Coil resistance~75.8 Ω ±7%
Holding torque1.5 N·m
Release / apply≤ 20 ms / ≤ 60 ms

Desk PSU: 24 V, ≥ 0.5 A, preferably dedicated to the brake; cable ≥ 0.5 mm². Coil has no polarity.

  • Desk validation: connect external 24 V directly to motor BK+ / BK− (always released while powered).
  • Production: 24 V through a relay whose coil is driven by the drive’s BK digital output (drive DO is a weak signal — it does not replace the 24 V supply).

Datasheet sources: MS1-R INT selection guide (EN) (section MS1H4-40B30CB-A33*R-INT), older MS1 guide data code 19010786 §1.3.5.

Verify before any ROS motion: apply 24 V → hear/feel brake release click; with servo off you should not feel a hard lock (horizontal desk).


2. Hardware wiring checklist

   Mains AC ──► SV660N (L/N/PE per label)
                    │
                    ├── U/V/W/PE ──► MS1 motor power
                    ├── CN2 ────────► encoder cable
                    ├── CN3 IN ◄──── EtherCAT NIC (master)
                    └── CN4 OUT     (unused on single-axis desk)

   External 24 VDC ──► motor BK+ / BK−   ← REQUIRED on …A334R
ConnectionCheck
Mains + PEDrive powers; keypad alive
Motor powerPhase order per cable; PE on
EncoderCN2 seated; no bent pins
EtherCATPC → CN3 IN only (not OUT)
Brake 24 VBK+/BK− powered; release click

Power the drive. Until the PC master is up you may see Init/ready-style glyphs; after IgH Idle + cable you want _28ry-class idle (see panel section).


3. Panel literacy (enough to spin)

Five LEDs are one composite status (not five unrelated screens):

  LED:   [ 1st ] [ 2nd ] [ 3rd ] [ 4th ] [ 5th ]
  field:  link    AL     mode    ---- servo ----
  ex.:     _       2       8       r       y     →  _28ry
PositionMeaning
1stPHY link segments (can look blank)
2ndEtherCAT AL: 1 Init, 2 PREOP, 4 SAFEOP, 8 OP
3rdMode: 8 CSP, 9 CSV, 1 PP
4th–5thry ready / rn running (enabled)
You wantMeaning
_28ryPREOP + CSP mode digit + ready — idle master OK
_88rnOP + CSP + enabled — ready for CSP demos
_89rnOP + CSV + enabled
_81rnOP + PP + enabled

AL blink: PREOP’s 2 blinks ~400 ms — normal. Fault is all five digits blinking with E… / EE….

Panel (as read)MeaningTypical CoEWhat to do
E6200Motor overload (I²t)0x603F=0x3230Stop, cool ≥30–60 s, reset once
E6400IGBT over-tempStop, cool; do not re-enable hot
EE081Network status switchover0x0E08Usually kill-in-OP; cool, H0d.01 once → want 28ry
EE150Excessive sync period0x0E15Sync0/jitter; stay at 100 Hz; fix RT later

Keypad clear (when cool): SETH0d.01 = 1 (alarm reset). One shot.

Cross-check from PC (after IgH is installed):

ethercat slaves
ethercat upload -p0 0x6041 0 --type uint16   # statusword
ethercat upload -p0 0x603F 0 --type uint16   # error code (0 = ok)
ethercat upload -p0 0x6061 0 --type int8     # mode display

Healthy OP + enabled CSP example: slaves OP +, 0x6041≈0x1637, 0x603F=0, 0x6061=8.


4. OS: Ubuntu 24.04 + realtime kernel

  1. Install Ubuntu 24.04 LTS (Noble).
  2. Install the realtime kernel:
sudo apt update
sudo apt install -y ubuntu-realtime
sudo reboot
  1. Confirm:
uname -r
# must contain: realtime

NVIDIA dual-GPU note (only if apt breaks)

On Intel + NVIDIA laptops, ubuntu-realtime often fails when DKMS tries to build proprietary NVIDIA modules against PREEMPT_RT. If dpkg is broken after that:

  • Do not interrupt a long “2%” header extract — wait.
  • After a NVIDIA DKMS failure: finish/fix dpkg, keep using the realtime kernel for EtherCAT; restore NVIDIA only on the generic kernel if you need the discrete GPU for other work.

(Longer NVIDIA/DKMS write-up: sibling post on this site about Ubuntu 24.04 PREEMPT_RT + dual GPU — optional.)

Optional: isolate CPUs for the control thread

Not required for a first 100 Hz spin, but recommended on this desk:

sudo nano /etc/default/grub
# append to GRUB_CMDLINE_LINUX_DEFAULT:
#   isolcpus=2,3 nohz_full=2,3 rcu_nocbs=2,3
sudo update-grub
sudo reboot
cat /proc/cmdline | grep isolcpus

5. ROS 2 Jazzy and build tools

Use system Python for ROS (which python3 should not be inside a project venv that shadows ros2).

sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key \
  -o /usr/share/keyrings/ros-archive-keyring.gpg

echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" \
  | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null

sudo apt update

sudo apt install -y \
  build-essential cmake git pkg-config autoconf libtool \
  python3-pip python3-dev \
  python3-colcon-common-extensions python3-rosdep python3-vcstool \
  net-tools ethtool \
  ros-jazzy-desktop \
  ros-jazzy-ros2-control \
  ros-jazzy-ros2-controllers \
  ros-jazzy-hardware-interface \
  ros-jazzy-xacro

sudo rosdep init    # ok if it says already initialized
rosdep update

echo "source /opt/ros/jazzy/setup.bash" >> ~/.bashrc
source ~/.bashrc
ros2 --help | head

6. IgH EtherCAT master (–disable-eoe required)

SV660 CoE breaks if IgH is built with EoE (mailbox contention). Always configure with --disable-eoe.

Dependencies

sudo apt install -y dkms linux-headers-$(uname -r)

Build and install

cd ~
git clone https://gitlab.com/etherlab.org/ethercat.git
cd ethercat
./bootstrap
./configure --sysconfdir=/etc --disable-8139too --enable-generic --disable-eoe
make -j$(nproc)
make -j$(nproc) modules          # required — otherwise ec_master missing
sudo make modules_install install
sudo depmod -a

Bind a NIC and permissions

Pick the EtherCAT interface (ip link), not your LAN if you have two NICs:

ip -br link
ETH_IFACE="eno1"   # <-- replace with your EtherCAT NIC

sudo cp -n /etc/sysconfig/ethercat /etc/sysconfig/ethercat.bak
sudo sed -i "s/MASTER0_DEVICE=\"\"/MASTER0_DEVICE=\"$ETH_IFACE\"/" /etc/sysconfig/ethercat
sudo sed -i 's/DEVICE_MODULES=""/DEVICE_MODULES="generic"/' /etc/sysconfig/ethercat

sudo tee /etc/udev/rules.d/99-EtherCAT.rules <<'EOF'
KERNEL=="EtherCAT[0-9]*", MODE="0666"
EOF
sudo udevadm control --reload-rules
sudo udevadm trigger

sudo /etc/init.d/ethercat start
ls -l /dev/EtherCAT0    # want crw-rw-rw-
ethercat slaves
# 0  0:0  PREOP  +  SV660_1Axis_...

Identity check:

ethercat slaves -v | head -40
# Vendor Id:    0x00100000
# Product code: 0x000c010d

Realtime privileges for ros2_control (FIFO)

Without this, launch may warn Could not enable FIFO RT scheduling policy and at higher rates spawners time out even though the drive reaches OP.

# Replace YOUR_USER with your Linux login name
sudo tee /etc/security/limits.d/99-realtime-ros.conf <<EOF
YOUR_USER       -       rtprio          99
YOUR_USER       -       nice            -20
YOUR_USER       -       memlock         unlimited
EOF

Log out and back in (new session). Then:

ulimit -r    # must be 99

Do not setcap cap_sys_nice=ep on ros2_control_node — that breaks LD_LIBRARY_PATH and the node exits 127.

One NIC for both Internet and EtherCAT

When you need apt/Internet on the same port:

sudo /etc/init.d/ethercat stop
sudo rmmod ec_generic ec_master 2>/dev/null || true
sudo systemctl restart NetworkManager

Back to motor work:

sudo /etc/init.d/ethercat start

7. Workspace (stacker + Inovance configs)

Upstream ICube examples alone do not ship this desk’s Inovance slave YAML / mode:=csp|csv|pp launch. Use the stacker tree whose 3rd-party holds the patched driver + ethercat_motor_drive.

export STACKER=/work/stacker   # or $HOME/stacker
export WS=$STACKER/codes/ros2_ws
cd "$WS"

# If 3rd-party clones are missing:
#   mkdir -p 3rd-party && cd 3rd-party
#   git clone https://github.com/ICube-Robotics/ethercat_driver_ros2.git
#   git clone https://github.com/ICube-Robotics/ethercat_driver_ros2_examples.git
# then ensure inovance_sv660_*.yaml + mode:= launch presets are present
# (stacker desk already has them under 3rd-party/...).

# Use system ROS Python
source /opt/ros/jazzy/setup.bash
which python3

cd "$WS"
rosdep install --from-paths 3rd-party --ignore-src -r -y
colcon build --symlink-install --base-paths 3rd-party
source "$WS/install/setup.bash"

Why these patches matter:

  • Inovance PDO / mode YAML (inovance_sv660_config.yaml, _csv, _pp)
  • Launch mode:=csp|csv|pp
  • Safe Ctrl+C: disable CiA402 while still OP, then PREOP (avoids EE081)
  • PP: control-word override during shutdown so ForwardCommandController cannot keep enable bits

Confirm scripts are executable:

ls "$WS/scripts"/spin_bare_motor_demo*.sh "$WS/scripts"/stop_motor_drive.sh

8. Every boot / every session checklist

# Brake 24 V ON (release click)
# Panel clear of E… / EE… (or cool + one H0d.01)

echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor   # performance

sudo /etc/init.d/ethercat status
# or: sudo /etc/init.d/ethercat start

bash "$WS/scripts/check_ethercat_link.sh"   # if present
ethercat slaves    # PREOP +
# Panel: _28ry

ulimit -r          # 99 — if 0, new login after limits.d

Stay at 100 Hz control / Sync0 for beginners.


9. First enable (no motion yet)

Terminal 1 (login shell with RT limits):

export STACKER=/work/stacker
export WS=$STACKER/codes/ros2_ws
ulimit -r
cd "$WS"
source /opt/ros/jazzy/setup.bash
source install/setup.bash

# If master already claimed:
# bash scripts/stop_motor_drive.sh

ros2 launch ethercat_motor_drive motor_drive.launch.py
# equivalent: mode:=csp

Expect log lines like Operation Enabled / controllers activated, and ideally:

Successful set up FIFO RT scheduling policy with priority 50

Checks:

# other terminal
source /opt/ros/jazzy/setup.bash
source "$WS/install/setup.bash"
ethercat slaves                          # OP +
ethercat upload -p0 0x6061 0 --type int8 # 8
ethercat upload -p0 0x6041 0 --type uint16
ethercat upload -p0 0x603F 0 --type uint16  # 0
ros2 control list_controllers
ps -o pid,cls,rtprio,comm -C ros2_control_node   # CLS=FF, RTPRIO~50 preferred

Panel target: _88rn.

Optional pin to isolated CPUs (if you set isolcpus=2,3):

PID=$(pgrep -n ros2_control_node)
sudo taskset -cp 2,3 "$PID"

If OP but controllers never activate / no motion later: fix ulimit -r / re-login first; keep 100 Hz.


10. What CSP means (read before spinning)

CSP (mode 8) = every cycle the master sends a target position (0x607A). The drive tracks; it does not invent a trajectory.

demo script ~100 Hz
  → /forward_position_controller/commands
  → RxPDO 0x607A (counts)
  → SV660 position loop
  → motor

Publishing one target far from actual is still “valid CSP” — the drive chases ASAP → whip / E6200. Always use a streamed soft path (the demo scripts).

Units: encoder counts. One revolution = 8388608 counts.


11. First smooth spin (CSP)

With launch still running and panel _88rn:

source /opt/ros/jazzy/setup.bash
source "$WS/install/setup.bash"

# Recommended first motion: smooth +360° quintic (no reverse)
bash "$WS/scripts/spin_bare_motor_demo3_smooth_360.sh"

Shaft should turn continuously and smoothly. If you hear stair-steps or trip E6200 immediately:

  1. Confirm brake 24 V is really on (most common miss).
  2. Stop launch, cool, clear fault once, retry soft.

Other CSP scripts (after demo3 works):

bash "$WS/scripts/spin_bare_motor_demo2_smooth_profile_position.sh"
# demo1 is harsher — not for first spin

Optional: CSV (velocity)

# stop CSP launch first (Ctrl+C), then:
ros2 launch ethercat_motor_drive motor_drive.launch.py mode:=csv
# panel ~ _89rn when enabled
bash "$WS/scripts/spin_bare_motor_demo4_csv.sh 5 1   # soft: 5 rpm × 1 s

Optional: PP (profile position)

ros2 launch ethercat_motor_drive motor_drive.launch.py mode:=pp
# panel ~ _81rn
bash "$WS/scripts/spin_bare_motor_demo5_pp.sh 30   # +30° internal profile

PDO map is fixed at activate — restart launch to change mode.


12. Stop cleanly

In the launch terminal: Ctrl+C.

Or:

bash "$WS/scripts/stop_motor_drive.sh"

Expect: slave PREOP, panel ready-class _28ry, 0x603F=0. Patched driver disables CiA402 before AL exit so EE081 should not latch.

Avoid kill -9 while enabled in OP.


13. Troubleshooting

SymptomLikely causeFix
Permission denied on /dev/EtherCAT0udev / permsudev rule above; ls -l666; restart master
ec_master not foundmodules not built/installedmake modules + modules_install + depmod on this kernel
Mailbox / EoE weirdnessIgH built with EoERebuild with --disable-eoe
PREOP OK, launch dies / no OPWrong vendor YAML, cable on OUT, WD/DCCable on CN3 IN; use Inovance YAML; read launch log
OP + enabled, no motionFIFO denied / controllers not activeulimit -r=99, re-login; list_controllers
Stairs sound + E6200Brake 24 V missingPower BK+/BK−; verify release click
EE081 after stopHard kill / CW held in PPCtrl+C / stop script; cool; one H0d.01
EE150Sync period badStay 100 Hz; improve RT later
E6200 after “OK” moveI²t / hunting / prior heatCool ≥30–60 s; one reset; softer next move
Fault reset → shaft jumpsCSP catch-up (607A≠6064)Realign / deactivate forward before reset; see CiA402 notes
setcap → exit 127Broken loader pathRemove setcap; use limits.d only

Manual fault clear

Panel SET → H0d.01 = 1   (once, when cool)

ROS rising-edge reset (launch up, after cool) uses reset_fault_controller — only after you understand catch-up risk; prefer panel clear + relaunch for day one.


14. Appendix

Glossary

EtherCAT / CoE

AbbrExpansion
IgHIgH EtherCAT Master (this desk’s master stack; /dev/EtherCAT0, ethercat CLI)
ESIEtherCAT Slave Information (XML describing the drive)
ALApplication Layer state: INIT → PREOP → SAFEOP → OP
OPOperational — cyclic PDO running
DCDistributed Clocks — shared time base for slaves
Sync0DC latch / interrupt; rate at which cyclic PDO is taken
SM / SM2Sync Manager; SM2 = RxPDO channel (watchdog on SV660N)
PDOProcess Data Object — cyclic process data every Sync0
RxPDOReceive PDO — master → drive (commands)
TxPDOTransmit PDO — drive → master (feedback)
SDOService Data Object — slow mailbox (config, fault code, mode)
CoECANopen over EtherCAT
EoEEthernet over EtherCAT (do not mix with CoE mailbox on SV660 — build IgH with --disable-eoe)
WDWatchdog (SM2 expects cyclic RxPDO)
WCWorking counter (how many slaves answered the cyclic frame)

CiA402 / servo

AbbrExpansion
CiA402CANopen drive profile (state machine + 0x60xx objects)
CSPCyclic Synchronous Position (mode 8) — master streams 0x607A
CSVCyclic Synchronous Velocity (mode 9)
CSTCyclic Synchronous Torque (mode 10)
PPProfile Position (mode 1) — drive ramps to one target
HMHoming mode
CW / SWControlword 0x6040 / Statusword 0x6041
I²tAccumulative thermal/current model (panel E6200 = E620.0)

Common objects on this axis: 0x607A target position, 0x6064 actual position (encoder counts, MS1 ≈ 2²³ / rev), 0x6060/0x6061 mode, 0x603F error code.

ROS 2 / this stack

AbbrExpansion
CMros2_control controller_manager (ros2_control_node)
JTCjoint_trajectory_controller
FIFO / RTSCHED_FIFO realtime scheduling (kernel PREEMPT_RT ≠ process is FIFO)
DDSROS 2 middleware (topics; not the EtherCAT cycle)

Panel

Keypad glyphs (_88rn, E6200, EE081, …) are summarized in Panel literacy above; full map: SV660N keypad panel status codes.

CoE cheat sheet

ObjectName
0x6040Controlword
0x6041Statusword
0x6060 / 0x6061Mode / mode display
0x607ATarget position
0x6064Position actual
0x60FFTarget velocity (CSV)
0x603FError code
0x6077Torque actual (scaled)

Success checklist (print this)

  1. Brake 24 V on
  2. uname -r has realtime
  3. IgH --disable-eoe, ethercat slaves → PREOP
  4. ulimit -r99
  5. Launch CSP → panel _88rn
  6. demo3 smooth spin
  7. Ctrl+C → PREOP, 0x603F=0

Further reading (optional)

These are not required if you followed this post: