Omron Forums Support Posted December 2, 2011 Share Posted December 2, 2011 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 More sharing options...
pennells Posted March 9, 2012 Share Posted March 9, 2012 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 More sharing options...
Omron Forums Support Posted March 9, 2012 Author Share Posted March 9, 2012 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 More sharing options...
pennells Posted March 9, 2012 Share Posted March 9, 2012 Thanks. That works great. I didn't question it because it was similar to the 24E2A. Link to comment Share on other sites More sharing options...
Omron Forums Support Posted March 15, 2012 Author Share Posted March 15, 2012 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 More sharing options...
Recommended Posts