Ubuntu24.04 基于 EtherCAT 的 SVD60N 主站

0、开发路线图

第一步 (基础):在 Ubuntu24.04 x64上交叉编译 SOEM,并编写一个简单的 CLI 程序,能够读到 SVD60N 的 Statusword (6041h)。

第二步 (逻辑):移植 SVD60NController 状态机,实现一键使能/断开。

第三步 (核心):建立 PDO 通讯线程,实现位置/速度反馈的稳定读取。

第四步 (UI):使用 Qt Creator 搭建布局,集成 QCustomPlot 进行绘图。

第五步 (高级):实现正弦波和三角波的生成算法,并进行 10ms 循环的稳定性测试。

1、第一步(基础)

在 Ubuntu24.04 x64上交叉编译 SOEM,并编写一个简单的 CLI 程序,能够读到 SVD60N 的 Statusword (6041h)。

1.1 下载 SOEM-v1.4.0 并编译

首先修改CMakeList.txt的第一行为:

bash 复制代码
cmake_minimum_required(VERSION 3.5)

然后执行编译步骤

bash 复制代码
# 进入 SOEM 源码目录
cd SOEM-1.4.0

# 创建并进入构建目录
mkdir build
cd build

# 配置 CMake (生成静态库)
cmake -DCMAKE_C_FLAGS="-Wno-stringop-truncation -Wno-error=stringop-truncation" -DCMAKE_BUILD_TYPE=Release ..

# 编译
make -j$(nproc)

1.2 编写测试程序(基于SOD)

新建一个文件夹,并写入main.cpp

cpp 复制代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <unistd.h>

extern "C" {
#include "ethercat.h"
}

int main(int argc, char *argv[]) {
    if (argc < 2) {
        std::printf("Usage: sudo ./svd60n_basic_test [ifname]\n");
        return 1;
    }

    char *ifname = argv[1];
    char IOmap[4096]; // 临时创建一个 IOmap

    if (ec_init(ifname)) {
        // 1. 扫描并初始化从站
        if (ec_config_init(FALSE) > 0) {
            std::printf("Found %d slaves.\n", ec_slavecount);

            // 2. 配置 IOMAP (这一步会设置 SyncManagers,对 SDO 通讯非常重要)
            // 即使我们暂时不用 PDO,这一步也能确保 Mailbox 初始化完成
            ec_config_map(&IOmap);

            // 3. 等待从站达到 PRE_OP 状态 (最长等待 2 秒)
            std::printf("Waiting for slaves to reach PRE_OP state...\n");
            ec_statecheck(0, EC_STATE_PRE_OP,  EC_TIMEOUTSTATE * 4);

            if (ec_slave[1].state == EC_STATE_PRE_OP) {
                std::printf("Slave 1 is in PRE_OP. Attempting SDO read...\n");

                uint16_t statusword = 0;
                int size = sizeof(statusword);

                // 4. 读取 SDO 0x6041
                int result = ec_SDOread(1, 0x6041, 0x00, FALSE, &size, &statusword, EC_TIMEOUTRXM);

                if (result > 0) {
                    std::printf("\n[SUCCESS] Slave 1 Statusword: 0x%04X\n", statusword);
                    // 打印二进制状态位以便分析
                    for(int i=15; i>=0; i--) std::printf("%d", (statusword >> i) & 1);
                    std::printf("\n");
                } else {
                    // 如果失败,打印错误码
                    std::printf("\n[ERROR] SDO read failed. Result: %d\n", result);
                    // 打印从站当前的 AL 状态码,看看为什么拒绝通讯
                    uint16_t al_status = 0;
                    int al_size = sizeof(al_status);
                    ec_SDOread(1, 0x120, 0x00, FALSE, &al_size, &al_status, EC_TIMEOUTRXM);
                    std::printf("AL Status Code: 0x%04X\n", ec_slave[1].ALstatuscode);
                }
            } else {
                std::printf("Slave did not reach PRE_OP. Current State: 0x%02X\n", ec_slave[1].state);
            }
        }
        ec_close();
    }
    return 0;
}

CMakeList如下:

cpp 复制代码
cmake_minimum_required(VERSION 3.10)
project(svd60n_basic_test)

set(CMAKE_CXX_STANDARD 17)

# --- 配置 SOEM 路径 (根据实际修改) ---
set(SOEM_DIR "/home/timgao/SOEM-1.4.0")

include_directories(${SOEM_DIR}/soem)
include_directories(${SOEM_DIR}/osal)
include_directories(${SOEM_DIR}/osal/linux)
include_directories(${SOEM_DIR}/oshw)
include_directories(${SOEM_DIR}/oshw/linux)

# 链接 SOEM 编译出的库文件 (注意路径可能因 build 目录结构不同而异)
# 通常在 SOEM/build/libsoem.a
link_directories(${SOEM_DIR}/build)

add_executable(svd60n_basic_test main.cpp)

# SOEM 在 Linux 上需要 pthread 和 rt 库
target_link_libraries(svd60n_basic_test soem pthread rt)

1.3 配置VMware网卡

在WMware虚拟网络编辑器,确保VMnet0处于桥接模式,并手动选择外部连接为对应的物理网口(而不是自动)。

1.4 编译并运行测试程序

bash 复制代码
mkdir build && cd build
cmake ..
make

sudo ./svd60n_basic_test ens34

应该看到输出:

bash 复制代码
Found 1 slaves.
Waiting for slaves to reach PRE_OP state...
Slave 1 is in PRE_OP. Attempting SDO read...

[SUCCESS] Slave 1 Statusword: 0x0250
0000001001010000

2、第二步(逻辑)

移植 SVD60NController 状态机,实现一键使能/断开。

逻辑拆分为三个核心组件:

  1. EtherCATMaster (底层驱动封装)

职责:负责 SOEM 的生命周期(网卡打开、从站扫描、PDO/SDO 原始读写)。

特性:作为一个单例或管理类,不包含具体的电机业务逻辑,只负责"发信"。

  1. SVD60NDevice (电机逻辑类)

职责:封装 DS402 状态机(State Machine)。

对应 Matlab 文件:SVD60NController.m + SVD60NDictionary.m。

核心方法:

requestState(TargetState):请求切换状态(如:请求"使能")。

processInternalState():由定时器或线程调用,检查当前 Statusword,发送对应的 Controlword。

  1. ControlThread (高优先级循环)

职责:驱动通讯循环。

特性:在 Linux 下使用 std::thread 或 QThread,以 10ms 的周期不断调用从站的数据交换。

相关推荐
weixin_462446231 小时前
ubuntu真机安装tljh jupyterhub支持跨域iframe
linux·运维·ubuntu
小码吃趴菜1 小时前
select/poll/epoll 核心区别
linux
Ghost Face...2 小时前
深入解析网卡驱动开发与移植
linux·驱动开发
a41324472 小时前
在CentOS系统上挂载硬盘到ESXi虚拟机
linux·运维·centos
MMME~2 小时前
Linux下的软件管理
linux·运维·服务器
迷途之人不知返2 小时前
Linux操作系统的基本指令
linux·服务器
松涛和鸣2 小时前
DAY49 DS18B20 Single-Wire Digital Temperature Acquisition
linux·服务器·网络·数据库·html
BIBI20492 小时前
通过 Studio 3T 远程连接 CentOS 7 上的 MongoDB
linux·mongodb·centos·nosql·配置·问题解决·环境搭建
小小ken2 小时前
ubuntu添加新网卡时,无法自动获取IP原因及解决办法
linux·网络·tcp/ip·ubuntu·dhcp