Jump to content
OMRON Forums

curtwilson

Members
  • Posts

    723
  • Joined

  • Last visited

  • Days Won

    1

Everything posted by curtwilson

  1. The present algorithm was designed to ensure that memory conflicts could not be created as tables were entered in development. We are looking to see if there is a way around these protections.
  2. As you change table sizes, PMAC has to use new memory in the table buffer to ensure that the table will not overwrite an existing table. The only way to get the previously used memory back is to reset the PMAC, so it loads the tables from the start of the buffer. I have no trouble setting my table buffer size greater than 16 MB. Set the size in the Project Properties window of the IDE (I set it to 64 MB), download the project, save it to flash, restart the PMAC with the reboot command, and reload the project. The Task Manager can confirm the size of the reserved buffer and how much you are using.
  3. I see two ways of handling this. The simple way is just to command an incremental jog move toward the hard stop with a commanded distance long enough to guarantee you will reach the hard stop. At some point during the move, the motor will hit the stop, and for the duration of the commanded move it will "bang its head against the wall", so to speak, each electrical cycle. When this is done, you can command a single commutation cycle out of the stop and use the HOMEZ command to set the motor's zero position. Of course, you must make sure that there will be neither mechanical nor electrical damage during the period that it is pushing into the hard stop. The second way will require some analysis. For a given commanded current level, the current loop will need to command a greater voltage output when moving (to overcome the motor back EMF) than when stalled (no significant back EMF). This difference is the fundamental distinction for stepper motor stall detection. The question is whether you can come up with a simple but reliable method to detect this. I would monitor either the Phase A and B PWM commands (sum of squares), or the direct and quadrature current loop integrator registers in memory (again sum of squares) to see if there is a distinct difference. I would first just use data gathering and plotting to understand what happens to these values when you hit the hard stop. If you can see a clear difference, you can write a PLC program to monitor registers and see when they go below some threshold.
  4. When you size/resize a CompTable using Script commands, Power PMAC automatically handles the memory management issues -- moving entries in the data buffer around, etc. to handle the newly declared size. This "under the hood" action makes it a lot easier to set up tables, as you are much freer to define and change tables than you were older PMACs. However, it does means that the apparently simple operation of setting an Nx value in the Script environment actually triggers a big set of actions to keep the entire table data buffer correct. When you set an Nx value in C, none of this happens. For this reason, you really must use the Script environment to change table structures, sizes, etc., even if you use C routines to fill the table data.
  5. The issue is an offset in the pointers to shared memory (pshm) between kernel-mode routines (like the ones that execute in the servo interrupt to execute the table) and user-mode routines (like the one you tried). If you had run this as a user-written servo, it would have worked. The key is to add OffsetTblSHM to your pointer address. Here is some code (including some extra lines and commented-out debugging print statements): #include // Global Gp Shared memory pointer int main(void) { float *fptr; InitLibrary(); // Required for accessing Power PMAC library pshm->P[200] = 200; CompData *CTptr; CTptr = pshm->CompTable; printf("CTptr: %X\n",CTptr); //fptr = CTptr->Data; //printf("fptr: %X\n",fptr); printf("OffsetTblSHM: %X\n",OffsetTblSHM); printf("Data: %X\n",pshm->CompTable[0].Data); fptr = pshm->CompTable[0].Data + OffsetTblSHM; printf("pshm->CompTable[0].Data + OffsetTblSHM: %X\n",pshm->CompTable[0].Data + OffsetTblSHM); pshm->P[201] = CTptr->Source[0]; pshm->P[202] = CTptr->Nx[0]; pshm->P[203] = *fptr; pshm->P[204] = *fptr+1; pshm->P[205] = *fptr+2; CloseLibrary(); return 0; }
  6. All of the "header" elements for the table can be accessed by the technique you show, because that structure is fixed in size. The actual table data points are managed differently, because they can be of any size, and so are located in a different part of memory. You want to declare a variable like: float *TableDataPtr; then assign: TableDataPtr = pshm->CompTable[12].Data; You now have a pointer to the first data point of the table -- Data[0][0] in Script terms. The data points are accessed as a 1D array even for a 2D table. I haven't worked out which index goes first, but a little experimentation will figure it out. Something like: TableDataPtr[ColumnIndex*NumOfRows + RowIndex] = pointval; or TableDataPtr[RowIndex*NumOfColumns + ColumnIndex] = pointval;
  7. Please see Chapter 5 of the Turbo PMAC User's Manual -- the section "Setting Up Turbo PMAC2 for Pulse-and-Direction Control" for explicit instructions on this. As to the principle, the encoder counter that accumulates the pulses acts as a simulated position feedback value. Using hardware for this means we can count the pulses much faster than software could. The PID loop, comparing this accumulated count as "feedback" position to the commanded position value, will ensure corrections to make sure that exactly the right number of pulses are generated. It's a dynamically simple loop acting on the simulated feedback, with only one stage of integration (the PID output command of a pulse frequency is effectively a velocity command), and no friction, backlash, or other effects that make tuning real feedback loops difficult.
  8. Analytically, it is best to think of this in terms of the detailed block diagram transfer functions, evaluating the gains of each step. For example, if you have a +/-10V analog output to a current mode amplifier that commands +/-30A over the full command range, driving a motor with a torque constant of 0.5 N-m/A, with an effective total inertia of 5 kg-m^2, with 360 motor units defined per revolution, you would have the following gains: Kdac = 10V / 32768 LSBs Kamp = 3A / V Kt = 0.5 N-m / A = 0.5 [kg-m^2/s^2] / A Kmech = 1/J = 0.2 (1 / [kg-m^2]) Kenc = 360 motor units / (2*Pi) The total gain is just the product of all of these individual gain terms.
  9. Most users who want this functionality load a parameterized motion program into memory, then use the PLC program to set variable values to determine destinations, speeds, etc. and even modes of operation (for branching logic) if necessary.
  10. The EncCtrl element in the ASIC only determines the direction sense of the incremental encoder decoding. The ASIC does not have a setup element to change the direction sense of the numerical serial encoder value it receives. However, the Encoder Conversion Table entry has a scale factor that multiplies the number it receives before passing it on to the motor feedback. If you change the sign of EncTable[n].ScaleFactor, you change the direction sense of the position value the motor uses for servo feedback. The direction sense used for servo feedback does not need to be the same as that used for phase commutation, even if both originally came from the same value.
  11. The most common mistake beginners make in PVT mode is to get the velocity units wrong. The value after the colon specifies the ending velocity in [axis units per (Isx90 milliseconds)]. At the default value for Isx90 of 1000, this is axis units per second. The time for the move is always specified in milliseconds.
  12. From the Software Reference Manual for I68: "A coordinate system must be activated in order for it to be addressed and accept commands..." Are you sure I68 is not set to 0? If it is 0, then &1 commands are legal, but &2 commands are not. Try increasing I68.
  13. I think the easiest way to do this is to try to list the first line of the program. For example: list prog 100,1 might return: 0:linear inc but for a non-existent program list prog 173,1 would return: stdin:19:1: error #22: PROGRAM NOT IN BUFFER: list prog 173,1
  14. A few points: 1. If you are not changing your axis definition assignments in the middle of the application, they should simply be part of the saved configuration for the PMAC. 2. Achieving full coordination between programs running in different coordinate systems is difficult. The whole point of the coordinate system concept in PMAC is that you put axes you want to keep coordinated in the same coordinate system. 3. You can use the PVT mode to get the motion of a linear-mode move -- you just have to break up the move into its individual parts (e.g. accel, slew, decel) and command each individually. This may be an easier way to do what you want. 4. If you really need to change your axis definitions from within a motion program, you should use the CMD"" functionality to execute the on-line commands from within the program, with the on-line commands within the quotes. Two recommendations for doing this: First, address your coordinate system in each command. Second, put a short DWELL in between each command to make sure they get executed from the internal buffer. For example: CMD"UNDEFINE ALL" DWELL10 CMD"&1 #1->240X" DWELL10 CMD"&2 #2->500Y" DWELL10 CMD"&2#3->666.667U" DWELL10 CMD"&2#4->138.889A" DWELL10
  15. Kandauru: You are confusing two separate issues. The first is how you generate trajectories for the two motors. We strongly recommend the leader/follower method that you have already implemented. Virtually everyone doing gantry control uses this method. The second issue is how you close the servo loops for the two motors. Most people get good enough performance just closing independent servo loops on each motor (what you have been trying so far). Those who cannot get their required performance with independent loop closure go to the cross-coupled gantry algorithm. The additional cross-coupling terms can improve performance, but not everyone needs this boost.
  16. A couple of points: The follower motor should NOT be assigned to an axis in the coordinate system (e.g. #2->X), as this will result in it being "double commanded". It is best to assign it to the "null" definition in the coordinate system (#2->0) so it shares enabling and disabling (commanded or fault). Most people first try independent servo control of the two axes first, using the default servo algorithm (Motor[x].Ctrl=Sys.ServoCtrl) for both motors. It is worth spending some time trying to optimize these settings. However, if you cannot get good enough performance, the next step is to implement the cross-coupled gantry servo algorithm. This is done by setting: Motor[1].Ctrl=Sys.GantryXctrl Motor[1].ExtraMotors=1 This adds cross-coupling terms Motor[x].Xpg, Xig, and Xvg for both motors based on the difference in following error. The IDE has windows to facilitate the tuning of these terms.
  17. Yes, I do think you should try the AdvGain parameter to compensate for the N/2-cycle delay introduced by the N-way moving average filter.
  18. First, make sure you understand the difference between "feedrate" (usually commanded by F in the motion program) and "feedrate override" (usually commanded with the % command outside the program. The feedrate value is used once per programmed move as that move is calculated as the commanded top speed. When "F{value}" is executed inside a motion program, its action is to set Coord[x].Tm = -{value}. The "-" indicates that this is a speed, not a move time, so that moves are specified by speed (feedrate). So if you want to specify "feedrate" from outside the motion program, you can command Coord[x].Tm = -{value}. This will NOT affect the presently executing moves. It would also be overridden by the next F command in the motion program. If you want to specify "feedrate override", which will begin to take effect immediately, probably the best way is what Richard suggests. If you are thinking in terms of percentages, you could do a command like: Coord[x].DesTimeBase = Sys.ServoPeriod * MyPercent / 100;
  19. If you want to calculate a moving average filter of your phase current feedback readings, the best way is to do it in a user-written phase for Motor 0. Motor[0].PhaseCtrl would be set to 1 to enable this task for the virtual motor. This algorithm would calculate the running average and leave the averaged values in two consecutive registers in the user shared memory buffer, e.g. Sys.Idata[256] and Sys.Idata[257]. Of course the values from which the average is computed could also be stored in this buffer. Then for your real motor, you would set Motor[x].pAdc to the address of the first register (averaged Phase A), e.g. Motor[x].pAdc = Sys.Idata[256].a. You can use the standard algorithm this way. Of course there is an inevitable trade-off between noise reduction and time delay. Some users who want great smoothness of motion are disabling the current loop completely and running the motor in "voltage mode". This mode is enabled by setting bit 3 (value 8) of Motor[x].PhaseMode to 1. (Requires V2.1 or newer firmware). This is described in the User's Manual. You lose a little responsiveness, but you should find smoother operation.
  20. You are using the 1/T interpolation function of the encoder conversion table to increase the resolution of your feedback from the 6 hardware states to 192 estimated states. It's great for smoothness, but it introduces time delays. The ECT executes as a servo task, which always comes after the phase task. And most people run the servo update at a lower frequency than the phase update (default by a factor of 4). With a divide-by-N to the servo update, you are then using feedback position that is 1 to N phase cycles old. This does not matter much at low speed, but at high speed it can be important. I suspect this is what you are seeing. I would try two things: First, set your servo update equal to your phase update (I7002 = 0, I7102 = 0 if you have it). If you don't want to retune your motors for a new servo update rate, set all your Ixx60 parameters equal to what I7m02 used to be. Now the ECT will update at the same frequency as the phase tasks, so you will always be using 1-cycle-old data. To improve further, you can use the Ixx56 "phase advance" parameter that is intended to compensate for time delays from input to output in the phase routine. All systems have time delays; you just have this extra one, so this compensation is more important. Most people set this interactively, but note that typical numbers are much smaller than 1.0.
  21. It's pretty straightforward to determine what relationship exists here, but I have no idea if you will find anything useful, and if you do, it would be different from drive to drive. If you set Motor[x].CurrentNullPeriod to a non-zero value, then when you enable the motor, it will first force a zero-voltage command on all phases for the specified number of phase cycles while it monitors the Phase A and B current readings. At the end of this period, it averages the values for each phase and puts the opposite of these values in the IaBias and IbBias elements. Most people use a period in the hundreds of phase cycles. So you should simply exercise the motor to varying degrees of severity to get a range of IGBT temperatures (which you read as extended data). In each round, you then kill the motor momentarily, re-enable it, and read the values in IaBias and IbBias. After many of these rounds, you can see if there is any meaningful mapping to which you could apply a mathematical fit. If there is, you could use a background PLC program to set the bias terms as a function of IGBT temp using the fit.
  22. Your host computer program that is feeding points to the PMAC needs to check frequently the HostMoveCounter and UMACMoveCounter registers, and when it finds them equal, to send the next set of points. The more frequently it does this, the smaller the move time that can be executed. Many people have gotten times of just a few milliseconds using this technique.
  23. You are doing fundamentally what all our Turbo EDM users do. How to tame the motion resulting from the noisy gap voltage measurement to get smooth but responsive motion is the challenge. Unfortunately, those who have done it successfully consider it their "secret sauce" and don't let us know the details. You will have to experiment with various digital filtering algorithms.
  24. You have made a very basic error in your setup, such that you are both coordinating and master/slaving these motors simultaneously. Therefore, you are double-commanding Motor 4. This is why in your Rapid mode move, you get double the speed you want on Motor 4. It is both commanded directly to Speed X and is slaved to Motor 3 at Speed X. In your Linear mode move, each Isx13 segment (probably about 10 msec), the slaving increment from the previous segment is taken out (normal following mode), so you end up double-commanding only the final segment (your extra 0.35 mm). If you set I406=3 (offset/superimpose-mode following) you would get the double speed like in Rapid moves. You must choose EITHER coordination (#3->X, #4->X, I406=0) or master/slave (#3->X, #4->0, I406=1), not both at the same time. We generally recommend coordination for axis moves, as it gives the second motor a smoother command trajectory. Some users like to turn on master/slave just for motor moves (jogging and homing), but they turn it off when they run motion programs.
  25. I suspect that your Phase B current value is "packed" into the low 16 bits of the same 32-bit word for which your Phase A current occupies the high 16 bits. Set Gate3[0].Chan[0].PackInData to 0 and repeat the test. The Phase B current value should then appear in the high 16 bits of AdcAmp[1]. You have two possible ways of setting up the channel and motor for direct PWM control with a Gate3. One is: Gate3.Chan[j].PackInData = 1 // Two ADC values in one register Gate3.Chan[j].PackOutData = 1 // Two PWM values in one register Motor[x].PhaseCtrl = 1 // Commutation using packed inputs and outputs This method is faster due to reduce input and output accesses, but harder to debug and analyze. The second method uses: Gate3.Chan[j].PackInData = 0 // Two ADC values in separate registers Gate3.Chan[j].PackOutData = 1 // PWM values in separate registers Motor[x].PhaseCtrl = 4 // Commutation using unpacked inputs and outputs This method is a little slower, but easier to work with. We generally recommend the second method unless you are really pushing the Power PMAC for CPU time, which you almost never are for a Power Clipper. Also, on the Power Clipper drive, we use the lower 16 bits of these registers for auxiliary information from the power stage.
×
×
  • Create New...