/// <summary> /// 초기화 함수. /// </summary> /// <returns>초기화 성공여부</returns> public bool Init() { //Local Var. bool bExtCmeFile = false; String Path = m_sCmePath; //Check Already Init. if (m_iTotalAxis > 0) { return(true); //이미 Initial 했으므로 } try { if (Cmmsdk.cmmGnDeviceLoad((int)MotnDefines._TCmBool.cmTRUE, ref m_iTotalAxis) != MotnDefines.cmERR_NONE) { Log.ShowMessage("Motor", "[Comizoa Motion]Cannot Load Device Fail!"); return(false); } if (m_iTotalAxis <= 0) { Log.ShowMessage("Motor", "[Comizoa Motion]Cannot Load Device (Load Axis is Zero!)"); return(false); } //Check Exist CME2 File. //bExtCmeFile = FNC.FileExists(Path); //if (bExtCmeFile) Cmmsdk.cmmGnInitFromFile(Path); //Cmmsdk.cmmAdvGetNumDefinedAxes(ref m_iTotalAxis); } catch (Exception ex) { Log.Trace("TAxisComi. Open " + ex.ToString()); } //Return. return(m_iTotalAxis > 0); }
/// <summary> /// 테스트로 한번의 트리거를 출력. /// </summary> /// <param name="_bOnLevel">출력 레벨</param> /// <param name="_iTime">시간us</param> public void OneShotTrg(bool _bOnLevel, int _iTime) { //CMP 출력은 One-shot pulse 로 출력되는데, 출력되는 펄스의 폭을 조절할 //수 있습니다. 설정 및 반환되는 PropVal 은 다음과 같습니다. //• 0 : 트리거 시점의 Command 펄스의 펄스폭과 동일한 펄스폭을 가짐 //• 양수의 값 : 이 값에 1.5us 가 곱해진 값이 펄스폭이 됩니다. 즉, 이 값을 //1 로 하면 1.5us, 2 로 하면 3us…와 같이 됩니다. int iTrgTime = (int)(_iTime / 1.5); int iRet = Cmmsdk.cmmCfgSetMioProperty(Para.iPhysicalNo, (int)MotnDefines._TCmMioPropId.cmCMP_PWIDTH, iTrgTime); int iCmpSrc = (int)MotnDefines._TCmCntr.cmCNT_COMM; // Command Position 0 //CmpMethod 1번으로 사용하는건 잘 모르겟음 일단 기본 베이스 맞춰서 1,2사용으로 함 //0 (cmDISABLE) Disable comparator //1 (cmEQ_BIDIR) CmpData = CmpSrc_Value (regardless of counting direction) 카운팅 방향에 상관 없이 //2 (cmEQ_PDIR) CmpData = CmpSrc_Value (while counting up) //3 (cmEQ_NDIR) CmpData = CmpSrc_Value (while counting down) //4 (cmLESS) CmpData > CmpSrc_Value //5 (cmGREATER) CmpData < CmpSrc_Value //(+)방향쪽으로 이동시에만 트리거펄스가 출력되고 (-)방향으로 이동할 때는 출력하지 //않도록(cmEQ_PDIR) 합니다. 엣지 개념이 아닌듯해서 1번으로 사용 int iCmpMethod = (int)MotnDefines._TCmCmpMethod.cmEQ_BIDIR; //if(_bActual) iCmpMethod = (int)MotnDefines._TCmCmpMethod.cmEQ_PDIR; // CmpData = CmpSrc_Value (while counting up) //else iCmpMethod = (int)MotnDefines._TCmCmpMethod.cmEQ_NDIR; // CmpData = CmpSrc_Value (while counting down) //위치 비교기 조건 설정 및 확인 Cmmsdk.cmmCmpTrgSetConfig(Para.iPhysicalNo, iCmpSrc, iCmpMethod); Cmmsdk.cmmCmpTrgSetOneData(Para.iPhysicalNo, MotionInfo.iCmdPos); }
/// <summary> /// IO입력 상태 가져오기. /// </summary> /// <param name="_iNo">IO번호</param> /// <returns>IO상태</returns> public bool GetIn(int _iNo, bool _bDirect = false) { //Check Error. if (_iNo >= m_iMaxIn || _iNo < 0) { return(false); } //Get Addr. int iBitAddr; int iModule; int iModuleDp; GetInfoInput(_iNo, out iModule, out iModuleDp, out iBitAddr); //OutPut if (_bDirect) { int iOn = 0; Cmmsdk.cmmDiGetOne(_iNo, ref iOn); return(iOn == 0 ? false : true); } else { bool bRet = ((m_aModuleInfo.iDataIn >> iBitAddr) & 0x01) == 0x01; return(bRet); } }
/// <summary> /// 하드웨어 트리거를 시작 위치 부터 끝위치 까지 일정 간격으로 트리거를 발생 시킨다. /// </summary> /// <param name="_dStt">시작 위치</param> /// <param name="_dEnd">종료 위치</param> /// <param name="_dDist">주기</param> /// <param name="_dTrgTime">트리거 시그널의 시간us</param> /// <param name="_bActual">엔코더기준인지 커맨드 기준인지</param> /// <param name="_bOnLevel">트리거 레벨</param> public void SetTrgBlock(double _dStt, double _dEnd, double _dPeriod, double _dTrgTime, bool _bActual, bool _bOnLevel) { //CMP 출력은 One-shot pulse 로 출력되는데, 출력되는 펄스의 폭을 조절할 //수 있습니다. 설정 및 반환되는 PropVal 은 다음과 같습니다. //• 0 : 트리거 시점의 Command 펄스의 펄스폭과 동일한 펄스폭을 가짐 //• 양수의 값 : 이 값에 1.5us 가 곱해진 값이 펄스폭이 됩니다. 즉, 이 값을 //1 로 하면 1.5us, 2 로 하면 3us…와 같이 됩니다. int iTrgTime = (int)(_dTrgTime / 1.5); int iRet = Cmmsdk.cmmCfgSetMioProperty(Para.iPhysicalNo, (int)MotnDefines._TCmMioPropId.cmCMP_PWIDTH, iTrgTime); //일정 간격의 비교위치 데이터 등록 //연속적인 위치 비교 출력 기능을 사용하기 위해서 일정한 위치 간격을 가지는 연속적인 위치 데이터를 자동으로 생성하여 //등록 하도록 합니다. //이 함수는 일정한 위치 간격으로 CMP 출력을 내보낼 때 cmmCmpTrgContRegTable()함수 대신에 사용할 수 있습니다. int iCmpSrc = 0; if (_bActual) { iCmpSrc = (int)MotnDefines._TCmCntr.cmCNT_COMM; // Command Position 0 } else { iCmpSrc = (int)MotnDefines._TCmCntr.cmCNT_FEED; // Feedback Position 1 } //CmpMethod 1번으로 사용하는건 잘 모르겟음 일단 기본 베이스 맞춰서 1,2사용으로 함 //0 (cmDISABLE) Disable comparator //1 (cmEQ_BIDIR) CmpData = CmpSrc_Value (regardless of counting direction) 카운팅 방향에 상관 없이 //2 (cmEQ_PDIR) CmpData = CmpSrc_Value (while counting up) //3 (cmEQ_NDIR) CmpData = CmpSrc_Value (while counting down) //4 (cmLESS) CmpData > CmpSrc_Value //5 (cmGREATER) CmpData < CmpSrc_Value //(+)방향쪽으로 이동시에만 트리거펄스가 출력되고 (-)방향으로 이동할 때는 출력하지 //않도록(cmEQ_PDIR) 합니다. 엣지 개념이 아닌듯해서 1번으로 사용 int iCmpMethod = (int)MotnDefines._TCmCmpMethod.cmEQ_BIDIR; //if(_bActual) iCmpMethod = (int)MotnDefines._TCmCmpMethod.cmEQ_PDIR; // CmpData = CmpSrc_Value (while counting up) //else iCmpMethod = (int)MotnDefines._TCmCmpMethod.cmEQ_NDIR; // CmpData = CmpSrc_Value (while counting down) //위치 비교기 조건 설정 및 확인 Cmmsdk.cmmCmpTrgSetConfig(Para.iPhysicalNo, iCmpSrc, iCmpMethod); //연속적인 위치데이터 등록 //이거 갯수는 맞을런지 모르겟다...추후 검증 필요 //NumData : 자동생성되는 총 데이터 수 라고 되어 있음 //public static extern unsafe int cmmCmpTrgContBuildTable( //[MarshalAs(UnmanagedType.I4)] int Axis, //[MarshalAs(UnmanagedType.R8)] double StartData, //[MarshalAs(UnmanagedType.R8)] double Interval, //[MarshalAs(UnmanagedType.I4)] int NumData); double dNumData = (_dEnd - _dStt) / _dPeriod; int iNumData = (int)dNumData + 1; Cmmsdk.cmmCmpTrgContBuildTable(Para.iPhysicalNo, _dStt, _dPeriod, iNumData); //연속적인 위치 비교 기능 시작 Cmmsdk.cmmCmpTrgContStart(Para.iPhysicalNo); }
/// <summary> /// 홈이 진행중인지 확인. /// </summary> public bool GetHoming() { int IsBusy = 1; int iBusy = 0; Cmmsdk.cmmHomeIsBusy(Para.iPhysicalNo, ref iBusy); return(iBusy == IsBusy); }
/// <summary> /// 시그널을 받아 놓는다. /// </summary> public void Update() { //for (int i = 0; i < m_iModuleCnt; i++) //{ Cmmsdk.cmmDoPutMulti(0, m_aModuleInfo.iCntOut, m_aModuleInfo.iDataOutSet); Cmmsdk.cmmDoGetMulti(0, m_aModuleInfo.iCntOut, ref m_aModuleInfo.iDataOutGet); Cmmsdk.cmmDiGetMulti(0, m_aModuleInfo.iCntIn, ref m_aModuleInfo.iDataIn); //} }
/// <summary> /// 현재 파라미터들을 아진 함수를 이용하여 세팅함. /// </summary> public void ApplyPara(double _dPulsePerUnit) { m_dPulsePerUnit = _dPulsePerUnit; int iRet2; int iMode; //S-Curve 설정할때 가/감속을 Percentage로 변환해서 셋팅해야하는데 셋팅된 가/감속 가져오기 애매해서 주석처리. //if (Para.dSCurveAcPer == 0 && Para.dSCurveDcPer == 0)//커브 안쓸때. //{ // iMode = (int)MotnDefines._TCmSpeedMode.cmSMODE_T;//대칭 //} //else //{ // iMode = (int)MotnDefines._TCmSpeedMode.cmSMODE_S;//비대칭 //} ////S-Curve 설정 //Cmmsdk.cmmCfgSetSpeedPattern(Para.iPhysicalNo, iMode, 2000, 10000, 10000 ); //Use Inpos int iUse = Para.bUseInpos ? 1 : 0; int iRet = Cmmsdk.cmmCfgSetMioProperty(Para.iPhysicalNo, (int)MotnDefines._TCmMioPropId.cmINP_EN, iUse); //EncInputMode 설정 Cmmsdk.cmmCfgSetInMode(Para.iPhysicalNo, (int)Para.eEncMulti, (int)Para.eEncInputMode); //Pulse Output 설정 int iRst = Cmmsdk.cmmCfgSetOutMode(Para.iPhysicalNo, (int)Para.ePulseOutput); //하드웨어 리밋 Cmmsdk.cmmCfgSetMioProperty(Para.iPhysicalNo, (int)MotnDefines._TCmMioPropId.cmEL_MODE, 1); // 0-즉시정지,1-감속정지 Cmmsdk.cmmCfgSetMioProperty(Para.iPhysicalNo, (int)MotnDefines._TCmMioPropId.cmEL_LOGIC, (int)Para.eLimPhase); Cmmsdk.cmmCfgSetMioProperty(Para.iPhysicalNo, (int)MotnDefines._TCmMioPropId.cmALM_MODE, 1); // 0-즉시정지,1-감속정지 Cmmsdk.cmmCfgSetMioProperty(Para.iPhysicalNo, (int)MotnDefines._TCmMioPropId.cmALM_LOGIC, (int)Para.eAlarmPhase); Cmmsdk.cmmCfgSetMioProperty(Para.iPhysicalNo, (int)MotnDefines._TCmMioPropId.cmEZ_LOGIC, (int)Para.eZphaPhase); Cmmsdk.cmmCfgSetMioProperty(Para.iPhysicalNo, (int)MotnDefines._TCmMioPropId.cmINP_LOGIC, (int)Para.eInposPhase); Cmmsdk.cmmCfgSetMioProperty(Para.iPhysicalNo, (int)MotnDefines._TCmMioPropId.cmORG_LOGIC, (int)Para.eHomePhase); Cmmsdk.cmmCfgSetMioProperty(Para.iPhysicalNo, (int)MotnDefines._TCmMioPropId.cmSVON_LOGIC, (int)Para.eServoPhase); //링카운터 (ex, 원으로 돌때 해당 포지션에서 0로 변경) //이 기능은 COMI-LX502 제품에서는 지원하지 않습니다. 대여받은게 하필 이거라 테스트 못해봄 iUse = Para.dSetMaxPos == 0 ? 0 : 1; Cmmsdk.cmmCfgSetRingCntr(Para.iPhysicalNo, (int)MotnDefines._TCmCntr.cmCNT_COMM, iUse, Para.dSetMaxPos * m_dPulsePerUnit); Cmmsdk.cmmCfgSetRingCntr(Para.iPhysicalNo, (int)MotnDefines._TCmCntr.cmCNT_FEED, iUse, Para.dSetMaxPos * m_dPulsePerUnit); if (Para.bGantryEnable) { SetLinkEnable(); } else { SetLinkDisable(); } }
/// <summary> /// 홈센서 기준 절대 위치로 이동. /// </summary> /// <param name="_dPos">이동할 위치 펄스단위</param> /// <param name="_dVel">이동할 속도 펄스단위</param> /// <param name="_dAcc">이동할 가속 펄스단위</param> /// <param name="_dDec">이동할 감속 펄스단위</param> /// <returns>성공여부</returns> public void GoAbs(double _dPos, double _dVel, double _dAcc, double _dDec) //abs move { //SpeedMode //0 또는 cmSMODE_C CONSTANT 속도모드 => 가감속을 수행하지 않습니다. //1 또는 cmSMODE_T TRAPEZOIDAL 속도모드 => 사다리꼴 가감속을 수행합니다. //2 또는 cmSMODE_S S-CURVE 속도모드 => S-CURVE 가감속을 수행합니다. //-1 또는 cmSMODE_KEEP 이전 속도 모드는 그대로 설정합니다. //int iSMode = Para.dSCurveAcPer == 0 || Para.dSCurveDcPer == 0 ? (int)MotnDefines._TCmSpeedMode.cmSMODE_T : (int)MotnDefines._TCmSpeedMode.cmSMODE_S; Cmmsdk.cmmCfgSetSpeedPattern(Para.iPhysicalNo, (int)Para.eSpeedMode, _dVel, _dAcc, _dDec); int iRet = Cmmsdk.cmmSxMoveToStart(Para.iPhysicalNo, _dPos); }
/// <summary> /// 홈동작 완료 확인. /// </summary> /// <returns>홈동작 완료여부</returns> public bool GetHomeDone() { int iRet = 0; bool bRet; const int HOME_SUCCESS = 1; // 홈 완료 Cmmsdk.cmmHomeGetSuccess(Para.iPhysicalNo, ref iRet); bRet = (iRet == HOME_SUCCESS); return(bRet); }
//===============================================================================요 밑으로 필요없는 애들(동기구동) /// <summary> /// Master/Slave모터간 동기구동 /// 이 함수는 밖에서 자유롭게 Link Enable 할수 있다. /// </summary> public bool SetLinkEnable(int _iSlvMotrNo = 0) { //if (Para.bGantryEnable) //int iRet = Cmmsdk.cmmMsRegisterSlave(Para.iGantrySubAdd, 500000, (int)MotnDefines._TCmBool.cmFALSE);//맥스 스피드를 하필 여기서 넣냐....그냥 상수로 때려넣음 //double.MaxValue 값 넣으면 슬레이브 커맨드가 막 왓다 갓다 하면서 병신짓함 int iRet = Cmmsdk.cmmMsRegisterSlave(Para.iGantrySubAdd, int.MaxValue, (int)MotnDefines._TCmBool.cmFALSE);//맥스 스피드를 하필 여기서 넣냐....그냥 상수로 때려넣음 if (iRet == 1) { return(true); } return(false); }
//Display용 모듈 순서 /// <summary> /// 초기화함수 /// </summary> /// <returns>성공했는지 실패했는지 여부</returns> public bool Init() { // Load Motion & DIO devices // int nNumAxes = 0; if (Cmmsdk.cmmGnDeviceLoad((int)MotnDefines._TCmBool.cmTRUE, ref nNumAxes) != MotnDefines.cmERR_NONE) { Log.ShowMessage("Dio", "Comizoa Device Loading Error"); return(false); } //Input 전체 채널 개수 Cmmsdk.cmmAdvGetNumAvailDioChan((int)MotnDefines._TCmBool.cmTRUE, ref m_iMaxIn); //현재 사용 가능한 Input채널 갯수를 찾는다.(첫번째 인자가 False이면 Output) //Output 전체 채널 개수 Cmmsdk.cmmAdvGetNumAvailDioChan((int)MotnDefines._TCmBool.cmFALSE, ref m_iMaxOut); //현재 사용 가능한 Input채널 갯수를 찾는다.(첫번째 인자가 False이면 Output) m_aModuleInfo = new TModuleInfo(); m_aModuleInfo.iCntIn = m_iMaxIn; m_aModuleInfo.iCntOut = m_iMaxOut; return(true); //Input모듈 개수 찾는곳 //for (int i = 0; i < m_iMaxIn; i++) //{ // //이거 안될수도 있음 확인해야함. 진섭. // //해당 함수는 IsInputChannel 인자로 선택 된 Input 혹은 Output의 Axis 인자로 선택 된 채널의 장치 Instance를 반환합니다. // //Instance는 같은 종류의 장치(ex SD404 2장)을 사용할 경우 각 장치를 구분하기 위한 숫자로 0번부터 시작합니다. // Cmmsdk.cmmAdvGetDioDevInstance(i, (int)MotnDefines._TCmBool.cmTRUE, ref m_iInModuleCnt); //Axis: DevInstance를 확인할 채널 // //IsInputChannel : input, output 선택( 1 : Input, 0 : Output) // //DevInstance: 선택 된 채널의 장치의 Instance //} //Output 모듈 개수 찾는곳 //for (int o = 0; o < m_iMaxOut; o++) //{ // //이거 안될수도 있음 확인해야함. 진섭. // //해당 함수는 IsInputChannel 인자로 선택 된 Input 혹은 Output의 Axis 인자로 선택 된 채널의 장치 Instance를 반환합니다. // //Instance는 같은 종류의 장치(ex SD404 2장)을 사용할 경우 각 장치를 구분하기 위한 숫자로 0번부터 시작합니다. // Cmmsdk.cmmAdvGetDioDevInstance(o, (int)MotnDefines._TCmBool.cmFALSE, ref m_iOutModuleCnt); //Axis: DevInstance를 확인할 채널 // //IsInputChannel : input, output 선택( 1 : Input, 0 : Output) // //DevInstance: 선택 된 채널의 장치의 Instance //} //m_iModuleCnt = 0; //m_iModuleCnt = m_iInModuleCnt + m_iOutModuleCnt; //m_aModuleInfo = new TModuleInfo[m_iModuleCnt]; }
/// <summary> /// 현재 동기구동 상태이면 return true; /// </summary> /// <returns></returns> public bool GetLinkMode() { int iSlaveState = 0; Cmmsdk.cmmMsCheckSlaveState(Para.iGantrySubAdd, ref iSlaveState); //-1 해당 축이 Slave 축으로 등록되어 있지만 모션 에러가 발생하였음을 의미합니다. 이 //때는 Slave 축을 다시 등록할 필요는 없지만 에러 상황은 해제 시켜주어야 합니다. //0 해당 축이 Slave 축으로 등록되어 있지 않습니다. //1 해당 축이 Slave 축으로서 등록되어 있으며 정상 동작을 하고 있습니다. if (iSlaveState == 1) { return(true); } return(false); }
/// <summary> /// 네트워크 타입들은 시그널을 받아 놓는다. /// </summary> public void Update() { int iMioState = 0; Cmmsdk.cmmStReadMioStatuses(Para.iPhysicalNo, ref iMioState); MotionStat.bAlarmSgnl = ((iMioState >> (int)MotnDefines._TCmMioState.cmIOST_ALM) & 0x01) == 0x01; MotionStat.bPLimSnsr = ((iMioState >> (int)MotnDefines._TCmMioState.cmIOST_ELP) & 0x01) == 0x01; MotionStat.bNLimSnsr = ((iMioState >> (int)MotnDefines._TCmMioState.cmIOST_ELN) & 0x01) == 0x01; MotionStat.bHomeSnsr = ((iMioState >> (int)MotnDefines._TCmMioState.cmIOST_ORG) & 0x01) == 0x01; MotionStat.bInPosSgnl = ((iMioState >> (int)MotnDefines._TCmMioState.cmIOST_INP) & 0x01) == 0x01; MotionStat.bZphaseSgnl = ((iMioState >> (int)MotnDefines._TCmMioState.cmIOST_EZ) & 0x01) == 0x01; Cmmsdk.cmmStGetCount(Para.iPhysicalNo, (int)MotnDefines._TCmCntr.cmCNT_COMM, ref MotionInfo.iCmdPos); Cmmsdk.cmmStGetCount(Para.iPhysicalNo, (int)MotnDefines._TCmCntr.cmCNT_FEED, ref MotionInfo.iActPos); }
/// <summary> /// 서보상태를 받아옴. /// </summary> /// <returns>온오프</returns> public bool GetServo() { int iRet = -1; int iOn = 0; //bRet = ((MotionInfo.uOutput >> 0) & 0x01) == 0x01; iRet = Cmmsdk.cmmGnGetServoOn(Para.iPhysicalNo, ref iOn); bool bRet = Convert.ToBoolean(iOn); if (Para.eServoPhase == LOGIC.LOGIC_B) { bRet = !bRet; } return(Convert.ToBoolean(bRet));//== MotnDefines.cmERR_NONE; }
/// <summary> /// -방향 조그 이동 /// </summary> /// <param name="_dVel">초당 구동 속도 펄스</param> /// <param name="_dAcc">구동 가속율 펄스</param> /// <param name="_dDec">감속율 펄스</param> public void JogN(double _dVel, double _dAcc, double _dDec) //Jogging to CCW. { //Move Jog. //Check Status. //if (m_bAlarm ) return false; //if (!m_bServo) return false; //if (Vel <= 0 ) return false; //if (Dec <= 0 ) Acc = Dec; //double dVel = ConvVel(Vel); //double dAcc = ConvAcc(Vel, Acc); //double dDec = ConvAcc(Vel, Dec); int iDir = (int)MotnDefines._TCmDir.cmDIR_N; // Cmmsdk.cmmCfgSetSpeedPattern(Para.iPhysicalNo, (int)Para.eSpeedMode, _dVel, _dAcc, _dDec); Cmmsdk.cmmSxVMoveStart(Para.iPhysicalNo, iDir); }
//특수기능 /// <summary> /// 하드웨어 트리거를 발생시킨다. /// </summary> /// <param name="_daPos">발생시킬 트리거 위치들</param> /// <param name="_dTrgTime">트리거 시그널의 시간us</param> /// <param name="_bActual">엔코더기준인지 커멘드 기준인지</param> /// <param name="_bOnLevel">트리거 레벨</param> public void SetTrgPos(double[] _daPos, double _dTrgTime, bool _bActual, bool _bOnLevel) //Target Actual Position or Command Position. { //CMP 출력은 One-shot pulse 로 출력되는데, 출력되는 펄스의 폭을 조절할 //수 있습니다. 설정 및 반환되는 PropVal 은 다음과 같습니다. //• 0 : 트리거 시점의 Command 펄스의 펄스폭과 동일한 펄스폭을 가짐 //• 양수의 값 : 이 값에 1.5us 가 곱해진 값이 펄스폭이 됩니다. 즉, 이 값을 //1 로 하면 1.5us, 2 로 하면 3us…와 같이 됩니다. int iTrgTime = (int)(_dTrgTime / 1.5); int iRet = Cmmsdk.cmmCfgSetMioProperty(Para.iPhysicalNo, (int)MotnDefines._TCmMioPropId.cmCMP_PWIDTH, iTrgTime); int iCmpSrc = 0; if (_bActual) { iCmpSrc = (int)MotnDefines._TCmCntr.cmCNT_COMM; // Command Position 0 } else { iCmpSrc = (int)MotnDefines._TCmCntr.cmCNT_FEED; // Feedback Position 1 } //CmpMethod 1번으로 사용하는건 잘 모르겟음 일단 기본 베이스 맞춰서 1,2사용으로 함 //0 (cmDISABLE) Disable comparator //1 (cmEQ_BIDIR) CmpData = CmpSrc_Value (regardless of counting direction) 카운팅 방향에 상관 없이 //2 (cmEQ_PDIR) CmpData = CmpSrc_Value (while counting up) //3 (cmEQ_NDIR) CmpData = CmpSrc_Value (while counting down) //4 (cmLESS) CmpData > CmpSrc_Value //5 (cmGREATER) CmpData < CmpSrc_Value //(+)방향쪽으로 이동시에만 트리거펄스가 출력되고 (-)방향으로 이동할 때는 출력하지 //않도록(cmEQ_PDIR) 합니다. 엣지 개념이 아닌듯해서 1번으로 사용 int iCmpMethod = (int)MotnDefines._TCmCmpMethod.cmEQ_BIDIR; //if(_bActual) iCmpMethod = (int)MotnDefines._TCmCmpMethod.cmEQ_PDIR; // CmpData = CmpSrc_Value (while counting up) //else iCmpMethod = (int)MotnDefines._TCmCmpMethod.cmEQ_NDIR; // CmpData = CmpSrc_Value (while counting down) //위치 비교기 조건 설정 및 확인 Cmmsdk.cmmCmpTrgSetConfig(Para.iPhysicalNo, iCmpSrc, iCmpMethod); //연속적인 위치데이터 등록 Cmmsdk.cmmCmpTrgContRegTable(Para.iPhysicalNo, _daPos, _daPos.Length); //연속적인 위치 비교 기능 시작 Cmmsdk.cmmCmpTrgContStart(Para.iPhysicalNo); }
/// <summary> /// 리셋 시그널 온오프 제어 /// </summary> /// <param name="_bOn">온오프</param> public void SetReset(bool _bOn) { if (_bOn) { Cmmsdk.cmmGnSetAlarmRes(Para.iPhysicalNo, 1); } else { Cmmsdk.cmmGnSetAlarmRes(Para.iPhysicalNo, 0); } //public static extern unsafe int cmmGnPulseAlarmRes( //[MarshalAs(UnmanagedType.I4)] int Axis, //[MarshalAs(UnmanagedType.I4)] int IsOnPulse, //[MarshalAs(UnmanagedType.I4)] int dwDuration, //[MarshalAs(UnmanagedType.I4)] int IsWaitPulseEnd); //if(_bOn) Cmmsdk.cmmGnPulseAlarmRes(Para.iPhysicalNo,0,100,100); //else Cmmsdk.cmmGnPulseAlarmRes(Para.iPhysicalNo,0,100,100); }
/// <summary> /// 서보 온오프 /// </summary> /// <param name="_bOn">온오프</param> public void SetServo(bool _bOn) { int iOn; //= _bOn ? 0 : 1; if (Para.eServoPhase == LOGIC.LOGIC_B) { iOn = _bOn ? 0 : 1; } else { iOn = _bOn ? 1 : 0; } Stop(); //다이렉트케이블이 같이 엮겨 있을때 Machine에서 그냥 MT_SetY로 쓰기때문에 사용한하게 됨. //if (Para.bUseBreak) SetY(Para.iBreakOffAdd, _bOn); Cmmsdk.cmmGnSetServoOn(Para.iPhysicalNo, iOn); if (!_bOn) { SetHomeDone(false); } //else //{ // //가끔 장비껐다가 켜서 홈잡을때 겐트리가 안엮여서 병신짓 할때 있어서 // //서보 온에서 한번씩 해본다. // //밖에 사이클홈에서 홈시작전에 확인 하여 알람 띄워보자. // //동기구동을 Gantry 이용해서 거는데 Para.bGantryEnable 조건 없으면 // //Reset할때마다 GetLinkMode false 시켜서 조건 건다. 진섭. // if (Para.bGantryEnable) // { // SetGantryEnable(); // } // //} }
/// <summary> /// IO출력 /// </summary> /// <param name="_iNo">IO번호</param> /// <param name="_bOn">true=ON , false=OFF</param> /// <returns>성공여부</returns> public bool SetOut(int _iNo, bool _bOn, bool _bDirect = false) { //Check Error. if (_iNo >= m_iMaxOut || _iNo < 0) { return(false); } //Get Addr. int iBitAddr; int iModule; int iModuleDp; GetInfoOutput(_iNo, out iModule, out iModuleDp, out iBitAddr); //OutPut if (_bDirect) { int iOn = _bOn ? 1 : 0; Cmmsdk.cmmDoPutOne(_iNo, iOn); return(true); } else//여기 꼭 확인해야함. 안될 가능성이 99.999999999%임 { int iOn = 0; if (_bOn) { m_aModuleInfo.iDataOutSet |= (((iOn >> iBitAddr) | 0x01) << iBitAddr); } else { m_aModuleInfo.iDataOutSet &= ~(((iOn >> iBitAddr) | 0x01) << iBitAddr); } return(true); } }
/// <summary> /// Command Encoder Target포지션 세팅. /// </summary> /// <param name="_dPos">세팅할 펄스</param> public void SetPos(double _dPos) { Cmmsdk.cmmStSetPosition(Para.iPhysicalNo, 0, _dPos); //Command position Cmmsdk.cmmStSetPosition(Para.iPhysicalNo, 1, _dPos); //Feedback position }
/// <summary> /// 닫기 함수. /// </summary> /// <returns>성공 했는지 실패했는지 여부</returns> public bool Close() { Cmmsdk.cmmGnDeviceUnload(); return(true); }
/// <summary> /// SetTrgPos로 세팅된 포지션 리셑 /// </summary> public void ResetTrgPos() { //연속위치비교 기능 종료 Cmmsdk.cmmCmpTrgContStop(Para.iPhysicalNo); }
/// <summary> /// 동기구동 해제 /// </summary> public bool SetLinkDisable(int _iSlvMotrNo = 0) { Cmmsdk.cmmMsUnregisterSlave(Para.iGantrySubAdd);//Axis 인자가 Slave로 설정되어 +1하여 갠트리 해제함. return(true); }
//Home씨퀜스. /// <summary> /// 홈을 수행한다. /// </summary> /// <returns>수행 성공여부.</returns> public bool GoHome(double _dHomeVelFirst, double _dHomeVelLast, double _dHomeAccFirst) { //원점복귀 작업을 수행합니다. cmmHomeMove() 함수는 모션이 완료되기 전까지 반환되지 않으며, //cmmHomeMoveStart() 함수는 모션을 시작시킨 후에 바로 반환됩니다. SetServo(true); //Home Mode //0 : ORG > Stop //1 : ORG > Stop > Back (Vr) > ORG-OFF > Foward(Vr) > ORG > Stop //2 : ORG > Slow down (Vini) > Stop on EZ Count //3 : ORG > Stop on EZ Count //4 : ORG > Stop > Back (Vr) > Stop on EZ Count //5 : ORG > Stop > Back (Vwork) > Stop on EZ //6 : EL > Stop > Back (Vr) > EL 0 > Stop //7 : EL > Stop > Back (Vr) > Stop on EZ count //8 : EL > Stop > Back (Vwork) > Stop on EZ count //9 : MODE0 > Operate till dev. counter 0 //10 : MODE3 > Operate till dev. counter 0 //11 : MODE5 > Operate till dev. counter 0 //12 : MODE8 > Operate till dev. counter 0 int iHomeMode = 0; if (Para.eHomeZMethod == Z_METHOD.HomeDirection) { if (Para.eHomeSignal == HOME_SIGNAL.HomeSensor) { iHomeMode = 3; } if (Para.eHomeSignal == HOME_SIGNAL.NLimitSensor) { iHomeMode = 7; } if (Para.eHomeSignal == HOME_SIGNAL.PLimitSensor) { iHomeMode = 7; } if (Para.eHomeSignal == HOME_SIGNAL.ZPhase) { iHomeMode = 3; //이거는 없네;;; } } else if (Para.eHomeZMethod == Z_METHOD.NotHomeDirection) { if (Para.eHomeSignal == HOME_SIGNAL.HomeSensor) { iHomeMode = 4; } if (Para.eHomeSignal == HOME_SIGNAL.NLimitSensor) { iHomeMode = 7; } if (Para.eHomeSignal == HOME_SIGNAL.PLimitSensor) { iHomeMode = 7; } if (Para.eHomeSignal == HOME_SIGNAL.ZPhase) { iHomeMode = 3; //이거는 없네;;; } } else { if (Para.eHomeSignal == HOME_SIGNAL.HomeSensor) { iHomeMode = 1; } if (Para.eHomeSignal == HOME_SIGNAL.NLimitSensor) { iHomeMode = 6; } if (Para.eHomeSignal == HOME_SIGNAL.PLimitSensor) { iHomeMode = 6; } if (Para.eHomeSignal == HOME_SIGNAL.ZPhase) { iHomeMode = 1; } } //Manual //long nHomeMode = 0; // 원점 복귀 모드 설정. 0 ~ 12 번 모드가 있습니다. //long nHomeDir = cmDIR_N; // 원점 복귀 방향. cmDIR_N: (-) 방향, cmDIR_P: (+) 방향 //long nEzCount = 0; // Encoder Z 상 카운트. ‘0’ 은 EZ 상 1 회 카운트를 의미합니다. //double fEscDist = 10.0f; // 원점 탈출 거리. 자동 원점 검색 기능에 사용되며, //// 최소 ‘1’ 이상의 값이어야 합니다. //double fOffset = 0.0f; // 원점 복귀 완료 후 Offset 값 (상대 거리) int iHomeDir = Para.bHomeNegDir ? 0 : 1; // 0 - N , 1 - P Cmmsdk.cmmHomeSetConfig(Para.iPhysicalNo, iHomeMode, iHomeDir, 1, Para.dHomeOffset * m_dPulsePerUnit); //iHomeClearMode //0 : Clears both position(C&F) at the moment ORG(/EL/EZ) signal works. //1 : Clears both position(C&F) after home completes. //2 : Set command smae as feedback after home completes. //-1 : Disable HomePosClearMode. int iHomeClearMode = 1; Cmmsdk.cmmHomeSetPosClrMode(Para.iPhysicalNo, iHomeClearMode); //Vr(Reverse Speed) //▶ Revel : cmmHomeSetSpeedPattern 함수의 인자이며, Reverse Speed 를 설정합니다. 복귀모드에 따라 Reverse Speed 를 //필요로 하는 모드가 있습니다. 앞의 복귀 모드 설명에서 Reverse Speed 는 Vr 로 표기되었습니다. //SpeedMode //0 또는 cmSMODE_C CONSTANT 속도모드 => 가감속을 수행하지 않습니다. //1 또는 cmSMODE_T TRAPEZOIDAL 속도모드 => 사다리꼴 가감속을 수행합니다. //2 또는 cmSMODE_S S-CURVE 속도모드 => S-CURVE 가감속을 수행합니다. Cmmsdk.cmmHomeSetSpeedPattern(Para.iPhysicalNo, (int)MotnDefines._TCmSpeedMode.cmSMODE_T, _dHomeVelFirst, _dHomeAccFirst, _dHomeAccFirst, _dHomeVelLast); //0 또는 cmDIR_N (-) 방향 //1 또는 cmDIR_P (+) 방향 int iFuncRet = Cmmsdk.cmmHomeMoveStart(Para.iPhysicalNo, iHomeDir); return(iFuncRet == MotnDefines.cmERR_NONE); }
/// <summary> /// 강제로 홈돈 시그널 세팅. /// </summary> /// <param name="_bOn">세팅 값.</param> public void SetHomeDone(bool _bOn) { int iOn = _bOn ? 1 : 0; Cmmsdk.cmmHomeSetSuccess(Para.iPhysicalNo, iOn); //HomeDone 강제 Setting. 0 == false, 1 == true. 진섭 }
//Motion Functions. /// <summary> /// 모터 정지 명령. /// </summary> public void Stop() { Cmmsdk.cmmSxStop(Para.iPhysicalNo, 0, 1); }
/// <summary> /// 모터 감속 무시 긴급정지. /// </summary> public void EmgStop() //Stop Without Deceleration. { Cmmsdk.cmmSxStopEmg(Para.iPhysicalNo); }