Bir enerji analizörünün kılavuzunu açıyorsunuz, karşınıza "Fonksiyon kodu: 03" yazan bir tablo çıkıyor. Yandaki inverterin kılavuzunda ise "Sadece 04 destekler" yazıyor. Peki bu numaralar da ne? 🤔 Bu yazıda MODBUS'un tüm fonksiyon kodlarını tek tek, örnek çerçeveleriyle ve sahada başınıza gelebilecek tuzaklarıyla birlikte ele alıyoruz.
- MODBUS'a hızlı bir giriş
- Fonksiyon kodu tam olarak nedir?
- Dört tip veri: coil, discrete input, register
- 📋 Tam MODBUS fonksiyon listesi
- Bit tabanlı fonksiyonlar (01, 02, 05, 0F)
- Register fonksiyonları (03, 04, 06, 10, 16, 17, 18)
- Tanılama ve cihaz bilgisi (07, 08, 0B, 0C, 11, 2B)
- Dosya kaydı fonksiyonları (14, 15)
- Hata (exception) kodları
- Kod aralıkları: public, user-defined, reserved
- Limitler ve seri hat / TCP farkı
- Sahadan pratik ipuçları
- Sık sorulan sorular
MODBUS'a hızlı bir giriş 🔌
MODBUS, 1979 yılında Modicon tarafından PLC'ler için tasarlanmış bir haberleşme protokolü. Yani sizden, benden, muhtemelen bu yazıyı okuyan çoğu mühendisten daha yaşlı. Buna rağmen hâlâ her yerde: enerji analizörlerinde, ısı kontrolörlerinde, inverterlerde, debimetrelerde, güneş invertörlerinde, jeneratör kontrol kartlarında...
Bu kadar uzun yaşamasının sebebi çok basit: protokol gerçekten sade ve açık. Telif ücreti yok, lisans yok, karmaşık bir yığın yok. Bir tarafta soru soran (client / master), diğer tarafta cevap veren (server / slave) var. Master sorar, slave cevaplar. Slave asla kendiliğinden konuşmaz — bu detay ilerideki birçok tasarım kararını açıklıyor.
Üç yaygın taşıma katmanı var:
- MODBUS RTU — Seri hat üzerinden (genelde RS-485), veriler ikili (binary) formatta. En yaygın kullanım.
- MODBUS ASCII — Yine seri hat, ama veriler okunabilir ASCII karakterler olarak. Bugün nadir.
- MODBUS TCP — Ethernet üzerinden, 502 numaralı port. (TLS'li güvenli sürümü ise 802 portunu kullanır.)
Taşıma katmanı değişse de fonksiyon kodları aynı kalır. Yani bu yazıda öğrendikleriniz hem RS-485 hattındaki bir sayaçta hem de Ethernet'teki bir gateway'de geçerli olacak. 👌
Fonksiyon kodu tam olarak nedir?
Fonksiyon kodu, mesajın içindeki tek bir bayttır ve "ne yapmak istiyorum?" sorusunun cevabıdır. Okumak mı istiyorum, yazmak mı? Bit mi okuyacağım, register mı? Cihazın kimliğini mi soracağım?
Bir MODBUS RTU çerçevesinin anatomisi şöyle görünür:
┌──────────┬──────────┬─────────────────────┬──────────┐
│ Adres │ Fonksiyon│ Veri │ CRC │
│ 1 bayt │ 1 bayt │ 0 – 252 bayt │ 2 bayt │
└──────────┴──────────┴─────────────────────┴──────────┘
▲ ▲ ▲ ▲
│ │ │ └─ Hata kontrolü
│ │ └─ Adres, adet, değerler...
│ └─ NE yapılacak (bizim konumuz!)
└─ KİM yapacak (1–247, 0 = broadcast)
Gerçek örnek: 11 03 00 6B 00 03 76 87
▲ ▲ └───┘ └───┘ └───┘
│ │ │ │ └─ CRC
│ │ │ └─ 3 adet register oku
│ │ └─ Başlangıç adresi 0x006B (107)
│ └─ Fonksiyon 0x03 = Read Holding Registers
└─ 17 numaralı cihaza soruyorum
MODBUS TCP'de ise adres ve CRC yerine 7 baytlık bir MBAP başlığı gelir; ortadaki "fonksiyon + veri" kısmı (buna PDU deniyor) bire bir aynı kalır:
MODBUS TCP: 00 01 00 00 00 06 11 03 00 6B 00 03
└─────── MBAP (7 bayt) ──────┘└─ PDU ─┘
│ │ │ │
│ │ │ └─ Unit ID (11)
│ │ └─ Uzunluk
│ └─ Protokol ID (her zaman 0000)
└─ İşlem (transaction) ID — cevabı eşleştirmek için
💡 Aklınızda kalsın: RTU'da 0x11 ilk bayttaysa "17 numaralı cihaz", ikinci bayttaysa "Report Server ID fonksiyonu" demektir. Aynı hex değeri, konuma göre bambaşka anlam taşır. Çerçeve okurken en sık yapılan karışıklıklardan biri budur.
Fonksiyonlardan önce: dört tip veri
Fonksiyon kodlarının neden bu kadar çok olduğunu anlamak için önce MODBUS'un veri modelini bilmek gerekiyor. Protokol her şeyi dört kutuya ayırır:
| Veri tipi | Boyut | Erişim | Klasik adres | Tipik örnek |
|---|---|---|---|---|
| Coil (Bobin) | 1 bit | Oku / Yaz | 0xxxx | Röle çıkışı, start/stop komutu |
| Discrete Input (Ayrık giriş) | 1 bit | Salt okunur | 1xxxx | Limit switch, kapı sensörü |
| Input Register (Giriş register'ı) | 16 bit | Salt okunur | 3xxxx | Ölçülen sıcaklık, akım değeri |
| Holding Register (Tutma register'ı) | 16 bit | Oku / Yaz | 4xxxx | Set değeri, PID parametresi, frekans referansı |
Mantık şu: bir şey bit mi yoksa sayı mı, ve onu yazabiliyor musunuz yoksa sadece okuyabiliyor musunuz? Bu iki soru 2 × 2 = 4 kutu yapıyor ve fonksiyon kodlarının büyük kısmı bu kutulara okuma/yazma yapmaktan ibaret. 😊
📋 Tam MODBUS Fonksiyon Listesi
İşte MODBUS Application Protocol Specification V1.1b3'te tanımlı tüm public (standart) fonksiyon kodları. Toplamda 19 tane; standartta bunların dışında tanımlı bir fonksiyon yok.
| Hex | Dec | İsim | Ne yapar? | Not |
|---|---|---|---|---|
0x01 | 1 | Read Coils | Yazılabilir bitleri okur | Yaygın |
0x02 | 2 | Read Discrete Inputs | Salt okunur bitleri okur | Yaygın |
0x03 | 3 | Read Holding Registers | Yazılabilir register'ları okur | Yaygın |
0x04 | 4 | Read Input Registers | Salt okunur register'ları okur | Yaygın |
0x05 | 5 | Write Single Coil | Tek bir biti 1 veya 0 yapar | Yaygın |
0x06 | 6 | Write Single Register | Tek bir register'a değer yazar | Yaygın |
0x07 | 7 | Read Exception Status | 8 bitlik özel durum baytını okur | Seri hat |
0x08 | 8 | Diagnostics | Alt fonksiyonlarla hat tanılaması yapar | Seri hat |
0x0B | 11 | Get Comm Event Counter | Haberleşme olay sayacını okur | Seri hat |
0x0C | 12 | Get Comm Event Log | Olay günlüğünü okur | Seri hat |
0x0F | 15 | Write Multiple Coils | Birden çok biti tek seferde yazar | Yaygın |
0x10 | 16 | Write Multiple Registers | Birden çok register'ı tek seferde yazar | Yaygın |
0x11 | 17 | Report Server ID | Cihazın kimliğini ve çalışma durumunu sorar | Seri hat |
0x14 | 20 | Read File Record | Dosya kaydı okur | Nadir |
0x15 | 21 | Write File Record | Dosya kaydı yazar | Nadir |
0x16 | 22 | Mask Write Register | Maske ile tek bit düzeyinde yazar | Nadir |
0x17 | 23 | Read/Write Multiple Registers | Tek işlemde hem okur hem yazar | Nadir |
0x18 | 24 | Read FIFO Queue | FIFO kuyruğundaki verileri okur | Nadir |
0x2B | 43 | Encapsulated Interface Transport | MEI kapsülleme (cihaz kimliği, CANopen) | Nadir |
Gerçek hayat notu 🔧 Bu 19 fonksiyondan sahada karşılaşacağınızın %95'i şu sekiz tanedir: 01, 02, 03, 04, 05, 06, 0F, 10. Geri kalanı çoğu ticari cihazda desteklenmez; sorduğunuzda size nazikçe "Illegal Function" hatası döner.
Bit tabanlı fonksiyonlar: 01, 02, 05, 0F
0x01 — Read Coils (Bobinleri Oku)
Yazılabilir bitleri okur. Cevapta bitler paketlenmiş gelir: her bayt 8 bit taşır ve en düşük anlamlı bit (LSB) ilk coil'e denk gelir. Bu ters sıralama ilk defa gören herkesi şaşırtır. 😅
İstek: 11 01 00 13 00 25 0E 84
└ 17 nolu cihaz, 19. adresten başla, 37 coil oku
Cevap: 11 01 05 CD 6B B2 0E 1B 45 E6
└ 5 bayt veri geliyor
İlk bayt CD = 1100 1101 (binary)
▲
└ Bu bit ilk coil (adres 19)
Sıra: coil19=1, 20=0, 21=1, 22=1, 23=0, 24=0, 25=1, 26=1
0x02 — Read Discrete Inputs (Ayrık Girişleri Oku)
0x01 ile bire bir aynı mantık, tek farkı salt okunur bitlere erişmesi. Bir sensörün durumunu okuyorsanız muhtemelen bu fonksiyonu kullanıyorsunuzdur.
İstek: 11 02 00 C4 00 16 BA A9
└ 196. adresten başla, 22 giriş oku
Cevap: 11 02 03 AC DB 35 20 18
0x05 — Write Single Coil (Tek Bobin Yaz)
Burada sevimli bir tuhaflık var: değer alanı 1 bit değil, 2 bayt. Ve sadece iki geçerli değer kabul eder — 0xFF00 = AÇ, 0x0000 = KAPAT. Neden 0x0001 değil? 1979'dan kalma bir tasarım tercihi diyelim. 🙂
İstek: 11 05 00 AC FF 00 4E 8B
└ 172. coil'i AÇ
Cevap: isteğin aynısı geri döner (echo)
0x0F — Write Multiple Coils (Çoklu Bobin Yaz)
Tek seferde 1968 coil'e kadar yazabilirsiniz. Veri yine paketlenmiş bit halinde gider. Cevap ise sadece "şu adresten şu kadarını yazdım" özetidir — verinin tamamını geri döndürmez.
İstek: 11 0F 00 13 00 0A 02 CD 01 BF 0B
└ 19. adresten başla, 10 coil yaz, 2 bayt veri: CD 01
Cevap: 11 0F 00 13 00 0A 26 99
Register fonksiyonları: 03, 04, 06, 10, 16, 17, 18
0x03 — Read Holding Registers (Tutma Register'larını Oku)
Bu, MODBUS dünyasının en çok kullanılan fonksiyonu. 🏆 Bir enerji analizöründen gerilim okumak, bir inverterden çalışma frekansını almak, bir kontrolörden set değerini öğrenmek — hepsi bu fonksiyonla.
İstek: 11 03 00 6B 00 03 76 87
└ 107. adresten başla, 3 register oku
Cevap: 11 03 06 02 2B 00 00 00 64 C8 BA
│ └─┬─┘ └─┬─┘ └─┬─┘
│ │ │ └─ Register 109 = 0x0064 = 100
│ │ └─ Register 108 = 0x0000 = 0
│ └─ Register 107 = 0x022B = 555
└─ 6 bayt (3 register × 2 bayt)
0x04 — Read Input Registers (Giriş Register'larını Oku)
0x03 ile teknik olarak neredeyse aynı; fark, salt okunur register'lara erişmesi. Bazı üreticiler ölçüm değerlerini 0x04'e, ayarları 0x03'e koyar. Bazıları ise her şeyi 0x03'e yığar ve 0x04'ü hiç desteklemez. Kılavuz okumaktan kaçış yok. 📖
0x06 — Write Single Register (Tek Register Yaz)
Tek bir 16 bit değeri yazar. Basit, hızlı, cevabı isteğin kopyasıdır.
İstek: 11 06 00 01 00 03 9A 9B
└ 1. register'a 3 değerini yaz
Cevap: 11 06 00 01 00 03 9A 9B (echo)
0x10 — Write Multiple Registers (Çoklu Register Yaz)
Tek seferde 123 register'a kadar yazar. 32 bitlik bir değeri (float, uzun tamsayı) yazacaksanız bu fonksiyonu kullanmanız zorunlu sayılır — çünkü iki register'ı 0x06 ile ayrı ayrı yazarsanız cihaz arada yarım değeri işleme alabilir.
İstek: 11 10 00 01 00 02 04 00 0A 01 02 C6 F0
│ │ │ │ └───┬───┘
│ │ │ │ └─ Veri: 0x000A ve 0x0102
│ │ │ └─ 4 bayt veri
│ │ └─ 2 register yazılacak
│ └─ 1. adresten başla
└ Fonksiyon 0x10
Cevap: 11 10 00 01 00 02 12 98
0x16 — Mask Write Register (Maskeli Register Yazma)
Bir register'ın tamamını değil, sadece belirli bitlerini değiştirmek istediğinizde işe yarar. Klasik "oku–değiştir–yaz" döngüsünü tek işleme indirger, böylece arada başka biri araya girip register'ı bozamaz.
Formül: Sonuç = (Mevcut AND And_Mask) OR (Or_Mask AND (NOT And_Mask))
İstek: 11 16 00 04 00 F2 00 25 66 E2
│ │ │ └─ Or_Mask = 0x0025
│ │ └─ And_Mask = 0x00F2
│ └─ Register adresi 4
└ Fonksiyon 0x16
0x17 — Read/Write Multiple Registers (Oku ve Yaz)
Tek mesajda önce yazma, sonra okuma yapar. Hat trafiğini yarıya indirdiği için hızlı döngü gerektiren uygulamalarda değerlidir. Ancak destekleyen cihaz sayısı sınırlıdır.
İstek: 11 17 00 03 00 06 00 0E 00 03 06 00 FF 00 FF 00 FF 4B 54
│ └──┬──┘ └──┬──┘ └──┬──┘ └──┬──┘ │ └──────┬──────┘
│ Oku adres Oku adet Yaz adres Yaz adet Bayt Yazılacak veri
└ Fonksiyon 0x17
0x18 — Read FIFO Queue (FIFO Kuyruğunu Oku)
Cihazın içindeki sıra tipi bir tampondan (kuyruk) veri çeker. En fazla 31 register döndürebilir. Alarm geçmişi ya da olay kuyruğu tutan özel cihazlarda karşınıza çıkabilir; genel amaçlı cihazlarda neredeyse hiç yok.
Tanılama ve cihaz bilgisi: 07, 08, 0B, 0C, 11, 2B
Bu grup "veri okuma" değil, "cihazla ilgili bilgi alma" işi görür. Büyük kısmı yalnızca seri hat (RTU/ASCII) için tanımlıdır ve MODBUS TCP'de standart değildir.
0x07 — Read Exception Status
Cihazın 8 bitlik özel durum baytını okur. Bu 8 bitin ne anlama geldiği tamamen üreticiye bağlıdır — biri "aşırı sıcaklık" der, diğeri "kalibrasyon gerekli" der. Çok kısa bir mesaj olduğu için hızlı durum sorgulamada tercih edilirdi.
0x08 — Diagnostics
Aslında tek bir fonksiyon değil, bir avuç alt fonksiyonun şemsiyesi. Fonksiyon kodundan hemen sonra 2 baytlık bir alt fonksiyon numarası gelir:
| Alt fonk. | Dec | İşlev |
|---|---|---|
0x00 | 0 | Return Query Data — gönderdiğinizi aynen geri yollar (echo testi) |
0x01 | 1 | Restart Communications Option — haberleşme portunu yeniden başlatır |
0x02 | 2 | Return Diagnostic Register — tanılama register'ını döndürür |
0x03 | 3 | Change ASCII Input Delimiter — ASCII ayırıcı karakteri değiştirir |
0x04 | 4 | Force Listen Only Mode — cihazı sadece dinleme moduna alır |
0x0A | 10 | Clear Counters and Diagnostic Register — sayaçları sıfırlar |
0x0B | 11 | Return Bus Message Count — hattaki toplam mesaj sayısı |
0x0C | 12 | Return Bus Communication Error Count — CRC hatası sayısı |
0x0D | 13 | Return Bus Exception Error Count — exception cevap sayısı |
0x0E | 14 | Return Server Message Count — cihaza gelen mesaj sayısı |
0x0F | 15 | Return Server No Response Count — cevapsız kalan mesaj sayısı |
0x10 | 16 | Return Server NAK Count |
0x11 | 17 | Return Server Busy Count |
0x12 | 18 | Return Bus Character Overrun Count — taşma hatası sayısı |
0x14 | 20 | Clear Overrun Counter and Flag |
Özellikle 0x0C (CRC hata sayacı) çok değerlidir: RS-485 hattınızda gürültü olup olmadığını anlamanın en dolaysız yoludur. Sayaç sürekli artıyorsa kablolamaya, sonlandırma direncine ve topraklamaya bakma vaktidir. ⚡
0x0B ve 0x0C — Comm Event Counter / Event Log
Cihazın kaç başarılı işlem yaptığını ve son olayların günlüğünü verir. Event log en fazla 64 olay taşır. Bugün pek kullanılmıyor, ama eski Modicon sistemlerinde hat sağlığını izlemenin standart yoluydu.
0x11 — Report Server ID
"Sen kimsin?" sorusunun MODBUS'çası. Cevap şu alanları içerir:
| Alan | Açıklama |
|---|---|
| Byte Count | Takip eden veri uzunluğu |
| Server ID | Üreticiye özel cihaz kimliği (standart değil!) |
| Run Indicator | 0x00 = durmuş, 0xFF = çalışıyor |
| Ek veri | Firmware sürümü, model adı vb. — tamamen üreticinin keyfine kalmış |
İstek: 11 11 CD EC ← veri alanı boş, sadece soruyoruz
0x2B — Encapsulated Interface Transport (MEI)
Bu fonksiyon bir "zarf" gibi çalışır: içine başka bir protokolün mesajını koyar. İki alt tipi var:
0x0D— CANopen General Reference0x0E— Read Device Identification (asıl işe yarayan)
0x2B/0x0E, cihazdan yapılandırılmış metin bilgileri çeker. 0x11'in aksine bu alanlar standarttır:
| Nesne ID | İsim | Seviye |
|---|---|---|
0x00 | VendorName — üretici adı | Basic (zorunlu) |
0x01 | ProductCode — ürün kodu | Basic (zorunlu) |
0x02 | MajorMinorRevision — sürüm | Basic (zorunlu) |
0x03 | VendorUrl — üretici web adresi | Regular |
0x04 | ProductName — ürün adı | Regular |
0x05 | ModelName — model adı | Regular |
0x06 | UserApplicationName — uygulama adı | Regular |
0x80–0xFF | Üreticiye özel alanlar | Extended |
Dosya kaydı fonksiyonları: 14 ve 15
MODBUS'un en az bilinen köşesi. 0x14 (Read File Record) ve 0x15 (Write File Record), cihazın içindeki "dosya" benzeri yapılara erişir. Burada dosya, 16 bitlik kayıtlardan oluşan bir bloktur; klasik adreslemede 6xxxxx aralığına denk gelir.
- Dosya numarası: 0x0001 – 0xFFFF
- Kayıt numarası: 0 – 9999
- Tek mesajda birden fazla alt-istek gönderilebilir
Pratikte veri kaydediciler (data logger), trend kaydı tutan cihazlar ve bazı akış bilgisayarları kullanır. Standart bir sensörde göremezsiniz.
İşler ters gittiğinde: Exception kodları ⚠️
Cihaz isteğinizi yerine getiremezse sessiz kalmaz — size bir hata cevabı döner. Bunu anlamanın yolu çok zarif: cevaptaki fonksiyon koduna 0x80 eklenir.
İstek: 11 03 00 6B 00 03 76 87 ← 0x03 ile okuma denemesi
Hata: 11 83 02 C1 34 ← 0x03 + 0x80 = 0x83
│ └─ Exception kodu 02 = Illegal Data Address
└─ "Bu bir hata cevabı" işareti
| Kod | İsim | Türkçesi ve tipik sebebi |
|---|---|---|
0x01 | Illegal Function | Cihaz bu fonksiyonu desteklemiyor. 0x04 sorup 0x03 kullanmanız gerekiyor olabilir. |
0x02 | Illegal Data Address | Adres cihazda yok. En sık sebep: 40001 / 0 kaymasını yanlış hesaplamak. |
0x03 | Illegal Data Value | Değer veya adet geçersiz. Örneğin 200 register birden okumaya çalışmak. |
0x04 | Server Device Failure | Cihazın içinde bir arıza oluştu. |
0x05 | Acknowledge | "İsteğini aldım ama uzun sürecek, bekle." Sonucu 0x0B ile sorabilirsiniz. |
0x06 | Server Device Busy | Cihaz meşgul, biraz sonra tekrar deneyin. |
0x08 | Memory Parity Error | Dosya kaydı okurken hafıza parite hatası (sadece 0x14 / 0x15). |
0x0A | Gateway Path Unavailable | Gateway hedefe giden yolu bulamadı — genelde gateway ayarı yanlış. |
0x0B | Gateway Target Device Failed to Respond | Gateway'in arkasındaki cihaz cevap vermiyor — kablo, adres veya baud hatası. |
🚨 En çok zaman kaybettiren ikili: 0x02 ve 0x0B. İlkinde adres haritasını, ikincisinde fiziksel bağlantıyı kontrol edin. Exception alıyor olmanız aslında iyi haberdir — demek ki hat çalışıyor, cihaz sizi duyuyor ve cevap veriyor. Hiç cevap alamamak çok daha kötüdür.
Kod aralıkları: public, user-defined ve reserved
Fonksiyon kodu bir bayt olduğuna göre teorik olarak 255 farklı değer alabilir. Standart bu alanı şöyle paylaştırmış:
| Aralık (Dec) | Sınıf | Anlamı |
|---|---|---|
| 1 – 64 | Public | Standartta tanımlı; boş kalanlar Modbus Organization rezervinde |
| 65 – 72 | User-defined | Üretici istediği fonksiyonu koyabilir |
| 73 – 99 | Public | Standart alan |
| 100 – 110 | User-defined | Üretici serbest alanı |
| 111 – 127 | Public | Standart alan |
| 128 – 255 | Exception | Hata cevaplarına ayrılmış; burada asla yeni fonksiyon tanımlanmaz |
Bir de reserved kodlar var: 9, 10, 13, 14, 41, 42, 90, 91, 125, 126, 127. Bunlar eski Modicon ürünlerinde kullanılmış, public sayılmıyor ve yeni tasarımlarda kullanılmaması isteniyor. Yani "boş görünüyor, ben buraya kendi fonksiyonumu koyayım" demeyin — geriye dönük uyumluluk sorunları çıkarır. 🙃
Limitler ve seri hat / TCP farkı
Her fonksiyonun tek mesajda taşıyabileceği veri miktarı sınırlı, çünkü bir MODBUS PDU'su en fazla 253 bayt olabiliyor. Bu limitler ezberlenmeye değer:
| Fonksiyon | Maksimum adet |
|---|---|
| 0x01 Read Coils | 2000 bit |
| 0x02 Read Discrete Inputs | 2000 bit |
| 0x03 Read Holding Registers | 125 register |
| 0x04 Read Input Registers | 125 register |
| 0x0F Write Multiple Coils | 1968 bit |
| 0x10 Write Multiple Registers | 123 register |
| 0x17 Read/Write Multiple | 125 okuma / 121 yazma |
| 0x18 Read FIFO Queue | 31 register |
Çerçeve boyutları da şöyle: RTU'da toplam 256 bayt (adres + PDU + CRC), TCP'de 260 bayt (7 baytlık MBAP + PDU).
Taşıma katmanı farkına gelirsek — 0x07, 0x08, 0x0B, 0x0C ve 0x11 fonksiyonları seri hat için tanımlanmıştır. MODBUS TCP'de bunları sormak genelde boşuna; bazı gateway'ler kabul eder, çoğu "Illegal Function" der.
Sahadan pratik ipuçları 🛠️
1. 40001 tuzağı
Kılavuzda "40001: Gerilim" yazıyorsa, protokol seviyesinde okumanız gereken adres 0'dır. Klasik gösterimde numaralandırma 1'den, protokolde 0'dan başlar. 40108 → adres 107. Bu tek satırlık bilgi, MODBUS'ta yaşanan hataların herhalde üçte birini önler. 😄
Kılavuzdaki gösterim → Protokol adresi
40001 → 0x0000 (fonksiyon 0x03)
40108 → 0x006B (fonksiyon 0x03)
30001 → 0x0000 (fonksiyon 0x04)
10001 → 0x0000 (fonksiyon 0x02)
00001 → 0x0000 (fonksiyon 0x01)
2. Bayt ve kelime sırası (endianness)
MODBUS register içindeki 2 baytı big-endian gönderir; bu standarttır. Ama 32 bitlik bir değer iki register'a yayıldığında hangi register önce gelir sorusunun cevabı standartta yoktur. Üretici A "yüksek kelime önce" der, üretici B tersini yapar. Bu yüzden float okurken saçma sayılar görüyorsanız, önce kelime sırasını (word swap) deneyin.
3. RS-485 sessizlik kuralı
RTU'da çerçevelerin nerede başlayıp bittiği, aradaki sessizlik süresiyle belirlenir: en az 3,5 karakterlik boşluk. 19200 baud üstünde ise sabit değerler kullanılır (t3.5 ≈ 1,75 ms). Yazılımınız çerçeveleri karıştırıyorsa, çoğu zaman suçlu bu zamanlamadır.
4. Broadcast'e cevap beklemeyin
Adres 0'a gönderilen mesaj tüm cihazlara gider ve hiçbiri cevap vermez. Sadece yazma fonksiyonlarıyla anlamlıdır; broadcast ile okuma yapamazsınız.
5. Az sorgu, çok veri
Ardışık 20 register'ı 20 ayrı istekle okumak yerine tek istekle okuyun. Her istek, hat üzerinde gidiş-dönüş gecikmesi demektir; RS-485'te bu gecikme veriden çok daha pahalıdır. Haritanızı ardışık okunabilecek şekilde planlamak performansı katbekat artırır. 🚀
6. Timeout'u baud hızına göre ayarlayın
9600 baud'da 125 register okumak, sadece veri iletimi için ~270 ms sürer. Varsayılan 100 ms'lik timeout ile çalışıyorsanız cihaz suçsuzdur, ayarınız yanlıştır.
Sık sorulan sorular ❓
0x03 mü kullanmalıyım, 0x04 mü?
Cihazın kılavuzu ne diyorsa o. Adres 40xxx ile gösterilmişse 0x03, 30xxx ile gösterilmişse 0x04. Emin değilseniz ikisini de deneyin — yanlış olan size "Illegal Function" ya da "Illegal Data Address" döner, zararı olmaz.
MODBUS TCP'de slave adresi (Unit ID) ne olmalı?
Doğrudan bir Ethernet cihazına bağlanıyorsanız genelde 1 veya 255 (bazı cihazlar 0 da kabul eder). Ama bir gateway'in arkasındaki seri cihaza ulaşıyorsanız, Unit ID o cihazın gerçek RS-485 adresidir ve kritiktir.
Neden hiç cevap alamıyorum?
Sırasıyla kontrol edin: baud hızı, parite, stop bit, slave adresi, A/B hatlarının ters bağlanmış olması, hat sonu 120 Ω sonlandırma direnci, ortak toprak. Exception almak bile bunlardan iyidir — demek ki hat sağlam.
Fonksiyon listesinde olmayan bir kod gördüm, ne yapmalıyım?
Önce 65–72 veya 100–110 aralığında mı bakın; öyleyse üreticiye özel bir fonksiyondur, cevabı sadece kılavuzda bulunur. 128'in üstündeyse bu bir fonksiyon değil, hata cevabıdır: 0x80 çıkarın, hangi isteğe cevap geldiğini görürsünüz.
Modbus güvenli mi?
Tek kelimeyle: hayır. Protokolde kimlik doğrulama, şifreleme, yetkilendirme yok. Hatta bağlanabilen herkes yazma yapabilir. Bu yüzden MODBUS ağlarını mutlaka izole edin. TLS tabanlı Modbus Security sürümü (port 802) bu boşluğu kapatmak için tanımlandı, ama saha yaygınlığı hâlâ düşük.
🔖 Terimler Sözlüğü
| Terim | Açıklama |
|---|---|
| ADU | Application Data Unit — adres, PDU ve hata kontrolünü içeren tam çerçeve. |
| PDU | Protocol Data Unit — fonksiyon kodu ve verisinden oluşan, taşıma katmanından bağımsız çekirdek kısım. |
| MBAP | MODBUS Application Protocol Header — MODBUS TCP'de mesajın başına eklenen 7 baytlık başlık. |
| Master / Client | Soruyu soran taraf. Haberleşmeyi her zaman o başlatır. |
| Slave / Server | Cevap veren taraf. Kendiliğinden asla konuşmaz. |
| Coil | Okunup yazılabilen 1 bitlik veri. Genelde bir röle veya komut bitidir. |
| Discrete Input | Sadece okunabilen 1 bitlik veri. Genelde bir sensör durumudur. |
| Holding Register | Okunup yazılabilen 16 bitlik değer. Ayarlar ve set değerleri burada durur. |
| Input Register | Sadece okunabilen 16 bitlik değer. Ölçüm sonuçları burada durur. |
| CRC | Cyclic Redundancy Check — RTU'da mesajın bozulup bozulmadığını kontrol eden 2 baytlık kod. |
| Exception | Cihazın "yapamıyorum" cevabı. Fonksiyon koduna 0x80 eklenerek gönderilir. |
| Broadcast | 0 adresine gönderilen, tüm cihazların dinlediği ve hiçbirinin cevaplamadığı mesaj. |
| MEI | Modbus Encapsulated Interface — 0x2B fonksiyonuyla başka protokol mesajlarını taşıma yöntemi. |
| Big-endian | Çok baytlı sayılarda en anlamlı baytın önce gönderilmesi. MODBUS register'ları böyle çalışır. |
| RS-485 | MODBUS RTU'nun en yaygın kullanıldığı, iki telli ve çok noktalı seri haberleşme standardı. |
📌 Ekstra Kaynaklar
- Modbus Organization — Resmî Spesifikasyonlar · Tüm standart dokümanların (uygulama protokolü, seri hat, TCP/IP, Modbus Security) tek adresten indirilebildiği kaynak. Herhangi bir tartışmada son sözü bu sayfa söyler.
- MODBUS Application Protocol Specification V1.1b3 (PDF) · Bu yazının temel aldığı 50 sayfalık ana doküman. Her fonksiyon kodunun tam gövde yapısı, durum diyagramları ve örnek çerçeveleri burada.
- Simply Modbus · Fonksiyon kodlarını bayt bayt, örnekli anlatan klasik referans site. Bir çerçeveyi elle çözümlerken açık tutulacak sekme.
- Wikipedia — Modbus · Protokolün tarihçesi, varyantları ve güvenlik konularına dair derli toplu bir genel bakış.
- libmodbus · Açık kaynak C kütüphanesi. Fonksiyonların gerçekte nasıl kodlandığını merak ediyorsanız, kaynak koda bakmak spesifikasyonu okumaktan daha öğretici olabilir.
Son söz: MODBUS'un 19 public fonksiyonu var, ama günlük hayatınızda sekiz tanesi işinizi görecek. Geri kalanları bilmenin faydası şu: bir gün karşınıza 0x2B ya da 0x16 çıktığında panik yapmak yerine "aa, bu cihaz kimliği soruyor" diyebileceksiniz. 😊
Siz sahada en çok hangi fonksiyonu kullanıyorsunuz? Ya da hangi cihaz size en tuhaf exception'ı döndürdü? Yorumlarda paylaşın. 👇

