Getting LinuxCNC with ethercat running on a Beckhoff CX2040

2023-04-17 Β· 1687 words Β· 8 minute read

I got an old Beckhoff CX2040 that was no longer in use into my hands and decided to try if I can get LinuxCNC with EtherCat support running on it.

My setup consists of the CX2040 itself and a CX2100-0004 45W power supply that also features the E-Bus connector for additional I/O terminals. I had an EL3255 5 port pontentiometer terminal and a EK1110 bus connector laying around and used those for a first test.

CX2040 + CX2100-0004 + EL3255 + EK1110

The feature I’m most interested in is the so called CCAT FPPGA inside the CX2040 that allows to interface with the vast variety of Beckhoff I/O terminals and other EtherCat devices without the need of an dedicated Ethernet port and a bus coupler.

As I wasn’t able to find any guide on how to get this up and running I decided to write it down into this blog post so that others can benefit from it and I have a place that helps me compensate for my memory gaps in the future 😏

LinuxCNC ISO πŸ”—

I downloaded the latest LinuxCNC ISO from their website which was LinuxCNC 2.8.4 Debian 10 Buster PREEMPT-RT ISO at the time of writing this. Using Balea Etcher I wrote the ISO onto a USB drive and plugged it into the CX2040. After powering the device, hitting F7 repeatedly gave me the boot selection menu. I chose graphical install and installed the system on the CFast card, nothing special here.

After completing the installation I upgraded the system as a first step.

sudo apt update
sudo apt upgrade -y

EtherCAT Master πŸ”—

I use the setup helper for the EtherLab IgH EtherCAT Master by ESS because it worked for me in my last EtherCAT experiments I did on a RaspberryPi 4.

First of all I installed several build requirements, the list is a extended version of what is listed in the repo README.

sudo apt install -y linux-headers-$(uname -r) build-essential libtool automake tree dkms git mercurial vim

After that I looked through the README and luckily it has a section about CCAT πŸ₯³

The first part of that secion points to another repo by jeonghanlee that is also a helper script to build and install Beckhoff’s CCAT driver .

CCAT driver πŸ”—

I followed the instructions whoch worked without any problems

git clone https://github.com/jeonghanlee/CCAT-env.git
cd CCAT-env

make init
make dkms_add
make dkms_build
make dkms_install

make setup

After that I did a lsmod | grep ccat which gave me a list off CCAT modules:

ccat_update            16384  0
ccat_systemtime        16384  0
ccat_sram              16384  0
ccat_gpio              16384  0
ccat_netdev            20480  0
ccat                   16384  2 ccat_sram,ccat_update
mfd_core               16384  2 ccat,lpc_ich

Nice 😎

But after a reboot the modules were not loaded anymore πŸ™

So I decided to do the make setup step again but that gave me an error that some linux kernel headers are missing. I installed them with sudo apt install linux-headers-4.19.0-23-rt-amd64 an tried again.

cd CCAT-env
make setup

That gave me

ccat
ccat_netdev
ccat_gpio
ccat_sram
ccat_systemtime
ccat_update
rmmod ccat_update
rmmod ccat_systemtime
rmmod ccat_sram
rmmod ccat
rmmod ccat_gpio
rmmod ccat_netdev
insmod /lib/modules/4.19.0-23-rt-amd64/updates/dkms/ccat.ko
insmod /lib/modules/4.19.0-23-rt-amd64/updates/dkms/ccat_netdev.ko
insmod /lib/modules/4.19.0-23-rt-amd64/updates/dkms/ccat_gpio.ko
insmod /lib/modules/4.19.0-23-rt-amd64/updates/dkms/ccat_sram.ko
insmod /lib/modules/4.19.0-23-rt-amd64/updates/dkms/ccat_systemtime.ko
insmod /lib/modules/4.19.0-23-rt-amd64/updates/dkms/ccat_update.ko


It is OK to see "RULES_DKMS: recipe for target 'setup' failed"
---------------------------------------------------------------------
crw------- 1 root root 244, 0 Apr 19 07:08 /dev/ccat_sram0
crw------- 1 root root 243, 0 Apr 19 07:08 /dev/ccat_update0
---------------------------------------------------------------------

After another reboot I chekd the modules with lsmod | grep ccat again and this time the loaded automatically.

EtherCAT Master part 2 πŸ”—

So the CCAT driver was sucessfully installed, time to go on with the instructions in the ESS repo.

cd ~
git clone https://github.com/icshwi/etherlabmaster.git
cd etherlabmaster

Now we need to check which intefrace is our CCAT interface. For that we simple do a ip a

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: enp2s0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN group default qlen 1000
    link/ether 00:01:05:25:a9:c2 brd ff:ff:ff:ff:ff:ff
3: enp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:01:05:25:a9:c3 brd ff:ff:ff:ff:ff:ff
    inet 192.168.99.117/24 brd 192.168.3.255 scope global dynamic noprefixroute enp3s0
       valid_lft 2684sec preferred_lft 2684sec
    inet6 fe80::201:5ff:fe25:a9d3/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
4: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:01:05:1e:6b:8e brd ff:ff:ff:ff:ff:ff

We have two Ethernet port on the CX2040 labeled X000 and X001. My network cable was plugged into X000 and enp3s0 is up and got an IP address from my router. So I guessed that enp2S0 is the other port labeled X001. That leaves us with the interface eth0 for the CCAT.

As shown in the instructions I set eth0 as my ETHERCAT_MASTER0

echo "ETHERCAT_MASTER0=eth0" > ethercatmaster.local

And from there I just followed the instructions

make init
echo "WITH_DEV_GENERIC = NO"  > configure/CONFIG_OPTIONS.local
echo "WITH_DEV_CCAT = YES" >> configure/CONFIG_OPTIONS.local
make ccat_patch
make build
make install
make dkms_add
make dkms_build
make dkms_install
make setup

After that I rebooted the CX2040.

I quickly checked if the ethercat service is up and running with systemctl status ethercat.service

● ethercat.service - EtherCAT Master Kernel Modules
   Loaded: loaded (/etc/systemd/system/ethercat.service; enabled; vendor preset: enabled)
   Active: active (exited) since Thu 2023-04-20 09:25:46 EDT; 32s ago
  Process: 803 ExecStart=/opt/etherlab/sbin/ethercatctl start (code=exited, status=0/SUCCESS)
 Main PID: 803 (code=exited, status=0/SUCCESS)

Indeed, it was πŸ₯³

I went on and checked the status of the EtherCAT Master with ethercat master

Master0
  Phase: Idle
  Active: no
  Slaves: 2
  Ethernet devices:
    Main: 00:01:05:1e:6b:8e (attached)
      Link: UP
      Tx frames:   74266
      Tx bytes:    4572920
      Rx frames:   74266
      Rx bytes:    5761176
      Tx errors:   0
      Tx frame rate [1/s]:    125    125    187
      Tx rate [KByte/s]:      7.3    7.3   11.2
      Rx frame rate [1/s]:    125    125    187
      Rx rate [KByte/s]:      9.3    9.3   14.1
    Common:
      Tx frames:   74266
      Tx bytes:    4572920
      Rx frames:   74266
      Rx bytes:    5761176
      Lost frames: 0
      Tx frame rate [1/s]:    125    125    187
      Tx rate [KByte/s]:      7.3    7.3   11.2
      Rx frame rate [1/s]:    125    125    187
      Rx rate [KByte/s]:      9.3    9.3   14.1
      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

It report 2 slaves found because I already connected a EL3255 , which is a 5 port analog terminal and an EK1110 which is an EtherCAT extension that eventually allows me to connect EtherCAT servo drives to the bus.

I wanted to see the the details so that I can verify that the devices are correctly recognized by entering ethercat slaves -v

=== Master 0, Slave 0 ===
Device: Main
State: PREOP
Flag: +
Identity:
  Vendor Id:       0x00000002
  Product code:    0x0cb73052
  Revision number: 0x00170000
  Serial number:   0x00000000
DL information:
  FMMU bit operation: no
  Distributed clocks: yes, 64 bit
  DC system time transmission delay: 0 ns
Port  Type  Link  Loop    Signal  NextSlave  RxTime [ns]  Diff [ns]   NextDc [ns]
   0  EBUS  up    open    yes             -   1347169212           0           0
   1  EBUS  up    open    yes             1   1347169522         310         155
   2  N/A   down  closed  no              -            -           -           -
   3  N/C   down  closed  no              -            -           -           -
Mailboxes:
  Bootstrap RX: 0x1000/244, TX: 0x10f4/244
  Standard  RX: 0x1000/128, TX: 0x1080/128
  Supported protocols: CoE, FoE
General:
  Group: AnaIn
  Image name:
  Order number: EL3255
  Device name: EL3255 5K. Potentiometerauswertung mit Sensorversorgung
  CoE details:
    Enable SDO: yes
    Enable SDO Info: yes
    Enable PDO Assign: yes
    Enable PDO Configuration: no
    Enable Upload at startup: no
    Enable SDO complete access: no
  Flags:
    Enable SafeOp: no
    Enable notLRW: no
  Current consumption: 80 mA
=== Master 0, Slave 1 ===
Device: Main
State: PREOP
Flag: +
Identity:
  Vendor Id:       0x00000002
  Product code:    0x04562c52
  Revision number: 0x00110000
  Serial number:   0x00000000
DL information:
  FMMU bit operation: no
  Distributed clocks: yes, delay measurement only
  DC system time transmission delay: 155 ns
Port  Type  Link  Loop    Signal  NextSlave  RxTime [ns]  Diff [ns]   NextDc [ns]
   0  EBUS  up    open    yes             0   1724581792           0         155
   1  MII   down  closed  no              -            -           -           -
   2  N/A   down  closed  no              -            -           -           -
   3  N/C   down  closed  no              -            -           -           -
General:
  Group: System
  Image name:
  Order number: EK1110
  Device name: EK1110 EtherCAT-VerlοΏ½ngerung
  Flags:
    Enable SafeOp: no
    Enable notLRW: no
  Current consumption: 130 mA

So the EtherCAT bus seems to work as expected.

No we want to integrate all of that into LinuxCNC.

LinuxCNC with EtherCAT πŸ”—

cd ~
git clone https://github.com/linuxcnc-ethercat/linuxcnc-ethercat.git
cd linuxcnc-ethercat
make configure

building with make lead to an error that ecrt.h could not be found, so I symlinked that

sudo ln -s /opt/etherlab/include/ecrt.h /usr/include/linuxcnc/ecrt.h

After that the linker wasn’t able to find libethercat.so so again, I symlinked that as well

sudo ln -s /opt/etherlab/lib/libethercat.so /usr/lib/libethercat.so

With these little hacks in place I was able to build and install

make
make install

CIA-402 HAL compnent πŸ”—

In order to use servodrives I added the CIA-402 HAL compnent by dbraun

cd ~
git clone https://github.com/dbraun1981/hal-cia402
cd hal-cia402
sudo halcompile --install cia402.comp

LinuxCNC EtherCAT setup πŸ”—

As a quick test I started LinuxCNC, selected sim β†’ axis β†’ axis and let it save the files.

Then I created a ethercat.hal file in ~/linuxcnc/configs/sim.axis/

loadusr -W lcec_conf ethercat-conf.xml
loadrt lcec
addf lcec.read-all servo-thread
addf lcec.write-all servo-thread

After that I created a ethercat-conf.xml in the same directory

<masters>
<master idx="0" appTimePeriod="1000000" refClockSyncCycles="5">
      <slave idx="0" type="EL3255" />
</master>
</masters>

As a last step I edited the ~/linuxcnc/configs/sim.axis/axis.ini file

...
# Hardware Abstraction Layer section --------------------------------------------------
[HAL]

# The run script first uses halcmd to execute any HALFILE
# files, and then to execute any individual HALCMD commands.
#

# list of hal config files to run through halcmd
# files are executed in the order in which they appear
HALFILE = core_sim.hal
HALFILE = sim_spindle_encoder.hal
HALFILE = axis_manualtoolchange.hal
HALFILE = simulated_home.hal
HALFILE = check_xyz_constraints.hal
HALFILE = ethercat.hal
...

in there I just added the line HALFILE = ethercat.hal

After starting LinuxCNC using the desktop icon I went to Machine β†’ HAL Configuration where I went to Pins β†’ lcec β†’ 0 β†’ 0

Here I was presented with a list of pot-... pins that belonged to the EL3255 I/O terminal πŸ₯³

Everything seems to work so far. I’ll continue this in another blog post soon