You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

546 lines
17 KiB
C++

// Motor.h: interface for the CMotor class.
//
//////////////////////////////////////////////////////////////////////
#pragma once
#include <memory>
#include <string>
#include <vector>
#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<stMtrPosTeach> 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<int> 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<bool> 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<CMtrProfile>& vecMtrProfile);
int PathMove(const stMotionPath& motionPath);
bool StopPathMove(const stMotionPath& motionPath);
private:
// all the various motion controller objects
std::shared_ptr<CMotorBase> m_motorBase;
};