Skip to content

Instantly share code, notes, and snippets.

@Bouni
Last active May 15, 2024 14:24
Show Gist options
  • Save Bouni/8b4532d0bdf012bd83c65d3eb62f8aa2 to your computer and use it in GitHub Desktop.
Save Bouni/8b4532d0bdf012bd83c65d3eb62f8aa2 to your computer and use it in GitHub Desktop.
Linux CNC + EtherCat + RPi 4 Setup

The folowing is a writup from Hakans forum post!

RPi Setup

  1. Download & Write image to SD card: www.linuxcnc.org/iso/linuxcnc-2.8.1-pi4.zip
  2. Configure Wifi via wpa_supplicant.conf
  3. Put SD card into RPi and verify that RT-PREEMT Kernel is running: uname -a
  4. Update everything and reboot: sudo apt update && sudo apt upgrade && sudo reboot

VNC In Order to start linuxcnc you need to establish a VNC session or start it headless via DISPLAY=:0 linuxcnc <yourinitfile>.ini. I had to start the pi once with a display connected to get VNC working for some reason, despite having enabled VNC via raspi-config.

Prepare for EtherCat Setup

  1. Check installed Kernel version uname -r
  2. Install linux-headers that match installed kernel sudo apt install linux-headers-4.19.71-rt24-v7l
  3. Install toolchain sudo apt install mercurial build-essential automake tree dkms bison flex

Install etherlab master

git clone https://github.com/icshwi/etherlabmaster
cd etherlabmaster
make init
echo "ENABLE_CYCLES = NO" > configure/CONFIG_OPTIONS.local
make build
make install
echo "ETHERCAT_MASTER0=eth0" > ethercatmaster.local
make dkms_add
make dkms_build
make dkms_install
make setup

Necessary dirty hack to get things working

sudo mkdir -p /usr/include/linuxcnc
sudo ln -s /opt/etherlab/include/*.h /usr/include/linuxcnc/
sudo ln -s /opt/etherlab/lib/lib* /usr/lib/

Reboot and verify that Ethercat is running

pi@linuxcnc:~ $ ethercat master
Master0
Phase: Idle
Active: no
Slaves: 3
Ethernet devices:
Main: dc:a6:32:05:7e:65 (attached)
Link: UP
Tx frames: 3990
Tx bytes: 239560
Rx frames: 3989
Rx bytes: 239500
Tx errors: 0
Tx frame rate [1/s]: 48 51 41
Tx rate [KByte/s]: 2.8 3.0 2.4
Rx frame rate [1/s]: 48 51 41
Rx rate [KByte/s]: 2.8 3.0 2.4
Common:
Tx frames: 3990
Tx bytes: 239560
Rx frames: 3989
Rx bytes: 239500
Lost frames: 0
Tx frame rate [1/s]: 48 51 41
Tx rate [KByte/s]: 2.8 3.0 2.4
Rx frame rate [1/s]: 48 51 41
Rx rate [KByte/s]: 2.8 3.0 2.4
Loss rate [1/s]: 0 0 0
Frame loss [%]: 0.0 0.0 0.0
Distributed clocks:
Reference clock: Slave 0
DC reference time: 0
Application time: 0
2000-01-01 00:00:00.000000000
pi@linuxcnc:~ $ ethercat slave
0 0:0 PREOP + EK1100 EtherCAT-Koppler (2A E-Bus)
1 0:1 PREOP + EL1008 8K. Dig. Eingang 24V, 3ms
2 0:2 PREOP + EL2008 8K. Dig. Ausgang 24V, 0.5A

Install linuxcnc-ethercat

  1. Install linuxcnc dev version sudo apt install linuxcnc-uspace-dev
  2. Download, build and install linuxcnc-ethercat
git clone https://github.com/sittner/linuxcnc-ethercat
cd linuxcnc-ethercat
make configure
make
sudo make install

Test linuxcnc with Ethercat

  1. Run linuxcnc
  2. Select sim→axis→axis, copy the files. Axis should start. Exit axis.
  3. go to the config folder cd linuxcnc/configs/sim.axis
  4. Edit an ini file of your choice and add to the [HAL] section HALFILE = ethercat.hal
  5. Create an ethercat.hal with this content
loadusr -W lcec_conf ethercat-conf.xml
loadrt lcec
addf lcec.read-all servo-thread
addf lcec.write-all servo-thread
  1. Create an ethercat-conf.xml with this content
<masters>
<master idx="0" appTimePeriod="1000000" refClockSyncCycles="5">
</master>
</masters>
  1. Start linux cnc and load the ini file you've just edited linuxcnc <yourinifile>.ini
  2. Test if an output for examle, works as expected
halcmd setp lcec.0.2.dout-7 1
# This will switch on the output 8 on the module No. 2, EL2008 in this example. 
halcmd setp lcec.0.<module-no>.dout-<output-no> <state>
# The physical hardware is needed for this, of course.

cia402

Hakan adapted the hal-cia402 files from @dbraun1981 https://github.com/dbraun1981/hal-cia402

  1. clone the repo git clone https://github.com/dbraun1981/hal-cia402.git
  2. cd into the repo cd hal-cia402
  3. Compile and install it: sudo halcompile --install cia402.comp

Servo drives

His lathe2-nopid.hal

# Generated by PNCconf at Sat Sep 10 10:10:56 2016
# If you make changes to this file, they will be
# overwritten when you run PNCconf again

loadrt [KINS]KINEMATICS
#autoconverted  trivkins
loadrt [EMCMOT]EMCMOT servo_period_nsec=[EMCMOT]SERVO_PERIOD num_joints=[KINS]JOINTS
loadusr -W lcec_conf ethercat-conf.xml
loadrt lcec
loadrt cia402 count=2

addf lcec.read-all            servo-thread
addf cia402.0.read-all        servo-thread
addf cia402.1.read-all        servo-thread
addf motion-command-handler   servo-thread
addf motion-controller        servo-thread
addf cia402.0.write-all       servo-thread
addf cia402.1.write-all       servo-thread
addf lcec.write-all           servo-thread

#*******************
#  AXIS X
#*******************

# --- joint signals for motion

net x-pos-cmd    <= joint.0.motor-pos-cmd
net x-vel-cmd    <= joint.0.vel-cmd
net x-pos-fb     <= joint.0.motor-pos-fb
net x-enable     <= joint.0.amp-enable-out

# --- connect stepper driver to joint

net x-pos-cmd    => cia402.0.pos-cmd
net x-pos-fb     => cia402.0.pos-fb
net x-enable     => cia402.0.enable

# --- ect60 settings

setp cia402.0.csp-mode 1
setp cia402.0.pos-scale 4000

# --- from stepper(ethercat) to cia402

net x-statusword      lcec.0.4.cia-statusword  => cia402.0.statusword
net x-opmode-display  lcec.0.4.opmode-display  => cia402.0.opmode-display
net x-drv-act-pos     lcec.0.4.actual-position => cia402.0.drv-actual-position
net x-drv-act-velo    lcec.0.4.actual-velocity => cia402.0.drv-actual-velocity

# --- from cia402 to stepper(ethercat) 

net x-controlword         cia402.0.controlword         => lcec.0.4.cia-controlword
net x-modes-of-operation  cia402.0.opmode              => lcec.0.4.opmode
net x-drv-target-pos      cia402.0.drv-target-position => lcec.0.4.target-position
net x-drv-target-velo     cia402.0.drv-target-velocity => lcec.0.4.target-velocity

#*******************
#  AXIS Z
#*******************

# --- joint signals for motion

net z-pos-cmd    <= joint.1.motor-pos-cmd
net z-vel-cmd    <= joint.1.vel-cmd
net z-pos-fb     <= joint.1.motor-pos-fb
net z-enable     <= joint.1.amp-enable-out

# --- connect stepper driver to the joint

net z-pos-cmd    => cia402.1.pos-cmd
net z-pos-fb     => cia402.1.pos-fb
net z-enable     => cia402.1.enable

# --- ect60 settings

setp cia402.1.csp-mode 1
setp cia402.1.pos-scale 10000

# --- from servo(ethercat) to cia402

net z-statusword      lcec.0.5.cia-statusword  => cia402.1.statusword
net z-opmode-display  lcec.0.5.opmode-display  => cia402.1.opmode-display
net z-drv-act-pos     lcec.0.5.actual-position => cia402.1.drv-actual-position
net z-drv-act-velo    lcec.0.5.actual-velocity => cia402.1.drv-actual-velocity

# --- from cia402 to servo(ethercat) 

net z-controlword         cia402.1.controlword         => lcec.0.5.cia-controlword
net z-modes-of-operation  cia402.1.opmode              => lcec.0.5.opmode
net z-drv-target-pos      cia402.1.drv-target-position => lcec.0.5.target-position
net z-drv-target-velo     cia402.1.drv-target-velocity => lcec.0.5.target-velocity

#*********************
#   E-STOP
#*********************

setp iocontrol.0.emc-enable-in 1

His ethercat-conf.xml



<?xml version="1.0" encoding="UTF-8"?>
<masters>
   <master idx="0" appTimePeriod="1000000" refClockSyncCycles="5">
      <slave idx="0" type="EK1100" />
      <slave idx="1" type="EL1008" />
      <slave idx="2" type="EL2008" />
      <slave idx="3" type="EL5101" />
      <slave idx="4" type="generic" vid="00000a88" pid="0A880002" configPdos="true">
         <dcConf assignActivate="300" sync0Cycle="*1" sync0Shift="0" />
         <sdoConfig idx="2000" subIdx="0">
            <sdoDataRaw data="70 17" />
         </sdoConfig>
         <!-- Max motor current (6.0) -->
         <sdoConfig idx="2011" subIdx="0">
            <sdoDataRaw data="01 00" />
         </sdoConfig>
         <!-- Closed loop -->
         <syncManager idx="2" dir="out">
            <pdo idx="1600">
               <pdoEntry idx="6040" subIdx="00" bitLen="16" halPin="cia-controlword" halType="u32" />
               <pdoEntry idx="6060" subIdx="00" bitLen="8" halPin="opmode" halType="s32" />
               <pdoEntry idx="607A" subIdx="00" bitLen="32" halPin="target-position" halType="s32" />
               <pdoEntry idx="60FF" subIdx="00" bitLen="32" halPin="target-velocity" halType="s32" />
            </pdo>
         </syncManager>
         <syncManager idx="3" dir="in">
            <pdo idx="1a00">
               <pdoEntry idx="6041" subIdx="00" bitLen="16" halPin="cia-statusword" halType="u32" />
               <pdoEntry idx="6061" subIdx="00" bitLen="8" halPin="opmode-display" halType="s32" />
               <pdoEntry idx="6064" subIdx="00" bitLen="32" halPin="actual-position" halType="s32" />
               <pdoEntry idx="606C" subIdx="00" bitLen="32" halPin="actual-velocity" halType="s32" />
               <pdoEntry idx="6077" subIdx="00" bitLen="32" halPin="actual-torque" halType="s32" />
            </pdo>
         </syncManager>
      </slave>
      <slave idx="5" type="generic" vid="00000a88" pid="0A880002" configPdos="true">
         <dcConf assignActivate="300" sync0Cycle="*1" sync0Shift="0" />
         <sdoConfig idx="2000" subIdx="0">
            <sdoDataRaw data="DC 05" />
         </sdoConfig>
         <!-- Max motor current (1.5) -->
         <sdoConfig idx="2011" subIdx="0">
            <sdoDataRaw data="00 00" />
         </sdoConfig>
         <!-- Open loop -->
         <syncManager idx="2" dir="out">
            <pdo idx="1600">
               <pdoEntry idx="6040" subIdx="00" bitLen="16" halPin="cia-controlword" halType="u32" />
               <pdoEntry idx="6060" subIdx="00" bitLen="8" halPin="opmode" halType="s32" />
               <pdoEntry idx="607A" subIdx="00" bitLen="32" halPin="target-position" halType="s32" />
               <pdoEntry idx="60FF" subIdx="00" bitLen="32" halPin="target-velocity" halType="s32" />
            </pdo>
         </syncManager>
         <syncManager idx="3" dir="in">
            <pdo idx="1a00">
               <pdoEntry idx="6041" subIdx="00" bitLen="16" halPin="cia-statusword" halType="u32" />
               <pdoEntry idx="6061" subIdx="00" bitLen="8" halPin="opmode-display" halType="s32" />
               <pdoEntry idx="6064" subIdx="00" bitLen="32" halPin="actual-position" halType="s32" />
               <pdoEntry idx="606C" subIdx="00" bitLen="32" halPin="actual-velocity" halType="s32" />
               <pdoEntry idx="6077" subIdx="00" bitLen="32" halPin="actual-torque" halType="s32" />
            </pdo>
         </syncManager>
      </slave>
   </master>
</masters>

and his lathe.ini

[EMC]
VERSION = 1.1
MACHINE = LinuxCNC-HAL-SIM-LATHE
  DEBUG = 0

[DISPLAY]
             DISPLAY = axis
               LATHE = 1
     BACK_TOOL_LATHE = 1
          CYCLE_TIME = 0.100
     POSITION_OFFSET = RELATIVE
   POSITION_FEEDBACK = ACTUAL
   MAX_FEED_OVERRIDE = 1.2
MAX_SPINDLE_OVERRIDE = 1.0
      PROGRAM_PREFIX = ../../nc_files/
       INTRO_GRAPHIC = linuxcnc.gif
          INTRO_TIME = 1
          INCREMENTS = 5mm 1mm .5mm .1mm .05mm .01mm .005mm

[FILTER]
PROGRAM_EXTENSION = .png,.gif,.jpg Grayscale Depth Image
PROGRAM_EXTENSION = .py Python Script
              png = image-to-gcode
              gif = image-to-gcode
              jpg = image-to-gcode
               py = python

[RS274NGC]
PARAMETER_FILE = ethercat-lathe.var

[EMCMOT]
      EMCMOT = motmod
COMM_TIMEOUT = 1.0
 BASE_PERIOD = 50000
SERVO_PERIOD = 1000000

[TASK]
      TASK = milltask
CYCLE_TIME = 0.001

[HAL]
          HALUI = halui
        HALFILE = lathe2-nopid.hal

[TRAJ]
         COORDINATES = XZ
        LINEAR_UNITS = mm
       ANGULAR_UNITS = degree
DEFAULT_LINEAR_VELOCITY = 100
MAX_LINEAR_VELOCITY = 12.0
DEFAULT_LINEAR_ACCELERATION = 20.0
MAX_LINEAR_ACCELERATION = 500.0

[EMCIO]
                      EMCIO = io
                 CYCLE_TIME = 0.100
                 TOOL_TABLE = lathe.tbl
       TOOL_CHANGE_POSITION = 2 0 1
TOOL_CHANGE_WITH_SPINDLE_ON = 1

[KINS]
        KINEMATICS = trivkins coordinates=xz
            JOINTS = 2

[AXIS_X]
         MIN_LIMIT = -1000.0
         MAX_LIMIT = 1000.0
      MAX_VELOCITY = 12
  MAX_ACCELERATION = 500.0

[JOINT_0]
              TYPE = LINEAR
            FERROR = 1.0
        MIN_FERROR = 0.9
      MAX_VELOCITY = 12.0
  MAX_ACCELERATION = 500.0
         MIN_LIMIT = -1000.0
         MAX_LIMIT = 1000.0
   HOME_SEARCH_VEL = 0.0
    HOME_LATCH_VEL = 0.0
     HOME_SEQUENCE = 0
    HOME_USE_INDEX = NO

[AXIS_Z]
       MIN_LIMIT = -1000.0
       MAX_LIMIT = 1000.0
    MAX_VELOCITY = 12
MAX_ACCELERATION = 500.0

[JOINT_1]
              TYPE = LINEAR
            FERROR = 1.0
        MIN_FERROR = 0.9
      MAX_VELOCITY = 12.0
  MAX_ACCELERATION = 500.0
         MIN_LIMIT = -1000.0
         MAX_LIMIT = 1000.0
   HOME_SEARCH_VEL = 0.0
    HOME_LATCH_VEL = 0.0
     HOME_SEQUENCE = 0
    HOME_USE_INDEX = NO

Notes

Roshi's Tutorial on how to setup the ethercat-conf.xml: https://docs.google.com/document/d/1GiB065ZIAaoMHPtVfTg9JV1Kn-19xGQl2X9DM9-THNM/edit#heading=h.37frqspzljja

thehade's post with a complete slave xml description

https://forum.linuxcnc.org/24-hal-components/22346-ethercat-hal-driver?start=920#170228

Nico2017 post on how to install Linuxcnc + Ethercat on a plain debian

https://forum.linuxcnc.org/27-driver-boards/35591-beckhoff-ethercat-64-with-bit-linuxcnc-how-to-install?start=30#135811

@Mehdidadash
Copy link

thank you for you very good and complete guide.
do you know how homing is done?
is it using drives self homing procidure ?

@Bouni
Copy link
Author

Bouni commented Dec 19, 2022

As far a I remember the homing is done by LinuxCNC, the drives himing mechanisms are not involved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment