Jump to content
OMRON Forums

custom servo loop and FE


Recommended Posts

I have a custom servo ctrl, where I set the despos of each motor, and then user the stock servoCtrl function.


I'm noting that Mpts->PosError != (Mptr->DesPos - Mptr->ActPos), contrary to the manual, unless I do the computation myself inuser_pid_ctrl.


Is this normal, or is the manual wrong when using a custom ctrl?


Also, while i'm here:


- I regularly have to reselect the "user servo setup" routine in "realtime routines". It will show the correct function already selected in the drop down menu, but I have to reselect it for each motor. Any known cause/fix for this? I've added code of my own to detect when it occurs, so my program doesn't go off using the wrong servoCtrl function.


-The usralgo.ko is only created in debug more, meaning code changes, even with a complete rebuild, in release mode are wrong (as I have to manually copy the usralgo.ko file to the release folder each time). Any fix for this?


All this with the latest ( IDE.






double user_pid_ctrl(struct MotorData *Mptr){
   Mptr->DesPos = SOMEVALUE;

   //Without this line, poserror is wrong
   Mptr->PosError = Mptr->DesPos - Mptr->ActPos;

   // Use the built in PID loop to run the actual command    
   return pshm->ServoCtrl(Mptr);


Link to comment
Share on other sites

  • 2 weeks later...
  • Replies 7
  • Created
  • Last Reply

Top Posters In This Topic

I can't duplicate this problem. My own user servos run fine assuming an externally computed PosError term.


I checked the internal code. PosError is computed before the specific servo algorithm is called. Our own built-in servo algorithms do not compute PosError inside them -- they also rely on this term being computed before they start.

Link to comment
Share on other sites

Mptr->DesPos (or Motor[xx].DesPos) is not a register that you can write to.


This is how to make it more clear:

double user_pid_ctrl(struct MotorData *Mptr)


if (pshm->P[1] == 1)

{Mptr->DesPos = 53;}

pshm->P[2] = Mptr->DesPos;

pshm->P[3] = Mptr->PosError;

return 0;



Put P1, P2,P3 in watch window and try changing P1 from 0 to 1 and notice how P2 and P3 change.

The value (SOMEVALUE) you write to DesPos will be lost after until the next servo cycle where you write it again to DesPos. PosError is calculated as (Mptr->DesPos - Mptr->ActPos). It is also not writable, as it is calculated by PMAC. If you write to it, your value will be lost.

Link to comment
Share on other sites

It looks like the underlying issue is this: the PosError value computed automatically by Power PMAC before the servo algorithm is entered must use the value of DesPos that existed before the servo algorithm started. If you change the value of DesPos inside your custom servo algorithm, of course the value previous computed for PosError will be wrong, and if you want it to be correct, you will need to recompute it, as you have been doing. You will also need to re-calculate the DesVel term (as the difference between your new DesPos and the previous cycle's DesPos) if you want to use velocity feedforward properly.


In the Script programming environment, we prevent people from writing to registers like these that PMAC computes automatically, because it has the potential to be very dangerous. The C programming language does not provide protections like this, so it is possible to write to DesPos in your own C subroutine. Do take great care in doing so.

Link to comment
Share on other sites

Fair enough. Thanks.


Is there a recommended way to implement this instead? I.e., given that an arm controller is computing a despos for each motor, how should this be passed on to the deltatau? The system seems quite normal otherwise, and with the computation added in, seems to work quite well.




Link to comment
Share on other sites

If you really want to compute an "arbitrary" (from the PMAC's point of view) position every servo cycle, what you are doing now is probably as good as any. The cost of re-computing position error and desired velocity is tiny.


However, most users conclude that it is not necessary to compute an arbitrary point every servo cycle, and instead command points at short intervals in a motion program, letting the PMAC interpolate between these points with one of its move modes. A common example of motion program code to do this in a robotic application is:



while (StreamingPoints) {

// Calculate or read axis points here

X(Xpos) Y(Ypos) Z(Zpos) A(Apos) B(Bpos) Z(Zpos)



"MySplineTime" is the time for each commanded move in milliseconds. It does not need to be an integer multiple of the servo cycle time.


"StreamingPoints" is a Boolean control flag.


The comment shows where you would insert your code for reading and/or computing the axis command positions. Most people just do it in our Script language, but you can also call a C subroutine to do this using our special "CfromScript" subroutine.


In action, PMAC computes the move equations for each axis from the move description. In the Spline mode, positions, velocities, and accelerations are guaranteed continuous, even at the move boundaries. When the Spline moves are quite short (a few milliseonds, but still greater than the servo time), there are few systems with the mechanical bandwidth to do anything physical that does not conform to these constraints.


The motion program must calculate two moves ahead to calculate a trajectory with two derivatives continuous. So there would be a time delay of two move times in this mode. Most, but not all, applications can tolerate this. Motion program execution is automatically sequenced so that it handles the timing of execution to stay two moves ahead.

Link to comment
Share on other sites

  • 2 months later...
To answer your second question, IDE version and newer fix the problem of needing to reselect the user servo setup after restarting the IDE or reopening a project. As this is not an official release you will need to contact someone at DT if you want to have this intermediate version.
Link to comment
Share on other sites

This topic is now closed to further replies.

  • Create New...