일상다반사/개발

C# NET 을 위한 Modbus Library 에 대한 간단한 고찰

Kua 2021. 8. 5. 09:29
이 글에서 나오는 소스코드는 읽는이의 이해를 돕기 위해 필자가 직접 작성한 "손코딩" 이므로, 동작을 보장하지 않습니다.

 

필자는 net452 를 대상으로 하는 SerialPort(RTU) 를 통한 모드버스 통신을 다음과 같은 라이브러리로 구현을 진행하였다.

 

  1. EasyModbus
  2. NModbus4

 

EasyModbus

EasyModbus 는 상당히 간결하게 코드를 작성할 수 있도록 도와준다.

 

public class Modbus_Example {
    public Modbus_Example() {
        try {
            ModbusClient modbusClient = new ModbusClient("COM1");
            modbusClient.UnitIdentifier = 2;
            modbusClient.Baudrate = 9600;
            modbusClient.Parity = System.IO.Ports.Parity.None;
            modbusClient.StopBits = System.IO.Ports.StopBits.One;
            modbusClient.ConnectionTimeout = 500;
            modbusClient.Connect();

            if (modbusClient.Connected) {
                int[] response_data = modbusClient.ReadHoldingRegisters(0, 0x24);
                // 관련 동작 ~~
            } else {
            	// 관련 동작 ~~
            }
        } catch (Exception ex) {
            // 예외처리
        }
    }
}

 

대체적으로 이런 느낌이다.

하지만 필자는 이 라이브러리를 가지고 2개 이상의 SerialPort, 2개 이상의 SlaveAddress(ID) 를 통신해야 했는데

한번 ReadHoldingRegisters 를 사용한 뒤에 다른 장치의 데이터를 가져오기 위해 finally 에 modbusClient.Disconnect(); 를 항상 사용하였었다.

 

그리고 Connect(); 를 시도할 때 발생하는 것인지

new ModbusClient(); 를 시도할 때 발생하는 것인지

사용할 때마다 Output(출력) 창에 4줄 정도 되는 문구가 나타나, 상당히 로그를 보기 까다로웠었다 .. ^^

 

NModbus4

 

 

Nuget Package Manager 에서 NModbus 를 검색한 사진이다.

설명에서 보다시피 NModbus 는 RTU 를 지원하지 않아, 필자는 사용할 수 없었다.

 

NModbus4 를 이용하여 개발한 예제

 

public class Modbus_Example {
    public Modbus_Example() {
    	serialPorts = new SerialPort[2];
        modbusSerialMasters = new ModbusSerialMaster[2];
        
        try {
            for (int i = 0; i < 2; i++) {
              try {
                serialPorts[i] = new SerialPort(COMM[i], 9600);
                serialPorts[i].Parity = Parity.None;
                serialPorts[i].StopBits = StopBits.One;
                serialPorts[i].ReadTimeout = 100;
                serialPorts[i].WriteTimeout = 100;
                serialPorts[i].Open();

                modbusSerialMasters[i] = ModbusSerialMaster.CreateRtu(serialPorts[i]);
              } catch (Exception ex) {
                  // 예외처리
              }
            }

            if (modbusClient.Connected) {
                int[] response_data = modbusClient.ReadHoldingRegisters(0, 0x24);
                // 관련 동작 ~~
            } else {
                // 관련 동작 ~~
            }
        } catch (Exception ex) {
            // 예외처리
        }
    }
    
    public void run() {
    	while (true) {
        	int currentPortIndex = ~~~
            if (serialPorts[currentPortIndex].IsOpen) {
                try {
                    ushort[] response_data = modbusSerialMasters[currentPortIndex].ReadHoldingRegisters(#SlaveAddress#, 0, 19);
                    // 관련 동작 ~~
                } catch (Exception ex) {
                    // 예외처리
                }
            } else {
                serialPorts[currentPortIndex].Open();
                if (serialPorts[currentPortIndex].IsOpen)
              	    modbusSerialMasters[currentPortIndex] = ModbusSerialMaster.CreateRtu(serialPorts[currentPortIndex]);
            }
        }
        Thread.Sleep(500);
    }
    
    protected SerialPort[] serialPorts;
    protected ModbusSerialMaster[] modbusSerialMasters;
}

 

큰 차이를 알겠는가?

 

차이는 다음과 같다.

 

  • NModbus4 는 RTU 통신에서 System.IO.Ports 의 SerialPort 를 사용한다.
  • NModbus4 는 ModbusSerialMaster.CreateRtu(System.IO.Ports.SerialPort) 메소드에서 SerialPort 인자를 요구하며 ModbusSerialMaster 로 리턴한다.
  • NModbus4 는 ReadHoldingRegister() 메소드에서 SlaveAddress 를 지정할 수 있다.
    EasyModbus 는 예로 new ModbusClient(); 에서 SlaveAddress 를 지정했다고 보면 된다.
    이로서, 따로 Disconnect 할 필요 없이 한 SerialPort 에서 여러 SlaveAddress 에 있는 데이터를 자유롭게 요청할 수 있다.
  • EasyModbus 는 int[] 로, NModbus4 는 ushort[] 로 리턴한다.

 

필자는 처음에 EasyModbus 를 이용해 온도센서 통신을 구현하였다.

그러고 다른 모듈을 통신하기 위해 EasyModbus 를 이용하여 테스트 중에 문제가 발생했다.

값이 잘 들어오다가 갑자기 마이너스 값이 크게 들어오는 것이다.

 

확인끝에... unsigned 를 사용해야 했었다고 한다.

그래서 다른 라이브러리를 모색하던 중 NModbus4 를 알게 되었고 EasyModbus 보다 더욱 잘 활용하고 있다.

 

 

ps.

사실 맨 처음 Modbus Library 를 찾을 떄 NModbus4 를 보았을 것이다.

그럼에도 당시에 EasyModbus 를 선택한 이유는 문서가 잘 정리되어 있기 때문일 것이다.

 

위에서 언급된 각 라이브러리에 대한 Github 주소목록

EasyModBus : https://github.com/rossmann-engineering/EasyModbusTCP.NET

NModbus4 : https://github.com/NModbus4/NModbus4

NModbus : https://github.com/NModbus/NModbus

728x90
1 2 3