1. LinuxCNC与PLC通信基础配置

LinuxCNC与PLC通信基础配置 学习卡片

任务目标

本案例完成LinuxCNC与PLC之间基于Modbus TCP的通信基础配置,实现双向数据交换:LinuxCNC读取PLC保持寄存器中的数值,并将自身状态写入PLC线圈。通过本案例,你将得到一个可独立运行的Modbus TCP通信配置,并验证数据读写是否成功。

环境与依赖

  • LinuxCNC 2.8+(已安装hal组件)
  • Python 3.6+,安装pymodbus库:pip install pymodbus
  • Modbus TCP从站设备或模拟器(如diagslave,或使用本案例附带的简易从站脚本)

实现方案

采用LinuxCNC的hal用户空间组件方式:编写一个Python HAL组件,通过Modbus TCP协议周期性地与PLC交换数据。该组件注册两个HAL引脚:plc-input(float,从PLC读取的值)和plc-output(bit,写入PLC的状态)。通信参数(IP、端口、寄存器地址、周期)通过命令行参数传入,便于与HAL配置文件集成。

关键完整代码


#!/usr/bin/env python3
# modbus_hal_io.py - LinuxCNC HAL component for Modbus TCP I/O
import hal, time, sys
from pymodbus.client import ModbusTcpClient

# --- HAL component setup ---
h = hal.component("modbus_io")
h.newpin("plc-input", hal.HAL_FLOAT, hal.HAL_IN)
h.newpin("plc-output", hal.HAL_BIT, hal.HAL_OUT)
h.ready()

# --- Parse arguments: ip port read_addr write_addr period_ms ---
if len(sys.argv) != 6:
    print("Usage: modbus_io <ip> <port> <read_addr> <write_addr> <period_ms>")
    sys.exit(1)

ip, port = sys.argv[1], int(sys.argv[2])
read_addr, write_addr = int(sys.argv[3]), int(sys.argv[4])
period = float(sys.argv[5]) / 1000.0

client = ModbusTcpClient(ip, port=port)
if not client.connect():
    print("ERROR: Cannot connect to Modbus device")
    sys.exit(1)

try:
    while True:
        # Read holding register (16-bit) from PLC
        rr = client.read_holding_registers(read_addr, 1)
        if rr.isError():
            print("Read error")
        else:
            h["plc-input"] = float(rr.registers[0])

        # Write current HAL pin state to PLC coil
        out_val = int(h["plc-output"])
        client.write_coil(write_addr, out_val)

        h.ready()  # update HAL
        time.sleep(period)
except KeyboardInterrupt:
    pass
finally:
    client.close()
    h.exit()

运行与集成

将上述代码保存为modbus_hal_io.py并赋予执行权限。在LinuxCNC的HAL配置文件中(如custom.hal)添加以下内容加载组件:


loadusr -W python /path/to/modbus_hal_io.py 192.168.1.100 502 0 0 100

参数含义:PLC IP为192.168.1.100,端口502,读取保持寄存器地址0,写入线圈地址0,通信周期100ms。启动LinuxCNC后,HAL引脚modbus_io.plc-input和modbus_io.plc-output即被创建。

验证方法

使用Modbus从站模拟器(如diagslave -m tcp -p 502)或真实PLC作为对端。验证步骤如下:

  1. 在从站端将保持寄存器0设为1234,在LinuxCNC的HAL终端执行getp modbus_io.plc-input,应输出1234.0。
  2. 在HAL终端执行setp modbus_io.plc-output 1,观察从站端线圈0状态变为ON。
  3. 若上述两项均符合预期,则通信配置成功。

预期输出:getp modbus_io.plc-input返回从站寄存器值(如1234.0);从站线圈状态随setp命令变化。此结果由代码逻辑直接推出,非实测数据。

常见问题

  • 连接失败:确认IP/端口正确,从站已启动,防火墙未阻断TCP 502端口。
  • 读取值不变:检查寄存器地址是否匹配从站映射表,部分PLC地址从1开始,需在代码中做偏移。
  • HAL引脚未出现:确认loadusr路径正确,且Python脚本无语法错误(可先手动运行脚本测试)。