Jump to content
OMRON Forums

curtwilson

Members
  • Posts

    723
  • Joined

  • Last visited

  • Days Won

    1

Everything posted by curtwilson

  1. To inject a swept sine ahead of the trajectory filter, I would use a motion program. The program would command full-circle moves in a loop, varying the move time each time through the loop. The cross axis for the circle would be a phantom motor.
  2. A few issues with your Question #4: I'm afraid the quick description of the DkillCoord() function is incorrect (the description of the actual Script DKILL command in the Software Reference Manual is correct). The DKILL function enables the brake first, then disables the servo after a delay. It’s meant for a controlled shutdown when you are already stopped, and you want the brake to fully engage before disabling the servo, so there is no motion on disabling. It is generally not appropriate to use when moving. I think a more appropriate function to use is AbortDkillCoord(), which implements the Script ADISABLE command. This implements an ABORT command followed by delayed kill for all motors in the coordinate system. The abort does a controlled closed-loop deceleration, bringing the motors to a stop faster than a kill would (and so in a shorter distance), and once stopped, the brakes can safely be enabled before the servos are disabled. Taking a step back, I don't see why you would need to disable at all. If I read you correctly, you are implementing a sophisticated software overtravel limit function. In our built-in software overtravel limit function, we always simply use the "abort" function for a controlled closed-loop deceleration to stop. We do not subsequently disable the servos, as there is generally no need to do so. Recovery is substantially quicker if you leave the motors in the enabled closed-loop zero-velocity state. This can be implemented with the AbortCoord() function.
  3. That looks like a 6-pole motor to me. A two-pole motor would have a single north pole and a single south pole on the rotor and one winding on the stator for each of the three phases. A four-pole motor would have two north poles and two south poles on the rotor and two windings on the stator for each of the three phases. A six-pole motor would have three north poles and three south poles on the rotor and three windings on the stator for each of the three phases. This stator fits into that last category.
  4. It should be emphasized that the inverse kinematic routine executes on the input to the segment buffer, not on the output. The input is always several segments ahead of the move execution from the output of the buffer, so if the kinematic subroutine is used to set outputs (like a laser on or off), it will not be synchronous with the execution of the motion segment calculated that cycle. If buffered lookahead is active, the difference between input to the buffer and output from the buffer can be very many segments. So even if the kinematics routine were called at even intervals, a commanded output would not be synchronous with the execution of the segment. Any kinematic routine that is trying to set outputs synchronous with the execution of segments must recognize this delay and compensate for it.
  5. David: You've got the sequence of calculations in the CK3E correct. The 32-bit rollover in the output of CSP mode is widely used successfully. I do not know any of the details of how the Copley drive handles these values.
  6. Whatever the details of the mechanism, changing parts of a register from multiple tasks that cannot be guaranteed to be fully separate in time is inherently problematic. The simplest fix is to use entire registers.
  7. Anton: To me, the big mystery of your results is this: The data gathering you use to analyze the problem is done in the same servo interrupt as the UWS that is supposed to set the bit. If the problem is that the background task resumes and clears the bit, this would not have happened yet when the gathering was done. Very strange!
  8. Anton: The problem can occur when a low-priority task has a multi-step operation that (1) reads a register; (2) does logical operations based on what it has read; and (3) writes back to that register based on what it read in (1) and what it decided in (2). The most common, but not the only, logical operation here is the modification of a subset of the register. The simple act of writing to a partial-word M-variable does this implicitly and automatically. It can also be done with explicit code. (Writing to a whole-word M-variable does not invoke this multi-step process.) The problem occurs when the low-priority task is interrupted between (1) and (3) by a high-priority task that writes to the same register. That task does write to the register successfully, but as soon as the low-priority task resumes, its step (3) will undo what the high-priority task has just done. Note that just having the low-priority task read the register at this time does not create the problem -- it is the write operation that creates the problem.
  9. Any time you do read/modify/write operations (whether explicit or implicit) on the same register from different priority levels, you can have the problem you are seeing. Let's say your background PLC has started to change the M-variable by reading the register, but is interrupted by the servo before it can write the modified value back to the register. The servo does its complete read/modify/write operation, then allows the background task to continue. The background task then finishes the modify-and-write operations (using what it read before the servo interrupt), and its write operation overwrites what the servo task just wrote, wiping out its change. (It is counter-intuitive for most people that the higher-priority task fails in this type of conflict.) Note that this does not happen with whole-word access that does not require this multi-step process. If memory is plentiful, the easiest thing is to devote an entire register to a variable, even if it is only using part of the register.
  10. To do this outside the motion program execution, you will want to have a PLC program scanning continually and issuing the "pread" command, which will return the axis positions in D-variables for the program (e.g. D0 for the A-axis position). Then you will explicitly compare the returned position values for each axis to your axis limits and abort motion if exceeded.
  11. You have a couple of possibilities. One is to do the calculations yourself in the kinematic subroutine -- e.g.: if (KinPosAxisA > MyMaxA || KinPosAxisA < MyMinA) … The other method is to assign an additional virtual motor that maps directly to the axis -- e.g.: KinPosMotor11 = KinPosAxisA Set your motor software limits for this virtual motor to the axis software limits you desire. You will need to define this as an inverse kinematic motor in the same coordinate system -- e.g.: &1 #11->I You will also need to disable other faults on this virtual motor: hardware limits, amplifier fault, following error.
  12. I am not able to duplicate your problem here. I get well-behaved "extensions" of programmed accel/decel times over a wide variety of settings. Here is one example with Ta & Td = 5 msec, and SegMoveTime = 0.5 msec as I suggested. My InvAmax stretched the accel and decel times out to 100 msec, keeping both at the rate set by InvAmax. This algorithm has been in successful use for over 20 years now. We will have to go into more detail to figure out why it is not working for you.
  13. In coordinated multi-axis motion, all axes must share the same acceleration times, so we can't have rate specification here like we do for single-axis moves. (We can have accel rate limiting, which stretches out the time for all axes in the CS if any motor violates its limit.) When we execute the segments (updating at servo rates), the splining algorithm we use guarantees continuity of acceleration at all segment boundaries, including at the very beginning and very end of a sequence. To do this, we add one segment at the beginning that starts at zero accel with jerk to bring up to accel, and similarly add one at the end to finish at zero accel. The net result is a segment at the beginning and one at the end that have an "S-curve" velocity profile. Jerk cannot be directly limited by lookahead, as the computations are far too complex and time-consuming to be done in real-time. Some users get the general effect by using the trajectory pre-filter after lookahead to "soften" the profiles. A second-order low-pass filter with a damping ratio of ~0.85 has been reported to work well for this purpose. The IDE tuning window control for the pre-filter makes it easy to add. You will have to experiment with the specification of the cutoff frequency to see what works for you in this application.
  14. First, some background. Initially, PMAC splits the programmed trajectory into uniform "segments", each of time Coord[x].SegMoveTime. Each segment has its own set of cubic coefficients that will be used at execution time to solve for instantaneous commanded position each servo cycle. The values of Motor[x].Desired.Pos, Vel, and Accel are the first three coefficients for the executing segment. They only represent the instantaneous values for the very beginning (t = 0) of the segment. Jerk is constant through the segment. In between these two steps, you can enable the lookahead algorithm, as you have. The algorithm evaluates the segments for possibility of exceeding motor limits -- in your example, the only relevant limit is acceleration as specified by the InvAmax parameter -- and extends segment times as needed to try to bring the trajectory within limits. The algorithm is very powerful, but it is not infinitely flexible. It works best if it has multiple segments over which to resolve features. So you want to set the SegMoveTime parameter as small as you can without overwhelming the computational capabilites, and do not set your Ta and Td times smaller than you really need. Remember that the Ta time is your minimum move time, and that lookahead never shortens the programmed Ta time, even if it would lead to an accel rate below the limit. In your case, try SegMoveTime = 0.5 and Ta = Td = 5, and see what happens. Remember to set Td after Ta if you want different values. Then you can optimize given your particular constraints. For plotting commanded trajectories, most users just gather Motor[x].DesPos, then let the IDE do single and double differencing for velocity and acceleration (and evaluating jerk as the slope of the acceleration plot).
  15. It looks like your fundamental problem is that you are trying to close your loop using a load encoder alone, which puts the compliance of the coupling between motor and load "inside the loop", leading to significant oscillations. It is quite common for people in this case to operate the motor open loop and use the load encoder just for end-of-move confirmation, as you propose. The open-loop control technique with the LV is called "direct microstepping" and it is explained in the manual. The end-of-move checking is done at the application level in user code, but it is not difficult. You command your move just as you would for true closed-loop control, add a short dwell to permit settling, then read the encoder value to compare it to what you ideally want, and issue a corrective move.
  16. Omron's 1S EtherCAT drives can operate at an 8 kHz update rate. If you want to command a large number of drives at this frequency, you may want to reduce the number of active PDOs per drive from the default to keep the transmission traffic reasonable.
  17. Unfortunately, with the Etherlab stack, there is no prospect for any improvements or extensions going forward, in setup or operation, so we are just maintaining it for existing applications. The new Quad Core ARM CPU has dramatically better performance for the Acontis stack, especially if you isolate it on its own core. We recently benchmarked reliable performance of 32 EtherCAT axes at an 8 kHz update rate.
  18. Implement the double-pass logic in Script, then call the CfromScript subroutine to do the math-intensive calculations in C. It will be called twice when double-pass is needed.
  19. We have not found a general robust solution. The vast majority of users do not change their table structures much at all. If you don't want to save your tables, try setting all of the Nx elements to 0 before you save, and then write toData[0]. I think it will go much quicker if you do this.
  20. You can command a dwell period that will inhibit subsequent moves for the duration of the dwell. For example: &1 cpx dwell5000 jog1:100000
  21. Generally, the different varieties of Yaskawa serial encoders can all be read with the same interface protocol. The data in the position registers may be in different places in the register(s). Remember that the reference to "20-bit" encoders is the resolution of a single turn of the encoder. These encoders generally have muliturn data as well.
  22. I think that position compensation tables will be the most computationally efficient method for most of these corrections. Since you are pushed for time, I would use first-order interpolation rather than third-order. (It only averages 8 points instead of 64.) Since you are correcting for measurement errors, I would put the correction in the measured feedback path. That way your corrections do not affect the feedforward. For the squareness errors, I would use the axis definition statements for efficiency. For tips on running a fast application, find the app note "Optimizing High Block Rate Applications..." in the File Depot here. (You say it is a CK3E CPU. Are you sure you don't mean CK3M?)
  23. If I understand you now, you want to write an algorithm in the engineering units of the plant, so your core algorithm will produce a result in volts that would be supplied to the DAC. In this case, you are correct that you need to multiply this value by 32,768/10 to get the numerical result that PMAC needs. Of course, the hardware DAC circuit acts as a gain block that effectively multiplies this by 10V/32,768LSBs.
  24. If you want to run this as part of your overall system simulation, then to convert PMAC's +/-32,768 numerical command range to voltage, you will want to add a gain block that multiplies this value by (10V / 32,768 LSBs). Note that this is the inverse of what you suggested. However, if you want to run your algorithm on the PMAC, you do NOT want to use this gain block. The result of your algorithm must be a numerical value in the +/-32,768 range. This is what the software will write when it is done. The gain block you propose is to simulate the function of the hardware DAC. It is part of your model of the plant, not of the software algorithm.
  25. It is possible to reset the encoder counter in a PMAC3 IC to zero by setting Gate3.Chan[j].CountReset to 1. (The AmpEna output for the channel must be zero.) However, we DO NOT recommend it because of the potential danger, and it is not needed for the origin search. When PMAC finds the trigger in the homing search move, it stores the captured encoder value in the Motor[x].HomeOffset register. This is the difference between motor zero and encoder zero positions, and you just need to use it in following calculations. When you have registers that can roll over, they can be displayed as unsigned or signed values. It does not matter, as long as you understand how they work. The 32-bit registers in the Gate3 are displayed as unsigned values, so show a range of 0 to +2^32-1. The low 12 bits are fraction, so the units are 1/4096 of a count, so the counts show a range of 0 to +2^20 (1 Meg). But, if you write a negative value to the element, it will still work. So if you have the program or command line: Gate3[0].Chan[0].CompA = -1000 * 4096 and then you query the value of CompA, you will see the value reported as: Gate3[0].Chan[0].CompA=4290871296 This value is equal to 2^32 - (1000*4096). But it will create a compare event at -1000 counts, which is what you want Remember that in general, the encoder registers can rollover multiple times over the motor position range in many applications.
×
×
  • Create New...