AxlGetBoardStatus가 SUCCESS일 때 미연결로 반환하던 반전 버그를 정정(실제 Ajin 연결 시 OnMonitoring 폴링이 스킵되던 원인). 연동해 OnMonitoring 미연결 가드를 앞으로 정리.
635 lines
22 KiB
C#
635 lines
22 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
|
|
namespace AuroraIO.AJINEXTEK
|
|
{
|
|
public class AjinIO : IOUnit
|
|
{
|
|
public class IOModuleInfo
|
|
{
|
|
public enum eModuleType { Digital, Analog };
|
|
#region IO Enumerator Definitions(IPG YLS, LBAD)
|
|
public enum eADIAddress
|
|
{
|
|
LaserReady,
|
|
EmissionStatus,
|
|
LaserError,
|
|
LaserIsOn,
|
|
ProgramActive,
|
|
Warning,
|
|
LaserModuleAlarm,
|
|
LaserAssigned,
|
|
LBADReadyStatus,
|
|
LBADJudgementComplete,
|
|
LBADJudgeOK,
|
|
LBADJudgeWARNING,
|
|
LBADJudgeNG,
|
|
LBADJudgeNA,
|
|
LDDError = 27,
|
|
LaserEMO_1,
|
|
LaserEMO_2,
|
|
LeakSensorHead,
|
|
LeakSensorChiller,
|
|
DICount
|
|
}
|
|
public enum eADOAddress
|
|
{
|
|
ProgramStart,
|
|
PCcontrolEnable,
|
|
ResetAlarm,
|
|
GuideLaserEnable,
|
|
AnalogControl,
|
|
ProgramStop,
|
|
LaserOn,
|
|
PulseMode,
|
|
PCLBADReadyStatus,
|
|
PCLBADWeldingTrigger,
|
|
PCLBADWeldingStop,
|
|
PCLBADJudgementCompleteAck,
|
|
DOCount
|
|
}
|
|
|
|
#endregion
|
|
public IOModuleInfo(int no, int iCount, int oCount, eModuleType type, int inputStart, int outputStart)
|
|
{
|
|
ioModuleNo = no;
|
|
inputCount = iCount;
|
|
outputCount = oCount;
|
|
ioModuleType = type;
|
|
inputStartIndex = inputStart;
|
|
outputStartIndex = outputStart;
|
|
|
|
}
|
|
eModuleType ioModuleType;
|
|
public eModuleType IoModuleType
|
|
{
|
|
get { lock (this) { return ioModuleType; } }
|
|
set { lock (this) { ioModuleType = value; } }
|
|
}
|
|
int ioModuleNo;
|
|
public int IOModuleNo
|
|
{
|
|
get { lock (this) { return ioModuleNo; } }
|
|
set { lock (this) { ioModuleNo = value; } }
|
|
}
|
|
|
|
int inputCount;
|
|
public int InputCount
|
|
{
|
|
get { lock (this) { return inputCount; } }
|
|
set { lock (this) { inputCount = value; } }
|
|
}
|
|
|
|
int outputCount;
|
|
public int OutputCount
|
|
{
|
|
get { lock (this) { return outputCount; } }
|
|
set { lock (this) { outputCount = value; } }
|
|
}
|
|
|
|
int inputStartIndex;
|
|
public int InputStartIndex
|
|
{
|
|
get { lock (this) { return inputStartIndex; } }
|
|
set { lock (this) { inputStartIndex = value; } }
|
|
}
|
|
int outputStartIndex;
|
|
public int OutputStartIndex
|
|
{
|
|
get { lock (this) { return outputStartIndex; } }
|
|
set { lock (this) { outputStartIndex = value; } }
|
|
}
|
|
}
|
|
List<IOModuleInfo> ioModulInfoList = new List<IOModuleInfo>();
|
|
#region 추상 함수 선언
|
|
|
|
public override int Open(string iP)
|
|
{
|
|
int error = 0;
|
|
string msg = "";
|
|
try
|
|
{
|
|
if (CAXL.AxlIsOpened() == (int)AXT_BOOLEAN.FALSE)
|
|
{
|
|
error = (int)CAXL.AxlOpen(7);
|
|
if (error != (int)AXT_FUNC_RESULT.AXT_RT_SUCCESS)
|
|
{
|
|
msg = string.Format("IO Device Open Fail!!({0})", GetErrorMessage(error));
|
|
return error;
|
|
}
|
|
}
|
|
//LoadIOTable();
|
|
return 0;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
public override void Close()
|
|
{
|
|
try
|
|
{
|
|
if (CAXL.AxlIsOpened() == (int)AXT_BOOLEAN.TRUE)
|
|
CAXL.AxlClose();
|
|
}
|
|
catch { }
|
|
}
|
|
public AjinIO()
|
|
{
|
|
|
|
}
|
|
|
|
public override int GetDICount()
|
|
{
|
|
int count = 0;
|
|
foreach(IOModuleInfo module in ioModulInfoList)
|
|
{
|
|
if(module.IoModuleType == IOModuleInfo.eModuleType.Digital)
|
|
{
|
|
count += module.InputCount;
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
public override int GetDOCount()
|
|
{
|
|
int count = 0;
|
|
foreach (IOModuleInfo module in ioModulInfoList)
|
|
{
|
|
if (module.IoModuleType == IOModuleInfo.eModuleType.Digital)
|
|
{
|
|
count += module.OutputCount;
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
public override int GetAICount()
|
|
{
|
|
int count = 0;
|
|
foreach (IOModuleInfo module in ioModulInfoList)
|
|
{
|
|
if (module.IoModuleType == IOModuleInfo.eModuleType.Analog)
|
|
{
|
|
count += module.InputCount;
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
public override int GetAOCount()
|
|
{
|
|
int count = 0;
|
|
foreach (IOModuleInfo module in ioModulInfoList)
|
|
{
|
|
if (module.IoModuleType == IOModuleInfo.eModuleType.Analog)
|
|
{
|
|
count += module.OutputCount;
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
|
|
public override void Instance(string mappingFolder)
|
|
{
|
|
IOMappingFolder = mappingFolder;
|
|
//LoadIOTable();
|
|
|
|
}
|
|
|
|
public override int Initialize()
|
|
{
|
|
int error = 0;
|
|
string msg = "";
|
|
int dioModuleCount = 0;
|
|
int aioModuleCount = 0;
|
|
|
|
|
|
#region DIO
|
|
error = (int)CAXD.AxdInfoGetModuleCount(ref dioModuleCount);
|
|
if ((error != (int)AXT_FUNC_RESULT.AXT_RT_SUCCESS) && (error != (int)AXT_FUNC_RESULT.AXT_RT_DIO_NOT_MODULE))
|
|
{
|
|
msg = string.Format("Read Module Count Error!!({0})", GetErrorMessage(error));
|
|
//messageDlg.messageDlg.RunDlg(msg, true, MessageDlg.DialogMode.MODAL);
|
|
return error;
|
|
}
|
|
|
|
int boardNo = 0;
|
|
int modulePos = 0;
|
|
uint moduleId = 0;
|
|
int moduleNo = 0;
|
|
int inputCount = 0;
|
|
int outputCount = 0;
|
|
int inputIndex = 0;
|
|
int outputIndex = 0;
|
|
|
|
if (0 < dioModuleCount)
|
|
{
|
|
ioModulInfoList.Clear();
|
|
|
|
for (int i = 0; i < dioModuleCount; i++)
|
|
{
|
|
error = (int)CAXD.AxdInfoGetModule(i, ref boardNo, ref modulePos, ref moduleId);
|
|
if (error != (int)AXT_FUNC_RESULT.AXT_RT_SUCCESS)
|
|
{
|
|
msg = string.Format("Read Module Count Error!!({0})", GetErrorMessage(error));
|
|
return error;
|
|
}
|
|
|
|
error = (int)CAXD.AxdInfoGetModuleNo(boardNo, modulePos, ref moduleNo);
|
|
if (error != (int)AXT_FUNC_RESULT.AXT_RT_SUCCESS)
|
|
{
|
|
msg = string.Format("Read Module Count Error!!({0})", GetErrorMessage(error));
|
|
return error;
|
|
}
|
|
|
|
error = (int)CAXD.AxdInfoGetInputCount(moduleNo, ref inputCount);
|
|
if (error != (int)AXT_FUNC_RESULT.AXT_RT_SUCCESS)
|
|
{
|
|
msg = string.Format("Read Module Count Error!!({0})", GetErrorMessage(error));
|
|
|
|
return error;
|
|
}
|
|
|
|
error = (int)CAXD.AxdInfoGetOutputCount(moduleNo, ref outputCount);
|
|
if (error != (int)AXT_FUNC_RESULT.AXT_RT_SUCCESS)
|
|
{
|
|
msg = string.Format("Read Module Count Error!!({0})", GetErrorMessage(error));
|
|
|
|
return error;
|
|
}
|
|
|
|
#region R&D 장비에서 설정문제인지 IO보드가 중복검색되어서, 예외처리 추가
|
|
bool isAlreadyExists = false;
|
|
|
|
foreach (IOModuleInfo module in ioModulInfoList)
|
|
{
|
|
if (moduleNo == module.IOModuleNo)
|
|
{
|
|
isAlreadyExists = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (isAlreadyExists) continue;
|
|
#endregion
|
|
|
|
IOModuleInfo tempModule = new IOModuleInfo(moduleNo, inputCount, outputCount, IOModuleInfo.eModuleType.Digital, inputIndex, outputIndex);
|
|
ioModulInfoList.Add(tempModule);
|
|
|
|
inputIndex += inputCount;
|
|
outputIndex += outputCount;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region AIO
|
|
error = (int)CAXA.AxaInfoGetModuleCount(ref aioModuleCount);
|
|
if ((error != (int)AXT_FUNC_RESULT.AXT_RT_SUCCESS) && (error != (int)AXT_FUNC_RESULT.AXT_RT_AIO_NOT_MODULE))
|
|
{
|
|
msg = string.Format("Read Module Count Error!!({0})", GetErrorMessage(error));
|
|
//messageDlg.messageDlg.RunDlg(msg, true, MessageDlg.DialogMode.MODAL);
|
|
return error;
|
|
}
|
|
|
|
if (0 < aioModuleCount)
|
|
{
|
|
boardNo = 0;
|
|
modulePos = 0;
|
|
moduleId = 0;
|
|
moduleNo = 0;
|
|
inputCount = 0;
|
|
outputCount = 0;
|
|
inputIndex = 0;
|
|
outputIndex = 0;
|
|
|
|
for (int i = 0; i < aioModuleCount; i++)
|
|
{
|
|
error = (int)CAXA.AxaInfoGetModule(i, ref boardNo, ref modulePos, ref moduleId);
|
|
if (error != (int)AXT_FUNC_RESULT.AXT_RT_SUCCESS)
|
|
{
|
|
msg = string.Format("Read Module Count Error!!({0})", GetErrorMessage(error));
|
|
return error;
|
|
}
|
|
|
|
error = (int)CAXA.AxaInfoGetModuleNo(boardNo, modulePos, ref moduleNo);
|
|
if (error != (int)AXT_FUNC_RESULT.AXT_RT_SUCCESS)
|
|
{
|
|
msg = string.Format("Read Module Count Error!!({0})", GetErrorMessage(error));
|
|
return error;
|
|
}
|
|
|
|
error = (int)CAXA.AxaInfoGetInputCount(moduleNo, ref inputCount);
|
|
if (error != (int)AXT_FUNC_RESULT.AXT_RT_SUCCESS)
|
|
{
|
|
msg = string.Format("Read Module Count Error!!({0})", GetErrorMessage(error));
|
|
|
|
return error;
|
|
}
|
|
|
|
error = (int)CAXA.AxaInfoGetOutputCount(moduleNo, ref outputCount);
|
|
if (error != (int)AXT_FUNC_RESULT.AXT_RT_SUCCESS)
|
|
{
|
|
msg = string.Format("Read Module Count Error!!({0})", GetErrorMessage(error));
|
|
|
|
return error;
|
|
}
|
|
|
|
#region R&D 장비에서 설정문제인지 IO보드가 중복검색되어서, 예외처리 추가
|
|
bool isAlreadyExists = false;
|
|
|
|
foreach (IOModuleInfo module in ioModulInfoList)
|
|
{
|
|
if (moduleNo == module.IOModuleNo)
|
|
{
|
|
isAlreadyExists = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (isAlreadyExists) continue;
|
|
#endregion
|
|
|
|
IOModuleInfo tempModule = new IOModuleInfo(moduleNo, inputCount, outputCount, IOModuleInfo.eModuleType.Analog, inputIndex, outputIndex);
|
|
ioModulInfoList.Add(tempModule);
|
|
|
|
inputIndex += inputCount;
|
|
outputIndex += outputCount;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
//IO 레벨 세팅
|
|
//error = SetIoLevel();
|
|
//Interrupt 세팅
|
|
//error = SetIntterrupt();
|
|
|
|
return 0;
|
|
}
|
|
|
|
public override bool IsConnected()
|
|
{
|
|
int err = (int)CAXL.AxlGetBoardStatus(0);
|
|
return err == (int)AXT_FUNC_RESULT.AXT_RT_SUCCESS;
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
public override int GetDoArray(ref bool[] array)
|
|
{
|
|
uint data = 0;
|
|
int lastIndex = 0;
|
|
foreach (IOModuleInfo module in ioModulInfoList)
|
|
{
|
|
if(module.IoModuleType == IOModuleInfo.eModuleType.Digital && module.OutputCount !=0)
|
|
{
|
|
int err = (int)CAXD.AxdoReadOutportDword(module.IOModuleNo, 0, ref data);
|
|
if (err != (int)AXT_FUNC_RESULT.AXT_RT_SUCCESS)
|
|
{
|
|
return err;
|
|
}
|
|
|
|
BitArray arr = new BitArray(BitConverter.GetBytes(data));
|
|
|
|
arr.CopyTo(array, lastIndex);
|
|
lastIndex += module.OutputCount;
|
|
}
|
|
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
public override int GetDiArray(ref bool[] array)
|
|
{
|
|
uint data = 0;
|
|
foreach (IOModuleInfo module in ioModulInfoList)
|
|
{
|
|
if (module.IoModuleType == IOModuleInfo.eModuleType.Digital && module.InputCount != 0)
|
|
{
|
|
int err = (int)CAXD.AxdiReadInportDword(module.IOModuleNo, 0, ref data);
|
|
if (err != (int)AXT_FUNC_RESULT.AXT_RT_SUCCESS)
|
|
{
|
|
return err;
|
|
}
|
|
|
|
//BitArray arr = new BitArray(BitConverter.GetBytes(data));
|
|
// 1안 ) 220118 이준혁Y 테스트 필요.
|
|
//BitArray arr = new BitArray(module.InputCount, false);
|
|
|
|
//for (int i = 0; i < module.InputCount; i++)
|
|
//{
|
|
// int selectBitToInt = (int)(Math.Pow(2, i));
|
|
// int selectedBitToInt = (int)data & selectBitToInt;
|
|
|
|
// if (selectedBitToInt == selectBitToInt) arr[i] = true;
|
|
// else arr[i] = false;
|
|
//}
|
|
// 2안) 220118 카운트 크기에 따라서, BitArray 다른 것으로 쓰게끔.
|
|
Byte tempByte = 0;
|
|
UInt16 tempUInt = 0;
|
|
BitArray arr = new BitArray(module.InputCount, false);
|
|
|
|
if (module.InputCount == 8)
|
|
{
|
|
tempByte = Convert.ToByte(data);
|
|
arr = new BitArray(BitConverter.GetBytes(tempByte).ToArray());
|
|
}
|
|
else if (module.InputCount == 16)
|
|
{
|
|
tempUInt = Convert.ToUInt16(data);
|
|
arr = new BitArray(BitConverter.GetBytes(tempUInt));
|
|
}
|
|
else if (module.InputCount == 32)
|
|
{
|
|
arr = new BitArray(BitConverter.GetBytes(data));
|
|
}
|
|
else;
|
|
|
|
arr.CopyTo(array, module.InputStartIndex);
|
|
|
|
}
|
|
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
public override int ReadDoBit(int index, ref bool bit)
|
|
{
|
|
uint data = 0;
|
|
|
|
int err = (int)CAXD.AxdoReadOutport(index, ref data);
|
|
if (err != (int)AXT_FUNC_RESULT.AXT_RT_SUCCESS)
|
|
{
|
|
return err;
|
|
}
|
|
bit = Convert.ToBoolean(data);
|
|
|
|
return 0;
|
|
}
|
|
|
|
public override int ReadDiBit(int index, ref bool bit)
|
|
{
|
|
uint data = 0;
|
|
|
|
int err = (int)CAXD.AxdiReadInport(index, ref data);
|
|
if (err != (int)AXT_FUNC_RESULT.AXT_RT_SUCCESS)
|
|
{
|
|
return err;
|
|
}
|
|
bit = Convert.ToBoolean(data);
|
|
|
|
return 0;
|
|
}
|
|
public override bool ReadDoBit(int index)
|
|
{
|
|
//현재 사용하지 않아서 추후 구현
|
|
//return true;
|
|
|
|
//[추후 구현] return true 스텁 의존 코드 확인 후 아래로 교체(ReadDiBit(int) 패턴)
|
|
uint data = 0;
|
|
|
|
int err = (int)CAXD.AxdoReadOutport(index, ref data);
|
|
if (err != (int)AXT_FUNC_RESULT.AXT_RT_SUCCESS)
|
|
{
|
|
throw new Exception(string.Format("ERR_IO_FAIL_TO_GET_BIT;ERROR CODE:{0}", err));
|
|
}
|
|
return Convert.ToBoolean(data);
|
|
}
|
|
public override bool ReadDiBit(int index)
|
|
{
|
|
uint data = 0;
|
|
|
|
int err = (int)CAXD.AxdiReadInport(index, ref data);
|
|
if (err != (int)AXT_FUNC_RESULT.AXT_RT_SUCCESS)
|
|
{
|
|
throw new Exception(string.Format("ERR_IO_FAIL_TO_GET_BIT;ERROR CODE:{0}", err));
|
|
}
|
|
return Convert.ToBoolean(data);
|
|
}
|
|
public override int WriteDoBit(int index, bool bit)
|
|
{
|
|
uint data = Convert.ToUInt16(bit);
|
|
|
|
int err = (int)CAXD.AxdoWriteOutport(index, data);
|
|
if (err != (int)AXT_FUNC_RESULT.AXT_RT_SUCCESS)
|
|
{
|
|
return err;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
public override void ClearList()
|
|
{
|
|
ListDI.Clear();
|
|
ListDO.Clear();
|
|
}
|
|
//int SetIoLevel()
|
|
//{
|
|
// string msg = string.Empty;
|
|
// int rv = 0;
|
|
// //AJin IO에서 접점 변경은 Active를 High(1) 또는 Low(0) Level 설정한다.
|
|
// //기본적으로 NO(Normal Open)접점이 Active상태에서 high(1) Level이므로 설정을 아래와 같이 한다.
|
|
// //input contact
|
|
|
|
// foreach (IOModuleInfo ioModule in ioModulInfoList)
|
|
// {
|
|
|
|
// for (int i = 0; i < ioModule.InputCount; i++)
|
|
// {
|
|
// uint uLevel = (uint)(ListDI[ioModule.InputStartIndex + i].ActiveLevel == InfoIO.ActiveLevelType.High ? 1 : 0);
|
|
|
|
// rv = (int)CAXD.AxdiLevelSetInportBit(ioModule.IOModuleNo, i, uLevel);
|
|
|
|
// if (rv != (int)AXT_FUNC_RESULT.AXT_RT_SUCCESS)
|
|
// {
|
|
// msg = string.Format("{0} Set DI Active Level Error({1})", ListDI[ioModule.InputStartIndex + i].Index, GetErrorMessage(rv));
|
|
// return rv;
|
|
// }
|
|
|
|
// }
|
|
|
|
// for (int i = 0; i < ioModule.OutputCount; i++)
|
|
// {
|
|
// uint uLevel = (uint)(ListDO[ioModule.OutputStartIndex + i].ActiveLevel == InfoIO.ActiveLevelType.High ? 1 : 0);
|
|
|
|
// rv = (int)CAXD.AxdoLevelSetOutportBit(ioModule.IOModuleNo, i, uLevel);
|
|
|
|
// if (rv != (int)AXT_FUNC_RESULT.AXT_RT_SUCCESS)
|
|
// {
|
|
// msg = string.Format("{0} Set Active Level Error({1})", ListDO[ioModule.OutputStartIndex + i].Index, GetErrorMessage(rv));
|
|
// return rv;
|
|
// }
|
|
// }
|
|
// }
|
|
// return rv;
|
|
//}
|
|
|
|
int SetIntterrupt()
|
|
{
|
|
string msg = string.Empty;
|
|
int rv = 0;
|
|
|
|
foreach (IOModuleInfo ioModule in ioModulInfoList)
|
|
{
|
|
//인터럽트 처리 사용 여부 설정
|
|
rv = (int)CAXD.AxdiInterruptSetModuleEnable(ioModule.IOModuleNo, 1);
|
|
|
|
if (rv != (int)AXT_FUNC_RESULT.AXT_RT_SUCCESS)
|
|
{
|
|
msg = string.Format("ModuleNo :{0}; Set Interrupted Error({1})",ioModule.IOModuleNo, GetErrorMessage(rv));
|
|
return rv;
|
|
}
|
|
|
|
uint eventNo=0;
|
|
//인터럽트 처리 방법 설정
|
|
rv = (int)CAXD.AxdiInterruptSetModule(ioModule.IOModuleNo,(IntPtr)null, 0, InterruptCallbackFunction, ref eventNo);
|
|
|
|
if (rv != (int)AXT_FUNC_RESULT.AXT_RT_SUCCESS)
|
|
{
|
|
msg = string.Format("ModuleNo :{0}; Set Interrupted Error({1})", ioModule.IOModuleNo, GetErrorMessage(rv));
|
|
return rv;
|
|
}
|
|
|
|
for (int i = 0; i < ioModule.InputCount; i++)
|
|
{
|
|
//Rising Edge 설정
|
|
|
|
rv = (int)CAXD.AxdiInterruptEdgeSetBit(ioModule.IOModuleNo, i,1,1);
|
|
|
|
|
|
if (rv != (int)AXT_FUNC_RESULT.AXT_RT_SUCCESS)
|
|
{
|
|
msg = string.Format("IO Index :{0}; Set Interrupted Error({1})", ListDI[ioModule.InputStartIndex + i].Index, GetErrorMessage(rv));
|
|
return rv;
|
|
}
|
|
|
|
//Falling Edge 설정
|
|
rv = (int)CAXD.AxdiInterruptEdgeSetBit(ioModule.IOModuleNo, i, 0, 1);
|
|
|
|
if (rv != (int)AXT_FUNC_RESULT.AXT_RT_SUCCESS)
|
|
{
|
|
msg = string.Format("IO Index :{0}; Set Interrupted Error({1})", ListDI[ioModule.InputStartIndex + i].Index, GetErrorMessage(rv));
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
#region ErrorMessage
|
|
public string GetErrorMessage(int errCode)
|
|
{
|
|
return Enum.ToObject(typeof(AXT_FUNC_RESULT), errCode).ToString();
|
|
}
|
|
|
|
#endregion ErrorMessage
|
|
|
|
}
|
|
}
|