산업용 통신 프로토콜
책 PLC 데이터 통신(구민사) 참고
PLC 수치체계
bit : 0 or 1(참 or 거짓)을 표현할 수 있는 기본 데이터 단위 (ex. P0~, M0~ 등이 해당)
byte : 1byte = 8bit = 2의 8승
word : 1word = 2byte = 16bit
double word : 1 double word = 2 word = 4byte = 32bit
P영역 : 기본적으로 I/O(Input/Output) 할당이 되는 메모리
모드버스 TCP IP 프로토콜 구조
FCode : BitMemory에 값을 읽을 건지(BitRead 0x01)
BitMemory에 값을 읽을 건지(BitRead 0x05)
WordMemory에 값을 읽을 건지(WordRead 0x03)
WordMemory에 값을 읽을 건지(WordRead 0x06)
Data : 몇번 Address의 값, 몇 개를 읽을 건지 or 몇번 Address에 무슨 값을 쓸 건지
TID, PID는 디바이스에서 제공하는 메뉴얼을 참고하여 값을 바꾸면 된다.
출력/입력 영역 워드 읽기
Form1.cs
\Desktop\IOT\visual studio edukitTest\modbus_wordRead\modbus_wordRead
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace modbus_wordRead
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void BT_Read_Click(object sender, EventArgs e)
{
BT_Stop.Enabled = true;
BT_Read.Enabled = false;
timer1.Enabled = true;
timer1.Interval = 100;
}
private void BT_Stop_Click(object sender, EventArgs e)
{
BT_Read.Enabled = true;
BT_Stop.Enabled = false;
timer1.Enabled = false;
}
private void timer1_Tick(object sender, EventArgs e)
{
byte[] SendData = new byte[]
{
0x00, 0x00, // TID
0x00, 0x00, // PID
0x00, 0x06, // Length
0x01, // UID
0x03, // 기능코드
0x00, 0x00, // 시작번지 = 00
0x00, 0x02 // Word 개수 = 2
};
SendMessage(SendData); // Data 전송 및 읽기
}
private void SendMessage(byte[] SendData)
{
//소켓 생성
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sock.SendTimeout = 3000;
sock.ReceiveTimeout = 3000;
IPAddress serverIP = IPAddress.Parse("192.168.0.120");
int serverPort = 502;
IPEndPoint ipep = new IPEndPoint(serverIP, serverPort);
sock.Connect(ipep);
if (sock.Connected)
{
sock.Send(SendData);
TB_SendFrame.Text = BitConverter.ToString(SendData);
Thread.Sleep(10);
byte[] _data = new byte[15];
sock.Receive(_data);
DataRead(_data);
}
sock.Close();
}
private void DataRead(byte[] ReadData)
{
int bytes = ReadData.Length;
if (bytes >= 9)
{
if (ReadData[7] != 0x83) // 0x83: 에러코드 => 에러코드가 아닐 때만
{
WordDataDisplay(ReadData);
TB_ReceivedFrame.Text = BitConverter.ToString(ReadData);
}
}
}
private void WordDataDisplay(byte[] ReadData)
{
byte[] RData0 = new byte[] { ReadData[10], ReadData[9] };
TB_D0.Text = Convert.ToString(BitConverter.ToInt16(RData0, 0));
byte[] RData1 = new byte[] { ReadData[12], ReadData[11], ReadData[14], ReadData[13] };
TB_D1.Text = Convert.ToString(BitConverter.ToInt32(RData1, 0));
TB_ReceivedFrame.Text = BitConverter.ToString(ReadData);
}
}
}
Form1.Designer.cs
\Desktop\IOT\visual studio edukitTest\modbus_wordRead\modbus_wordRead
namespace modbus_wordRead
{
partial class Form1
{
/// <summary>
/// 필수 디자이너 변수입니다.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 사용 중인 모든 리소스를 정리합니다.
/// </summary>
/// <param name="disposing">관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form 디자이너에서 생성한 코드
/// <summary>
/// 디자이너 지원에 필요한 메서드입니다.
/// 이 메서드의 내용을 코드 편집기로 수정하지 마세요.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.TB_D1 = new System.Windows.Forms.TextBox();
this.TB_C0 = new System.Windows.Forms.TextBox();
this.TB_ReceivedFrame = new System.Windows.Forms.TextBox();
this.TB_SendFrame = new System.Windows.Forms.TextBox();
this.label4 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.label1 = new System.Windows.Forms.Label();
this.BT_Read = new System.Windows.Forms.Button();
this.BT_Stop = new System.Windows.Forms.Button();
this.timer1 = new System.Windows.Forms.Timer(this.components);
this.groupBox1.SuspendLayout();
this.SuspendLayout();
//
// groupBox1
//
this.groupBox1.Controls.Add(this.TB_D1);
this.groupBox1.Controls.Add(this.TB_C0);
this.groupBox1.Controls.Add(this.TB_ReceivedFrame);
this.groupBox1.Controls.Add(this.TB_SendFrame);
this.groupBox1.Controls.Add(this.label4);
this.groupBox1.Controls.Add(this.label3);
this.groupBox1.Controls.Add(this.label2);
this.groupBox1.Controls.Add(this.label1);
this.groupBox1.Controls.Add(this.BT_Read);
this.groupBox1.Controls.Add(this.BT_Stop);
this.groupBox1.Location = new System.Drawing.Point(0, 12);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(322, 257);
this.groupBox1.TabIndex = 0;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Modbus TCP(03)";
//
// TB_D1
//
this.TB_D1.Location = new System.Drawing.Point(92, 215);
this.TB_D1.Name = "TB_D1";
this.TB_D1.Size = new System.Drawing.Size(206, 21);
this.TB_D1.TabIndex = 10;
//
// TB_C0
//
this.TB_C0.Location = new System.Drawing.Point(92, 181);
this.TB_C0.Name = "TB_C0";
this.TB_C0.Size = new System.Drawing.Size(206, 21);
this.TB_C0.TabIndex = 9;
//
// TB_ReceivedFrame
//
this.TB_ReceivedFrame.Location = new System.Drawing.Point(27, 147);
this.TB_ReceivedFrame.Name = "TB_ReceivedFrame";
this.TB_ReceivedFrame.Size = new System.Drawing.Size(271, 21);
this.TB_ReceivedFrame.TabIndex = 8;
//
// TB_SendFrame
//
this.TB_SendFrame.Location = new System.Drawing.Point(27, 99);
this.TB_SendFrame.Name = "TB_SendFrame";
this.TB_SendFrame.Size = new System.Drawing.Size(271, 21);
this.TB_SendFrame.TabIndex = 7;
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(24, 219);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(65, 12);
this.label4.TabIndex = 6;
this.label4.Text = "D1(DWord)";
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(23, 187);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(58, 12);
this.label3.TabIndex = 5;
this.label3.Text = "C0(Word)";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(26, 132);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(69, 12);
this.label2.TabIndex = 4;
this.label2.Text = "수신 Frame";
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(26, 84);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(69, 12);
this.label1.TabIndex = 3;
this.label1.Text = "송신 Frame";
//
// BT_Read
//
this.BT_Read.Location = new System.Drawing.Point(27, 30);
this.BT_Read.Name = "BT_Read";
this.BT_Read.Size = new System.Drawing.Size(128, 37);
this.BT_Read.TabIndex = 1;
this.BT_Read.Text = "읽기";
this.BT_Read.UseVisualStyleBackColor = true;
this.BT_Read.Click += new System.EventHandler(this.BT_Read_Click);
//
// BT_Stop
//
this.BT_Stop.Location = new System.Drawing.Point(172, 30);
this.BT_Stop.Name = "BT_Stop";
this.BT_Stop.Size = new System.Drawing.Size(126, 37);
this.BT_Stop.TabIndex = 2;
this.BT_Stop.Text = "정지";
this.BT_Stop.UseVisualStyleBackColor = true;
this.BT_Stop.Click += new System.EventHandler(this.BT_Stop_Click);
//
// timer1
//
this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(336, 281);
this.Controls.Add(this.groupBox1);
this.Name = "Form1";
this.Text = "Form1";
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.TextBox TB_D1;
private System.Windows.Forms.TextBox TB_C0;
private System.Windows.Forms.TextBox TB_ReceivedFrame;
private System.Windows.Forms.TextBox TB_SendFrame;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button BT_Read;
private System.Windows.Forms.Button BT_Stop;
private System.Windows.Forms.Timer timer1;
}
}
결과
생산량 리미트 값 읽어오기
StartAddress 값 변경
Form1.cs
\Desktop\IOT\visual studio edukitTest\modbus_wordRead\modbus_wordRead
private void timer1_Tick(object sender, EventArgs e)
{
byte[] SendData = new byte[]
{
0x00, 0x00, // TID
0x00, 0x00, // PID
0x00, 0x06, // Length
0x01, // UID
0x03, // 기능코드
// 0x00, 0x00, // 시작번지 = 00
0x27, 0x10, // 시작번지 = D10000 => 생산량 리미트
0x00, 0x02 // Word 개수 = 2
};
SendMessage(SendData); // Data 전송 및 읽기
}
결과
D0, D10000에 Word 쓰기
Form1.cs
\Desktop\IOT\visual studio edukitTest\modbus_wordWrite\modbus_wordWrite
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace modbus_wordWrite
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Send_bt_Click(object sender, EventArgs e)
{
byte[] SendData = new byte[]
{
0x00,0x00, //TID
0x00,0x00, //PID
0x00,0x06, //Length
0x01, //UID
0x06, //Fcode 기능 뭐할지? 워드값 write
0x00,0x00, //시작 번지
//tb_d0있는 값이 SendData 합쳐짐
};
byte[] Data_W = BitConverter.GetBytes(Convert.ToInt16(TB_D0.Text));
byte[] Data = new byte[] { Data_W[1], Data_W[0] };
SendData = Combine(SendData, Data);
SendMessage(SendData);
}
private void Send_bt2_Click(object sender, EventArgs e)
{
byte[] SendData = new byte[]
{
0x00,0x00, //TID
0x00,0x00, //PID
0x00,0x06, //Length
0x01, //UID
0x06, //Fcode 기능 뭐할지? 워드값 write
0x27,0x10, //시작 번지 Address
// D1000 0
};
byte[] Data_W = BitConverter.GetBytes(Convert.ToInt16(TB_D10000.Text));
byte[] Data = new byte[] { Data_W[1], Data_W[0] };
SendData = Combine(SendData, Data);
SendMessage(SendData);
}
private void SendMessage(byte[] SendData)
{
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sock.SendTimeout = 3000;
sock.ReceiveTimeout = 3000;
IPAddress serverIP = IPAddress.Parse("192.168.0.120"); //string 을 ip주소체계로 바꿔줌
int serverPort = 502;
IPEndPoint ipep = new IPEndPoint(serverIP, serverPort);
sock.Connect(ipep); //연결 시도
if (sock.Connected)
{
sock.Send(SendData);
TB_SendFrame.Text = BitConverter.ToString(SendData); //내가 뭘 보냈는지 TB_SENDFrame라는 Textbox에 찍어줌
}
sock.Close();
}
private byte[] Combine(byte[] a, byte[] b)
{
byte[] c = new byte[a.Length + b.Length];
Buffer.BlockCopy(a, 0, c, 0, a.Length);
Buffer.BlockCopy(b,0, c, a.Length, b.Length);
return c;
}
}
}
Form1.Designer.cs
\Desktop\IOT\visual studio edukitTest\modbus_wordWrite\modbus_wordWrite
namespace modbus_wordWrite
{
partial class Form1
{
/// <summary>
/// 필수 디자이너 변수입니다.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 사용 중인 모든 리소스를 정리합니다.
/// </summary>
/// <param name="disposing">관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form 디자이너에서 생성한 코드
/// <summary>
/// 디자이너 지원에 필요한 메서드입니다.
/// 이 메서드의 내용을 코드 편집기로 수정하지 마세요.
/// </summary>
private void InitializeComponent()
{
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.BT_WriteD10000 = new System.Windows.Forms.Button();
this.label3 = new System.Windows.Forms.Label();
this.TB_D10000 = new System.Windows.Forms.TextBox();
this.TB_SendFrame = new System.Windows.Forms.TextBox();
this.label2 = new System.Windows.Forms.Label();
this.BT_WriteD0 = new System.Windows.Forms.Button();
this.TB_D0 = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.groupBox1.SuspendLayout();
this.SuspendLayout();
//
// groupBox1
//
this.groupBox1.Controls.Add(this.BT_WriteD10000);
this.groupBox1.Controls.Add(this.label3);
this.groupBox1.Controls.Add(this.TB_D10000);
this.groupBox1.Controls.Add(this.TB_SendFrame);
this.groupBox1.Controls.Add(this.label2);
this.groupBox1.Controls.Add(this.BT_WriteD0);
this.groupBox1.Controls.Add(this.TB_D0);
this.groupBox1.Controls.Add(this.label1);
this.groupBox1.Location = new System.Drawing.Point(12, 12);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(326, 240);
this.groupBox1.TabIndex = 0;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "groupBox1";
//
// BT_WriteD10000
//
this.BT_WriteD10000.Location = new System.Drawing.Point(6, 149);
this.BT_WriteD10000.Name = "BT_WriteD10000";
this.BT_WriteD10000.Size = new System.Drawing.Size(300, 23);
this.BT_WriteD10000.TabIndex = 7;
this.BT_WriteD10000.Text = "쓰기";
this.BT_WriteD10000.UseVisualStyleBackColor = true;
this.BT_WriteD10000.Click += new System.EventHandler(this.BT_WriteD10000_Click);
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(9, 116);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(81, 12);
this.label3.TabIndex = 6;
this.label3.Text = "D10000(word)";
//
// TB_D10000
//
this.TB_D10000.Location = new System.Drawing.Point(96, 112);
this.TB_D10000.Name = "TB_D10000";
this.TB_D10000.Size = new System.Drawing.Size(216, 21);
this.TB_D10000.TabIndex = 5;
//
// TB_SendFrame
//
this.TB_SendFrame.Location = new System.Drawing.Point(6, 204);
this.TB_SendFrame.Name = "TB_SendFrame";
this.TB_SendFrame.Size = new System.Drawing.Size(300, 21);
this.TB_SendFrame.TabIndex = 4;
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(10, 184);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(69, 12);
this.label2.TabIndex = 3;
this.label2.Text = "송신 Frame";
//
// BT_WriteD0
//
this.BT_WriteD0.Location = new System.Drawing.Point(11, 70);
this.BT_WriteD0.Name = "BT_WriteD0";
this.BT_WriteD0.Size = new System.Drawing.Size(300, 23);
this.BT_WriteD0.TabIndex = 2;
this.BT_WriteD0.Text = "쓰기";
this.BT_WriteD0.UseVisualStyleBackColor = true;
this.BT_WriteD0.Click += new System.EventHandler(this.BT_WriteD0_Click);
//
// TB_D0
//
this.TB_D0.Location = new System.Drawing.Point(96, 30);
this.TB_D0.Name = "TB_D0";
this.TB_D0.Size = new System.Drawing.Size(216, 21);
this.TB_D0.TabIndex = 1;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(10, 33);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(57, 12);
this.label1.TabIndex = 0;
this.label1.Text = "D0(word)";
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(357, 264);
this.Controls.Add(this.groupBox1);
this.Name = "Form1";
this.Text = "Form1";
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.TextBox TB_SendFrame;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Button BT_WriteD0;
private System.Windows.Forms.TextBox TB_D0;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.TextBox TB_D10000;
private System.Windows.Forms.Button BT_WriteD10000;
}
}
결과
Mqtt 메세지 받으면 생산량 리미트 D10000에 데이터 쓰기
(Mqtt value를 받아서 그 값을 write)
맨 위의 Form 부분에 MQTT 연결 코드 추가
(어젠 Form oad에 적었었는데 여기에 적어도 된다.)
Form1.cs
\Desktop\IOT\visual studio edukitTest\modbus_wordWrite\modbus_wordWrite
public partial class Form1 : Form
{
static MqttClient mqttClient;
public Form1()
{
InitializeComponent();
// form 더블클릭하여 자동생성 했음
//form load 될때 mqtt가 연결 시도를 할 수 있도록 여기 작성
mqttClient = new MqttClient("localhost", 1883, false, null, null, MqttSslProtocols.TLSv1_2); // 로컬호스트의 1883 포트에 연결
mqttClient.ProtocolVersion = MqttProtocolVersion.Version_3_1_1; // 기본값 3.1.1, 버전이 맞아야 연결된다.
mqttClient.MqttMsgPublishReceived += MqttClient_MqttMsgPublishReceived;
//mqttClient.ConnectionClosed += MqttClient_ConnectionClosed;
byte code = mqttClient.Connect(Guid.NewGuid().ToString()); // clientID
mqttClient.Subscribe(new string[] { "test" },
new byte[] { MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE });
}
subscribe 받아서 뭘 할지 명령 추가
private void MqttClient_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
{
// mqtt 데이터 신호 받았을 때(subscribe) 무슨 처리를 할 지 작성하는 메소드
string mes = Encoding.Default.GetString(e.Message);
Console.WriteLine(mes);
byte[] SendData = new byte[]
{
0x00, 0x00,
0x00, 0x00,
0x00, 0x06,
0x01,
0x06,
0x27, 0x10, // D10000
};
byte[] Data_W = BitConverter.GetBytes(Convert.ToInt16(mes));
byte[] Data = new byte[] { Data_W[1], Data_W[0] };
SendData = Combine(SendData, Data);
SendMessage(SendData);
}
난 짤 때 SendData에 대체 뭘 넣어야하나 고민했는데 그냥 위처럼 넣어서 mes로만 해주면 되는 거였다...
근데 이렇게 하면 소켓서버쪽에 어제도 발생했던 에러가 발생한다.
invoke를 붙여서 해결
this.Invoke(new Action(() =>
{
TB_SendFrame.Text = BitConverter.ToString(SendData);
}));
결과
이더넷 전용 통신
서버 모드 변경
XG5000 - 내장~FEnet
변경해주고 쓰기(링크인에이블 체크 해제)해주면 된다.
TCP 포트번호
(modbus는 502를 썼다)
XGT 전용 프로토콜 구성
고정영역은 건드리지 않는다.
XGT 통신으로 BIT 읽기
Form1.cs
\Desktop\IOT\visual studio edukitTest\XGT_BitRead\XGT_BitRead
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace XGT_WordRead
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Form(true);
}
private void BT_Read_Click(object sender, EventArgs e)
{
Form(false);
timer1.Enabled = true;
timer1.Interval = 100;
}
private void BT_Stop_Click(object sender, EventArgs e)
{
Form(true);
timer1.Enabled = false;
}
private void Form(bool t)
{
BT_Read.Enabled = t;
BT_Stop.Enabled = !t;
}
private void timer1_Tick(object sender, EventArgs e)
{
byte[] DataFrame = MakeDataFrame();
byte[] SendFrame = MakeCompanyFrame(DataFrame);
SendFrame = Combine(SendFrame, DataFrame);
SendMessage(SendFrame);
}
private byte[] MakeDataFrame() // command에 해당
{
byte[] DataFrame = new byte[]
{
0x54, 0x00, // 명령어(읽기)
0x02, 0x00, // 데이터 타입 = Word
0x00, 0x00, // 예약 영역(고정)
0x03, 0x00 // 읽어올 변수개수 = 3
};
byte[] VariableBlock = MakeVariableBlock();
DataFrame = Combine(DataFrame, VariableBlock);
return DataFrame;
}
private byte[] MakeVariableBlock()
{
byte[] VariableBlock = new byte[0];
VariableBlock = MakeBlock("%CW00", VariableBlock); // bit면 X, Word면 W
VariableBlock = MakeBlock("%DW00", VariableBlock);
VariableBlock = MakeBlock("%DW10", VariableBlock);
return VariableBlock;
}
private byte[] MakeBlock(string VariableName, byte[] VariableBlock)
{
byte[] VariableLength = new byte[2] { 0x05, 0x00 }; // 변수명 길이 : %부터 세면 %DW10 총 5글자
VariableBlock = Combine(VariableBlock, VariableLength);
byte[] Variable = Encoding.Default.GetBytes(VariableName);
VariableBlock = Combine(VariableBlock, Variable);
return VariableBlock;
}
private byte[] MakeCompanyFrame(byte[] DataFrame) // Company
{
string Company_ID = "LSIS-XGT";
byte[] CompanyFrame = Encoding.Default.GetBytes(Company_ID);
byte[] CPU_Info = new byte[]
{
0x00, 0x00, // 예비
0x00, 0x00, // PLC 정보
0xB0, // XGB(MK)
0x33, // 프레임 방향 = PC->PLC
0x00, 0x00 // 프레임 순서 번호 = 0번
};
CompanyFrame = Combine(CompanyFrame, CPU_Info);
byte[] Length = new byte[] { (byte)DataFrame.Length, 0x00 }; // 데이터의 길이(바이트 수)
CompanyFrame = Combine(CompanyFrame, Length);
byte[] FEnetPosition = new byte[] { 0x01 }; // 0번 베이스, 1번 슬롯
CompanyFrame = Combine(CompanyFrame, FEnetPosition);
byte[] BCC = new byte[1];
ushort crc = Calc(CompanyFrame);
BCC[0] = (byte)crc; // 맨 밑의 crc 체크섬
CompanyFrame = Combine(CompanyFrame, BCC);
return CompanyFrame;
}
private void SendMessage(byte[] SendFrame)
{
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sock.SendTimeout = 3000;
sock.ReceiveTimeout = 3000;
IPAddress serverIP = IPAddress.Parse("192.168.0.120");
int serverPort = 2004; // modbus는 502
IPEndPoint ipep = new IPEndPoint(serverIP, serverPort);
if (sock.IsBound == true) sock.Close();
sock.Connect(ipep);
if (sock.Connected)
{
sock.Send(SendFrame);
TB_SendFrame.Text = BitConverter.ToString(SendFrame);
byte[] Rdata = new byte[100];
sock.Receive(Rdata);
TB_ReceivedFrame.Text = BitConverter.ToString(Rdata);
ReceivedDataProcessing(Rdata);
}
sock.Close();
}
private void ReceivedDataProcessing(byte[] RData)
{
short Datas = BitConverter.ToInt16(RData, 32); // 앞의 데이터는 다 쓸모 없어서 스킵
TB_C0.Text = Datas.ToString();
Datas = BitConverter.ToInt16(RData, 36); // 데이터 + 데이터크기(2) = 3씩 더하면 됨(데이터 크기도 쓸모 없어서 스킵)
TB_D0.Text = Datas.ToString();
Datas = BitConverter.ToInt16(RData, 40);
TB_D10.Text = Datas.ToString();
}
private byte[] Combine(byte[] a, byte[] b) // 바이트 합치기
{
byte[] c = new byte[a.Length + b.Length];
Buffer.BlockCopy(a, 0, c, 0, a.Length);
Buffer.BlockCopy(b, 0, c, a.Length, b.Length);
return c;
}
private static ushort Calc(byte[] data) // CRC코드 생성
{
ushort crc = 0xFFFF;
for (int pos = 0; pos < data.Length; pos++)
{
crc ^= (UInt16)data[pos];
for (int i = 8; i != 0; i--)
{
if ((crc & 0x0001) != 0)
{
crc >>= 1;
crc ^= 0xA001;
}
else crc >>= 1;
}
}
return crc;
}
}
}
Form1.Designer.cs
\Desktop\IOT\visual studio edukitTest\XGT_BitRead\XGT_BitRead
namespace XGT_BitRead
{
partial class Form1
{
/// <summary>
/// 필수 디자이너 변수입니다.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 사용 중인 모든 리소스를 정리합니다.
/// </summary>
/// <param name="disposing">관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form 디자이너에서 생성한 코드
/// <summary>
/// 디자이너 지원에 필요한 메서드입니다.
/// 이 메서드의 내용을 코드 편집기로 수정하지 마세요.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.BT_Read = new System.Windows.Forms.Button();
this.BT_Stop = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.TB_ReceivedFrame = new System.Windows.Forms.TextBox();
this.CB_M100 = new System.Windows.Forms.CheckBox();
this.CB_M101 = new System.Windows.Forms.CheckBox();
this.CB_M102 = new System.Windows.Forms.CheckBox();
this.CB_M103 = new System.Windows.Forms.CheckBox();
this.CB_P27 = new System.Windows.Forms.CheckBox();
this.CB_P26 = new System.Windows.Forms.CheckBox();
this.CB_P25 = new System.Windows.Forms.CheckBox();
this.CB_P24 = new System.Windows.Forms.CheckBox();
this.timer1 = new System.Windows.Forms.Timer(this.components);
this.TB_SendFrame = new System.Windows.Forms.TextBox();
this.groupBox1.SuspendLayout();
this.SuspendLayout();
//
// groupBox1
//
this.groupBox1.Controls.Add(this.CB_P27);
this.groupBox1.Controls.Add(this.CB_P26);
this.groupBox1.Controls.Add(this.CB_P25);
this.groupBox1.Controls.Add(this.CB_P24);
this.groupBox1.Controls.Add(this.CB_M103);
this.groupBox1.Controls.Add(this.CB_M102);
this.groupBox1.Controls.Add(this.CB_M101);
this.groupBox1.Controls.Add(this.CB_M100);
this.groupBox1.Controls.Add(this.TB_ReceivedFrame);
this.groupBox1.Controls.Add(this.TB_SendFrame);
this.groupBox1.Controls.Add(this.label2);
this.groupBox1.Controls.Add(this.label1);
this.groupBox1.Controls.Add(this.BT_Stop);
this.groupBox1.Controls.Add(this.BT_Read);
this.groupBox1.Location = new System.Drawing.Point(12, 12);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(398, 228);
this.groupBox1.TabIndex = 0;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "BIT 개별 읽기";
//
// BT_Read
//
this.BT_Read.Location = new System.Drawing.Point(18, 32);
this.BT_Read.Name = "BT_Read";
this.BT_Read.Size = new System.Drawing.Size(171, 37);
this.BT_Read.TabIndex = 1;
this.BT_Read.Text = "읽기";
this.BT_Read.UseVisualStyleBackColor = true;
this.BT_Read.Click += new System.EventHandler(this.BT_Read_Click);
//
// BT_Stop
//
this.BT_Stop.Location = new System.Drawing.Point(205, 32);
this.BT_Stop.Name = "BT_Stop";
this.BT_Stop.Size = new System.Drawing.Size(173, 37);
this.BT_Stop.TabIndex = 2;
this.BT_Stop.Text = "정지";
this.BT_Stop.UseVisualStyleBackColor = true;
this.BT_Stop.Click += new System.EventHandler(this.BT_Stop_Click);
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(16, 83);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(69, 12);
this.label1.TabIndex = 3;
this.label1.Text = "송신 Frame";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(16, 140);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(69, 12);
this.label2.TabIndex = 4;
this.label2.Text = "수신 Frame";
//
// TB_SendFrame
//
this.TB_SendFrame.Name = "TB_SendFrame";
this.TB_SendFrame.Size = new System.Drawing.Size(360, 21);
this.TB_SendFrame.TabIndex = 5;
this.TB_SendFrame.Location = new System.Drawing.Point(18, 103);
//
// TB_ReceivedFrame
//
this.TB_ReceivedFrame.Location = new System.Drawing.Point(18, 158);
this.TB_ReceivedFrame.Name = "TB_ReceivedFrame";
this.TB_ReceivedFrame.Size = new System.Drawing.Size(360, 21);
this.TB_ReceivedFrame.TabIndex = 6;
//
// CB_M100
//
this.CB_M100.AutoSize = true;
this.CB_M100.CheckAlign = System.Drawing.ContentAlignment.TopCenter;
this.CB_M100.Location = new System.Drawing.Point(18, 196);
this.CB_M100.Name = "CB_M100";
this.CB_M100.RightToLeft = System.Windows.Forms.RightToLeft.No;
this.CB_M100.Size = new System.Drawing.Size(38, 30);
this.CB_M100.TabIndex = 7;
this.CB_M100.Text = "M100";
this.CB_M100.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
this.CB_M100.UseVisualStyleBackColor = true;
//
// CB_M101
//
this.CB_M101.AutoSize = true;
this.CB_M101.CheckAlign = System.Drawing.ContentAlignment.TopCenter;
this.CB_M101.Location = new System.Drawing.Point(62, 196);
this.CB_M101.Name = "CB_M101";
this.CB_M101.RightToLeft = System.Windows.Forms.RightToLeft.No;
this.CB_M101.Size = new System.Drawing.Size(38, 30);
this.CB_M101.TabIndex = 8;
this.CB_M101.Text = "M101";
this.CB_M101.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
this.CB_M101.UseVisualStyleBackColor = true;
//
// CB_M102
//
this.CB_M102.AutoSize = true;
this.CB_M102.CheckAlign = System.Drawing.ContentAlignment.TopCenter;
this.CB_M102.Location = new System.Drawing.Point(106, 196);
this.CB_M102.Name = "CB_M102";
this.CB_M102.RightToLeft = System.Windows.Forms.RightToLeft.No;
this.CB_M102.Size = new System.Drawing.Size(38, 30);
this.CB_M102.TabIndex = 9;
this.CB_M102.Text = "M102";
this.CB_M102.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
this.CB_M102.UseVisualStyleBackColor = true;
//
// CB_M103
//
this.CB_M103.AutoSize = true;
this.CB_M103.CheckAlign = System.Drawing.ContentAlignment.TopCenter;
this.CB_M103.Location = new System.Drawing.Point(151, 196);
this.CB_M103.Name = "CB_M103";
this.CB_M103.RightToLeft = System.Windows.Forms.RightToLeft.No;
this.CB_M103.Size = new System.Drawing.Size(38, 30);
this.CB_M103.TabIndex = 10;
this.CB_M103.Text = "M103";
this.CB_M103.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
this.CB_M103.UseVisualStyleBackColor = true;
//
// CB_P27
//
this.CB_P27.AutoSize = true;
this.CB_P27.CheckAlign = System.Drawing.ContentAlignment.TopCenter;
this.CB_P27.Location = new System.Drawing.Point(340, 196);
this.CB_P27.Name = "CB_P27";
this.CB_P27.RightToLeft = System.Windows.Forms.RightToLeft.No;
this.CB_P27.Size = new System.Drawing.Size(29, 30);
this.CB_P27.TabIndex = 14;
this.CB_P27.Text = "P27";
this.CB_P27.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
this.CB_P27.UseVisualStyleBackColor = true;
//
// CB_P26
//
this.CB_P26.AutoSize = true;
this.CB_P26.CheckAlign = System.Drawing.ContentAlignment.TopCenter;
this.CB_P26.Location = new System.Drawing.Point(295, 196);
this.CB_P26.Name = "CB_P26";
this.CB_P26.RightToLeft = System.Windows.Forms.RightToLeft.No;
this.CB_P26.Size = new System.Drawing.Size(29, 30);
this.CB_P26.TabIndex = 13;
this.CB_P26.Text = "P26";
this.CB_P26.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
this.CB_P26.UseVisualStyleBackColor = true;
//
// CB_P25
//
this.CB_P25.AutoSize = true;
this.CB_P25.CheckAlign = System.Drawing.ContentAlignment.TopCenter;
this.CB_P25.Location = new System.Drawing.Point(251, 196);
this.CB_P25.Name = "CB_P25";
this.CB_P25.RightToLeft = System.Windows.Forms.RightToLeft.No;
this.CB_P25.Size = new System.Drawing.Size(29, 30);
this.CB_P25.TabIndex = 12;
this.CB_P25.Text = "P25";
this.CB_P25.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
this.CB_P25.UseVisualStyleBackColor = true;
//
// CB_P24
//
this.CB_P24.AutoSize = true;
this.CB_P24.CheckAlign = System.Drawing.ContentAlignment.TopCenter;
this.CB_P24.Location = new System.Drawing.Point(207, 196);
this.CB_P24.Name = "CB_P24";
this.CB_P24.RightToLeft = System.Windows.Forms.RightToLeft.No;
this.CB_P24.Size = new System.Drawing.Size(29, 30);
this.CB_P24.TabIndex = 11;
this.CB_P24.Text = "P24";
this.CB_P24.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
this.CB_P24.UseVisualStyleBackColor = true;
//
// timer1
//
this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(420, 250);
this.Controls.Add(this.groupBox1);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.CheckBox CB_P27;
private System.Windows.Forms.CheckBox CB_P26;
private System.Windows.Forms.CheckBox CB_P25;
private System.Windows.Forms.CheckBox CB_P24;
private System.Windows.Forms.CheckBox CB_M103;
private System.Windows.Forms.CheckBox CB_M102;
private System.Windows.Forms.CheckBox CB_M101;
private System.Windows.Forms.CheckBox CB_M100;
private System.Windows.Forms.TextBox TB_SendFrame;
private System.Windows.Forms.TextBox TB_ReceivedFrame;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button BT_Stop;
private System.Windows.Forms.Button BT_Read;
private System.Windows.Forms.Timer timer1;
}
}
이 코드 실행할 때 SendFrame에서 자꾸 에러가 났었는데 디자인cs파일에서 SendFrame이 요상하게 되어있었다(this는 빠지고 두개가 있질 않나...) ReceivedFrame 참고해서 수정해주니 잘 작동했다.
결과
XGT 통신으로 Word 읽기
Form1.cs
\Desktop\IOT\visual studio edukitTest\XGT_BitRead\XGT_WordRead
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace XGT_BitRead
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Form(true);
}
private void BT_Read_Click(object sender, EventArgs e)
{
Form(false);
timer1.Enabled = true;
timer1.Interval = 100;
}
private void BT_Stop_Click(object sender, EventArgs e)
{
Form(true);
timer1.Enabled = false;
}
private void Form(bool t)
{
BT_Read.Enabled = t;
BT_Stop.Enabled = !t;
}
private void timer1_Tick(object sender, EventArgs e)
{
byte[] DataFrame = MakeDataFrame();
byte[] SendFrame = MakeCompanyFrame(DataFrame);
SendFrame = Combine(SendFrame, DataFrame);
SendMessage(SendFrame);
}
private byte[] MakeDataFrame() // command에 해당
{
byte[] DataFrame = new byte[]
{
0x54, 0x00, // 명령어(읽기)
0x00, 0x00, // 데이터 타입 = BIT
0x00, 0x00, // 예약 영역(고정)
0x08, 0x00 // 읽어올 변수개수 = 8
};
byte[] DataBlock = MakeVariableBlock();
DataFrame = Combine(DataFrame, DataBlock);
return DataFrame;
}
private byte[] MakeVariableBlock()
{
// 모드버스 할때는 시작 번지를 HEX로 계산해줬어야 했음
byte[] VariableBlock = new byte[0];
VariableBlock = MakeBlock("%MX100", VariableBlock); // bit면 X, Word면 W
VariableBlock = MakeBlock("%MX101", VariableBlock);
VariableBlock = MakeBlock("%MX102", VariableBlock);
VariableBlock = MakeBlock("%PX024", VariableBlock);
VariableBlock = MakeBlock("%PX025", VariableBlock);
VariableBlock = MakeBlock("%PX026", VariableBlock);
VariableBlock = MakeBlock("%PX027", VariableBlock);
VariableBlock = MakeBlock("%MX103", VariableBlock);
return VariableBlock;
}
private byte[] MakeBlock(string VariableName, byte[] VariableBlock)
{
byte[] VariableLength = new byte[2] { 0x06, 0x00 }; // 변수명 길이 : %부터 세면 %MX103 총 6글자
VariableBlock = Combine(VariableBlock, VariableLength);
byte[] VariableFrame = Encoding.Default.GetBytes(VariableName);
VariableBlock = Combine(VariableBlock, VariableFrame);
return VariableBlock;
}
private byte[] MakeCompanyFrame(byte[] DataFrame) // Company
{
string Company_ID = "LSIS-XGT";
byte[] CompanyFrame = Encoding.Default.GetBytes(Company_ID);
byte[] CPU_Info = new byte[]
{
0x00, 0x00, // 예비
0x00, 0x00, // PLC 정보
0xB0, // XGB(MK)
0x33, // 프레임 방향 = PC->PLC
0x00, 0x00 // 프레임 순서 번호 = 0번
};
CompanyFrame = Combine(CompanyFrame, CPU_Info);
byte[] Length = new byte[] { (byte)DataFrame.Length, 0x00 }; // 데이터의 길이(바이트 수)
CompanyFrame = Combine(CompanyFrame, Length);
byte[] FEnetPosition = new byte[] { 0x01 }; // 0번 베이스, 1번 슬롯
CompanyFrame = Combine(CompanyFrame, FEnetPosition);
byte[] BCC = new byte[1];
ushort crc = Calc(CompanyFrame);
BCC[0] = (byte)crc; // 맨 밑의 crc 체크섬
CompanyFrame = Combine(CompanyFrame, BCC);
return CompanyFrame;
}
private void SendMessage(byte[] SendFrame)
{
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sock.SendTimeout = 3000;
sock.ReceiveTimeout = 3000;
IPAddress serverIP = IPAddress.Parse("192.168.0.120");
int serverPort = 2004; // modbus는 502
IPEndPoint ipep = new IPEndPoint(serverIP, serverPort);
if (sock.IsBound == true) sock.Close();
sock.Connect(ipep);
if (sock.Connected)
{
sock.Send(SendFrame);
TB_SendFrame.Text = BitConverter.ToString(SendFrame);
byte[] Rdata = new byte[100];
sock.Receive(Rdata);
TB_ReceivedFrame.Text = BitConverter.ToString(Rdata);
Received_Data_Processing(Rdata);
}
sock.Close();
}
private void Received_Data_Processing(byte[] RData)
{
CB_M100.Checked = BitConverter.ToBoolean(RData, 32); // 앞의 데이터는 다 쓸모 없어서 스킵
CB_M101.Checked = BitConverter.ToBoolean(RData, 35); // 데이터 + 데이터크기(2) = 3씩 더하면 됨(데이터 크기도 쓸모 없어서 스킵)
CB_M102.Checked = BitConverter.ToBoolean(RData, 38); // Bool 표현(byte)
CB_M103.Checked = BitConverter.ToBoolean(RData, 41); // Bool 표현(byte)
CB_P24.Checked = BitConverter.ToBoolean(RData, 44); // Bool 표현(byte)
CB_P25.Checked = BitConverter.ToBoolean(RData, 47); // Bool 표현(byte)
CB_P26.Checked = BitConverter.ToBoolean(RData, 50); // Bool 표현(byte)
CB_P27.Checked = BitConverter.ToBoolean(RData, 53); // Bool 표현(byte)
}
private byte[] Combine(byte[] a, byte[] b) // 바이트 합치기
{
byte[] c = new byte[a.Length + b.Length];
Buffer.BlockCopy(a, 0, c, 0, a.Length);
Buffer.BlockCopy(b, 0, c, a.Length, b.Length);
return c;
}
private static ushort Calc(byte[] data) // CRC코드 생성
{
ushort crc = 0xFFFF;
for (int pos = 0; pos < data.Length; pos++)
{
crc ^= (UInt16)data[pos];
for (int i = 8; i != 0; i--)
{
if ((crc & 0x0001) != 0)
{
crc >>= 1;
crc ^= 0xA001;
}
else crc >>= 1;
}
}
return crc;
}
}
}
Form1.Designer.cs
\Desktop\IOT\visual studio edukitTest\XGT_BitRead\XGT_WordRead
namespace XGT_WordRead
{
partial class Form1
{
/// <summary>
/// 필수 디자이너 변수입니다.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 사용 중인 모든 리소스를 정리합니다.
/// </summary>
/// <param name="disposing">관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form 디자이너에서 생성한 코드
/// <summary>
/// 디자이너 지원에 필요한 메서드입니다.
/// 이 메서드의 내용을 코드 편집기로 수정하지 마세요.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.BT_Read = new System.Windows.Forms.Button();
this.BT_Stop = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.label4 = new System.Windows.Forms.Label();
this.label5 = new System.Windows.Forms.Label();
this.TB_SendFrame = new System.Windows.Forms.TextBox();
this.TB_ReceivedFrame = new System.Windows.Forms.TextBox();
this.TB_C0 = new System.Windows.Forms.TextBox();
this.TB_D0 = new System.Windows.Forms.TextBox();
this.TB_D10 = new System.Windows.Forms.TextBox();
this.timer1 = new System.Windows.Forms.Timer(this.components);
this.groupBox1.SuspendLayout();
this.SuspendLayout();
//
// groupBox1
//
this.groupBox1.Controls.Add(this.TB_D10);
this.groupBox1.Controls.Add(this.TB_D0);
this.groupBox1.Controls.Add(this.TB_C0);
this.groupBox1.Controls.Add(this.TB_ReceivedFrame);
this.groupBox1.Controls.Add(this.TB_SendFrame);
this.groupBox1.Controls.Add(this.label5);
this.groupBox1.Controls.Add(this.label4);
this.groupBox1.Controls.Add(this.label3);
this.groupBox1.Controls.Add(this.label2);
this.groupBox1.Controls.Add(this.label1);
this.groupBox1.Controls.Add(this.BT_Stop);
this.groupBox1.Controls.Add(this.BT_Read);
this.groupBox1.Location = new System.Drawing.Point(12, 12);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(386, 272);
this.groupBox1.TabIndex = 0;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "WORD 개별 읽기";
//
// BT_Read
//
this.BT_Read.Location = new System.Drawing.Point(18, 29);
this.BT_Read.Name = "BT_Read";
this.BT_Read.Size = new System.Drawing.Size(156, 33);
this.BT_Read.TabIndex = 0;
this.BT_Read.Text = "읽기";
this.BT_Read.UseVisualStyleBackColor = true;
this.BT_Read.Click += new System.EventHandler(this.BT_Read_Click);
//
// BT_Stop
//
this.BT_Stop.Location = new System.Drawing.Point(208, 29);
this.BT_Stop.Name = "BT_Stop";
this.BT_Stop.Size = new System.Drawing.Size(156, 33);
this.BT_Stop.TabIndex = 1;
this.BT_Stop.Text = "정지";
this.BT_Stop.UseVisualStyleBackColor = true;
this.BT_Stop.Click += new System.EventHandler(this.BT_Stop_Click);
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(16, 79);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(69, 12);
this.label1.TabIndex = 2;
this.label1.Text = "송신 Frame";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(16, 128);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(69, 12);
this.label2.TabIndex = 3;
this.label2.Text = "수신 Frame";
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(16, 183);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(94, 12);
this.label3.TabIndex = 4;
this.label3.Text = "수신 데이터(C0)";
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(16, 213);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(93, 12);
this.label4.TabIndex = 5;
this.label4.Text = "수신 데이터(D0)";
//
// label5
//
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(16, 243);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(99, 12);
this.label5.TabIndex = 6;
this.label5.Text = "수신 데이터(D10)";
//
// TB_SendFrame
//
this.TB_SendFrame.Location = new System.Drawing.Point(18, 94);
this.TB_SendFrame.Name = "TB_SendFrame";
this.TB_SendFrame.Size = new System.Drawing.Size(346, 21);
this.TB_SendFrame.TabIndex = 1;
//
// TB_ReceivedFrame
//
this.TB_ReceivedFrame.Location = new System.Drawing.Point(18, 143);
this.TB_ReceivedFrame.Name = "TB_ReceivedFrame";
this.TB_ReceivedFrame.Size = new System.Drawing.Size(346, 21);
this.TB_ReceivedFrame.TabIndex = 7;
//
// TB_C0
//
this.TB_C0.Location = new System.Drawing.Point(147, 180);
this.TB_C0.Name = "TB_C0";
this.TB_C0.Size = new System.Drawing.Size(217, 21);
this.TB_C0.TabIndex = 8;
//
// TB_D0
//
this.TB_D0.Location = new System.Drawing.Point(147, 210);
this.TB_D0.Name = "TB_D0";
this.TB_D0.Size = new System.Drawing.Size(217, 21);
this.TB_D0.TabIndex = 9;
//
// TB_D10
//
this.TB_D10.Location = new System.Drawing.Point(147, 240);
this.TB_D10.Name = "TB_D10";
this.TB_D10.Size = new System.Drawing.Size(217, 21);
this.TB_D10.TabIndex = 10;
//
// timer1
//
this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(415, 301);
this.Controls.Add(this.groupBox1);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.TextBox TB_D10;
private System.Windows.Forms.TextBox TB_D0;
private System.Windows.Forms.TextBox TB_C0;
private System.Windows.Forms.TextBox TB_ReceivedFrame;
private System.Windows.Forms.TextBox TB_SendFrame;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button BT_Stop;
private System.Windows.Forms.Button BT_Read;
private System.Windows.Forms.Timer timer1;
}
}
결과
위의 폼에
주사위의 수치(D01100), 생산량 리미트(D10000)를 추가해보기
Form1.cs
\Desktop\IOT\visual studio edukitTest\XGT_BitRead\XGT_WordRead
변수개수 수정(3개 -> 5개)
private byte[] MakeDataFrame() // command에 해당
{
byte[] DataFrame = new byte[]
{
0x54, 0x00, // 명령어(읽기)
0x02, 0x00, // 데이터 타입 = Word
0x00, 0x00, // 예약 영역(고정)
0x05, 0x00 // 읽어올 변수개수 = 5
};
byte[] VariableBlock = MakeVariableBlock();
DataFrame = Combine(DataFrame, VariableBlock);
return DataFrame;
}
메모리 값 위치 지정(이건 잘못된 코드로 밑에서 수정하게 된다)
private byte[] MakeVariableBlock()
{
byte[] VariableBlock = new byte[0];
VariableBlock = MakeBlock("%CW00", VariableBlock); // bit면 X, Word면 W
VariableBlock = MakeBlock("%DW00", VariableBlock);
VariableBlock = MakeBlock("%DW10", VariableBlock);
VariableBlock = MakeBlock("%DW01100", VariableBlock);
VariableBlock = MakeBlock("%DW10000", VariableBlock);
return VariableBlock;
}
읽어올 변수명 길이 수정(8글자)
private byte[] MakeBlock(string VariableName, byte[] VariableBlock)
{
byte[] VariableLength = new byte[2] { 0x08, 0x00 }; // 변수명 길이 최대 총 8글자
VariableBlock = Combine(VariableBlock, VariableLength);
byte[] Variable = Encoding.Default.GetBytes(VariableName);
VariableBlock = Combine(VariableBlock, Variable);
return VariableBlock;
}
데이터 받아오는 항목 추가
private void ReceivedDataProcessing(byte[] RData)
{
short Datas = BitConverter.ToInt16(RData, 32); // 앞의 데이터는 다 쓸모 없어서 스킵
TB_C0.Text = Datas.ToString();
Datas = BitConverter.ToInt16(RData, 36); // 4씩 더하면 됨
TB_D0.Text = Datas.ToString();
Datas = BitConverter.ToInt16(RData, 40);
TB_D10.Text = Datas.ToString();
Datas = BitConverter.ToInt16(RData, 44);
TB_D01100.Text = Datas.ToString();
Datas = BitConverter.ToInt16(RData, 48);
TB_D10000.Text = Datas.ToString();
}
여기까지 수정하고 나니
값이 5로 지정되어 있어 0이 뜨지 말아야 할 생산량 리미트까지 0이 떴다(뭔가 오류가 있음)
강사님이 보시고 수정한 변수명 길이는 8글자인데 기존 변수명은 5글자라서 오류가 난 것 같다고 알려주셨다.
그래서 위의 변수명 길이도 수정해줬다.
private byte[] MakeVariableBlock()
{
byte[] VariableBlock = new byte[0];
VariableBlock = MakeBlock("%CW00000", VariableBlock); // bit면 X, Word면 W
VariableBlock = MakeBlock("%DW00000", VariableBlock);
VariableBlock = MakeBlock("%DW00010", VariableBlock);
VariableBlock = MakeBlock("%DW01100", VariableBlock);
VariableBlock = MakeBlock("%DW10000", VariableBlock);
return VariableBlock;
}
결과
XGT 통신으로 Word 개별 쓰기
책을 참고하여 주사위값, 생산량 리미트는 알아서 추가해보았다.
Form1.cs
\Desktop\IOT\visual studio edukitTest\XGT_BitRead\XGT_WordWrite
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace XGT_WordWrite
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void BT_Set_Click(object sender, EventArgs e)
{
byte[] DataFrame = MakeDataFrame();
byte[] Frame = MakeCompanyFrame(DataFrame);
Frame = Combine(Frame, DataFrame);
SendMessage(Frame);
}
private byte[] MakeDataFrame() // command에 해당
{
byte[] DataFrame = new byte[]
{
0x58, 0x00, // 명령어(쓰기)
0x02, 0x00, // 데이터 타입 = Word
0x00, 0x00, // 예약 영역(고정)
0x04, 0x00 // 읽어올 변수개수 = 4
};
byte[] VariableBlock = MakeVariableBlock();
DataFrame = Combine(DataFrame, VariableBlock);
byte[] Data = MakeDatas();
DataFrame = Combine(DataFrame, Data);
return DataFrame;
}
private byte[] MakeVariableBlock()
{
byte[] VariableBlock = new byte[0];
byte[] VariableLength = new byte[2] { 0x08, 0x00 }; // 변수 길이
VariableBlock = Combine(VariableBlock, VariableLength);
byte[] VariableFrame = Encoding.Default.GetBytes("%DW00000");
VariableBlock = Combine(VariableBlock, VariableFrame);
VariableBlock = Combine(VariableBlock, VariableLength);
VariableFrame = Encoding.Default.GetBytes("%DW01000");
VariableBlock = Combine(VariableBlock, VariableFrame);
VariableBlock = Combine(VariableBlock, VariableLength);
VariableFrame = Encoding.Default.GetBytes("%DW01100");
VariableBlock = Combine(VariableBlock, VariableFrame);
VariableBlock = Combine(VariableBlock, VariableLength);
VariableFrame = Encoding.Default.GetBytes("%DW10000");
VariableBlock = Combine(VariableBlock, VariableFrame);
return VariableBlock;
}
private byte[] MakeDatas()
{
byte[] Data = new byte[0];
byte[] DataCount = new byte[2] { 0x02, 0x00 }; // byte 수
Data = Combine(Data, DataCount);
byte[] WordData = BitConverter.GetBytes(Convert.ToInt16(TB_D0.Text));
Data = Combine(Data, WordData);
Data = Combine(Data, DataCount);
WordData = BitConverter.GetBytes(Convert.ToInt16(TB_D1.Text));
Data = Combine(Data, WordData);
Data = Combine(Data, DataCount);
WordData = BitConverter.GetBytes(Convert.ToInt16(TB_D01100.Text));
Data = Combine(Data, WordData);
Data = Combine(Data, DataCount);
WordData = BitConverter.GetBytes(Convert.ToInt16(TB_D10000.Text));
Data = Combine(Data, WordData);
return Data;
}
private byte[] MakeCompanyFrame(byte[] DataFrame) // Company
{
string Company_ID = "LSIS-XGT";
byte[] CompanyFrame = Encoding.Default.GetBytes(Company_ID);
byte[] CPU_Info = new byte[]
{
0x00, 0x00, // 예비
0x00, 0x00, // PLC 정보
0xB0, // XGB(MK)
0x33, // 프레임 방향 = PC->PLC
0x00, 0x00 // 프레임 순서 번호 = 0번
};
CompanyFrame = Combine(CompanyFrame, CPU_Info);
byte[] Length = new byte[] { (byte)DataFrame.Length, 0x00 }; // 데이터의 길이(바이트 수)
CompanyFrame = Combine(CompanyFrame, Length);
byte[] FEnetPosition = new byte[] { 0x01 }; // 0번 베이스, 1번 슬롯
CompanyFrame = Combine(CompanyFrame, FEnetPosition);
byte[] BCC = new byte[1];
ushort crc = Calc(CompanyFrame);
BCC[0] = (byte)crc; // 맨 밑의 crc 체크섬
CompanyFrame = Combine(CompanyFrame, BCC);
return CompanyFrame;
}
private void SendMessage(byte[] SendFrame)
{
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sock.SendTimeout = 3000;
sock.ReceiveTimeout = 3000;
IPAddress serverIP = IPAddress.Parse("192.168.0.120");
int serverPort = 2004; // modbus는 502
IPEndPoint ipep = new IPEndPoint(serverIP, serverPort);
if (sock.IsBound == true) sock.Close();
sock.Connect(ipep);
if (sock.Connected)
{
sock.Send(SendFrame);
TB_SendFrame.Text = BitConverter.ToString(SendFrame);
}
sock.Close();
}
private byte[] Combine(byte[] a, byte[] b) // 바이트 합치기
{
byte[] c = new byte[a.Length + b.Length];
Buffer.BlockCopy(a, 0, c, 0, a.Length);
Buffer.BlockCopy(b, 0, c, a.Length, b.Length);
return c;
}
private static ushort Calc(byte[] data) // CRC코드 생성
{
ushort crc = 0xFFFF;
for (int pos = 0; pos < data.Length; pos++)
{
crc ^= (UInt16)data[pos];
for (int i = 8; i != 0; i--)
{
if ((crc & 0x0001) != 0)
{
crc >>= 1;
crc ^= 0xA001;
}
else crc >>= 1;
}
}
return crc;
}
}
}
Form1.Designer.cs
\Desktop\IOT\visual studio edukitTest\XGT_BitRead\XGT_WordWrite
namespace XGT_WordWrite
{
partial class Form1
{
/// <summary>
/// 필수 디자이너 변수입니다.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 사용 중인 모든 리소스를 정리합니다.
/// </summary>
/// <param name="disposing">관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form 디자이너에서 생성한 코드
/// <summary>
/// 디자이너 지원에 필요한 메서드입니다.
/// 이 메서드의 내용을 코드 편집기로 수정하지 마세요.
/// </summary>
private void InitializeComponent()
{
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.BT_Set = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.label4 = new System.Windows.Forms.Label();
this.label5 = new System.Windows.Forms.Label();
this.TB_D0 = new System.Windows.Forms.TextBox();
this.TB_D1 = new System.Windows.Forms.TextBox();
this.TB_D01100 = new System.Windows.Forms.TextBox();
this.TB_D10000 = new System.Windows.Forms.TextBox();
this.TB_SendFrame = new System.Windows.Forms.TextBox();
this.groupBox1.SuspendLayout();
this.SuspendLayout();
//
// groupBox1
//
this.groupBox1.Controls.Add(this.TB_SendFrame);
this.groupBox1.Controls.Add(this.TB_D10000);
this.groupBox1.Controls.Add(this.TB_D01100);
this.groupBox1.Controls.Add(this.TB_D1);
this.groupBox1.Controls.Add(this.TB_D0);
this.groupBox1.Controls.Add(this.label5);
this.groupBox1.Controls.Add(this.label4);
this.groupBox1.Controls.Add(this.label3);
this.groupBox1.Controls.Add(this.label2);
this.groupBox1.Controls.Add(this.label1);
this.groupBox1.Controls.Add(this.BT_Set);
this.groupBox1.Location = new System.Drawing.Point(12, 12);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(361, 265);
this.groupBox1.TabIndex = 0;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "WORD 개별 쓰기";
//
// BT_Set
//
this.BT_Set.Location = new System.Drawing.Point(18, 23);
this.BT_Set.Name = "BT_Set";
this.BT_Set.Size = new System.Drawing.Size(313, 37);
this.BT_Set.TabIndex = 1;
this.BT_Set.Text = "설정";
this.BT_Set.UseVisualStyleBackColor = true;
this.BT_Set.Click += new System.EventHandler(this.BT_Set_Click);
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(16, 87);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(19, 12);
this.label1.TabIndex = 2;
this.label1.Text = "D0";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(16, 121);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(19, 12);
this.label2.TabIndex = 3;
this.label2.Text = "D1";
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(16, 154);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(101, 12);
this.label3.TabIndex = 4;
this.label3.Text = "주사위값(D01100)";
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(16, 185);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(125, 12);
this.label4.TabIndex = 5;
this.label4.Text = "생산량리미트(D10000)";
//
// label5
//
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(19, 217);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(69, 12);
this.label5.TabIndex = 6;
this.label5.Text = "송신 Frame";
//
// TB_D0
//
this.TB_D0.Location = new System.Drawing.Point(147, 84);
this.TB_D0.Name = "TB_D0";
this.TB_D0.Size = new System.Drawing.Size(184, 21);
this.TB_D0.TabIndex = 7;
//
// TB_D1
//
this.TB_D1.Location = new System.Drawing.Point(147, 116);
this.TB_D1.Name = "TB_D1";
this.TB_D1.Size = new System.Drawing.Size(184, 21);
this.TB_D1.TabIndex = 8;
//
// TB_D01100
//
this.TB_D01100.Location = new System.Drawing.Point(147, 149);
this.TB_D01100.Name = "TB_D01100";
this.TB_D01100.Size = new System.Drawing.Size(184, 21);
this.TB_D01100.TabIndex = 9;
//
// TB_D10000
//
this.TB_D10000.Location = new System.Drawing.Point(147, 181);
this.TB_D10000.Name = "TB_D10000";
this.TB_D10000.Size = new System.Drawing.Size(184, 21);
this.TB_D10000.TabIndex = 10;
//
// TB_SendFrame
//
this.TB_SendFrame.Location = new System.Drawing.Point(18, 238);
this.TB_SendFrame.Name = "TB_SendFrame";
this.TB_SendFrame.Size = new System.Drawing.Size(313, 21);
this.TB_SendFrame.TabIndex = 11;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(388, 288);
this.Controls.Add(this.groupBox1);
this.Name = "Form1";
this.Text = "Form1";
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.TextBox TB_SendFrame;
private System.Windows.Forms.TextBox TB_D10000;
private System.Windows.Forms.TextBox TB_D01100;
private System.Windows.Forms.TextBox TB_D1;
private System.Windows.Forms.TextBox TB_D0;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button BT_Set;
}
}
결과
위에 했던 내용들의 반복이라 크게 어려운 부분은 없었다.
근데 궁금한 게 생겼다.
WordRead에서도 그렇고 WordWrite에서도 처음 시작할 때만 타입?을 지정해주고 다음은 그냥 쓰는 것 같은데 그 이유가 궁금해서 앞에 또 붙여봤다.
오류 메세지엔 이미 지역 변수/함수가 정의되어 있다고 떴다.
아 위에 정의한 걸 밑에서 또 쓰는 거구나...하고 이해했다.
JS나 파이썬은 그래도 나름 몇번 봤다고 저게 헷갈리진 않았는데...C#에선 저렇게 생겼구나...
비전 인식
주사위 값
C#은 너무 복잡하기 때문에 파이썬으로 진행
Vision.py
\Desktop\IOT\visual studio edukitTest\Vision_Python\vision.py
##pip install opencv-python
##pip install pyserial
import cv2
import numpy as np
from socket import *
from select import *
import sys
from time import sleep
HOST = '192.168.0.120'
PORT = 2004
BUFSIZE = 1024
ADDR = (HOST,PORT)
clientSocket = socket(AF_INET, SOCK_STREAM)# 서버에 접속하기 위한 소켓을 생성한다.
clientSocket.connect(ADDR) # 서버에 접속을 시도한다.
print('connect is success')
cap = cv2.VideoCapture(1) # 0 or 1 (0: 노트북 내장 카메라, 1: usb 연결된 카메라)
readings = [-1, -1] # vision dice detection open source
display = [0, 0]
Circle_Inertia = 0.6
Gaussian_ksize = (7, 7)
canny_threshold_min = 100
canny_threshold_max = 250
###
params = cv2.SimpleBlobDetector_Params()
params.filterByInertia = True
params.minInertiaRatio = Circle_Inertia
detector = cv2.SimpleBlobDetector_create(params)
###
while True:
ret, frame = cap.read()
frame_blurred = cv2.GaussianBlur(frame, Gaussian_ksize, 1)
frame_gray = cv2.cvtColor(frame_blurred, cv2.COLOR_BGR2GRAY)
frame_canny = cv2.Canny(frame_gray, canny_threshold_min, canny_threshold_max, apertureSize=3, L2gradient=True)
####
keypoints = detector.detect(frame_canny)
num = len(keypoints)
readings.append(num)
if readings[-1] == readings[-2] == readings[-3] == readings[-4] == readings[-5] == readings[-6]:
#if readings[-5] != readings[-4]:
# cv2.imwrite("Before.png", frame)
im_with_keypoints = cv2.drawKeypoints(frame, keypoints, np.array([]), (0, 0, 255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv2.putText(im_with_keypoints, str(num), (500, 250), cv2.FONT_HERSHEY_SCRIPT_SIMPLEX, 5, (0, 255, 0))
# socket으로 데이터를 줌
socketTxData = bytes([76,83,73,83,45,88,71,84,0,0,0,0,160,51,0,0,22,0,0,0,88,0,2,0,0,0,1,0,8,0,37,68,87,48,49,49,48,48,2,0,])
##76 83 73 83 45 88 71 84 0 0 0 0 176 51 0 0 22 0 1 1 8 8 8 8 0 2 0 0 0 108037688748494948482030
num_little = num.to_bytes(2, 'little')
# print(num_little)
# socketTxData.insert(socketTxData+num_little)
if num != 0:
print(num)
try:
clientSocket.send(socketTxData + num_little)
msg = clientSocket.recv(1024)
print(msg)
except Exception as e:
print(e)
print('%s:%s'%ADDR)
cv2.imwrite("After.png", im_with_keypoints)
# cv2.imshow("Dice Reader", im_with_keypoints) #break선언시 실행 불가
# break
sleep(0.3)
cv2.destroyAllWindows()
소켓으로 보낼 데이터 값은 어디서 보는가?
=> WordWrite 수정해서 디버그하여 알아볼 수 있다.
private byte[] MakeDataFrame() // command에 해당
{
byte[] DataFrame = new byte[]
{
0x58, 0x00, // 명령어(쓰기)
0x02, 0x00, // 데이터 타입 = Word
0x00, 0x00, // 예약 영역(고정)
0x01, 0x00 // 읽어올 변수개수 = 4
};
byte[] VariableBlock = MakeVariableBlock();
DataFrame = Combine(DataFrame, VariableBlock);
byte[] Data = MakeDatas();
DataFrame = Combine(DataFrame, Data);
return DataFrame;
}
private byte[] MakeVariableBlock()
{
byte[] VariableBlock = new byte[0];
byte[] VariableLength = new byte[2] { 0x08, 0x00 }; // 변수 길이
//VariableBlock = Combine(VariableBlock, VariableLength);
//byte[] VariableFrame = Encoding.Default.GetBytes("%DW00000");
//VariableBlock = Combine(VariableBlock, VariableFrame);
//VariableBlock = Combine(VariableBlock, VariableLength);
//VariableFrame = Encoding.Default.GetBytes("%DW01000");
//VariableBlock = Combine(VariableBlock, VariableFrame);
VariableBlock = Combine(VariableBlock, VariableLength);
byte[] VariableFrame = Encoding.Default.GetBytes("%DW01100"); // 주사위 인식 memory
VariableBlock = Combine(VariableBlock, VariableFrame);
//VariableBlock = Combine(VariableBlock, VariableLength);
//VariableFrame = Encoding.Default.GetBytes("%DW10000");
//VariableBlock = Combine(VariableBlock, VariableFrame);
return VariableBlock;
}
private byte[] MakeDatas()
{
byte[] Data = new byte[0];
byte[] DataCount = new byte[2] { 0x02, 0x00 }; // byte 수
//Data = Combine(Data, DataCount);
//byte[] WordData = BitConverter.GetBytes(Convert.ToInt16(TB_D0.Text));
//Data = Combine(Data, WordData);
//Data = Combine(Data, DataCount);
//WordData = BitConverter.GetBytes(Convert.ToInt16(TB_D1.Text));
//Data = Combine(Data, WordData);
Data = Combine(Data, DataCount);
byte[] WordData = BitConverter.GetBytes(Convert.ToInt16(TB_D01100.Text));
Data = Combine(Data, WordData);
//Data = Combine(Data, DataCount);
//WordData = BitConverter.GetBytes(Convert.ToInt16(TB_D10000.Text));
//Data = Combine(Data, WordData);
return Data;
}
디버그
=> F9로 해당 구문에 중단점 생성 - F5로 실행 - 마우스 갖다 대고 왼쪽 화살표 클릭하여 자세한 데이터값 확인 가능
디버깅 단축키
F9 중단점
F5 중단점마다 실행
F10 다음 코드 실행
F11 프로시저 실행
멈춰 있는 상태에서 마우스 갖다 대면 값이 다 보임
결과
이런 식으로 연동하면 좋다.
느낀 점
점점 코드에 익숙해지는 속도가 빨라지는 것 같아 뿌듯하다.
비전 인식 코드에서 익숙한 코드가 몇 줄 보여서 반가웠다.
배운걸 잘 하는데 그치지 않고 하나를 배워서 응용하는 능력이 좀더 좋아졌으면 좋겠다.
계속 코드를 보면서 익숙해져야지...
'공부 > [TIL] Digital Twin Bootcamp' 카테고리의 다른 글
TIL_220124_Backend (0) | 2022.01.25 |
---|---|
TIL_220121_IOT (0) | 2022.01.21 |
TIL_220119_IOT (0) | 2022.01.19 |
TIL_220118_IOT (0) | 2022.01.18 |
TIL_220117_IOT (0) | 2022.01.17 |