initial commit
This commit is contained in:
556
Cs_HMI/SubProject/ProPLC/Arduino/MemoryAccess.cs
Normal file
556
Cs_HMI/SubProject/ProPLC/Arduino/MemoryAccess.cs
Normal file
@@ -0,0 +1,556 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.ComponentModel;
|
||||
using System.Reflection;
|
||||
using System.Runtime;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace arDev.Arduino
|
||||
{
|
||||
public partial class DIO : arRS232
|
||||
{
|
||||
protected object lockobj = new object();
|
||||
public struct SetupInfo
|
||||
{
|
||||
public byte ioInterval;
|
||||
public byte ResetCount;
|
||||
public byte SpeedH;
|
||||
public byte SpeedL;
|
||||
public byte SpeedZ;
|
||||
public byte pindirRevDILow;
|
||||
public byte pindirRevDIHigh;
|
||||
public byte UpTime;
|
||||
public byte BalanceThd;
|
||||
public byte MarkThd;
|
||||
public byte SpeedC;
|
||||
public byte BalanceThdUp;
|
||||
|
||||
public Boolean IsValid;
|
||||
public void Clear()
|
||||
{
|
||||
pindirRevDIHigh = 0;
|
||||
pindirRevDILow = 0;
|
||||
ioInterval = 0;
|
||||
ResetCount = 0;
|
||||
SpeedH = 0;
|
||||
SpeedL = 0;
|
||||
SpeedC = 0;
|
||||
BalanceThd = 0;
|
||||
BalanceThd = 0;
|
||||
UpTime = 0;
|
||||
MarkThd = 0;
|
||||
SpeedZ = 0;
|
||||
IsValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
public SetupInfo setupInfo;
|
||||
private Boolean STX11 = false;
|
||||
private Boolean STX21 = false;
|
||||
//private Boolean ETX11 = false;
|
||||
// private byte[] buffer1;
|
||||
// readonly List<byte> Tempbuffer1 = new List<byte>();
|
||||
readonly ManualResetEvent mre = new ManualResetEvent(true);
|
||||
// protected string errorMessage = string.Empty;
|
||||
// readonly System.IO.Ports.SerialPort dev = null;
|
||||
private byte LEN1 = 0;
|
||||
//private byte CHK1 = 0;
|
||||
//private int bufferCount1 = 0;
|
||||
|
||||
public DateTime ConnTryTime = DateTime.Now.AddDays(-1);
|
||||
protected DateTime[] SetFlagTime = new DateTime[32];
|
||||
readonly Boolean[] Flag = new bool[32];
|
||||
readonly Boolean[] DIValue = new bool[16];
|
||||
readonly Boolean[] DOValue = new bool[16];
|
||||
public UInt16[] AIValue = new ushort[3];
|
||||
public byte[] AOValue = new byte[3];
|
||||
public string ioBinStr = string.Empty;
|
||||
public string SetupStr = string.Empty;
|
||||
public byte RunTime = 0;
|
||||
|
||||
public byte[] MAG_VALUE = new byte[2];
|
||||
public byte[] SV_SPEED = new byte[2];
|
||||
public Boolean isDisposed = false; //dispose가 호출되었는가?
|
||||
|
||||
public string LastMessage { get; set; }
|
||||
public DateTime LastMessageTime { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 생성자
|
||||
/// </summary>
|
||||
public DIO()
|
||||
{
|
||||
//설정의 값
|
||||
setupInfo = new SetupInfo();
|
||||
setupInfo.Clear();
|
||||
|
||||
SV_SPEED[0] = 0;
|
||||
SV_SPEED[1] = 0;
|
||||
|
||||
//마그넷 센서(0~100)
|
||||
MAG_VALUE[0] = 50;
|
||||
MAG_VALUE[1] = 50;
|
||||
|
||||
lastRecvTime = DateTime.Parse("1982-11-23");
|
||||
|
||||
for (int i = 0; i < Flag.Length; i++)
|
||||
Flag[i] = false;
|
||||
for (int i = 0; i < DIValue.Length; i++)
|
||||
DIValue[i] = false;
|
||||
for (int i = 0; i < DOValue.Length; i++)
|
||||
DOValue[i] = false;
|
||||
for (int i = 0; i < AIValue.Length; i++)
|
||||
AIValue[i] = 0;
|
||||
for (int i = 0; i < AOValue.Length; i++)
|
||||
AOValue[i] = 0;
|
||||
for (int i = 0; i < SetFlagTime.Length; i++)
|
||||
SetFlagTime[i] = DateTime.Parse("1982-11-23");
|
||||
|
||||
}
|
||||
|
||||
protected override bool CustomParser(byte[] buf, out byte[] remainBuffer)
|
||||
{
|
||||
List<byte> remain = new List<byte>();
|
||||
|
||||
|
||||
Boolean bComplete = false;
|
||||
for (int i = 0; i < buf.Length; i++)
|
||||
{
|
||||
var incomByte = buf[i];
|
||||
if (bComplete == true)
|
||||
{
|
||||
remain.Add(incomByte);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (STX11 == false)
|
||||
{
|
||||
if (incomByte != '@')
|
||||
{
|
||||
STX21 = false;
|
||||
// ETX11 = false;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
STX11 = true;
|
||||
tempBuffer.Clear();
|
||||
tempBuffer.Add(incomByte);
|
||||
}
|
||||
}
|
||||
else if (STX21 == false)
|
||||
{
|
||||
if (tempBuffer.Count != 1 || tempBuffer.Count < 1 || tempBuffer[0] != '@' || incomByte != '@')
|
||||
{
|
||||
STX11 = false;
|
||||
//ETX11 = false;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
STX21 = true;
|
||||
tempBuffer.Add(incomByte);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tempBuffer.Add(incomByte);
|
||||
|
||||
//여기서부터는무조건 누적한다.
|
||||
if (tempBuffer.Count == 3)
|
||||
{
|
||||
if (tempBuffer[0] != '@' || tempBuffer[1] != '@')
|
||||
{
|
||||
STX11 = false;
|
||||
STX21 = false;
|
||||
// ETX11 = false;
|
||||
LEN1 = 0;
|
||||
tempBuffer.Clear();
|
||||
}
|
||||
else LEN1 = incomByte; //데이터 길이가온다
|
||||
}
|
||||
//else if (Tempbuffer1.Count == LEN1 + 5) //ETX1
|
||||
//{
|
||||
// if (incomingByte != 0x0D)
|
||||
// {
|
||||
// //ETX가 와야하는데 다른데이터가 왔다
|
||||
// STX11 = false;
|
||||
// STX21 = false;
|
||||
// // ETX11 = false;
|
||||
|
||||
// var str = System.Text.Encoding.Default.GetString(Tempbuffer1.ToArray());
|
||||
// RaiseMessage(MessageType.ReceiveData, "에러 모두 파기 : " + str, true);
|
||||
|
||||
// Tempbuffer1.Clear();
|
||||
// }
|
||||
//}
|
||||
else if (tempBuffer.Count == LEN1 + 6)
|
||||
{
|
||||
//전체길이를 만족햇다.
|
||||
if (incomByte != 0x0A)
|
||||
{
|
||||
//ETX가 와야하는데 다른데이터가 왔다
|
||||
STX11 = false;
|
||||
STX21 = false;
|
||||
// ETX11 = false;
|
||||
//var str = System.Text.Encoding.Default.GetString(Tempbuffer1.ToArray());
|
||||
RaiseMessage(MessageType.Error, "에러 모두 파기 : ETX 값 오류");
|
||||
tempBuffer.Clear();
|
||||
}
|
||||
else if (tempBuffer[tempBuffer.Count - 2] != 0x0D)
|
||||
{
|
||||
//ETX가 와야하는데 다른데이터가 왔다
|
||||
STX11 = false;
|
||||
STX21 = false;
|
||||
// ETX11 = false;
|
||||
//var str = System.Text.Encoding.Default.GetString(Tempbuffer1.());
|
||||
RaiseMessage(MessageType.Error, "에러 모두 파기 : ETX 값 오류");
|
||||
tempBuffer.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
STX11 = false;
|
||||
STX21 = false;
|
||||
// ETX11 = false;
|
||||
//if (LastReceiveBuffer == null) LastReceiveBuffer = new byte[tempBuffer.Count];
|
||||
//else if (LastReceiveBuffer.Length != tempBuffer.Count) Array.Resize(ref LastReceiveBuffer, Tempbuffer1.Count);
|
||||
//tempBuffer.CopyTo(LastReceiveBuffer)tempBuffer
|
||||
//tempBuffer.Clear();
|
||||
bComplete = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
remainBuffer = remain.ToArray();
|
||||
return bComplete;
|
||||
}
|
||||
|
||||
|
||||
bool Checksum(byte[] buffer, int datalength)
|
||||
{
|
||||
//체크섬필요 221118
|
||||
if (buffer[buffer.Length-3] == '*')
|
||||
{
|
||||
return true;
|
||||
}
|
||||
byte checksum = 0;
|
||||
for (int i = 3; i < datalength + 3; i++)
|
||||
{
|
||||
checksum = (byte)(checksum ^ buffer[i]);
|
||||
}
|
||||
return checksum == buffer[buffer.Length - 3];
|
||||
}
|
||||
|
||||
public override bool ProcessRecvData(byte[] data)
|
||||
{
|
||||
var hexString = GetHexString(data);//.gethe
|
||||
var len = data[2];
|
||||
if (len + 6 != data.Length)
|
||||
{
|
||||
RaiseMessage(MessageType.Error, string.Format("길이오류 예상:{0},수신:{1},{2}", len + 5, data.Length, hexString));
|
||||
}
|
||||
else if (data[0] != 0x40 || data[1] != 0x40 || data[data.Length - 2] != 0x0D || data[data.Length - 1] != 0x0A)
|
||||
{
|
||||
RaiseMessage(MessageType.Error, string.Format("헤더 오류 : {0}", hexString));
|
||||
}
|
||||
else if (Checksum(data, len) == false) //체크섬 221118
|
||||
{
|
||||
RaiseMessage(MessageType.Error, string.Format("체크섬 오류 : {0}", hexString));
|
||||
}
|
||||
else
|
||||
{
|
||||
//RaiseMessage(MessageType.ReceiveData, hexString);
|
||||
lastRecvTime = DateTime.Now;
|
||||
var cmd = data[3];
|
||||
if (cmd == 'I') //IOData
|
||||
{
|
||||
if (len != 10)
|
||||
RaiseMessage(MessageType.Error, "IO수신길이오류:" + DateTime.Now.ToString("mm:ss.fff") + " 수신 : " + hexString);
|
||||
else Parse_IOData(data);
|
||||
}
|
||||
else if (cmd == 'T')
|
||||
{
|
||||
// Boolean errorMessage = buffer[4] == 1;
|
||||
var message = System.Text.Encoding.Default.GetString(data, 5, len - 2);//데이터타입과 에러여부 제거
|
||||
LastMessage = message;
|
||||
LastMessageTime = DateTime.Now;
|
||||
RaiseMessage(MessageType.Normal, message);
|
||||
}
|
||||
else if (cmd == 'S') //setup 정보 200310 (홈)
|
||||
{
|
||||
if (len != 13)
|
||||
RaiseMessage(MessageType.Error, "SETUP수신길이오류:" + DateTime.Now.ToString("mm:ss.fff") + " 수신 : " + hexString);
|
||||
else Parse_SetupData(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
RaiseMessage(MessageType.Normal, "Unknown:" + hexString + "\n" + "Data=" + System.Text.Encoding.Default.GetString(data));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Parse_IOData(byte[] buffer)
|
||||
{
|
||||
var IOData = BitConverter.ToUInt32(buffer, 4);
|
||||
|
||||
//var newMagF = BitConverter.ToUInt16(buffer, 8);
|
||||
//va1r newMagB = BitConverter.ToUInt16(buffer, 10);
|
||||
//var newAlign = BitConverter.ToUInt16(buffer, 12);
|
||||
//if (newMagF != AIValue[0] || newMagB != AIValue[1])
|
||||
//{
|
||||
// AIValue[0] = newMagF;// BitConverter.ToUInt16(buffer, 8); //마그넷센서 F
|
||||
// AIValue[1] = newMagB; //BitConverter.ToUInt16(buffer, 10); //마그넷센서 B
|
||||
// PositionChanged?.Invoke(this, null);
|
||||
//}
|
||||
//AIValue[2] = newAlign;
|
||||
//AOValue[0] = buffer[14]; //왼쪽바퀴 속도
|
||||
//AOValue[1] = buffer[15]; //오른쪽바퀴 속도
|
||||
//AOValue[2] = buffer[16]; //Z축 속도
|
||||
//SV_SPEED[0] = buffer[21]; //왼쪽바퀴의 설정속도
|
||||
//SV_SPEED[1] = buffer[22]; //오른쪽바퀴의 설정속도
|
||||
//MAG_VALUE[0] = buffer[23]; //magnet front
|
||||
//MAG_VALUE[1] = buffer[24]; //magnet rear
|
||||
RunTime = buffer[12];
|
||||
|
||||
//플래그값 확인
|
||||
byte[] buf_flag = new byte[4];
|
||||
Array.Copy(buffer, 8, buf_flag, 0, 4);
|
||||
var baF = new System.Collections.BitArray(buf_flag);
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
Boolean val = baF[i];
|
||||
|
||||
//입력
|
||||
if (this.Flag[i] != val)
|
||||
{
|
||||
Flag[i] = val;
|
||||
|
||||
//변경이벤트 생성
|
||||
FlagChanged?.Invoke(this, new FlagValueEventArgs(i, !val, val));
|
||||
}
|
||||
}
|
||||
|
||||
//IO값 확인
|
||||
byte[] buf_iodata = new byte[4];
|
||||
Array.Copy(buffer, 4, buf_iodata, 0, 4);
|
||||
var ba = new System.Collections.BitArray(buf_iodata);
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
Boolean val = ba[i];
|
||||
if (i >= 16)
|
||||
{
|
||||
//출력
|
||||
if (DOValue[i - 16] != val)
|
||||
{
|
||||
DOValue[i - 16] = val;
|
||||
|
||||
//변경이벤트 생성
|
||||
ValueChanged?.Invoke(this, new IOValueEventArgs(IODirection.Output, i - 16, !val, val));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//입력
|
||||
if (DIValue[i] != val)
|
||||
{
|
||||
DIValue[i] = val;
|
||||
|
||||
//변경이벤트 생성
|
||||
ValueChanged?.Invoke(this, new IOValueEventArgs(IODirection.Input, i, !val, val));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ioBinStr = Convert.ToString(IOData, 2).PadLeft(32, '0');
|
||||
//string msg = string.Format(DateTime.Now.ToString("mm:ss.fff") + " IO:{0},AN={1:0000},{2:0000},FG={3},AO={4},{5}",
|
||||
// binstr, An1, An2, FGData, Ao11, Ao12);
|
||||
}
|
||||
void Parse_SetupData(byte[] buffer)
|
||||
{
|
||||
setupInfo.ioInterval = buffer[4];
|
||||
setupInfo.ResetCount = buffer[5];
|
||||
setupInfo.SpeedH = buffer[6];
|
||||
setupInfo.SpeedL = buffer[7];
|
||||
setupInfo.SpeedZ = buffer[8];
|
||||
setupInfo.pindirRevDIHigh = buffer[9];
|
||||
setupInfo.pindirRevDILow = buffer[10];
|
||||
setupInfo.UpTime = buffer[11];
|
||||
setupInfo.BalanceThd = buffer[12];
|
||||
setupInfo.MarkThd = buffer[13];
|
||||
setupInfo.SpeedC = buffer[14];
|
||||
setupInfo.BalanceThdUp = buffer[15];
|
||||
|
||||
SetupStr = string.Format("I:{0},R={1},H={2},L={3},Z={4},UP={5},BL={6},MK={7},SPD_C={8},BLUP={9}",
|
||||
setupInfo.ioInterval,
|
||||
setupInfo.ResetCount,
|
||||
setupInfo.SpeedH,
|
||||
setupInfo.SpeedL,
|
||||
setupInfo.SpeedZ,
|
||||
setupInfo.UpTime,
|
||||
setupInfo.BalanceThd,
|
||||
setupInfo.MarkThd,
|
||||
setupInfo.SpeedC,
|
||||
setupInfo.BalanceThdUp);
|
||||
}
|
||||
|
||||
public byte MakeChecksum(byte[] buffer)
|
||||
{
|
||||
//return 0;
|
||||
byte chk = 0;
|
||||
foreach (var b in buffer)
|
||||
chk = (byte)(chk ^ b);
|
||||
return chk;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#region "Method"
|
||||
|
||||
protected Boolean Sendcommand(byte cmd, byte p1, byte p2)
|
||||
{
|
||||
//이번호의 상태를 on/off 해줘야함
|
||||
List<byte> buffer = new List<byte>
|
||||
{
|
||||
cmd, //command
|
||||
p1,
|
||||
p2
|
||||
};
|
||||
|
||||
byte dataLen = (byte)buffer.Count; //데이터길이
|
||||
byte checksum = MakeChecksum(buffer.ToArray());
|
||||
|
||||
buffer.Insert(0, (byte)'@'); //stx
|
||||
buffer.Insert(1, (byte)'@'); //stx
|
||||
buffer.Insert(2, dataLen);
|
||||
buffer.Add(checksum); //길이를 제외한 실제 데이터 영역만 체크섬
|
||||
buffer.Add(0x0D); //etx
|
||||
buffer.Add(0x0A); //etx
|
||||
|
||||
return WriteData(buffer.ToArray());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 이벤트를 강제 생성합니다.(내부변수값도 변경됩니다)
|
||||
/// </summary>
|
||||
/// <param name="Direction"></param>
|
||||
/// <param name="idx"></param>
|
||||
/// <param name="value"></param>
|
||||
public void RaiseEvent(IODirection dir, int idx, Boolean value)
|
||||
{
|
||||
if (ValueChanged != null)
|
||||
{
|
||||
if (!mre.WaitOne(100))
|
||||
{
|
||||
RaiseMessage( MessageType.Error, "RaiseEvent WaitOne Timeout");
|
||||
return;
|
||||
}
|
||||
|
||||
mre.Reset();
|
||||
|
||||
bool curValue;
|
||||
if (dir == IODirection.Input)
|
||||
{
|
||||
curValue = DIValue[idx];
|
||||
DIValue[idx] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
curValue = DOValue[idx];
|
||||
DOValue[idx] = value;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
//이벤트를 할당한곳에서 오류가 나면 이곳에서 에러가 잡힌다.
|
||||
ValueChanged(this, new IOValueEventArgs(dir, idx, curValue, value));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
RaiseMessage(MessageType.Error, ex.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
mre.Set();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//public Boolean GetFlag(byte idx)
|
||||
//{
|
||||
// return Flag[idx];
|
||||
//}
|
||||
|
||||
public Boolean GetValueI(byte idx)
|
||||
{
|
||||
if (idx < DIValue.Length) return DIValue[idx];
|
||||
else return false;
|
||||
}
|
||||
|
||||
public Boolean GetValueO(byte idx)
|
||||
{
|
||||
if (idx < DOValue.Length) return DOValue[idx];
|
||||
else return false;
|
||||
}
|
||||
|
||||
|
||||
//public Boolean SetValueI(int idx,Boolean value)
|
||||
//{
|
||||
// if (idx < DIValue.Length)
|
||||
// {
|
||||
// DIValue[idx] = value;
|
||||
// return true;
|
||||
// }
|
||||
// else return false;
|
||||
//}
|
||||
|
||||
public Boolean SetValue(byte idx, Boolean value)
|
||||
{
|
||||
byte SET_PINMODE = 3;
|
||||
if (value == true) return Sendcommand(SET_PINMODE, idx, 1);
|
||||
else return Sendcommand(SET_PINMODE, idx, 0);
|
||||
}
|
||||
|
||||
|
||||
public Boolean SetToggle(byte idx)
|
||||
{
|
||||
var curbalue = GetValueO(idx);
|
||||
return SetValue(idx, !curbalue);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public string GetErrorMessage()
|
||||
{
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user