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.
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