00 IO-Link nedir
IO-Link (IEC 61131-9) — sensör ve aktüatörlere point-to-point dijital haberleşme kanalı açan, standart 3-telli kablo ile çalışan akıllı sensör arayüz protokolü.
Temel kavram
Geleneksel dijital sensörler yalnızca bir bit bilgi taşır: açık veya kapalı. Analog sensörler 4-20 mA veya 0-10 V çıkışıyla bir ölçüm değeri iletir ancak sensör parametreleri, durum bilgisi ve tanılama verisi taşıyamaz. IO-Link bu boşluğu doldurur: aynı 3-telli M12 kablo üzerinden hem process data hem de parametre yönetimi, hem de tanılama gerçekleştirilir.
IO-Link Master (PLC/controller'da)
┌─────────────────────────┐
│ Port 1 ────── M12 ─────┤──── Akıllı Basınç Sensörü
│ Port 2 ────── M12 ─────┤──── RFID Okuyucu
│ Port 3 ────── M12 ─────┤──── Akıllı Konum Sensörü
│ Port 4 ────── M12 ─────┤──── IO-Link Hub (8 kanal)
└─────────────────────────┘
PLC arayüzü (PROFINET/EtherNet IP)
SIO ile geriye uyumluluk
IO-Link cihazları SIO (Standard I/O) modunda standart dijital sensör gibi davranır. IO-Link uyumlu master bağlandığında cihaz otomatik olarak COM moduna (IO-Link iletişim) geçer. Bu sayede aynı cihaz hem yeni hem de eski sistemlerle çalışır.
IO-Link vs diğer protokoller
| Özellik | IO-Link | PROFIBUS PA | 4-20 mA |
|---|---|---|---|
| Tel sayısı | 3 (24V, GND, C/Q) | 2 (bus powered) | 2 |
| Max hız | 230.4 kbps | 31.25 kbps | N/A |
| Parametrelendirme | Evet (ISDU) | Evet | Hayır |
| Tanılama | Zengin event mekanizması | Diagnostics bytes | Yok |
| Topoloji | Point-to-point | Bus | Point-to-point |
| Standart kablo | M12, ekransız | Özel kablo | 2-telli |
01 Fiziksel katman
IO-Link 24 VDC sistemlerde çalışır. 3-telli M12 kablo ile güç ve iletişim aynı anda sağlanır. Ekransız kablo kullanılabilmesi büyük maliyet avantajıdır.
Pin atamaları (M12, A-kodlu)
| Pin | Sinyal | Açıklama |
|---|---|---|
| 1 | L+ (24 VDC) | Cihaz güç kaynağı (+24V, max 200 mA) |
| 3 | L− (GND) | Güç ve sinyal referansı |
| 4 | C/Q | İletişim/Veri hattı (SIO modunda standart I/O) |
| 2 | N/C veya ek I/O | Bazı cihazlarda ikinci I/O kanalı |
| 5 | N/C | Genellikle kullanılmaz |
SIO ve COM modu
Kablo ve mesafe
| Parametre | Değer |
|---|---|
| Max kablo uzunluğu | 20 m (master port'tan cihaza) |
| Kablo tipi | Ekransız, 3 veya 4 iletken |
| Kablo kesiti | Min 0.34 mm² (22 AWG) |
| Konnektör | M12, A-kodlu, IP67/IP68 |
IO-Link kablo uzunluğu 20 m ile sınırlıdır çünkü protokol sinyali alındı onayı (ACK) zamanlama gereksinimlerine dayanır. Uzun kablo propagasyon gecikmesi protokol zamanlamasını bozar. Daha uzun mesafe için IO-Link master'ı field cihazına yakın konumlandır.
02 İletişim modeli
IO-Link point-to-point bağlantı modeli: her port tek bir cihaz ile haberleşir. Açılış prosedürü SIO'dan COM moduna geçişi otomatikleştirir.
Açılış prosedürü (Wake-up)
Master Device
────── ──────
1. Port açılır (SIO modu) SIO dijital çıkış aktif
2. Wake-up pulse gönder ──────►
3. ◄── COM1 müzakeresi
4. COM3 teklifini gönder ─────►
5. ◄── COM3 kabul (veya düşür)
6. Master Data Exchange ──────►
7. ◄── Process Data yanıtı
[periyodik siklik veri değişimi devam eder]
Kapasite değişimi (Capability Exchange)
Açılış sırasında master ve cihaz birbirinin yeteneklerini sorgular. Cihaz IODD'sından (IO Device Description) tanınan parametreler, process data boyutu ve desteklenen servisler aktarılır. Bu aşamada master cihazın Vendor ID ve Device ID bilgilerini de öğrenir.
Index SubIndex Parametre Açıklama
──────────────────────────────────────────────────────────
0x0000 0 DirectParamPage1 Temel cihaz bilgisi sayfası
0x0000 1 VendorID Üretici kimliği (16-bit)
0x0000 2 DeviceID Cihaz kimliği (24-bit)
0x000A 0 FirmwareRevision Yazılım versiyonu (string)
0x000B 0 ApplicationTag Kullanıcı tanımlı etiket
0x000C 0 FunctionTag Fonksiyon etiketi
0x000D 0 LocationTag Konum etiketi
SDCI (Single Drop Communication Interface)
IO-Link standardı SDCI olarak da bilinir. "Single Drop" tek bir cihazın master portuna bağlandığını belirtir. Her master portu bağımsız çalışır — 8 portlu master, 8 farklı cihaza eşzamanlı haberleşir.
03 Protokol detayları
M-sequence mesaj türleri, ISDU asiklik servisler, Event mekanizması ve OSSD güvenlik çıkışları — IO-Link protokolünün iç işleyişi.
M-sequence türleri
IO-Link iletişimi M-sequence (message sequence) adı verilen yarı duplex mesaj değişimi ile gerçekleşir. Master her zaman iletişimi başlatır:
| M-sequence tipi | Yapı | Kullanım |
|---|---|---|
| TYPE_0 | 2 byte master + 1 byte device | Küçük process data (<2 byte) |
| TYPE_1 | 2 byte master + N byte device | Orta process data |
| TYPE_2 | M byte master + N byte device | Büyük process data + ISDU |
ISDU — Index Service Data Unit
Asiklik parametre okuma/yazma servisi. Her parametre bir Index ve SubIndex ile adreslenir. Siklik process data trafiğini etkilemeden arka planda çalışır.
/* ISDU İstek servisleri: */
/* 0x60 READ — belirtilen index/subindex'ten okuma */
/* 0x68 WRITE — belirtilen index/subindex'e yazma */
/* Örnek ISDU frame (asiklik okuma): */
/* Master → Device: */
/* [MC=0x60][Index_high][Index_low][SubIndex] */
/* Device → Master: */
/* [RWA=0x40][Data bytes...][Checksum] */
/* ISDU Hata kodları: */
/* 0x80 Application error */
/* 0x20 Index not available */
/* 0x10 Subindex not available */
/* 0x30 Access denied (read-only index'e write) */
Event mekanizması
IO-Link cihazları asenkron olarak olay bildirimi yapabilir. Üç event kategorisi vardır:
OSSD (Output Signal Switching Device)
IO-Link güvenlik sensörlerinde (ışık perdesi, lazer tarayıcı) kullanılan güvenlik çıkışı standardı. SIL 2/3 ve PLd/e gereksinimler için iki kanal çapraz kontrol ile doğrulama yapılır.
04 IODD — IO Device Description
IODD (IO Device Description) — her IO-Link cihazının parametrelerini, process data yapısını ve kullanıcı arayüzü bilgilerini tanımlayan XML tabanlı cihaz tanımlama dosyası.
IODD yapısı
<?xml version="1.0" encoding="utf-8"?>
<IODevice xmlns="http://www.io-link.com/IODD/2010/10"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ProfileHeader>
<ProfileIdentification>IO Device Profile</ProfileIdentification>
<ProfileRevision>1.1</ProfileRevision>
</ProfileHeader>
<DeviceIdentity>
<VendorId>57</VendorId> <!-- SICK AG -->
<DeviceId>139986</DeviceId>
<VendorName>SICK AG</VendorName>
<VendorText xml:lang="EN">www.sick.com</VendorText>
<DeviceName xml:lang="EN">PAC50</DeviceName>
</DeviceIdentity>
<DeviceFunction>
<ProcessDataCollection>
<!-- Giriş process data: 3 byte -->
<ProcessData id="pd_in">
<ProcessDataIn bitLength="24">
<Datatype xsi:type="RecordT">
<RecordItem subindex="1" bitOffset="0" bitLength="16">
<Name xml:lang="EN">PressureValue</Name>
</RecordItem>
<RecordItem subindex="2" bitOffset="16" bitLength="8">
<Name xml:lang="EN">StatusByte</Name>
</RecordItem>
</Datatype>
</ProcessDataIn>
</ProcessData>
</ProcessDataCollection>
<Parameters>
<Parameter index="0x0060" subIndex="0" accessRights="rw">
<Name xml:lang="EN">UpperSwitchPoint</Name>
<Datatype xsi:type="UIntegerT" bitLength="16"/>
</Parameter>
</Parameters>
</DeviceFunction>
</IODevice>
IODD Finder ve IODD Checker
import xml.etree.ElementTree as ET
def parse_iodd_parameters(iodd_file: str) -> list:
"""IODD dosyasından parametre listesi çıkar."""
ns = {'iodd': 'http://www.io-link.com/IODD/2010/10'}
tree = ET.parse(iodd_file)
root = tree.getroot()
params = []
for param in root.findall('.//iodd:Parameter', ns):
idx = param.get('index', '?')
sub = param.get('subIndex', '0')
acc = param.get('accessRights', 'r')
name = param.find('iodd:Name', ns)
params.append({
'index': idx,
'sub': sub,
'access': acc,
'name': name.text if name is not None else '?'
})
return params
params = parse_iodd_parameters('SICK-PAC50-IODD1.1.xml')
for p in params:
print(f" {p['index']}/{p['sub']} [{p['access']}] {p['name']}")
05 Linux IO-Link stack
Linux üzerinde IO-Link master erişimi için açık kaynak stack, USB master adaptörler ve sysfs arayüzü.
Açık kaynak IO-Link Linux stack
# Hilscher io-link-linux açık kaynak stack:
git clone https://github.com/openIOLink/io-link-master-shield-hat-sw.git
cd io-link-master-shield-hat-sw
# Raspberry Pi için derleme:
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make -j4
# openIOLink HAT için kurulum:
sudo make install
sysfs arayüzü
# IO-Link master HAT SPI üzerinden erişilir:
ls /sys/bus/spi/devices/
# spi0.0 → IO-Link master çipi (MAX14819 gibi)
# Cihaz bilgisi oku (port 0):
cat /sys/class/iolink/iolinkmaster0/port0/vendor_id
cat /sys/class/iolink/iolinkmaster0/port0/device_id
cat /sys/class/iolink/iolinkmaster0/port0/com_speed
# COM3
# Process data oku:
cat /sys/class/iolink/iolinkmaster0/port0/process_data_in
# 03A5 00 (3 byte hex: basınç=933, durum=0x00)
IO-Link master modülleri
06 Python ile IO-Link
Python ile IO-Link master kontrolü: cihaz keşfi, ISDU parametre okuma/yazma ve process data parse işlemleri.
iolink Python kütüphanesi
# openIOLink Python kütüphanesi:
pip install iolink
# Alternatif: ifm IO-Link master için ifm-iolink:
pip install python-iolink
Cihaz keşfi ve ISDU okuma
import spidev, time, struct
# MAX14819 tabanlı HAT için düşük seviye SPI erişimi
class IOLinkMaster:
# Register adresleri (MAX14819)
REG_MASTERSTS = 0x00
REG_INTERRUPTEN = 0x01
REG_CQCTRL1 = 0x02
REG_DEVID = 0x10
REG_PDOUT = 0x20
REG_PDIN = 0x28
def __init__(self, spi_bus=0, spi_dev=0):
self.spi = spidev.SpiDev()
self.spi.open(spi_bus, spi_dev)
self.spi.max_speed_hz = 1_000_000
self.spi.mode = 1
def _reg_read(self, reg: int) -> int:
resp = self.spi.xfer2([reg | 0x80, 0x00])
return resp[1]
def _reg_write(self, reg: int, val: int):
self.spi.xfer2([reg & 0x7F, val])
def get_vendor_id(self, port=0) -> int:
"""ISDU index 0x0000, subindex 1 — Vendor ID."""
# Basit istek (tam ISDU state machine gerekir)
hi = self._reg_read(self.REG_DEVID + port * 4)
lo = self._reg_read(self.REG_DEVID + port * 4 + 1)
return (hi << 8) | lo
def read_process_data(self, port=0, length=3) -> bytes:
"""Siklik process data oku."""
result = bytearray()
for i in range(length):
result.append(self._reg_read(self.REG_PDIN + port * 8 + i))
return bytes(result)
def close(self):
self.spi.close()
# Kullanım:
master = IOLinkMaster(spi_bus=0, spi_dev=0)
print(f'Vendor ID (port 0): 0x{master.get_vendor_id(0):04X}')
try:
while True:
pd = master.read_process_data(port=0, length=3)
if len(pd) == 3:
pressure = struct.unpack('>H', pd[0:2])[0] # big-endian uint16
status = pd[2]
# Örnek ölçek: 1 LSB = 0.1 mbar
print(f'Basınç: {pressure / 10.0:.1f} mbar Durum: 0x{status:02X}')
time.sleep(0.1)
except KeyboardInterrupt:
master.close()
HTTP üzerinden IO-Link master erişimi (ifm AL1350)
import requests, json
MASTER_IP = "192.168.0.250"
def iolink_isdu_read(port: int, index: int, subindex: int = 0):
"""ifm AL1350 REST API ile ISDU okuma."""
url = f"http://{MASTER_IP}/iolink/v1/devices/port[{port}]/isdu"
payload = {
"code": "request",
"cid": 1,
"adr": f"/iolink/v1/devices/port[{port}]/isdu",
"data": {
"index": index,
"subindex": subindex,
"accesstype": "getdata"
}
}
resp = requests.post(url, json=payload, timeout=2)
return resp.json()
def iolink_get_process_data(port: int):
"""Port process data oku."""
url = f"http://{MASTER_IP}/iolink/v1/devices/port[{port}]/processdata"
resp = requests.get(url, timeout=1)
return resp.json()
# Port 1'deki cihazın seri numarasını oku (index 0x0015):
result = iolink_isdu_read(port=1, index=0x0015, subindex=0)
print('Seri no:', result.get('data', {}).get('value', '?'))
# Process data oku:
pd = iolink_get_process_data(port=1)
print('Process data:', pd)
07 IO-Link Wireless
IEC 61131-9 Amendment — IO-Link protokolünün 2.4 GHz ISM bandına taşınması. Deterministik 5 ms cycle time ile kablolu IO-Link performansına yakın kablosuz bağlantı.
IO-Link Wireless özellikleri
| Parametre | IO-Link (kablolu) | IO-Link Wireless |
|---|---|---|
| Frekans | N/A (kablo) | 2.4 GHz ISM bandı |
| Max cihaz/master | 1 (point-to-point) | 8 cihaz / 1 master |
| Cycle time | COM3: ~2 ms | Deterministik 5 ms |
| Mesafe | 20 m (kablo) | 20 m (line-of-sight) |
| Frekans atlama | N/A | FHSS (Frequency Hopping Spread Spectrum) |
| Gecikme | <2 ms | <5 ms |
Kullanım senaryoları
IO-Link Wireless master / device çipleri
IO-Link Wireless Sanayi 4.0 (IIoT) altyapısında kablosuz sensör ağları için önemli bir yapı taşıdır. Ancak Wi-Fi veya Bluetooth LE ile karıştırılmamalıdır — IO-Link Wireless deterministik ve özel protokol olup genel amaçlı kablosuz değildir.
08 Pratik: Basınç sensörü entegrasyonu ve S7-1500
Sick PAC50 IO-Link basınç sensörü ile IODD tabanlı parametre yapılandırma, Siemens S7-1500 + CM IO-Link master üzerinden Python erişimi ve IO-Link Hub ile 8 sensör → 1 EtherNet/IP port.
SICK PAC50 — IODD ile parametre ayarı
import requests
MASTER_IP = "192.168.0.250"
PORT = 1 # PAC50 bağlı port
def isdu_read(port, index, subindex=0):
url = f"http://{MASTER_IP}/iolink/v1/devices/port[{port}]/isdu"
data = {"index": index, "subindex": subindex, "accesstype": "getdata"}
resp = requests.post(url, json={"code": "request", "cid": 1,
"adr": url, "data": data}, timeout=2)
return resp.json().get("data", {}).get("value")
def isdu_write(port, index, subindex, value):
url = f"http://{MASTER_IP}/iolink/v1/devices/port[{port}]/isdu"
data = {"index": index, "subindex": subindex,
"accesstype": "setdata", "value": value}
resp = requests.post(url, json={"code": "request", "cid": 2,
"adr": url, "data": data}, timeout=2)
return resp.status_code == 200
# Cihaz kimliğini oku:
vendor_id = isdu_read(PORT, 0x0000, 1)
device_id = isdu_read(PORT, 0x0000, 2)
print(f'Vendor ID: 0x{vendor_id:04X}, Device ID: 0x{device_id:06X}')
# Vendor ID: 0x0039 (SICK), Device ID: 0x022312
# PAC50 üst alarm eşiğini ayarla (index 0x0060): 9000 = 900.0 mbar
ok = isdu_write(PORT, 0x0060, 0, 9000)
print('Üst eşik yazma:', 'OK' if ok else 'HATA')
# Mevcut ölçüm oku (index 0x0094):
meas = isdu_read(PORT, 0x0094, 0)
print(f'Basınç: {int(meas) / 10.0:.1f} mbar')
S7-1500 CM IO-Link master yapılandırması (TIA Portal)
1. CM 4×IO-Link modülü ekle:
Device view → S7-1500 → Add module → CM 4×IO-Link (6ES7137-6BD00-0BA0)
2. Port yapılandırması (Port 1):
CM modülü → Port 1 → Properties
Port mode: IO-Link
Validation: No check (veya vendor/device ID ile doğrula)
Process data length: 3 byte giriş, 0 byte çıkış
3. IODD yükle:
Options → Manage device description files → Import
SICK-PAC50-IODD1.1.xml seç → İçe aktar
4. Parametre ata:
Device parameters tabı → UpperSwitchPoint = 9000
5. I/O adresleri:
Input: IB200-IB202 → 3 byte process data
IW200 = basınç değeri (big-endian), IB202 = durum
S7-1500 üzerindeki verilere Python ile snap7 erişimi
import snap7, struct, time
plc = snap7.client.Client()
plc.connect('192.168.0.10', 0, 1)
while True:
# IB200-IB202: PAC50 process data (3 byte)
data = plc.read_area(snap7.types.Areas.PE, 0, 200, 3)
pressure_raw = struct.unpack('>H', data[0:2])[0]
status = data[2]
pressure_mbar = pressure_raw / 10.0
print(f'Basınç: {pressure_mbar:.1f} mbar Durum: 0x{status:02X}')
if status & 0x01:
print(' ⚠ ÜST ALARM AKTİF')
if status & 0x02:
print(' ⚠ ALT ALARM AKTİF')
time.sleep(0.5)
plc.disconnect()
IO-Link Hub — 8 sensör → 1 EtherNet/IP port
IO-Link Hub (örn. Balluff BNI010M veya ifm AL1324), 8 IO-Link cihazı bağlayan bir çoklayıcıdır. EtherNet/IP veya PROFINET üst bağlantısı ile PLC'ye tek bir fieldbus bağlantısı üzerinden 8 sensörün tüm process data ve parametrelerine erişilir.
EtherNet/IP (PLC ← → Hub)
────────────────────────────────────────
IO-Link Hub (ifm AL1324)
├── Port 1: Basınç sensörü (PAC50)
├── Port 2: Sıcaklık sensörü (TDxxxxS)
├── Port 3: Pozisyon sensörü
├── Port 4: RFID okuyucu
├── Port 5: Akıllı pnömatik valf
├── Port 6: Renk sensörü
├── Port 7: Titreşim sensörü
└── Port 8: IO-Link Wireless master
from pycomm3 import CIPDriver
# pycomm3: pip install pycomm3
with CIPDriver('192.168.0.51') as plc:
# ifm AL1324 — port 1 process data assembly (instance 100)
result = plc.generic_message(
service=0x0E, # Get_Attribute_Single
class_code=0x04, # Assembly object
instance=100, # Input assembly
attribute=3, # Data attribute
connected=False,
route_path=True
)
if result:
raw = result.value
# Her port 4 byte: 3B process data + 1B port status
for port in range(8):
offset = port * 4
pd = raw[offset:offset+3]
ps = raw[offset+3]
pressure = (pd[0] << 8 | pd[1]) / 10.0
print(f'Port {port+1}: {pressure:.1f} mbar (status=0x{ps:02X})')
IO-Link Hub EtherNet/IP üreticiden üreticiye farklı assembly numaraları ve veri düzeni kullanır. Gerçek uygulamada üreticinin EDS (Electronic Data Sheet) dosyasını ve IO-Link Hub kılavuzunu incelemek gerekir. ifm, Balluff ve Sick'in IO-Link Hub'ları için Python tabanlı SDK ve örnek kodlar üreticilerin web sitelerinde mevcuttur.