// Motor.h: interface for the CMotor class. // ////////////////////////////////////////////////////////////////////// #pragma once #include #include #include #include "Hardware.h" #include "Card.h" #include "DllDefines.h" #include "MotionPath.h" // Motion card Type #define PCI_8134 0 #define PCI_8134_STR "8134" #define PCI_8164_ADLINK 1 #define PCI_8164_ADLINK_STR "8164" #define PCI_GALIL 2 #define PCI_GALIL_STR "Galil" // ETEL #define PCI_ETEL 3 #define PCI_ETEL_STR "ETEL" #define PCI_APS_ADLINK 4 // master driver for many different supported cards, eg 7856, 8256, ECAT #define PCI_APS_ADLINK_STR "ADLINK_APS" #define PCI_7856_MOTIONNET_ADLINK 5 #define ACS_MOTOR_ID 6 #define ACS_MOTOR_STR "ACS" #define ACS_MUTEX_NAME "acs_mutex" // advantech ethercat #define PCI_ETHERCAT_MASTER_ADVANTECH 7 // master driver for many different supported cards, eg 1203 #define PCI_ETHERCAT_MASTER_ADVANTECH_STR "ADVANTECH_ETHERCAT" #define PCI_1203_ETHERCAT_MOTION_ADVANTECH 8 // #define PCIe_ADLINK_ECAT_MOTION 9 #define MAX_MOTION_CONTROLLER_TYPE 10 #define MAX_MC_MOTOR 64 // Max motor per machine #define MAX_MOTOR 50 // #define MAX_MOTOR_MODULE_ARRAY MAX_MOTOR // #define MAX_IO_MODULE_ARRAY 75 // #define MAX_MOTOR_POS 30 #define MOTOR_STEPPER 0 #define MOTOR_STEPPER_ENC 1 #define MOTOR_SERVO 2 #define MOTOR_SERVO_REVERSE 3 #define MOTOR_STEPPER_WITH_INP 4 #define MOTOR_STEPPER_WITH_ENC_AND_INP 5 // created more motor types to // handle Adlink motor control to use only internal counter #define MOTOR_STEPPER_ENC_INTERNAL 6 #define MOTOR_STEPPER_WITH_ENC_AND_INP_INTERNAL 7 #define MOTOR_STEPPER_REVERSE_ENC_INTERNAL 8 #define MOTOR_STEPPER_WITH_REVERSE_ENC_AND_INP_INTERNAL 9 #define MOTOR_PULSE_OUTPUT_1P 0 // Out, Dir #define MOTOR_PULSE_OUTPUT_2P 1 // CW, CCW (+ve = OUT -> CW) #define MOTOR_PULSE_OUTPUT_4AB_PHASE_LEADING 6 // A Phase, B Phase (+ve = OUT Leading) // 8134 IO Status /* ------------ I/O Status Definition ------------------------------------- */ #define pos_limit 0x01 #define neg_limit 0x02 #define psd_switch 0x04 #define nsd_switch 0x08 #define org_limit 0x10 #define idx_switch 0x20 #define alm_switch 0x40 #define svon_sts 0x80 #define rdy_sts 0x100 #define int_sts 0x200 #define erc_sts 0x400 #define inp_sts 0x800 /* ------------ I/O Status Definition ------------------------------------- */ // 8164 IO status #define Ready_IO 0x0001 #define Alarm_IO 0x0002 #define Pos_Limit_IO 0x0004 #define Neg_Limit_IO 0x0008 #define Org_IO 0x0010 #define Index_IO 0x0200 #define Inp_IO 0x2000 #define Svon_IO 0x4000 // Galil Tell Switch #define LATCHED 0x01 #define HOME_SENSOR_STATUS 0x02 #define REV_LIMIT_SENSOR 0x04 #define FWD_LIMIT_SENSOR 0x08 #define UNDEFINED 0x10 #define MOTOR_ON 0x20 #define MOTOR_LIMIT_ERROR 0x40 #define MOTOR_IN_MOTION 0x80 // ETEL Inputs #define ETEL_HOME_SENSOR 0x0002 #define ETEL_NEG_LIMIT_SENSOR 0x0100 #define ETEL_POS_LIMIT_SENSOR 0x0200 // ETEL M60 STATUS #define ETEL_STATUS_CONTROLLER_POWER_ON 0x1 #define ETEL_STATUS_HOME_COMPLETED 0x4 #define ETEL_STATUS_MOTOR_PRESENT 0x8 #define ETEL_STATUS_MOTOR_IS_MOVING 0x10 #define ETEL_STATUS_MOTOR_IS_IN_POSITION 0x20 #define ETEL_STATUS_MOTOR_ERROR 0x400 #define ETEL_STATUS_MOTOR_DOING_HOMING 0x2000 enum MOTION_STATUS { MOTION_END, MOTION_HOMING, MOTION_MOVING, MOTION_LIMIT_POS_HIT, MOTION_LIMIT_NEG_HIT, MOTION_LIMIT_HIT, MOTION_MTR_OFF, MOTION_DRIVER_ALARM, MOTION_ERROR, MOTION_FAILED_TO_STOP, MOTION_MTR_ON, MOTION_COMMAND_SUCCESS, MOTION_EXCEED_SOFT_LIMIT_ERROR, MOTION_FORCE_STOP, MAX_MOTION_STATUS, }; enum HOMING_METHOD { HOME_SENSOR, HOME_INDEX, HOME_SENSOR_INDEX, HOME_BY_LIMIT, HOME_BY_LIMIT_THEN_INDEX = 27, }; struct stMtrPosTeach { std::string strPos{}; BOOL bTeachEnable{ FALSE }; }; // motor profile data structure class IODLLCLASS CMtrProfile { public: std::string m_strMotorName{}; int m_iMtrNo; // motor no wrt the type of card used int m_iMtrType; // servo or stepper, with or without encoder feedback // int m_iUpr; // unit per motor revolution // int m_iPPR; // pulse per revolution // int m_iEPPR; // encoder pulse per revolution double m_dUpr; // unit per motor revolution double m_dPPR; // pulse per revolution double m_dEPPR; // encoder pulse per revolution int m_iPosDir; // positive dir is CW or CCW int m_iClk; // OUT/DIR or CW/CCW type int m_iHomeMode; // homing mode int m_iHomeDir; // homing dir int m_iIndexLogic; // index or z pulse signal logic from the encoder int m_iALM; // motor driver alarm signal logic int m_iINP; // in-position logic from motor driver int m_iPosEL; // positive limit sensor signal logic int m_iNegEL; // negative limit sensor signal logic int m_iORGI; // home sensor signal logic int m_iRDY; // motor driver Ready signal logic int m_iSON; // motor enable signal logic int m_iCLR; // motor driver clear alarm signal logic double m_dConst; // constant speed, must be double double m_dStartUp; // start speed, must be double double m_dCruise; // max speed, must be double double m_dAcce; // acceleration double m_dDec; // deceleration int m_iCardType; // card type, eg 8134 double m_dSAcce; // s-curve profile acceleration double m_dSDec; // s-curve profile deceleration double m_dHomeLeaveSteps; // leave steps for homing int m_iEncoderType; // type of encoder, 1xAB, 2xAB, 4xAB, CW/CCW double m_dPosSoftLimit; // positive Software Limit double m_dNegSoftLimit; // negative Software Limit int m_iCardNo; int m_iSlaveId{}; // for EtherCAT, slave ID int m_iMotorPosArrayIndex; std::vector m_motorPos; }; class IODLLCLASS CMtrPos { public: // default constructor CMtrPos(); // constructor to initialised current instance motor num CMtrPos(int iMtrNo); // destructor virtual ~CMtrPos(); // get current motor position based on motor number. // if int iMtrNo = -1, return current instance motor position int GetCurPos(int iMtrNo = -1); // set total no of motor based on motor number void SetNoOfMtr(int iNoOfMtr); enum { INVALID = -1, NO_POS_SET = -1, }; bool IsValidMotor(int iMtrNo); protected: // set the current position of motor based on motor number // if int iMtrNo = -1, return set current instance motor position void SetCurPos(int iPos, int iMtrNo = -1); private: static std::vector m_vecMtrCurPos; // array to keep track all motor current position static int m_iNoOfInstance; // keep track no of instance static int m_iNoOfMtr; // keep track of total number of motor int m_iMtrNo; // keep track motor number enum { NO_SPECIFIC_MOTOR = -1, }; }; class IODLLCLASS CMtrOnOff { public: // default constructor CMtrOnOff(); // constructor to initialised current instance motor num CMtrOnOff(int iMtrNo); virtual ~CMtrOnOff(); // get current motor On/Off based on motor number. // if int iMtrNo = -1, return current instance motor position bool GetCurMtrOnOff(int iMtrNo = -1); // set total no of motor based on motor number void SetNoOfMtr(int iNoOfMtr); enum { INVALID = -1, NO_STATE_SET = -1, }; int GetMotorCount(); bool IsValidMotor(int iMtrNo); protected: // set the current On/Off of motor based on motor number // if int iMtrNo = -1, return set current instance motor On/Off void SetCurMtrOnOff(bool bOnOffState, int iMtrNo = -1); private: static std::vector m_vecMtrCurOnOff; // array to keep track all motor current On/Off States int m_iMtrNo{ NO_SPECIFIC_MOTOR }; // keep track motor number static int m_iNoOfInstance; // keep track no of instance static int m_iNoOfMtr; // keep track of total number of motor enum { NO_SPECIFIC_MOTOR = -1, }; }; class CMotorBase; // applicable to GALIL pulse stretcher enum GALIL_PULSE_TYPE { STRETCH_NON, // 600 ns STRETCH_TYPE1, // 2ms }; class IODLLCLASS CMotor : public CCard // public CMtrPos, CCard, CMtrOnOff, CMyWait { public: int GetCurPos(); int SetMultipleTrigger(double dStartPosition, double dStopPosition, double dIntervalDistance, int nNoOfTrigger, int nCmpSource = 1); int SetMultipleTrigger(double* pdPosition, int nNoOfTrigger, int nCmpSource = 1); int SMoveContinuously(bool bCW = true); int MoveContinuously(bool bCW = true); // ************************************************************ // Applicable to Galil Axis - STARTS // ************************************************************ // currently used by Galil only enum INTERRUPT_CODE { NEG_LIMIT_HIT = 1, POS_LIMIT_HIT, HOME_MOVE_COMPLETE, }; std::string GetVariable(const std::string& csVariableName); int StopProgramAndMotion(); int UpdateProfile(); int SendCommand(const std::string& csCommand); // ************************************************************ // Applicable to Galil Axis - ENDS // ************************************************************ // ************************************************************ // Methods to enquire other motors status - STARTS // ************************************************************ double GetOtherAxisPosition(const CMtrProfile& mtrProfile); // Check other axis home sensor BOOL IsHomed(const CMtrProfile& mtrProfile); // Get other axis motion IO status int GetMotionIOStatus(const CMtrProfile& mtrProfile); // Get Other axis servo ready status BOOL IsServoReady(const CMtrProfile& mtrProfile); // Get Other axis Alarm status BOOL IsServoAlarm(const CMtrProfile& mtrProfile); // Get Other axis negative limit status BOOL IsNegLmtHit(const CMtrProfile& mtrProfile); // Get Other axis positive limit status BOOL IsPosLmtHit(const CMtrProfile& mtrProfile); // Get Other axis positive limit status bool IsMtrOn(const CMtrProfile& mtrProfile); // ************************************************************ // Methods to enquire other motors status - ENDS // ************************************************************ int SetConversionFactor(double dUPR, double dPPR, double dEPPR); // currently only support 8134 int SimultaneousMove(int nNoOfAxis, CMtrProfile* mtrProfile, double* dPosition, double* dStartVel, double* dMaxVel, double* dAcc, int nMode = 0); // currently only support 8134A bool StopSimultaneousMove(int nFirstAxisNo); int SetVirtualHomePosition(double dVirtualHomePosition); int ResetSingleTrigger(double dPosition = 0.0); void UpdatePosition(int nPos); void ResetRequiredMotionEvents(); double ConvertToPulse(double dDistance); bool IsEnableIntCheck(); void DisableIntCheck(); void EnableIntCheck(); // specify the pulse (time) stretch type used for galil card // applicable to GALIL, ADLINK 8164 int SetSingleTrigger(double dPosition, int nCmpSource = 1, int nPulseStretch = STRETCH_NON); // bool HomingByLimit(); double GetNegativeSoftLimit(); double GetPositiveSoftLimit(); void SetNegativeSoftLimit(double dNegSoftLimit); void SetPositiveSoftLimit(double dPosSoftLimit); int SetCommandPosition(double dPosition); // return: success = MOTION_END; error = MOTION_ERROR; Force Stop = MOTION_FORCE_STOP DWORD WaitHomeDone(); int GetMotionIOStatus(); BOOL IsServoReady(); BOOL IsServoAlarm(); BOOL IsNegLmtHit(); BOOL IsPosLmtHit(); BOOL IsHomed(); BOOL IsIndex(); bool IsMtrOn(); double GetCommandPosition(); void UpdatePosition(); HANDLE GetMotionInProgressTrigger(); HANDLE GetHomeMotionDoneTrigger(); HANDLE GetMotionDoneTrigger(); double GetPosErr(); // forced set the current position int SetPosition(double dPosition); // return the current motor position double GetPosition(); // move relative distance int MoveRel(double dDistance, int nPos = -1); // default NO Position // added new absolute move mode // move absolute int MoveAbs(double dPosition, int nPos = -1, int nMode = 0); // default NO Position // move relative distance with s-curve profile int SMoveRel(double dDistance, int nPos = -1); // default NO Position // added new absolute move mode // move absolute with s-curve profile int SMoveAbs(double dPosition, int nPos = -1, int nMode = 0); // default NO Position // added new absolute move mode // move motor based on position array with s-curve profile int SMove(int iPos, int nMode = 0); // wait for motion stop based on pulse send out or in-position signal // call this function after calling a move operation // return: success = MOTION_END; error = MOTION_ERROR; Force Stop = MOTION_FORCE_STOP // positive limit = MOTION_LIMIT_POS_HIT; negative limit = MOTION_LIMIT_NEG_HIT DWORD WaitMotionDone(DWORD dwTimeout = 1000); // constructor to initialised motor number, number of position and motor position array // CMotor(int iMtrNo, int iNoOfPos, double *dpPos); // constructor to initialised motor number, number of position and motor position array and motor profile // constructor to initialised motor position array and motor profile CMotor(const CMtrProfile& mtrProfile, double* dpPos); virtual ~CMotor(); // destructor // added new absolute move mode // move motor based on position array int Move(int iPos, int nMode = 0); // home motor, normal or use limit sensor as home. Whether to reset position tracking int Home(DWORD dwTimeout, bool bResetPositionTrack = true, bool bByLimit = false); void EnableResetPositionDuringHoming(bool bResetPositionDuringHoming); // stop motor with decceleration int DecStop(); // Emergence stop motor int EmerStop(); // On/Off motor int OnMtr(bool bOn); int SetConst(double dConst); int SetStartUp(double dStartUp, bool bHomeSlow = false); int SetCruise(double dCruise, bool bHomeSlow = false); int SetAcce(double dAcce, bool bHomeSlow = false); int SetDec(double dDec, bool bHomeSlow = false); int SetSAcce(double dSAcce); int SetSDec(double dSDec); // This method is used to reset alarm via MotionNet int ResetAlarm(bool bReset); // These methods only applies to ETEL Gantry Mode int GantryEnable(int nNoOfAxis, CMtrProfile* mtrProfile); int GantryDisable(int nNoOfAxis, CMtrProfile* mtrProfile); // Method to force a compare output pulse int TriggerCompareOutput(); int SegmentedMotion(int nAxis, const CMtrProfile* pMtrProfile, double* dPositions); int SegmentedLine(double* dPositions); int SegmentedEnd(); int SegmentedArc(double* dCenter, double* dFinalPoint, int rotation); int MasterSlaveEnable(const CMtrProfile& slaveMtrProfile, double offset, double leftBoundary, double rightBoundary); int MasterSlaveDisable(const CMtrProfile& slaveMtrProfile); bool SetFixSpdRange(double dMaxVel, bool bRealWorldUnit = false); bool UnFixSpdRange(); // LERP - Linear Interpolation bool StartXYRelMoveLinear(double dDistX, double dDistY, double dStartVel, double dMaxVel, double dAcc, double dDec); bool StartZURelMoveLinear(double dDistZ, double dDistU, double dStartVel, double dMaxVel, double dAcc, double dDec); bool StartXYSRelMoveLinear(double dDistX, double dDistY, double dStartVel, double dMaxVel, double dAcc, double dDec, double dSAcc, double dSDec); bool StartZUSRelMoveLinear(double dDistZ, double dDistU, double dStartVel, double dMaxVel, double dAcc, double dDec, double dSAcc, double dSDec); // void RegisterPathMoveMtrProfile(const std::vector& vecMtrProfile); int PathMove(const stMotionPath& motionPath); bool StopPathMove(const stMotionPath& motionPath); private: // all the various motion controller objects std::shared_ptr m_motorBase; };