Jump to content
OMRON Forums

Virtual Motor Setup Using Pulse-and-Direction on Gate3/ACC-24E3


Omron Forums Support

Recommended Posts

Below is a setup file that one can use to get virtual motors on motors 1-4 using Pulse-and-Direction settings on Gate3 (with Gate3 at index 0):

 

/* Gate3 Version */
Sys.WpKey = $AAAAAAAA // Permit write access to Gate3 structures

/* Activate motors 1-4 */
Motor[1].ServoCtrl=1
Motor[2].ServoCtrl=1
Motor[3].ServoCtrl=1
Motor[4].ServoCtrl=1

// Write servo output to channel’s PFM register
Motor[1].pDac=Gate3[0].Chan[0].Pfm.a	// 1st channel PFM
Motor[2].pDac=Gate3[0].Chan[1].Pfm.a	// 2nd channel PFM
Motor[3].pDac=Gate3[0].Chan[2].Pfm.a	// 3rd channel PFM
Motor[4].pDac=Gate3[0].Chan[3].Pfm.a	// 4th channel PFM

// Set PFM Clock Divisor
Gate3[0].PfmClockDiv=5
Gate3[0].PfmClockDiv=5

// Set up channel output for PFM signal
// Not needed for simulation; only to monitor output signal
Gate3[0].Chan[0].OutputMode=8		// PFM on Phase D
Gate3[0].Chan[1].OutputMode=8		// PFM on Phase D
Gate3[0].Chan[2].OutputMode=8		// PFM on Phase D
Gate3[0].Chan[3].OutputMode=8		// PFM on Phase D

// Wrap PFM output back into channel’s encoder counter
Gate3[0].Chan[0].EncCtrl=8 // Internal pulse and direction clockwise
Gate3[0].Chan[1].EncCtrl=8 // Internal pulse and direction clockwise
Gate3[0].Chan[2].EncCtrl=8 // Internal pulse and direction clockwise
Gate3[0].Chan[3].EncCtrl=8 // Internal pulse and direction clockwise

// Disable overtravel limit inputs
// May be needed if there are no physical switches present
Motor[1].pLimits=0
Motor[2].pLimits=0
Motor[3].pLimits=0
Motor[4].pLimits=0

// Disable amplifier enable output
// May be needed if channel is also connected to real amplifier
Motor[1].pAmpEnable=0
Motor[2].pAmpEnable=0
Motor[3].pAmpEnable=0
Motor[4].pAmpEnable=0

// Disable amplifier fault input
// May be needed if channel is also connected to real amplifier
Motor[1].pAmpFault=0
Motor[2].pAmpFault=0
Motor[3].pAmpFault=0
Motor[4].pAmpFault=0

// Set derivative gain term in servo loop to zero
// This is a Type 1 servo (single integration); does not need Kd
Motor[1].Servo.Kvfb=0
Motor[2].Servo.Kvfb=0
Motor[3].Servo.Kvfb=0
Motor[4].Servo.Kvfb=0

// Lower proportional gain term from default
Motor[1].Servo.Kp=40
Motor[2].Servo.Kp=40
Motor[3].Servo.Kp=40
Motor[4].Servo.Kp=40

// Add Kvff and Ki
Motor[1].Servo.Kvff=40;
Motor[2].Servo.Kvff=40;
Motor[3].Servo.Kvff=40;
Motor[4].Servo.Kvff=40;

Motor[1].Servo.Ki=0.001;
Motor[2].Servo.Ki=0.001;
Motor[3].Servo.Ki=0.001;
Motor[4].Servo.Ki=0.001;

// Deactivate commutation for all motors
Motor[0].PhaseCtrl=0			// No phase commutation active
Motor[2].PhaseCtrl=0			// No phase commutation active
Motor[3].PhaseCtrl=0			// No phase commutation active
Motor[4].PhaseCtrl=0			// No phase commutation active

// Create encoder conversion table entries for all motors
EncTable[1].type=1;
EncTable[1].pEnc=Acc24E3[0].Chan[0].ServoCapt.a;
EncTable[1].pEnc1=Sys.pushm;
EncTable[1].index1=0;
EncTable[1].index2=0;
EncTable[1].index3=0;
EncTable[1].index4=0;
EncTable[1].ScaleFactor=1.0/256.0;
EncTable[1].MaxDelta=0;
EncTable[1].SinBias=0;
EncTable[1].CosBias=0;

EncTable[2].type=1;
EncTable[2].pEnc=Acc24E3[0].Chan[1].ServoCapt.a;
EncTable[2].pEnc1=Sys.pushm;
EncTable[2].index1=0;
EncTable[2].index2=0;
EncTable[2].index3=0;
EncTable[2].index4=0;
EncTable[2].ScaleFactor=1.0/256.0;
EncTable[2].MaxDelta=0;
EncTable[2].SinBias=0;
EncTable[2].CosBias=0;

EncTable[3].type=1;
EncTable[3].pEnc=Acc24E3[0].Chan[2].ServoCapt.a;
EncTable[3].pEnc1=Sys.pushm;
EncTable[3].index1=0;
EncTable[3].index2=0;
EncTable[3].index3=0;
EncTable[3].index4=0;
EncTable[3].ScaleFactor=1.0/256.0;
EncTable[3].MaxDelta=0;
EncTable[3].SinBias=0;
EncTable[3].CosBias=0;

EncTable[4].type=1;
EncTable[4].pEnc=Acc24E3[0].Chan[3].ServoCapt.a;
EncTable[4].pEnc1=Sys.pushm;
EncTable[4].index1=0;
EncTable[4].index2=0;
EncTable[4].index3=0;
EncTable[4].index4=0;
EncTable[4].ScaleFactor=1.0/256.0;
EncTable[4].MaxDelta=0;
EncTable[4].SinBias=0;
EncTable[4].CosBias=0;

// Point motors to encoder conversion table entries
Motor[1].pEnc=EncTable[1].a
Motor[2].pEnc=EncTable[2].a
Motor[3].pEnc=EncTable[3].a
Motor[4].pEnc=EncTable[4].a

Motor[1].pEnc2=EncTable[1].a
Motor[2].pEnc2=EncTable[2].a
Motor[3].pEnc2=EncTable[3].a
Motor[4].pEnc2=EncTable[4].a

/* Set up various PFM-Related Gate3 settings */
Gate3[0].Chan[0].OutFlagD=1;
Gate3[0].Chan[1].OutFlagD=1;
Gate3[0].Chan[2].OutFlagD=1;
Gate3[0].Chan[3].OutFlagD=1;

Gate3[0].chan[0].packoutdata=0
Gate3[0].chan[0].packindata=0
Gate3[0].Chan[0].PfmWidth=10

Gate3[0].chan[1].packoutdata=0
Gate3[0].chan[1].packindata=0
Gate3[0].Chan[1].PfmWidth=10

Gate3[0].chan[2].packoutdata=0
Gate3[0].chan[2].packindata=0
Gate3[0].Chan[2].PfmWidth=10

Gate3[0].chan[3].packoutdata=0
Gate3[0].chan[3].packindata=0
Gate3[0].Chan[3].PfmWidth=10

Sys.WpKey=$0 // Write-protect Gate3 registers

Link to comment
Share on other sites

  • 3 months later...
  • Replies 4
  • Created
  • Last Reply

Top Posters In This Topic

I see to be missing something. I did all of the above and try to drive the virtual joint in open-loop or closed-loop and it doesn't move (like the brakes are on). The Dac shows it's being driven and, in closed-loop, the following error goes up but the actual position and velocity does not change. I figure it must be some simple setting somewhere that I missed but cannot figure it out.
Link to comment
Share on other sites

Hi there,

 

The example was wrong actually, sorry about that. I updated it in the above post. Please copy the data again from the above post and try again, and please let me know if it works.

 

For your information, I changed these parameters only:

 

// Set up channel output for PFM signal
// Not needed for simulation; only to monitor output signal
Gate3[0].Chan[0].OutputMode=8        // PFM on Phase D
Gate3[0].Chan[1].OutputMode=8        // PFM on Phase D
Gate3[0].Chan[2].OutputMode=8        // PFM on Phase D
Gate3[0].Chan[3].OutputMode=8        // PFM on Phase D

 

Link to comment
Share on other sites

Here's another example with slightly different servo loop gains that might work better for some steppers:

 

/* Gate3 Version */
Sys.WpKey = $AAAAAAAA // Permit write access to Gate3 structures

/* Activate motors 1-4 */
Motor[1].ServoCtrl=1
Motor[2].ServoCtrl=1
Motor[3].ServoCtrl=1
Motor[4].ServoCtrl=1

// Write servo output to channel’s PFM register
Motor[1].pDac=Gate3[0].Chan[0].Pfm.a    // 1st channel PFM
Motor[2].pDac=Gate3[0].Chan[1].Pfm.a    // 2nd channel PFM
Motor[3].pDac=Gate3[0].Chan[2].Pfm.a    // 3rd channel PFM
Motor[4].pDac=Gate3[0].Chan[3].Pfm.a    // 4th channel PFM

// Set PFM Clock Divisor
Gate3[0].PfmClockDiv=5
Gate3[0].PfmClockDiv=5

// Set up channel output for PFM signal
// Not needed for simulation; only to monitor output signal
Gate3[0].Chan[0].OutputMode=8        // PFM on Phase D
Gate3[0].Chan[1].OutputMode=8        // PFM on Phase D
Gate3[0].Chan[2].OutputMode=8        // PFM on Phase D
Gate3[0].Chan[3].OutputMode=8        // PFM on Phase D

// Wrap PFM output back into channel’s encoder counter
Gate3[0].Chan[0].EncCtrl=8 // Internal pulse and direction clockwise
Gate3[0].Chan[1].EncCtrl=8 // Internal pulse and direction clockwise
Gate3[0].Chan[2].EncCtrl=8 // Internal pulse and direction clockwise
Gate3[0].Chan[3].EncCtrl=8 // Internal pulse and direction clockwise

// Disable overtravel limit inputs
// May be needed if there are no physical switches present
Motor[1].pLimits=0
Motor[2].pLimits=0
Motor[3].pLimits=0
Motor[4].pLimits=0

// Disable amplifier enable output
// May be needed if channel is also connected to real amplifier
Motor[1].pAmpEnable=0
Motor[2].pAmpEnable=0
Motor[3].pAmpEnable=0
Motor[4].pAmpEnable=0

// Disable amplifier fault input
// May be needed if channel is also connected to real amplifier
Motor[1].pAmpFault=0
Motor[2].pAmpFault=0
Motor[3].pAmpFault=0
Motor[4].pAmpFault=0

// Set derivative gain term in servo loop to zero
// This is a Type 1 servo (single integration); does not need Kd
Motor[1].Servo.Kvfb=0
Motor[2].Servo.Kvfb=0
Motor[3].Servo.Kvfb=0
Motor[4].Servo.Kvfb=0

// Lower proportional gain term from default
Motor[1].Servo.Kp=1
Motor[2].Servo.Kp=1
Motor[3].Servo.Kp=1
Motor[4].Servo.Kp=1

// Add Kvff and Ki
Motor[1].Servo.Kvff=1.5;
Motor[2].Servo.Kvff=1.5;
Motor[3].Servo.Kvff=1.5;
Motor[4].Servo.Kvff=1.5;

Motor[1].Servo.Ki=0.001;
Motor[2].Servo.Ki=0.001;
Motor[3].Servo.Ki=0.001;
Motor[4].Servo.Ki=0.001;

Motor[1].Servo.Kbreak=0;        // zero gain in deadband area
Motor[1].Servo.BreakPosErr=1;   // deadband of 1 count should keep stepper driver from coming out of standby power mode

Motor[2].Servo.Kbreak=0;        // zero gain in deadband area
Motor[2].Servo.BreakPosErr=1;   // deadband of 1 count should keep stepper driver from coming out of standby power mode

Motor[3].Servo.Kbreak=0;        // zero gain in deadband area
Motor[3].Servo.BreakPosErr=1;   // deadband of 1 count should keep stepper driver from coming out of standby power mode

Motor[4].Servo.Kbreak=0;        // zero gain in deadband area
Motor[4].Servo.BreakPosErr=1;   // deadband of 1 count should keep stepper driver from coming out of standby power mode

// Deactivate commutation for all motors
Motor[0].PhaseCtrl=0            // No phase commutation active
Motor[2].PhaseCtrl=0            // No phase commutation active
Motor[3].PhaseCtrl=0            // No phase commutation active
Motor[4].PhaseCtrl=0            // No phase commutation active

// Create encoder conversion table entries for all motors
EncTable[1].type=1;
EncTable[1].pEnc=Gate3[0].Chan[0].ServoCapt.a;
EncTable[1].pEnc1=Sys.pushm;
EncTable[1].index1=0;
EncTable[1].index2=0;
EncTable[1].index3=0;
EncTable[1].index4=0;
EncTable[1].ScaleFactor=1.0/256.0;
EncTable[1].MaxDelta=0;
EncTable[1].SinBias=0;
EncTable[1].CosBias=0;

EncTable[2].type=1;
EncTable[2].pEnc=Gate3[0].Chan[1].ServoCapt.a;
EncTable[2].pEnc1=Sys.pushm;
EncTable[2].index1=0;
EncTable[2].index2=0;
EncTable[2].index3=0;
EncTable[2].index4=0;
EncTable[2].ScaleFactor=1.0/256.0;
EncTable[2].MaxDelta=0;
EncTable[2].SinBias=0;
EncTable[2].CosBias=0;

EncTable[3].type=1;
EncTable[3].pEnc=Gate3[0].Chan[2].ServoCapt.a;
EncTable[3].pEnc1=Sys.pushm;
EncTable[3].index1=0;
EncTable[3].index2=0;
EncTable[3].index3=0;
EncTable[3].index4=0;
EncTable[3].ScaleFactor=1.0/256.0;
EncTable[3].MaxDelta=0;
EncTable[3].SinBias=0;
EncTable[3].CosBias=0;

EncTable[4].type=1;
EncTable[4].pEnc=Gate3[0].Chan[3].ServoCapt.a;
EncTable[4].pEnc1=Sys.pushm;
EncTable[4].index1=0;
EncTable[4].index2=0;
EncTable[4].index3=0;
EncTable[4].index4=0;
EncTable[4].ScaleFactor=1.0/256.0;
EncTable[4].MaxDelta=0;
EncTable[4].SinBias=0;
EncTable[4].CosBias=0;

// Point motors to encoder conversion table entries
Motor[1].pEnc=EncTable[1].a
Motor[2].pEnc=EncTable[2].a
Motor[3].pEnc=EncTable[3].a
Motor[4].pEnc=EncTable[4].a

Motor[1].pEnc2=EncTable[1].a
Motor[2].pEnc2=EncTable[2].a
Motor[3].pEnc2=EncTable[3].a
Motor[4].pEnc2=EncTable[4].a

/* Set up various PFM-Related Gate3 settings */
Gate3[0].Chan[0].OutFlagD=1;
Gate3[0].Chan[1].OutFlagD=1;
Gate3[0].Chan[2].OutFlagD=1;
Gate3[0].Chan[3].OutFlagD=1;

Gate3[0].chan[0].packoutdata=0
Gate3[0].chan[0].packindata=0
Gate3[0].Chan[0].PfmWidth=10

Gate3[0].chan[1].packoutdata=0
Gate3[0].chan[1].packindata=0
Gate3[0].Chan[1].PfmWidth=10

Gate3[0].chan[2].packoutdata=0
Gate3[0].chan[2].packindata=0
Gate3[0].Chan[2].PfmWidth=10

Gate3[0].chan[3].packoutdata=0
Gate3[0].chan[3].packindata=0
Gate3[0].Chan[3].PfmWidth=10

Sys.WpKey=$0 // Write-protect Gate3 registers

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.

×
×
  • Create New...