모드버스 프로토콜을 이용해서 CUWIN과 CUBLOC을 서로 연결하는 방법에 대해서 알아보겠습니다. 아래 그림처럼 CUWIN은 모드버스의 마스터가 되고, CUBLOC은 모드버스 SLAVE가 됩니다.
일체형 모듈인 MSB612RA-DC을 사용하였습니다.
MSB LOGIC 프로그램을 이용해서 다음과 같이 셋팅후 다운로드하시면, CUBLOC쪽은 MODBUS SLAVE로 실행할 수 있는 모든 준비를 마치게 됩니다.
레더로직은 아무것도 없이 그냥 END명령 하나만 넣으시면 됩니다.
CUWIN과 CUBLOC을 연결하는 방법입니다. CUWIN은 CWV-070BR을 사용했습니다.
CUWIN의 RS2323C COM1과 MSB의 RS232C 채널1을 다음과 같이 서로 연결합니다.
MODBUS 프로토콜을 C#으로 일일이 구현하기에는 매우 번거로우므로, 공개된 라이브러리를 활용해서 MODBUS를 구현하도록 하겠습니다. google에서 NMODBUS를 검색하거나, https://code.google.com/p/nmodbus/ 로 이동하십시오.
보시는 것처럼 MODBUS 프로토콜을 다양한 언어환경에서 구현할 수 있도록 라이브러리를 공개하고 있는 사이트입니다.
다운로드탭을 누른뒤, 가장 최근버젼의 바이너리 파일을 다운로드 받으세요. 받은 파일의 압축을 풀고난뒤, netcf 폴더까지 이동을 하시면 아래처럼 4개의 파일이 보입니다. (netcf 는 .Net Compact Framework 라는 뜻입니다.)
이 4개 파일을 비주얼스튜디오의 솔루션탐색기에서 아래 화면처럼 "추가"하십시오.
참조에 해당 파일이 추가된 것을 확인할 수 있습니다.
이제 C#프로그램 쪽을 보도록 하겠습니다.
using Modbus.Device;
using 선언부에 위와 같은 문장을 삽입하세요.
사용할 RS232C포트를 오픈합니다.
_serialPort = new SerialPort("COM1", 115200); _serialPort.Open();
그 다음 ModbusSerialMaster를 초기화 해주는 명령을 써줍니다.
_modbusMaster = ModbusSerialMaster.CreateRtu(_serialPort); _modbusMaster.Transport.ReadTimeout = 500; _modbusMaster.Transport.WriteTimeout = 500; _modbusMaster.Transport.Retries = 0;
이것으로 MODBUS를 사용할 준비는 끝난 것입니다. 이제 아래 메소드중 원하는 메소드를 불러서 사용하시면 됩니다. NMODBUS 에 대해서 구체적인 부분이 알고싶으시면 NMODBUS API 메뉴얼을 참조하세요.
bool[] ReadCoils(byte slaveAddress, ushort startAddress, ushort numberOfPoints); ushort[] ReadHoldingRegisters(byte slaveAddress, ushort startAddress, ushort numberOfPoints); ushort[] ReadInputRegisters(byte slaveAddress, ushort startAddress, ushort numberOfPoints); bool[] ReadInputs(byte slaveAddress, ushort startAddress, ushort numberOfPoints); ushort[] ReadWriteMultipleRegisters(byte slaveAddress, ushort startReadAddress, ushort numberOfPointsToRead, ushort startWriteAddress, ushort[] writeData); void WriteMultipleCoils(byte slaveAddress, ushort startAddress, bool[] data); void WriteMultipleRegisters(byte slaveAddress, ushort startAddress, ushort[] data); void WriteSingleCoil(byte slaveAddress, ushort coilAddress, bool value); void WriteSingleRegister(byte slaveAddress, ushort registerAddress, ushort value);
아래 데모 프로그램은 큐블록 MSB612RA-DC의 포트 하나를 ON 또는 OFF 하거나,A/D값을 읽어오는 예제입니다.
using System; using System.Linq; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Threading; using Modbus.Device; using System.IO.Ports; namespace NModbusTest { public partial class Form1 : Form { public Form1() { InitializeComponent(); } ModbusSerialMaster _modbusMaster; SerialPort _serialPort; const int SLAVE_ADDRESS = 1; private void Form1_Load(object sender, EventArgs e) { _serialPort = new SerialPort("COM1", 115200); _serialPort.Open(); _modbusMaster = ModbusSerialMaster.CreateRtu(_serialPort); _modbusMaster.Transport.ReadTimeout = 500; _modbusMaster.Transport.WriteTimeout = 500; _modbusMaster.Transport.Retries = 0; } void ReportError(string s) { MessageBox.Show(s); } private void ReadADC() { try { ushort[] result = _modbusMaster.ReadInputRegisters(SLAVE_ADDRESS, 276, 1); _adcLabel.Text = result[0].ToString(); } catch (Exception ex) { ReportError(ex.Message); } } private void ReadDigitalOutput() { try { bool[] result = _modbusMaster.ReadCoils(SLAVE_ADDRESS, 32, 1); if (result[0]) { _digitalOutLabel.Text = "ON"; } else { _digitalOutLabel.Text = "OFF"; } } catch (Exception ex) { ReportError(ex.Message); } } private void WriteDigitalOutput(bool on) { try { _modbusMaster.WriteSingleCoil(SLAVE_ADDRESS, 32, on); } catch (Exception ex) { ReportError(ex.Message); } } private void _digitalOutReadButton_Click(object sender, EventArgs e) { ReadDigitalOutput(); } private void _onButton_Click(object sender, EventArgs e) { WriteDigitalOutput(true); } private void _offButton_Click(object sender, EventArgs e) { WriteDigitalOutput(false); } private void _adcReadButton_Click(object sender, EventArgs e) { ReadADC(); } private void Form1_Closing(object sender, CancelEventArgs e) { _modbusMaster.Dispose(); _modbusMaster = null; _serialPort.Close(); _serialPort.Dispose(); _serialPort = null; } } }
다음은 동작 동영상입니다. 프로토콜 아날라이저를 사용해서, CUWIN 과 CUBLOC간의 데이터 통신 상황을 모니터링 하고 있습니다.
한가지 부연설명을 더 하자면, MODBUS 어드레스에 관한 것입니다.
ushort[] result = _modbusMaster.ReadInputRegisters(SLAVE_ADDRESS, 276, 1);
이 메소드는 276번지에서 1 워드를 읽어오는 메소드입니다. MSB의 A/D 채널0의 결과를 저장하는 MODBUS 상의 어드레스가 276번지입니다.
MSB상의 모드버스 어드레스는 다음 표를 참고하세요. MSB LOGIC 사용설명서상에서 발췌한 내용입니다.