Modbus คืออะไร

โลโก้ Modbus รูปจาก https://logos-download.com

Modbus คืออะไร

Modbus เป็นโปรโตคอลสื่อสารที่พัฒนาขึ้นโดยบริษัท Modicon (ปัจจุบันคือบริษัท Schneider Electric) เพื่อใช้สื่อสารอุปกรณ์ PLC ของทางบริษัทเอง โดยในปัจจุบันมี Modbus Organization คอยทำหน้าที่ในการดูแลมาตรฐานของตัวโปรโตคอลต่อจากทาง Schneider Electric ซึ่งในปัจจุบัน Modbus เป็นหนึ่งในโปรโตคอลที่นิยมเป็นอย่างมากสำหรับใช้ในการสื่อสารระหว่างอุปกรณ์ต่างๆในวงการอุตสาหกรรมเนื่องมาจากตัวโปรโตคอลมีความเรียบง่าย และตัวโปรโตคอลเองเปิดเป็นสาธารณะ (Royalty free) ทำให้ทุกคนสามารถพัฒนาอุปกรณ์ที่ใช้โปรโตคอล Modbus ได้โดยไม่เสียค่าใช้จ่าย

โดยตัวโปรโตคอลมีลัษณะการทำงานแบบ Request/Reply โดยอุปกรณ์ที่ต้องการอ่านข้อมูลจะเรียกว่า Modbus Master/Client และอุปกรณ์ที่ถูกอ่านข้อมูลจะเรียกว่า Modbus Slave/Server โดยในเครื่อข่ายของอุปกรณ์ที่สือสารด้วยโปรโตคอล Modbus จะประกอบไปด้วย Master เพียงหนึ่งตัว แต่สามารถมี Slave ได้ตั้งแต่ 1 ตัวไปจนถึง 247 ตัว โดยแต่ละ Slave จะมี ID ประจำตัวตั้งแต่ 1 ถึง 247 เพื่อให้ Master สามารถเลือกสั่ง Read/Write ข้อมูลไปยัง Register ที่เก็บข้อมูลของอุปกรณ์ตัวที่ต้องการได้ หรือจะใช้ Broadcast address (0x00) เพื่อทำการ Write ข้อมูลไปยังทุก Slave ที่เชื่อมต่ออยู่บนบัสได้

ชนิดของโปรโตคอล Modbus

เราสามารถแบ่งชนิดของโปรโตคอล Modbus ออกได้เป็น 2 กลุ่มใหญ่ๆ คือ

1. กลุ่มที่สื่อสารผ่านสาย Serial ไม่ว่าจะเป็น RS-232 ที่ใช้ต่อ 1-1 ระหว่าง Master และ Slave หรือ RS-485 half duplex ที่รองรับการเชื่อมต่อแบบ multi-drop ที่สามารถต่อเข้ากับ Slave มากกว่า 1 ตัวบนบัสเดียวกันได้ โดยชนิดของโปรโตคอล Modbus ที่อยู่ในกลุ่มนี้จะประกอบไปด้วย Modbus RTU และ Modbus ASCII ซึ่งในปัจจุบันจะสามารถพบเห็นอุปกรณ์ที่เป็น Modbus RTU ได้เยอะกว่า Modbus ASCII โดยความต่างที่สำคัญระหว่างโปรโตคอล 2 แบบนี้คือ

Modbus RTU จะส่งข้อมูลในรูปแบบ Binary แต่ Modbus ASCII จะส่งข้อมูลในรูปแบบตัวอักษร ASCII แทน
ตัวอย่างเช่น หากต้องการส่งข้อมูล 0x4E โปรโตคอลทั้ง 2 แบบจะมีการส่งข้อมูลดังนี้

ในการตัด Message Modbus RTU จะใช้การนับเวลาว่าเกิน 3.5 character time หรือยัง หากไม่มีข้อมูลเข้ามาภายในเวลาดังกล่าวจะถือว่า Message ทั้งหมดที่ได้รับมีเท่านี้ แต่ในส่วนของ Modbus ASCII จะมี Header ของ Message เป็น semi colon (:) และปิดท้าย Message ด้วย CRLF

ในการตรวจสอบความถูกต้องของ Message Modbus RTU จะใช้ CRC-16-IBM ในการเช็คความถูกต้อง แต่ Modbus ASCII จะใช้ LRC ในการเช็คความถูกต้อง

2. กลุ่มที่สื่อสารผ่าน Ethernet ก็คือ Modbus TCP โดยเป็นการส่ง frame ข้อมูลของโปรโตคอล Modbus ผ่าน TCP/IP network โดยปกติ Modbus TCP Slave จะใช้งานพอร์ตหมายเลข 502 ในการรับข้อมูลจาก Master Modbus TCP ถูกพัฒนาขึ้นเพื่อใช้งานกับอุปกรณ์และเครือข่าย Ethernet ที่มีความเร็วในการรับส่งข้อมูลสูงและแก้ปัญหาเรื่องจำนวน Slave ที่จำกัดอยู่แค่ 247 ตัวของ Modbus RTU/ASCII

ชนิดของ Modbus Register

โดยหมายเลขของ Register address ที่อยู่ใน message จะเริ่มที่ 0x0000 แบบ Register address ในตารางเสมอ แต่จะขึ้นอยู่กับข้อมูลในเอกสารของทางผู้ผลิตว่าจะระบุเลข Address มาในรูปแบบไหน หากระบุมาในรูปแบบของ Modbus address จะต้องนำมาลบกับเลข Modbus base address เริ่มต้นเสมอ เช่น หากเอกสารแจ้งว่าสามารถอ่านค่าแรงดันไฟฟ้าได้ที่หมายเลข Address 30003 แปลว่าเลข Register address จริงๆของ register คือ 0x0002 (30003 – 30001) และในบางครั้งทางผู้ผลิตก็จะใช้หมายเลข Register address ผืนเดียวกันกับทั้ง Input และ Holding register เลย

ตัวอย่างเอกสารระบุข้อมูลของ Register ที่ระบุหมายเลข Address ในรูปแบบ Data address เลย และใช้ช่วงหมายเลข Address เดียวกันทั้ง Input และ Holding register  ที่มาของตาราง

Modbus data frame

Frame ข้อมูลของโปรโตคอล Modbus จะประกอบไปด้วย 2 ส่วนใหญ่ๆคือ ADU (Application Data Unit) และ PDU (Protocol Data Unit)

ADU ประกอบด้วย ข้อมูลระบุตัวตน Slave + PDU + Error check โดยแต่ละชนิดของโปรโตคอล Modbus จะมีลักษณะของ ADU ที่แตกต่างกันไป

PDU ประกอบไปด้วย Function code + Data โดยทุกชนิดของโปรโตคอล Modbus จะมีโครงสร้างของ PDU เหมือนกัน

รูปแสดงโครงสร้างของ ADU และ PDU ของโปรโตคอล Modbus แต่ละชนิด

โดย ADU ของ Modbus TCP จะตัดส่วนของ Error check ออกไปเนื่องจาก Ethernet มีกระบวนการ error check อยู่แล้ว

Modbus function code และ exception code

Function code 0x01 Read coil statusRTU

เป็นฟังก์ชั่นไว้ใช้สำหรับอ่านสถานะ Coil/Digital Output จาก Slave ว่ามีค่าเป็น On หรือ Off
ตัวอย่าง PDU ของการอ่านสถานะ coil ที่ 20 ถึง 56

Request

01 0013 0025
01 : Function Code 1
0013 : Address แรกของ coil ที่ต้องการอ่าน โดย coil หมายเลข 1 จะอยู่ที่ Address 0x0000, coil ที่ 20 จึงอยู่ที่ Address 19 (20 -1) = 0x0013
0025 : จำนวน coil ที่ต้องการอ่าน 37 coil = 0x0025

Reply

01 05 CD6BB20E1B
01 : The Function Code 1
05 : จำนวน bytes ของข้อมูลส่วน data
CD : Coils 27 – 20 (1100 1101)
6B : Coils 35 – 28 (0110 1011)
B2 : Coils 43 – 36 (1011 0010)
0E : Coils 51 – 44 (0000 1110)
1B: 3 zero padding + Coils 56 – 52 (0001 1011)
MSB จะเก็บข้อมูลของ coil หมายเลขที่สูงกว่าไว้ และ bit มีค่า 0 หมายถึงสถานะ off และ 1 หมายถึงสถานะ on และตำแหน่ง bit ที่ไม่ได้ใช้งานจะเติม zero padding ไว้

Function code 0x02 Read discrete input

เป็นฟังก์ชั่นไว้ใช้สำหรับอ่านสถานะ Discrete input จาก Slave ว่ามีค่าเป็น On หรือ Off

ตัวอย่าง PDU ของการอ่านสถานะของ Discrete input ที่ 197 ถึง 218

Request

02 00C4 0016

02 : Function Code 2

00C4 : Address ของ input

0016 : จำนวนของ input ที่ต้องการอ่าน 22 inputs

Reply

02 03 ACDB35

02 : Function Code 2

03 : จำนวน bytes ของข้อมูลส่วน data

AC : Discrete Inputs 10204 -10197 (1010 1100)

DB : Discrete Inputs 10212 – 10205 (1101 1011)

35 : 2 zero padding + Discrete Inputs 10218 – 10213 (0011 0101)

MSB จะเก็บข้อมูลของ coil หมายเลขที่สูงกว่าไว้ และ bit มีค่า 0 หมายถึงสถานะ off และ 1 หมายถึงสถานะ on และตำแหน่ง bit ที่ไม่ได้ใช้งานจะเติม zero padding ไว้

Function code 0x03 Read holding register

เป็นฟังก์ชั่นไว้สำหรับอ่านค่า Holding register จาก Slave ว่ามีค่าเป็นเท่าไร โดย register มีขนาด 16 bits
ตัวอย่าง PDU ของการอ่านค่า register modbus address 40108 ถึง 40110

REQUEST

03 006B 0003
03 : Function Code 3

006B : Register address เริ่มต้น 40108 – 40001 = 107 = 0x6B

0003 : จำนวน register ที่ต้องการอ่าน

REPLY

03 06 AE41 5652 4340
03 : Function Code 3

06 : จำนวน bytes ของข้อมูลส่วน data

AE41 5652 4340 : ข้อมูลใน register 40108 40109 40110

Function code 0x04 Read input register

เป็นฟังก์ชั่นไว้สำหรับอ่านค่า Input register จาก Slave ว่ามีค่าเป็นเท่าไร โดย register มีขนาด 16 bits
ตัวอย่าง PDU ของการอ่านค่า register address 0x0008

REQUEST

04 0008 0001
04 : Function Code 4
0008 : Register address เริ่มต้น
0001 : จำนวน register ที่ต้องการอ่าน

REPLY

04 02 000A
04 : Function Code 4
02 : จำนวน bytes ของข้อมูลส่วน data
000A : ข้อมูลใน register

 

FUNCTION CODE 0X05 WRITE SINGLE COIL

เป็นฟังก์ชั่นไว้สำหรับใช้เขียนค่ากลับไปยัง Coil/Digital Output 1 output ของ Slave ว่าให้สถานะเป็น On หรือ Off

 

ตัวอย่าง PDU สำหรับสั่งให้ coil ที่ 173 เปลี่ยนสถานะเป็น On

 

REQUEST

05 00AC FF00
05 : Function Code 5
00AC : Address ของ coil 173 – 1 = 172 = 0x00AC
FF00 : สถานะที่ต้องการ โดย FF00 = On, 0000 = Off

 

REPLY

05 00AC FF00
หากสั่งงานสำเร็จ Slave จะ echo PDU เดียวกันกลับมา

FUNCTION CODE 0X06 WRITE SINGLE REGISTER

เป็นฟังก์ชั่นไว้สำหรับใช้เขียนค่ากลับไปยัง Holding register 1 register ของ Slave
ตัวอย่าง PDU ของการเขียนข้อมูลไปยัง Address 40002

REQUEST

06 0001 0003
06 : Function Code 6
0001 : Address ของ register
0003 : ค่าที่ต้องการเขียนลง register

REPLY

06 0001 0003
หากสั่งงานสำเร็จ Slave จะ echo PDU เดียวกันกลับมา

Function code 0x0F Write multiple coils

เป็นฟังก์ชั่นไว้สำหรับใช้เขียนค่ากลับไปยัง Coil/Digital Output พร้อมกันหลาย output
ตัวอย่าง PDU ของการเขียนค่ากลับไปยัง coil ตั้งแต่หมายเลข 20 ไปถึงจนถึง 29

Request

0F 0013 000A 02 CD01
0F: Function Code 15 0x0F
0013 : Address 20 – 1 = 19 = 0x0013
000A : จำนวน coil ที่ต้องการสั่งงาน
02 : จำนวน byte ในส่วน data
CD : Coils 27 – 20 (1100 1101)
01 : 6 zero padding + Coils 29 – 28 (0000 0001)

Reply

0F 0013 000A
0F: Function Code 15 0x0F
0013 : Address
000A : จำนวน coil ที่สั่งงานสำเร็จ

Function code 0x10 Write multiple registers

เป็นฟังก์ชั่นไว้สำหรับใช้เขียนค่ากลับไปยัง Holding register พร้อมกันหลาย register
ตัวอย่าง PDU ของการเขียนค่าลงไปยัง register Modbus address 40002 และ 40003

Request

10 0001 0002 04 000A 0102
10 : Function Code 16 0x10
0001 : Start register address 40002 – 40001 = 1 = 0x0001
0002 : จำนวน register ที่ต้องการเขียน
04 : จำนวน byte ในส่วน data
000A : ค่าที่ต้องการเขียนลง register 40002
0102 : ค่าที่ต้องการเขียนลง register 40003

Reply

10 0001 0002
10 : Function Code 16 0x10
0001 : Start register address
0002 : จำนวน register ที่เขียนสำเร็จ

Exception code

โดยปกติแล้วหาก Modbus Slave ได้รับคำสั่งจาก Master และสามารถทำงานตามคำสั่งได้สำเร็จ Slave จะตอบกลับไปด้วย message ที่ประกอบไปด้วย function code ที่ได้รับ และ data แต่หาก Slave ไม่สามารถทำตามคำสั่งได้ Slave จะตอบกลับไปด้วย exception response แทน
วิธีสังเกตว่าคำตอบที่ได้รับเป็น exception response หรือไม่ สามารถดูได้จากเลข function code ที่ตอบกลับมา โดยหากเป็น exception เลข function code MSB จะโดน set เป็น 1 หรือมองว่าเลข function code เดิม บวกด้วย 0x80 ก็ได้

ตาราง Exception function code

และในส่วนของ data ก็จะเป็นเลข Exception code ที่บอกปัญหาที่เกิดขึ้นแทน

ตัวอย่าง PDU ของการอ่านค่า Input register address ที่ไม่มีอยู่

Request

04 FFFF 0001
04 : Function code
FFFF : Register address ที่ต้องการอ่าน ซึ่งไม่มีอยู่บน Slave
0001 : ต้องการอ่าน 1 register

Reply

84 02
84 : Exception function code ของ 0x04
02 : Exception code Illegal Data Address
นอกจากนี้ยังมี Function code และ Exception code อื่นๆที่ไม่ได้กล่าวถึงอยู่อีก โดยสามารถศึกษาเพิ่มเติมได้จากเอกสาร spec ของโปรโตคอล Modbus ได้ที่ลิ้งค์นี้

ข้อจำกัดในการใช้งานโปรโตคอล Modbus

  • เนื่องจากตัวโปรโตคอลมีลัษณะการทำงานแบบ Request/Reply ทำให้ไม่สามารถมีการทำงานแบบ Event ได้ ต้องรอให้ทาง Master คอย Polling ข้อมูลเองเพื่อที่จะทราบช้อมูล Event ต่างๆบน Slave เอง
  • Modbus RTU/ASCII มีจำนวน Slave ได้ไม่เกิน 247 ตัว
  • ในการใช้งาน Modbus RTU/ASCII แต่ละอุปกรณ์บนบัสควรจะต้องมี Serial parameters ต่างๆเช่น Baud rate, byte size หรือ parity bit ตรงกันทั้งหมด เพื่อที่ Modbus Master จะได้ไม่ต้อง Initialize ตัว Serial port ใหม่ทุกครั้ง และในบางครั้งทำให้ต้องลด Baud rate ของแต่ละอุปกรณ์ลงมาให้เท่ากันทั้งบัส ทำให้บางอุปกรณ์ Read/Write ข้อมูลได้ช้ากว่าที่ควรจะเป็น
  • มี Master ได้แค่ 1 ตัวบนบัส Modbus RTU/ASCII เนื่องจากใน ช่วงเวลาหนึ่งจะมีอุปกรณ์ส่งข้อมูลบนบัสได้แค่ 1 อุปกรณ์เท่านั้น หากมี Master มากกว่า 1 ตัว อาจจะทำให้เกิดการ Read/Write ข้อมูลชนกันได้ แต่ในส่วนของอุปกรณ์ที่เป็น Modbus TCP จะขึ้นอยู่กับทางผู้ผลิตที่ Implement ตัว Modbus Slave ว่าจะยอมให้มีการเปิด TCP connection มาที่ตัว Slave ได้กี่ connection

เครดิตใต้โพส

ขอบคุณ https://www.simplymodbus.ca/ สำหรับข้อมูลประกอบ