跳到主要内容

CiA 401 — 通用 I/O 模块

CiA 401 (IEC 61131-9) 是基于 CoE 的通用数字/模拟 I/O 设备协议。

CiA 401 运行在 CoE (SDO) 之上,仅当从站支持 CoE 时可用。

通过 slave.cia401 访问(首次取用时自动创建,任何从站都拿得到)。从站实际是否支持 CiA 401 取决于其对象字典:对象不存在时读接口返回 0 / False,写接口返回 False。

快速开始​

通过方法读写 IO 通道。逐通道 API 的 channel 从 0 开始;16/32 位批量 API 与极性/滤波 API 的 group 直接用 SDO 子索引(从 1 开始);错误模式/安全值 API 的 group 从 0 开始(内部换算子索引)。

类别方法类型读写说明
数字 IOread_di(n)bool只读读取数字输入通道 n
write_do(n, state)bool只写写入数字输出通道 n,返回 SDO 写入结果
模拟 IOread_ai(n)int只读读取模拟输入通道 n
write_ao(n, value)bool只写写入模拟输出通道 n,返回 SDO 写入结果

示例:

io = slave.cia401

# 数字 IO
sensor: bool = io.read_di(0)
io.write_do(0, True)
io.write_do(1, sensor)

# 模拟 IO
adc: int = io.read_ai(0)
io.write_ao(0, 16384)
实时控制

高频率 I/O 控制应使用 PDO 映射 而非 SDO。SDO 适合参数配置和诊断。

方法 API​

所有 write_* / set_* 方法返回 bool(SDO 写入是否成功,失败不抛异常)。

read_di()​

def read_di(self, channel: int) -> bool

读取数字输入。内部按 8 通道一组自动计算组号和位偏移。

参数:

  • channel (int) — 通道号(从 0 开始)

read_do()​

def read_do(self, channel: int) -> bool

读回上次写入的数字输出状态 (SDO 0x6200)。

参数:

  • channel (int) — 通道号 (从 0 开始)

write_do()​

def write_do(self, channel: int, state: bool) -> bool

设置数字输出,不影响同组其他通道(读改写)。读当前值失败时不写入,直接返回 False。

参数:

  • channel (int) — 通道号(从 0 开始)
  • state (bool) — 目标状态

返回值:

  • bool — SDO 写入是否成功

read_ai()​

def read_ai(self, channel: int) -> int

读取模拟输入值。自动适应 16 位和 32 位设备,返回有符号值。

参数:

  • channel (int) — 通道号(从 0 开始)

read_ao()​

def read_ao(self, channel: int) -> int

读回当前模拟输出设定值 (SDO 0x6411),有符号 16 位。

参数:

  • channel (int) — 通道号 (从 0 开始)

write_ao()​

def write_ao(self, channel: int, value: int) -> bool

写入模拟输出值(有符号 16 位)。

参数:

  • channel (int) — 通道号(从 0 开始)
  • value (int) — 有符号 16 位输出值

返回值:

  • bool — SDO 写入是否成功

write_ao_raw()​

def write_ao_raw(self, channel: int, value: int) -> bool

写入模拟输出原始值(无符号 16 位),适用于输出范围 0~65535 的设备。

参数:

  • channel (int) — 通道号(从 0 开始)
  • value (int) — 无符号 16 位输出值

返回值:

  • bool — SDO 写入是否成功

read_ai_raw()​

def read_ai_raw(self, channel: int) -> int

读取模拟输入原始值(无符号 16 位)。适用于 AI 数据范围为 0~65535 的设备。

参数:

  • channel (int) — 通道号(从 0 开始)

返回值:

  • int — 无符号 16 位模拟值

read_ai32()​

def read_ai32(self, channel: int) -> int

读取 32 位模拟输入值(无符号)。适用于高精度 AI 设备,数据范围 0~4294967295。

参数:

  • channel (int) — 通道号(从 0 开始)

返回值:

  • int — 无符号 32 位模拟值

示例:

io = slave.cia401

# 有符号读取 (默认, 可能高位值变负数)
ai_signed = io.read_ai(0)

# 无符号 16 位原始读取 (0~65535)
ai_u16 = io.read_ai_raw(0)

# 无符号 32 位读取 (高精度设备)
ai_u32 = io.read_ai32(0)

批量 IO 方法​

除逐通道操作外,还支持 16/32 位批量读写,一次操作多个通道。批量 API 的 group 直接作为 SDO 子索引,从 1 开始。

read_di16()​

def read_di16(self, group: int) -> int

读取 16 位数字输入 (16 个通道)。

参数:

  • group (int) — 组号(即 SDO 子索引,从 1 开始)

返回值:

  • int — 16 位输入值, 每位对应一个通道

read_di32()​

def read_di32(self, group: int) -> int

读取 32 位数字输入 (32 个通道)。

参数:

  • group (int) — 组号(即 SDO 子索引,从 1 开始)

返回值:

  • int — 32 位输入值, 每位对应一个通道

read_do16() / write_do16()​

def read_do16(self, group: int) -> int
def write_do16(self, group: int, value: int) -> bool

读取或写入 16 位数字输出 (16 个通道)。

参数:

  • group (int) — 组号(即 SDO 子索引,从 1 开始)
  • value (int) — 16 位输出值(仅 write_do16)

返回值:

  • read_do16 → int — 16 位输出值
  • write_do16 → bool — SDO 写入是否成功

示例:

io.write_do16(1, 0x00FF)          # 组 1: 低 8 位输出高, 高 8 位输出低
do16 = io.read_do16(1)

read_do32() / write_do32()​

def read_do32(self, group: int) -> int
def write_do32(self, group: int, value: int) -> bool

读取或写入 32 位数字输出 (32 个通道)。参数同 read_do16 / write_do16。

read_ao32() / write_ao32()​

def read_ao32(self, channel: int) -> int
def write_ao32(self, channel: int, value: int) -> bool

读取或写入 32 位模拟输出值(有符号)。适用于高精度模拟输出设备。

参数:

  • channel (int) — 通道号(从 0 开始)
  • value (int) — 有符号 32 位输出值(仅 write_ao32)

示例:

io.write_ao32(0, 65536)           # 写入 32 位高精度值
ao = io.read_ao32(0) # 读回当前值

按字节与整体访问​

read_di_byte() / write_do_byte()​

def read_di_byte(self, index: int) -> int
def write_do_byte(self, index: int, value: int) -> bool

按字节索引读数字输入 (0x6000) / 写数字输出 (0x6200)。

参数:

  • index (int) — 字节索引(即 SDO 子索引,从 1 开始)
  • value (int) — 8 位输出值(仅 write_do_byte)

read_all_di() / write_all_do()​

def read_all_di(self) -> Optional[bytes]
def write_all_do(self, data: bytes) -> bool

完整访问(complete access)一次读写全部数字输入/输出字节。

参数:

  • data (bytes) — 全部数字输出数据字节(仅 write_all_do)

返回值:

  • read_all_di → Optional[bytes] — 全部输入数据,失败返回 None
  • write_all_do → bool — SDO 写入是否成功

模拟输入中断与限值​

read_global_interrupt_enable() / write_global_interrupt_enable()​

def read_global_interrupt_enable(self) -> bool
def write_global_interrupt_enable(self, enable: bool) -> bool

读取或设置模拟输入全局中断使能 (0x6423)。

参数:

  • enable (bool) — True = 使能, False = 禁用(仅 write_global_interrupt_enable)

read_ai_upper_limit() / write_ai_upper_limit()​

def read_ai_upper_limit(self, channel: int) -> int
def write_ai_upper_limit(self, channel: int, value: int) -> bool

读取或写入模拟输入中断上限值 (0x6424)。当 AI 值超过上限时触发中断。写入为有符号 16 位,读取自适应 16/32 位。

参数:

  • channel (int) — 通道号(从 0 开始)
  • value (int) — 有符号 16 位上限值(仅 write_ai_upper_limit)

read_ai_lower_limit() / write_ai_lower_limit()​

def read_ai_lower_limit(self, channel: int) -> int
def write_ai_lower_limit(self, channel: int, value: int) -> bool

读取或写入模拟输入中断下限值 (0x6425)。当 AI 值低于下限时触发中断。写入为有符号 16 位,读取自适应 16/32 位。

参数:

  • channel (int) — 通道号(从 0 开始)
  • value (int) — 有符号 16 位下限值(仅 write_ai_lower_limit)

示例:

io = slave.cia401

# 启用全局中断
io.write_global_interrupt_enable(True)

# 设置通道 0 的上下限
io.write_ai_upper_limit(0, 30000)
io.write_ai_lower_limit(0, 1000)

# 读取当前限值配置
upper = io.read_ai_upper_limit(0)
lower = io.read_ai_lower_limit(0)
enabled = io.read_global_interrupt_enable()

数字输入配置​

set_di_polarity() / get_di_polarity()​

def set_di_polarity(self, group: int, polarity: int) -> bool
def get_di_polarity(self, group: int) -> int

设置或读取数字输入极性 (0x6002)。可按位反转输入信号逻辑。

参数:

  • group (int) — 组号(即 SDO 子索引,从 1 开始)
  • polarity (int) — 8 位极性掩码,每位对应一个通道,1=反转(仅 set_di_polarity)

set_di_filter() / get_di_filter()​

def set_di_filter(self, group: int, filter_enable: int) -> bool
def get_di_filter(self, group: int) -> int

设置或读取数字输入滤波使能 (0x6003)。用于消除输入信号抖动。

参数:

  • group (int) — 组号(即 SDO 子索引,从 1 开始)
  • filter_enable (int) — 8 位滤波使能掩码(仅 set_di_filter)

虚拟 DI​

write_virtual_di()​

def write_virtual_di(self, di_index: int, state: bool) -> bool

写入虚拟 DI 命令 (0x2120:0x)。0x2120 是 PdoMapped 对象,SDO 写会被 abort 0x06020000,方法内部自动回退 PDO 写入并记日志(首次 abort 后缓存判定,后续直接走 PDO)。

参数:

  • di_index (int) — 虚拟 DI 子索引(1-4 → 0x2120:01-04)
  • state (bool) — 目标状态(True = 1)

返回值:

  • bool — True = 写入成功(SDO 或 PDO);False = SDO 与 PDO 均失败(当前无 0x2120 的 PDO 映射)

错误状态读取​

get_do_error_mode() / get_do_error_value()​

def get_do_error_mode(self, group: int) -> int
def get_do_error_value(self, group: int) -> int

读取数字输出错误模式和错误安全值的当前配置。group 从 0 开始(每 8 个通道一组)。get_do_error_mode() 返回整数 (0=HOLD / 1=SAFE_VALUE)。

错误处理​

set_do_error_mode()​

def set_do_error_mode(self, group: int, mode: int) -> bool

设置数字输出错误模式。当 EtherCAT 通信丢失时,决定输出如何响应。

参数:

  • group (int) — 组号(从 0 开始,每 8 个通道为一组:组 0 = 通道 0-7,组 1 = 通道 8-15)
  • mode (int) — 错误模式 (传 CiA401ErrorMode.HOLD / CiA401ErrorMode.SAFE_VALUE, 即整数 0 / 1)

CiA401ErrorMode 常量类:

CiA401ErrorMode 是普通常量类 (非 IntEnum), 成员即整数常量。

from darra_ethercat import CiA401ErrorMode

class CiA401ErrorMode:
HOLD = 0 # 保持当前输出值
SAFE_VALUE = 1 # 切换到预设的安全值
错误模式方法的参数/返回为 int

set_do_error_mode() / set_ao_error_mode() 的 mode 参数与 get_do_error_mode() / get_ao_error_mode() 的返回值类型均为 int。传入 CiA401ErrorMode.SAFE_VALUE 即整数 1, 读回的也是整数 0 / 1, 与该常量类的成员值直接比较即可。

set_do_error_value()​

def set_do_error_value(self, group: int, value: int) -> bool

设置数字输出通信丢失时的安全值。仅在 SAFE_VALUE 模式下生效。

参数:

  • group (int) — 组号(从 0 开始)
  • value (int) — 安全输出值(8 位,每位对应一个通道)

set_ao_error_mode()​

def set_ao_error_mode(self, channel: int, mode: int) -> bool

设置模拟输出错误模式。

参数:

  • channel (int) — 通道号(从 0 开始)
  • mode (int) — 错误模式 (传 CiA401ErrorMode.HOLD / CiA401ErrorMode.SAFE_VALUE, 即整数 0 / 1)

set_ao_error_value()​

def set_ao_error_value(self, channel: int, value: int) -> bool

设置模拟输出通信丢失时的安全值。仅在 SAFE_VALUE 模式下生效。

参数:

  • channel (int) — 通道号(从 0 开始)
  • value (int) — 有符号 16 位安全输出值

get_ao_error_mode() / get_ao_error_value()​

def get_ao_error_mode(self, channel: int) -> int
def get_ao_error_value(self, channel: int) -> int

读取模拟输出错误模式和错误安全值的当前配置。get_ao_error_mode() 返回整数 (0=HOLD / 1=SAFE_VALUE),get_ao_error_value() 返回有符号 16 位安全值。

示例:

io.set_do_error_mode(0, CiA401ErrorMode.SAFE_VALUE)
io.set_do_error_value(0, 0x00)

io.set_ao_error_mode(0, CiA401ErrorMode.SAFE_VALUE)
io.set_ao_error_value(0, 0)

标准对象索引常量​

下列常量是 CiA401 类的类属性 (经 CiA401.OD_DI 等访问), 可搭配 slave.coe.sdo_read / sdo_write 直接访问对象字典。表中「读写」指该对象经 SDO 访问的能力:

类别常量值读写说明
数字输入OD_DI0x6000只读数字输入
虚拟 DIOD_VIRTUAL_DI0x2120只写虚拟 DI 命令 (PdoMapped; SDO 写 abort 0x06020000, 须走 PDO)
数字输入OD_DI_16BIT0x6001只读16 位数字输入
数字输入OD_DI_POLARITY0x6002读写数字输入极性
数字输入OD_DI_FILTER0x6003读写数字输入滤波使能
数字输入OD_DI_32BIT0x6020只读32 位数字输入
数字输出OD_DO0x6200读写数字输出
数字输出OD_DO_16BIT0x6201读写16 位数字输出
数字输出OD_DO_ERROR_MODE0x6206读写数字输出错误模式
数字输出OD_DO_ERROR_VALUE0x6207读写数字输出错误值
数字输出OD_DO_32BIT0x6220读写32 位数字输出
模拟输入OD_AI0x6400只读模拟输入
模拟输入OD_AI_SI_UNIT0x6420只读模拟输入量程
模拟输入OD_AI_GLOBAL_INTERRUPT0x6423读写模拟输入全局中断使能
模拟输入OD_AI_UPPER_LIMIT0x6424读写模拟输入中断上限
模拟输入OD_AI_LOWER_LIMIT0x6425读写模拟输入中断下限
模拟输出OD_AO0x6411读写模拟输出
模拟输出OD_AO_32BIT0x6412读写32 位模拟输出
模拟输出OD_AO_SI_UNIT0x6430只读模拟输出量程
模拟输出OD_AO_ERROR_MODE0x6443读写模拟输出错误模式
模拟输出OD_AO_ERROR_VALUE0x6444读写模拟输出错误值

完整示例​

from darra_ethercat import CiA401ErrorMode

io = slave.cia401

# 数字 IO
sensor = io.read_di(0)
limit = io.read_di(5)

io.write_do(0, True)
io.write_do(1, sensor)

# 批量数字 IO
di16 = io.read_di16(1) # 读取组 1 (16 个通道)
io.write_do16(1, 0x00FF) # 组 1: 低 8 位输出高

# 模拟 IO
adc = io.read_ai(0)
temp = adc * 0.1
io.write_ao(0, 0 if temp > 50 else 16384)

# 无符号读取
ai_u16 = io.read_ai_raw(0)
ai_u32 = io.read_ai32(0)

# 模拟输入限值配置
io.write_global_interrupt_enable(True)
io.write_ai_upper_limit(0, 30000)
io.write_ai_lower_limit(0, 1000)

# 安全配置
io.set_do_error_mode(0, CiA401ErrorMode.SAFE_VALUE)
io.set_do_error_value(0, 0x00)

io.set_ao_error_mode(0, CiA401ErrorMode.SAFE_VALUE)
io.set_ao_error_value(0, 0)