Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| comfilepi:nmodbus4_k:index [2026/02/15 06:05] – [NModbus4 라이브러리 추가] admin | comfilepi:nmodbus4_k:index [Unknown date] (current) – removed - external edit (Unknown date) 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ====== NModbus4 사용법 ====== | ||
| - | |||
| - | 산업현장에서 많이 사용하고 있는 MODBUS 프로토콜을 ComfilePi에서 동작시키는 방법을 알아보겠습니다. Nmodbus4 라이브러리를 이용하면 쉽고 간단하게 MODBUS프로토콜을 구현할 수 있습니다. | ||
| - | \\ | ||
| - | \\ | ||
| - | =====ComfilePi와 PLC 결선 ===== | ||
| - | | ||
| - | |||
| - | ^ {{ : | ||
| - | |||
| - | ※//PLC는 컴파일테크놀로지의 [[https:// | ||
| - | |||
| - | |||
| - | =====NModbus4 라이브러리 추가 ===== | ||
| - | |||
| - | NModbus4 라이브러리를 Visual Studio 2017에 추가하는 방법에 대해 알아보겠습니다. | ||
| - | |||
| - | * 1. 프로젝트를 만든 후 우측의 **" | ||
| - | {{ : | ||
| - | * 2. **" | ||
| - | {{ : | ||
| - | * 3. 출력창에서 NModbus4 라이브러리 설치 상태를 확인 할 수 있습니다. | ||
| - | {{ : | ||
| - | |||
| - | ===== Modbus 프로그래밍 ===== | ||
| - | NModbus4의 Function(함수)와 Serial Port설정에 대해 알아 보겠습니다. | ||
| - | * 1. Serial Port설정 : 데스크탑 PC의 Serial Port와 ComfilePi의 Serial Port는 다릅니다. 프로젝트 코드에 아래와 같이 SerialPort를 설정 해야합니다. | ||
| - | * ※ ComfilePi의 **COM0**는 **"/ | ||
| - | <code xbasic> | ||
| - | string portName = Environment.OSVersion.Platform == PlatformID.Win32NT ? " | ||
| - | SerialPort port = new SerialPort(portName, | ||
| - | port.ReadTimeout = 100; | ||
| - | port.WriteTimeout = 100; | ||
| - | port.Open(); | ||
| - | </ | ||
| - | * 2. ComfilePi를 Master로 사용시 PLC의 상태를 읽어오고 제어할 수 있는 함수입니다. | ||
| - | * ※ ModbusRTU Master는 **ModbusSerialMaster** 클래스를 사용합니다. | ||
| - | <code xbasic> | ||
| - | bool[] ReadCoils(byte slaveAddress, | ||
| - | |||
| - | ushort[] ReadHoldingRegisters(byte slaveAddress, | ||
| - | |||
| - | ushort[] ReadInputRegisters(byte slaveAddress, | ||
| - | |||
| - | bool[] ReadInputs(byte slaveAddress, | ||
| - | |||
| - | ushort[] ReadWriteMultipleRegisters(byte slaveAddress, | ||
| - | |||
| - | void WriteMultipleCoils(byte slaveAddress, | ||
| - | |||
| - | void WriteMultipleRegisters(byte slaveAddress, | ||
| - | |||
| - | void WriteSingleCoil(byte slaveAddress, | ||
| - | |||
| - | void WriteSingleRegister(byte slaveAddress, | ||
| - | |||
| - | </ | ||
| - | * 3. NModbus4 라이브러를 이용해 만든 실행파일(.exe)을 ComfilePi에서 사용하려면 **실행파일(.exe)**과 **NModbus4.dll**를 ComfilePi의 '/ | ||
| - | |||
| - | \\ | ||
| - | |||
| - | ===== 프로그램 ===== | ||
| - | ModbusRTU 프로토콜로, | ||
| - | |||
| - | ====- Example 1==== | ||
| - | 소스코드 다운로드 ☞ {{ : | ||
| - | |||
| - | {{ : | ||
| - | <code xbasic> | ||
| - | using Modbus.Device; | ||
| - | using System; | ||
| - | using System.IO.Ports; | ||
| - | using System.Windows.Forms; | ||
| - | |||
| - | namespace SimpleModbusExample | ||
| - | { | ||
| - | public partial class Form1 : Form | ||
| - | { | ||
| - | const int SLAVE_ADDRESS = 1; | ||
| - | const int COIL_ADDRESS = 32; | ||
| - | |||
| - | public Form1() | ||
| - | { | ||
| - | InitializeComponent(); | ||
| - | } | ||
| - | |||
| - | SerialPort _port; | ||
| - | ModbusSerialMaster _master; | ||
| - | |||
| - | private void Form1_Load(object sender, EventArgs e) | ||
| - | { | ||
| - | // Intialize serial port | ||
| - | string portName = Environment.OSVersion.Platform == PlatformID.Win32NT ? " | ||
| - | _port = new SerialPort(portName, | ||
| - | _port.ReadTimeout = 100; | ||
| - | _port.WriteTimeout = 100; | ||
| - | _port.Open(); | ||
| - | |||
| - | // Initialize Modbus master | ||
| - | _master = ModbusSerialMaster.CreateRtu(_port); | ||
| - | |||
| - | // Read the current state of the output | ||
| - | ReadState(); | ||
| - | } | ||
| - | |||
| - | private void Form1_FormClosed(object sender, FormClosedEventArgs e) | ||
| - | { | ||
| - | // Destroy Modbus master | ||
| - | _master.Dispose(); | ||
| - | _master = null; | ||
| - | |||
| - | // Destroy serial port | ||
| - | _port.Close(); | ||
| - | _port.Dispose(); | ||
| - | _port = null; | ||
| - | } | ||
| - | |||
| - | private void OnButton_Click(object sender, EventArgs e) | ||
| - | { | ||
| - | // Turn output ON | ||
| - | _master.WriteSingleCoil(SLAVE_ADDRESS, | ||
| - | |||
| - | } | ||
| - | |||
| - | private void OffButton_Click(object sender, EventArgs e) | ||
| - | { | ||
| - | // Turn output OFF | ||
| - | _master.WriteSingleCoil(SLAVE_ADDRESS, | ||
| - | } | ||
| - | |||
| - | void ReadState() | ||
| - | { | ||
| - | // Read the current state of the output | ||
| - | var state = _master.ReadCoils(SLAVE_ADDRESS, | ||
| - | |||
| - | // Update the UI | ||
| - | if (state[0]) | ||
| - | { | ||
| - | StateLabel.Text = " | ||
| - | } | ||
| - | else | ||
| - | { | ||
| - | StateLabel.Text = " | ||
| - | } | ||
| - | } | ||
| - | |||
| - | private void ReadStateButton_Click(object sender, EventArgs e) | ||
| - | { | ||
| - | // Read the current state of the output | ||
| - | ReadState(); | ||
| - | } | ||
| - | } | ||
| - | } | ||
| - | </ | ||
| - | |||
| - | \\ | ||
| - | |||
| - | ====- Example 2==== | ||
| - | 소스코드 다운로드 ☞ {{ : | ||
| - | |||
| - | {{ : | ||
| - | <code xbasic> | ||
| - | using System; | ||
| - | using System.Windows.Forms; | ||
| - | using System.IO.Ports; | ||
| - | using Modbus.Device; | ||
| - | using System.Threading; | ||
| - | |||
| - | namespace ModbusExample | ||
| - | { | ||
| - | public partial class Form1 : Form | ||
| - | { | ||
| - | public Form1() | ||
| - | { | ||
| - | InitializeComponent(); | ||
| - | } | ||
| - | |||
| - | private volatile bool _stopModbus; | ||
| - | private Thread _modbusThread; | ||
| - | |||
| - | private void RunModbus() | ||
| - | { | ||
| - | string portName = Environment.OSVersion.Platform == PlatformID.Win32NT ? " | ||
| - | SerialPort port = new SerialPort(portName, | ||
| - | port.ReadTimeout = 100; | ||
| - | port.WriteTimeout = 100; | ||
| - | port.Open(); | ||
| - | |||
| - | _stopModbus = false; | ||
| - | |||
| - | ModbusSerialMaster master = ModbusSerialMaster.CreateRtu(port); | ||
| - | IAsyncResult result = null; | ||
| - | |||
| - | while(!_stopModbus) | ||
| - | { | ||
| - | // Read UI's button states and assign to device' | ||
| - | bool[] outputs = new bool[4]; | ||
| - | result = BeginInvoke(new Action(() => | ||
| - | { | ||
| - | outputs[0] = button1.IsOn; | ||
| - | outputs[1] = button2.IsOn; | ||
| - | outputs[2] = button3.IsOn; | ||
| - | outputs[3] = button4.IsOn; | ||
| - | })); | ||
| - | |||
| - | while (!_stopModbus && !result.IsCompleted) | ||
| - | { | ||
| - | Thread.Yield(); | ||
| - | } | ||
| - | |||
| - | if (!_stopModbus) | ||
| - | { | ||
| - | try | ||
| - | { | ||
| - | master.WriteMultipleCoils(1, | ||
| - | } | ||
| - | catch (Exception ex) | ||
| - | { | ||
| - | Console.WriteLine(ex.Message); | ||
| - | } | ||
| - | } | ||
| - | |||
| - | // Read inputs and assign to UI's Lamps | ||
| - | if (!_stopModbus) | ||
| - | { | ||
| - | try | ||
| - | { | ||
| - | var inputs = master.ReadCoils(1, | ||
| - | |||
| - | result = BeginInvoke(new Action(() => | ||
| - | { | ||
| - | lamp8.IsOn = inputs[3]; | ||
| - | lamp9.IsOn = inputs[2]; | ||
| - | lamp10.IsOn = inputs[1]; | ||
| - | lamp11.IsOn = inputs[0]; | ||
| - | })); | ||
| - | } | ||
| - | catch (Exception ex) | ||
| - | { | ||
| - | Console.WriteLine(ex.Message); | ||
| - | } | ||
| - | } | ||
| - | |||
| - | while (!_stopModbus && !result.IsCompleted) | ||
| - | { | ||
| - | Thread.Yield(); | ||
| - | } | ||
| - | } | ||
| - | |||
| - | master.Dispose(); | ||
| - | |||
| - | port.Close(); | ||
| - | port.Dispose(); | ||
| - | } | ||
| - | |||
| - | private void Form1_Load(object sender, EventArgs e) | ||
| - | { | ||
| - | _modbusThread = new Thread(RunModbus); | ||
| - | _modbusThread.IsBackground = true; | ||
| - | _modbusThread.Start(); | ||
| - | } | ||
| - | |||
| - | private void Form1_FormClosed(object sender, FormClosedEventArgs e) | ||
| - | { | ||
| - | _stopModbus = true; | ||
| - | _modbusThread.Join(); | ||
| - | } | ||
| - | } | ||
| - | } | ||
| - | |||
| - | </ | ||
| - | |||
| - | [[..: | ||
