Amazing to find someone else who knows what ethercat is, there are dozens of us!!
Written in Zig
GatorCAT is written in zig, SOEM in C, and IGH in C
SOEM can be difficult to use because the C code is barely readable (single letter variable names, horrible acronyms, no references to documentation, and no real documentation). While my documentation is certainly incomplete, I tried to at least cite the relevant IEC standard for the data structures and behavior implemented (the IEC standard, as far as I can tell, is a duplicate of the ETG standard and does not require ETG membership to access). I also believe that by being written in zig, it is more readable.
Another reason for zig is the build system and cross compilation as a first class use case. When working with IGH and SOEM, you need to learn the C build system, which in my experience was extremely difficult, and I didn’t even get to cross compilation. Learning the incantations required to get CMAKE to depend on Igh or SOEM was me constantly googling and spamming ChatGPT with prompts.
Cross compilation is also trivial in zig. In industrial controls, we are often using ARM based processors or other low-cost hardware to execute fairly simple control tasks (low rate data collection and sequencing). At my work, we often use raspberry pi compute module based industrial computers (Onlogic Factor 201), so this requires cross compilation to integrate well with my x86_64 laptop and CI build pipelines.
Declarative Configuration
GatorCAT attemps to provide a declarative API for the configuration of EtherCAT devices, similar to the user experience when using PLC runtimes like CODESYS and TwinCAT. The vast majority of use cases have known contents of the ethercat network at compile time, and want the network contents validated at runtime.
SOEM provides no help in this regard and expects the user to write procedural code to validate the contents of the network and configure the subdevices. This requires extensive knowledge about ethercat, when the PLC runtimes and IDEs(that are everyone’s first intro to ethercat) provide point and click, drop downs, and automatic scanning interfaces that make it easy.
I didn’t make it very far with Igh(see difficult installation (kernel modules) and CMAKE build system). It seems to have a reasonably declarative subdevice configuration API.
License
GatorCAT is more permissibly licenced (MIT) when compared to SOEM (GPL with exceptions) and IGH (LGPL).
User Space
GatorCAT is currently implemented in user space. SOEM is userspace and IGH is kernel module.
I chose to implement userspace first because it is easier, and I believe there is currently limited support for compiling kernel modules in zig. Raw sockets can get you very far in my experience. I have applications at work using commercial ethercat implementations (Acontis) using raw sockets holding 2000 us cycle times with 150 us of jitter. This on a typical Debian system with PREEMPT_RT patches, real time priority process, CPU frequency scaling disabled. Didn’t even need to implement ISOL_CPUS or IPC_LOCK (yet).
I think the future is user space for ethercat. Most applications do not require 100 us cycle times. Ethercat was designed to run on standard operating systems, it is why distributed clocks exists, so that the control cycle can be independent of the main device frame jitter.
I have also heard that advances in the Linux networking space (XDP) have enabled 100 us cycle times on standard PREEMPT_RT linux in userspace already. See this tweet by the creator of the rust project ethercrab.
Feature Completeness
Igh is the most feature complete, followed by SOEM and GatorCAT.
GatorCAT notably is missing support for distributed clocks and Ethernet over EtherCAT(EoE). Though the support for EoE in SOEM im not sure is simple to use.
What happened when you tried SOEM?
You are correct that I attempted to use SOEM, and attempted to wrap it in python. But what I came to realize was SOEM was lacking understandable organization and control flow. It was difficult to understand how to react to failures, and the code is riddled with hidden retry logic configurable by C DEFINEs (see every check of the working counter or timeout in the library).
I also found myself battling the build system more than my intended application.
SOEM also lacks any data hiding and least-priviledge principles, making it difficult to understand. The library is essentially a giant book of functions that all take references to a global mega-struct of mutable data. Attempting to assess the thread safety of certain operations is extremely difficult.
SOEM is designed to be copy-pasted into your codebase and modified to fit your use case. It is not designed to use as a library (hence the DEFINEs everywhere). There is very little support for runtime constructed or dynamically configured ethercat networks.
Primary Push
The thing that primarily pushed me to start this project was a desire to replace my dependence on commercial ethercat imementations at work (CODESYS, Acontis). CODESYS being horrible because of its horrible programming language (structured text) and lack of plain text project storage format, and Acontis because of the general annoyance of working with black box Hungarian notation extremely expensive pre-compiled licensed binaries. I will say though that Acontis’ configuration tools have allowed me to debug and configure very large and complex ethercat networks (200+ subdevices) and I would generally recommend it for commercial applications. If you need low risk to your delivery schedules and compatibility with virtually all ethercat devices and features and don’t mind the cost, use Acontis. Just be prepared for the most poorly written python library you will ever see in your life (if you don’t just use the C library).