Jump to content
OMRON Forums

curtwilson

Members
  • Posts

    723
  • Joined

  • Last visited

  • Days Won

    1

Everything posted by curtwilson

  1. If you put code like the following in a background PLC program that is continually scanning: dtogread; MyXDistToGo = D6; MyYDistToGo = D7; MyZDistToGo = D8; then you have the information you want readily available to your MMI by simply querying the values of your user variables, in the same way as you acquire other values.
  2. When running a motion program with the target-position buffer enabled, Coord[x].TPExec.Pos holds the axis target (move-end) position for the presently executing move. Coord[x].CdPos holds the axis target position for the most recently calculated move, which can be, and often is, one or more moves ahead of the presently executing move. The whole point of the target-position buffer is to store these position values from calculation time to execution time. When you request the present target position values with the on-line "t" or program "tread" command, Power PMAC just reports back the values of TPExec.Pos. When you request the present distance-to-go values with the on-line "g" or program "dtogread" command Power PMAC subtracts the present instantaneous (motor) command positions, converted to axis values, from the values of TPExec.Pos. Note that we do not automatically compute the instantaneous positions in axis coordinates on an ongoing basis, as this would be a huge computational overhead, so this is done only "on demand". I suggest you use the buffered program "dtogread" command if you do not want to do on-line queries. It automatically does all of these calculations for you (including cutter comp offsets) and places the results in local variables Di for your use. When you command a rapid move directly from a PLC program, none of this motion program logic is used. It is easy, however, to use the PLC program to command a rapid move with motion program logic. For example, you could replace your PLC program line: X(MyXdest) Y(MyYDest) with: cmd"&1 cpx rapid X(MyXdest) Y(MyYdest)" or with: start500 where you have: open prog 500 rapid X(MyXdest) Y(MyYdest) close
  3. I have not been able to get this to fail. Obviously, your system is behaving as if a buffer had not been defined. Of, course, make sure your setup variables have the values you want. With Coord[1].TPSize set to 0, issue the "free" command. One of the response lines tells you how much memory is available for the "lookahead buffers". This buffer space is used for the dynamic lookahead buffers, the cutter comp buffers, and the target position buffers. A target position buffer requires 288 bytes per move, so you will need at least 294,912 bytes free to be able to define a 1024-move buffer.
  4. It appears you have some non-zero backlash set, or possibly something funky in the servo deadband settings. Probably the best thing to do to smooth the following but still be able to discard the "excess" from overspeed is to implement low-pass filter in the encoder conversion table entry for the master encoder. If you set EncTable[n].index2 for the entry greater than 31, it will add a 1st-order on the input data. The time constant of this filter is [256 / (256 - index2)] - 1 servo cycles. If you set index2 to the maximum value of 255, you will have a time constant of 257 servo cycles. This may provide enough smoothing. MasterMaxAccel would be set to 0 to enable the following mode that discards excess on following overspeed.
  5. The Clipper (and all Turbo PMACs) does provide tools for dealing with this issue, but there is a fundamental physical trade-off that will always be there. When your path changes direction, there is a centripetal acceleration perpendicular to the path of magnitude V^2/R, where V is the vector speed, and R is the instantaneous radius of curvature. With a large acceleration/blending time from TA & TS parameters, your cornering radius stays large, and keeps the acceleration small, so you can do it smoothly. As you reduce your TA/TS time, your cornering radius gets smaller, and your cornering acceleration gets larger, and you have noticed that this rocks your machine. Of course, a perfectly sharp corner (R=0) would require infinite acceleration at any non-zero speed, so you must stop to get this sharp corner. The "lookahead" feature of Turbo PMAC helps you manage the trade-off. As most people use it, the TA and TS times are set small enough to get the desired corner size without excessive rounding. Turbo PMAC initially calculates this path at the programmed speed (usually from the F value), and it often results at this point in excessive acceleration at the corners. This initially computed trajectory is then passed through the lookahead algorithm, which checks the trajectory segment by segment against motor acceleration limits in Ixx17. When a violation is found, motion is slowed enough to keep the acceleration within limits, but the path is not changed. The result is that speed will decrease into relatively sharp corners, the corner is taken just slow enough to keep acceleration within bounds, and then speed increases back up to the programmed speed as the corner is exited (the process ends up being just like how you take a corner in your car). Most users are able to find settings that manage the trade-off well enough, but as I emphasize, the trade-off will always be there. If you want pretty sharp corners with accelerations small enough not to vibrate your machine, the corners will need to be taken more slowly than the straight sections of the path. If this is so slow that your laser over-burns the part at corners, you may need to modulate your laser power based on instantaneous vector speed (many people do this with a 1 or 2-line PLC program).
  6. The "HOMEZ" command can be issued as an on-line command from the host computer as well as a buffered command from within a PMAC program.
  7. The value in the internal motor position register addressed by Mxx61 has a maximum possible value of (2^48)/2. At this point, it rolls over to a negative number. When just commanding motor moves, like jogs, this does not matter at all - it will just report a negative position value. However, when the motor position is computed from a programmed axis position, the floating-point axis position will not roll over, and when the axis position corresponds to a motor position greater than this value, it will not compute a proper motor position. Usually you will get a following error at this point. While the position range cannot be made infinite, there are things you can do to extend the effective range. If you can reduce the Ixx08 motor scale factor and keep good servo performance, you can increase the range proportionally (remember to increase Ixx30 proportionally to keep the same effective servo gain). A couple of users have forced the starting position to the maximum negative value to double the range. If you ever come to a commanded stop, even for a moment, you can execute a "homez" command to reset the motor position to zero.
  8. The relevant paragraph in the HW Reference manual is: If the output of the XOR gate on either the A or B channel of the encoder is false, the encoder is considered “lost”. The status bit Gate3.Chan[j].LossStatus in the channel’s status register Gate3.Chan[j].Status is set to 1. This is a “transparent” status bit that will return to 0 if the signal is regained. The “latched” status bit Gate3.Chan[j].LossCapt in the same register is set to 1 if a loss is detected, and held at 1 until specifically reset (writing a 0 to the bit will reset it).
  9. The "transparent" encoder loss bit Gate3.Chan[j].LossStatus is automatically cleared as soon as the encoder signal is restored. The "latched" encoder loss bit Gate3.Chan[j].LossCapt can be cleared by writing a 0 to the bit (as documented in the description of the bit in the Software Reference Manual chapter on status elements). Of course, if there is not a valid encoder signal, it will immediately be set to 1 again.
  10. The most important thing to do is to ask yourself if you really want to be controlling the motor this way. Virtually everyone who tries this method runs into this type of problem due to mismatch between the command interval and the feedback interval. Your best tool for improving the settling will be to create some deadband in the control loop with Ix64 and Ix65 so that fractional count errors do not keep the servo loop active. Most people get better performance from commanding the stepper drive open loop (in PMAC, feed the pulse train back to the counter with I9n0=8) and just using the encoder for confirmation, not as part of the feedback loop. This requires an extra encoder channel on the PMAC; do you have one available?
  11. With firmware version 1.16A, it is not a Turbo PMAC (whose firmware versions are 1.9xx). Issue the on-line TYPE command to the PMAC, and it will tell you a lot of information about itself.
  12. Jeff: The ACC-24E3 manual that is now available on the forum has over 30 pages on the serial encoders it supports. The information is also available in the User's Manual chapter on Setting Up Feedback. Biss-C is not one of the protocols supported by the ACC-24E3. Unfortunately, the protocol was not finalized when we had to cut silicon on the "DSPGATE3" ASIC used in the ACC-24E3. However, it is supported in the FPGA-based ACC-84E, which can be used in both Turbo PMAC and Power PMAC systems.
  13. The fundamental problem you have is that when you are programming the axis moves here, the PMAC has no way of knowing what the tool-tip speed (aka part surface feed) is. It has no knowledge of the interrelated geometry of the axes. A controller that permits you to program directly in the tool-tip coordinates to get the positions and speeds of the tip must have knowledge of the machine geometry and the capability to convert these tool-tip coordinates to the underlying axis coordinates. This conversion is known as the inverse kinematic transformation (a term more commonly used in robotics). Unfortunately, the older non-Turbo PMAC you are using does not have the capability to perform this conversion. The newer Turbo PMAC and Power PMAC controllers do have this capability, and many people do use it for tool-tip NC programming. If you have a controller that cannot do the conversion (which is quite common), your CAD/CAM system must do it, for speeds as well as positions. Since the tool tip speed can vary continuously as the rotary axes move even for constant Cartesian axis speed, you must split the moves into very small pieces with potentially a different speed for each little move block. It is very common to use "inverse time mode" in this situation, with a new F value on each line representing the reciprocal of the move time. (PMAC typically reads this in a subroutine and sets a move time equal to 60000/(Fvalue).
  14. I have no trouble using the "pread" command in a PLC program to get the axis ("tool-tip") positions from the selected coordinate system. You should be reading D32, not writing to it. It tells you which axes have been reported. If you know already, you don't need to bother reading it, but it is a good diagnostic tool -- what value does it return for you? My PLC program text: open plc 17 Ldata.coord = 1; dread; P6 = D6; P7 = D7; P8 = D8; disable plc 17; close
  15. It should be pointed out that the underlying problem could reside in Coordinate System 1. Power PMAC checks whether it is time to calculate moves in coordinate systems from lower numbered to higher numbered. If both CS1 and CS2 need moves calculated at the same time, it will do the moves for CS1 first. By the time it gets to CS2, even if only a few calculations are needed, it could be too late. You may want to try increasing the value of Sys.PreCalc so that calcuations are started earlier in the executing move, increasing the probability that they will finish in time.
  16. The information you find through Script in Gate1.PartData[k] does not have a comparable structure in C. These elements are hardware registers in the ID chips associated with the DSPGATE1 IC; they are not part of the gate array IC itself. On power-on/reset, Power PMAC automatically reads these hardware registers and puts processed information from them into software elements. In Script, these are accessed as: Gate1.PartNum Gate1.PartOpt Gate1.PartRev Gate1.PartType In C, these are accessed through separate software data structures: pshm->Gate1PartData.Num pshm->Gate1PartData.Opt pshm->Gate1PartData.Rev pshm->Gate1PartData.Type If you want to read the actual hardware registers in your application, as to check the encoder-loss status bits, you will need to use the pointer technique you have already figured out.
  17. I think the best place to do this is in a custom servo algorithm for a virtual Motor 0. This algorithm's result will be written into Motor[x].CompDac for the target Motor x. When Motor x runs its own servo algorithm, this offset in the CompDac register (which usually would come from a torque compensation table) will automatically be added to the motor's own servo command. The units of this "double" floating-point register are those of a 16-bit DAC (+/-32,768). The Motor 0 servo algorithm will run after all motors have updated their commanded positions, but before any real motors have closed their servo loops, so no delay is created.
  18. To find the move mode, first look at Coord[x].MoveMode. A value of 3 indicates RAPID mode, a value of 0 indicates one of the "blended" modes: LINEAR, CIRCLE1, CIRCLE2. Coord[x].Omega0[0] equals 0.0 for LINEAR mode moves (including CIRCLE mode moves with no IJK vector or R, which execute as LINEAR). Bit 4 of Coord[n].Cdata is 0 for CIRCLE1 and 1 for CIRCLE2. All of these are for the most recently calculated move, which could be one or more moves ahead of the executing move. For those users running RS-274 "G-code" programs, most who want this type of status information will embed it in their G-code subroutines. This provides the maximum flexibility to tailor the status information to the particular application needs. You can, for example, use a "synchronous assignment" so the status value will reflect the presently executing move. For example: N0: rapid; // G00 MyCalcMoveMode = 0; // Set at move calculation time MyExecMoveMode == 0; // Set at move execution time return; N1000: linear; // G01 MyCalcMoveMode = 1; // Set at move calculation time MyExecMoveMode == 1; // Set at move execution time return; N2000: circle1; // G02 MyCalcMoveMode = 2; // Set at move calculation time MyExecMoveMode == 2; // Set at move execution time return; N3000: circle2; // G03 MyCalcMoveMode = 3; // Set at move calculation time MyExecMoveMode == 3; // Set at move execution time return; ... This is useful for other reasons, as for the increasing number of users who implement G00 as a "fast linear" mode to get features such as a straight-line path with kinematics in a non-Cartesian system. To find out your present normal vector, you can look at Coord[x].Normal. Normal[0] is the I-component, Normal[1] is the J, and Normal[2] is the K. As with move mode, many G-code users will set their own status variable in the G17, G18, and G19 subroutines. To find your present cutter comp mode, you can look at Coord[x].CCMode. It is 0 for CC0, 1 for CC1, and 2 for CC2. Once again, a user status variable can be set in the G40, G41, and G42 subroutines.
  19. Power PMAC does not automatically compute the axis ("tool-tip") positions on an ongoing basis. It converts the commanded axis positions for a move end point (for a non-segmented move) or move segment point (for a segmented move) to motor positions through the transformation matrix (if any) and then through either the axis definitions or the inverse kinematic subroutine. From that point on, all automatic calculations of command and actual position are done in motor coordinates. If you want tool-tip data for various reporting purposes, we provide the axis data querying functions, of which your "&1p" is one form. The on-line commands for these functions provide the data for all used axes in text form. It seems that you would rather not parse this text response to isolate your X, Y, and Z axis values. It looks like using the buffered program equivalent "pread" command from a PLC program would be a better option for you. This puts the axis positions calculated from the present (actual) motor positions into local "D" variables for the coordinate systems: the X position is in D6, Y in D7, and Z in D8. It does this by processing the motor positions either through the automatically inverted axis definition statements or through the forward kinematic subroutine. If there is an axis transformation matrix, these "base" axis positions are then processed through the automatically inverted axis transformation matrix to get the "transformed" (programmed) axis positions. Your PLC program can then process these values further and/or send them somewhere for logging etc. If you want the "base" (which is what I think you call "raw") axis positions, you can multiply these values by the transformation matrix values. For example: MyBaseX = Tdata[1].Diag[6] * D6 + Tdata[1].XYZ[0] * D7 + Tdata[1].XYZ[1] * D8 + Tdata[1].Bias[6] MyBaseY = Tdata[1].XYZ[2] * D6 + Tdata[1].Diag[7] * D7 + Tdata[1].XYX[3] * D8 + Tdata[1].Bias[7] MyBaseZ = Tdata[1].XYZ[4] * D6 + Tdata[1].XYZ[5] * D7 + Tdata[1].Diag[8] * D8 + Tdata[1].Bias[8]
  20. It's an intended part of the feature. The in-position featrue is intended as an asynchronous function, enabling the user to take some action as soon as the motor (or all motors in a coordinate system) has pulled within a desired tolerance at the end of a move, without knowing ahead of time how long this is going to take. This is logically at odds with a timed delay. The typical use of the in-position function in a motion program is: X10; // Move command dwell 0; // Stop lookahead pre-calculation while (Coord[1].InPos == 0) {} // Wait for in-position LaserOn = 1; // Action when achieve in-position Even if we permitted InPos to go true during a delay, allowing the changing the 3rd line of this example to: while (Coord[1].InPos == 0) delay 10; it would not provide any better functionality than what we have -- and would slow down the response due to the delay time.
  21. Yes, the execution of a "delay" command in a motion program causes the move timer to be active, which means that the InPos status bit cannot be true. An easy way to verify this for yourself: bring up the motor or coordinate system status window in the IDE, then type into the terminal window something like: &1 cpx delay 10000 You should see the in-position bit go false for 10 seconds.
  22. This is explained in detail in the User's Manual chapter on writing C programs, starting on page 483 of the manual. http://forums.deltatau.com/filedepot/download.php?f=Power%20PMAC/Manuals/Power%20PMAC%20User [FILE REMOVED]
  23. Here's a very simple example of C access to registers in the ACC-24E3 ASIC. It should get you going. As stated in the above post, the method is the same for all of the ASICs. void CaptCompISR (void) { volatile GateArray3 *MyFirstGate3IC; // ASIC structure pointer int *CaptCounter; // Logs number of triggers int *CaptPosStore; // Storage pointer MyFirstGate3IC = GetGate3MemPtr(0); // Pointer to IC base CaptCounter = (int *)pushm + 65535; // Sys.Idata[65535] CaptPosStore = (int *)pushm + *CaptCounter + 65536; *CaptPosStore = MyFirstGate3IC->Chan[0].HomeCapt; // Store in array (*CaptCounter)++; // Increment counter MyFirstGate3IC->IntCtrl = 1; // Clear interrupt source }
  24. To see whether PLC n is enabled, look at the state of status bit Plc[n].Active (0 = disabled, 1 = enabled). If it is enabled, status bit Plc[n].Running tells you whether it has been paused or not (0 = paused, 1 = not paused). A paused PLC can resume from the point where it was stopped; a disabled PLC can only restart from the top.
  25. Michael, Thanks for your interest. As I said, we spent a lot of time looking at these issues in setting up our architecture, as you are not the only user (or even more importantly, non-user!) desiring a more "pure" C-based approach. But in the end, we did not see that it would add real utility to people in most cases. However, I think you gloss over the key issue, what you call the "proper controls to avaoid collisions with the motion program executor". This, in my view, is the very difficult part, what I refer to as the "sequencing" issue. We have spent 25 years honing our internal sequencing engine to make it as powerful, flexible, and easy to use as possible. The user would have to take over much of this complexity in a C-based application if he wanted to do sophisticated motion trajectories. There are a couple of points in the process where it would not be too difficult to open it up to the user with an API. One is the end stage. The end result of all of our processing is a series of motion segments of the cubic polynomial form. The user could feed the queue of these segments with the cubic coefficients P0, V0, A0, and J, plus the time T for each segment. Mathematically, this is just one simple step removed from our PVT move description. There is a controller out there for which this is the main interface to the internal motion engine. People find it very difficult to use, as it pushes most of the complexity that we handle automatically into the user application. At the other end, if we limit ourselves to RAPID mode moves, which have virtually none of the difficult sequencing issues, it would not be too difficult to supply an API to permit "direct" commanding of moves from C without assembling a string. You may have noticed that this is the only move mode that we permit to be commanded directly from our Script PLCs -- this is because of the absence of most sequencing issues here. You could even break into an executing move at the instant of the command with a new move (distinct from blending at the end of the move as in other modes). However, the API function call here would be of a similar level of complexity to the sprintf/Command method you already have available. The question now comes whether it is worth implementing, testing, documenting, and supporting two ways of doing the same thing.
×
×
  • Create New...