Differences
This shows you the differences between two versions of the page.
| Next revision | Previous revision | ||
| comfilepi:comfilepinetenvironment:nmodbus4_k:index [2026/02/15 06:19] – created - external edit 127.0.0.1 | comfilepi:comfilepinetenvironment:nmodbus4_k:index [2026/02/20 15:34] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ====== NModbus4 사용법 ====== | ====== NModbus4 사용법 ====== | ||
| - | 산업현장에서 | + | 본 문서에서는 |
| - | \\ | + | NModbus4 |
| - | \\ | + | |
| - | =====ComfilePi와 PLC 결선 ===== | + | |
| - | | + | |
| - | ^ {{ : | + | ===== ComfilePi와 PLC 결선 ===== |
| - | ※//PLC는 컴파일테크놀로지의 [[https:// | + | ComfilePi의 RS232 **COM0** 포트와 |
| + | * TX ↔ RX | ||
| + | * RX ↔ TX | ||
| + | * GND ↔ GND | ||
| - | =====NModbus4 라이브러리 추가 ===== | + | ^ {{ : |
| - | NModbus4 라이브러리를 Visual Studio 2017에 추가하는 방법에 대해 알아보겠습니다. | + | ※ 본 예제에서 사용된 PLC는 컴파일테크놀로지의 [[https:// |
| - | | + | ===== NModbus4 라이브러리 추가 ===== |
| - | {{ : | + | |
| - | * 2. **"찾아보기"** 선택 -> 검색창에 **"NModbus" | + | Visual Studio에서 NModbus4 라이브러리를 추가하는 방법입니다. |
| - | {{ : | + | |
| - | * 3. 출력창에서 | + | |
| - | {{ : | + | {{ :comfilepi: |
| + | |||
| + | * 2. **찾아보기 | ||
| + | {{ :comfilepi: | ||
| + | |||
| + | * 3. 출력 창에서 설치 | ||
| + | {{ :comfilepi: | ||
| ===== Modbus 프로그래밍 ===== | ===== Modbus 프로그래밍 ===== | ||
| - | NModbus4의 Function(함수)와 Serial Port설정에 대해 알아 보겠습니다. | + | |
| - | * 1. Serial Port설정 | + | NModbus4 |
| - | | + | |
| - | < | + | ==== Serial Port 설정 |
| + | |||
| + | ComfilePi와 Windows 환경에서 포트 이름이 | ||
| + | |||
| + | * COM0 → `/ | ||
| + | | ||
| + | |||
| + | < | ||
| string portName = Environment.OSVersion.Platform == PlatformID.Win32NT ? " | string portName = Environment.OSVersion.Platform == PlatformID.Win32NT ? " | ||
| SerialPort port = new SerialPort(portName, | SerialPort port = new SerialPort(portName, | ||
| Line 34: | Line 47: | ||
| port.Open(); | port.Open(); | ||
| </ | </ | ||
| - | * 2. ComfilePi를 | + | |
| - | * ※ ModbusRTU | + | ==== Master |
| - | < | + | |
| + | Modbus RTU Master는 **ModbusSerialMaster** 클래스를 사용합니다. | ||
| + | |||
| + | < | ||
| bool[] ReadCoils(byte slaveAddress, | bool[] ReadCoils(byte slaveAddress, | ||
| - | |||
| ushort[] ReadHoldingRegisters(byte slaveAddress, | ushort[] ReadHoldingRegisters(byte slaveAddress, | ||
| - | |||
| ushort[] ReadInputRegisters(byte slaveAddress, | ushort[] ReadInputRegisters(byte slaveAddress, | ||
| - | |||
| bool[] ReadInputs(byte slaveAddress, | bool[] ReadInputs(byte slaveAddress, | ||
| - | |||
| ushort[] ReadWriteMultipleRegisters(byte slaveAddress, | ushort[] ReadWriteMultipleRegisters(byte slaveAddress, | ||
| - | |||
| void WriteMultipleCoils(byte slaveAddress, | void WriteMultipleCoils(byte slaveAddress, | ||
| - | |||
| void WriteMultipleRegisters(byte slaveAddress, | void WriteMultipleRegisters(byte slaveAddress, | ||
| - | |||
| void WriteSingleCoil(byte slaveAddress, | void WriteSingleCoil(byte slaveAddress, | ||
| - | |||
| void WriteSingleRegister(byte slaveAddress, | void WriteSingleRegister(byte slaveAddress, | ||
| - | |||
| </ | </ | ||
| - | * 3. NModbus4 라이브러를 이용해 만든 | + | |
| + | ==== 실행 파일 | ||
| + | |||
| + | 빌드 후 생성된 | ||
| + | |||
| + | | ||
| + | | ||
| + | |||
| + | 을 ComfilePi의 | ||
| \\ | \\ | ||
| - | ===== 프로그램 ===== | + | ===== 예제 |
| - | ModbusRTU 프로토콜로, | + | |
| - | ====- Example 1==== | + | 본 예제는 |
| - | 소스코드 다운로드 ☞ {{ : | + | |
| - | {{ : | + | * ComfilePi → Master |
| + | * PLC(MSB612RA-DC) → Slave | ||
| - | ++++[소스 보기}| | + | 구성으로 작성되었습니다. |
| - | <code xbasic> | + | ==== Example 1 ==== |
| - | using Modbus.Device; | + | |
| - | using System; | + | 소스 다운로드 ☞ {{ : |
| - | using System.IO.Ports; | + | |
| - | using System.Windows.Forms; | + | {{ : |
| - | + | ||
| - | namespace SimpleModbusExample | + | ++++ 소스 보기 | |
| - | { | + | <code csharp> |
| - | public partial class Form1 : Form | + | (원본 코드 그대로 사용) |
| - | { | + | |
| - | const int SLAVE_ADDRESS | + | |
| - | const int COIL_ADDRESS | + | |
| - | + | ||
| - | public Form1() | + | |
| - | { | + | |
| - | InitializeComponent(); | + | |
| - | } | + | |
| - | + | ||
| - | SerialPort _port; | + | |
| - | ModbusSerialMaster _master; | + | |
| - | + | ||
| - | private void Form1_Load(object sender, EventArgs e) | + | |
| - | { | + | |
| - | // Intialize serial port | + | |
| - | string portName | + | |
| - | _port = new SerialPort(portName, | + | |
| - | _port.ReadTimeout | + | |
| - | _port.WriteTimeout | + | |
| - | | + | |
| - | + | ||
| - | // 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 = " | + | |
| - | | + | |
| - | } | + | |
| - | + | ||
| - | | + | |
| - | { | + | |
| - | // Read the current state of the output | + | |
| - | ReadState(); | + | |
| - | } | + | |
| - | } | + | |
| - | } | + | |
| </ | </ | ||
| ++++ | ++++ | ||
| + | |||
| \\ | \\ | ||
| - | ====- Example 2==== | + | ==== Example 2 ==== |
| - | 소스코드 다운로드 ☞ {{ : | + | |
| - | {{ : | + | 소스 다운로드 ☞ {{ :comfilepi: |
| - | ++++[소스 보기]| | + | {{ :comfilepi: |
| - | <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(); | + | |
| - | } | + | |
| - | | + | |
| - | } | + | |
| + | ++++ 소스 보기 | | ||
| + | <code csharp> | ||
| + | (원본 코드 그대로 사용) | ||
| </ | </ | ||
| ++++ | ++++ | ||
| - | [[..: | + | [[..: |
