Documentation ¶
Overview ¶
Package newport provides an HTTP server for ESP and XPS series motion controllers.
This package could use some polish, it feels like there is more code here than needed.
When using LTA actuators that have been treated less than perfectly, you may get lots of "following errors." The below text is lifted from the programmer's manual and may help correct them.
6.2.3 Correcting Following Errors
If the system is stable and the user wants to improve performance, start with the current PID parameters. The goal is to reduce following error during motion and to eliminate it at stop.
Guidelines for further tuning (based on performance starting point and desired outcome) are provided in the following paragraphs.
Following Error Too Large ¶
This is the case of a soft PID loop caused by low values for Kp and Kd. It is especially common after performing the procedures described in paragraph 6.2.2. First increase Kp by a factor of 1.5 to 2. Repeat this operation while monitoring the following error until it starts to exhibit excessive ringing characteristics (more than 3 cycles after stop). To reduce ringing, add some damping by increasing the Kd parameter. Increase it by a factor of 2 while monitoring the following error. As Kd is increased, overshoot and ringing will decrease almost to zero.
NOTE Remember that if acceleration is set too high, overshoot cannot be completely eliminated with Kd.
If Kd is further increased, at some point oscillation will reappear, usually at a higher frequency. Avoid this by keeping Kd at a high enough value, but not so high as to re-introduce oscillation. Increase Kp successively by approximately 20% until signs of excessive ringing appear again. Alternately increase Kd and Kp until Kd cannot eliminate overshoot and ringing at stop. This indicates Kp is larger than its optional value and should be reduced. At this point, the PID loop is very tight. Ultimately, optimal values for Kp and Kd depend on the stiffness of the loop and how much ringing the application can tolerate.
NOTE The tighter the loop, the greater the risk of instability and oscillation when load conditions change.
Errors At Stop (Not In Position)
If you are satisfied with the dynamic response of the PID loop but the stage does not always stop accurately, modify the integral gain factor Ki. As described in the Motion Control Tutorial section, the Ki factor of the PID works to reduce following error to near zero. Unfortunately it can also contribute to oscillation and overshoot. Change this parameter carefully, and if possible, in conjunction with Kd.
Start with the integral limit (IL) set to a high value and Ki value at least two orders of magnitude smaller than Kp. Increase its value by 50% at a time and monitor overshoot and final position at stop.
If intolerable overshoot develops, increase the Kd factor. Continue increasing Ki, IL and Kd alternatively until an acceptable loop response is obtained. If oscillation develops, immediately reduce Ki and IL. Remember that any finite value for Ki will eventually reduce the error at stop. It is simply a matter of how much time is acceptable for the application. In most cases it is preferable to wait a few extra milliseconds to get to the stop in position rather than have overshoot or run the risk of oscillations.
Following Error During Motion ¶
This is caused by a Ki, and IL value that is too low. Follow the procedures in the previous paragraph, keeping in mind that it is desirable to increase the integral gain factor as little as possible.
6.2.4 Points to Remember
• Use the Windows-based "ESP_tune.exe" utility to change PID parameters and to visualize the effect. Compare the results and parameters used with the previous iteration.
• The ESP301 controller uses a servo loop based on the PID with velocity and acceleration feed-forward algorithm.
• Use the lowest acceleration the application can tolerate. Lower acceleration generates less overshoot.
• Use the default values provided with the system for all standard motion devices as a starting point.
• Use the minimum value for Ki, and IL that gives acceptable performance. The integral gain factor can cause overshoot and oscillations.
Index ¶
- Constants
- Variables
- func XPSErr(code int) error
- type Command
- type ESP301
- func (esp *ESP301) Disable(axis string) error
- func (esp *ESP301) Enable(axis string) error
- func (esp *ESP301) GetEnabled(axis string) (bool, error)
- func (esp *ESP301) GetPos(axis string) (float64, error)
- func (esp *ESP301) GetVelocity(axis string) (float64, error)
- func (esp *ESP301) Home(axis string) error
- func (esp *ESP301) MoveAbs(axis string, pos float64) error
- func (esp *ESP301) MoveRel(axis string, pos float64) error
- func (esp *ESP301) RawCommand(cmd string) (string, error)
- func (esp *ESP301) ReadErrors() ([]string, error)
- func (esp *ESP301) SetFollowingErrorConfiguration(axis string, enableChecking, disableMotorPowerOnError, abortMotionOnError bool) error
- func (esp *ESP301) SetVelocity(axis string, vel float64) error
- func (esp *ESP301) Wait(axis string) error
- type ErrAliasNotFound
- type ErrCommandNotFound
- type MockController
- func (c *MockController) Disable(axis string) error
- func (c *MockController) Enable(axis string) error
- func (c *MockController) GetEnabled(axis string) (bool, error)
- func (c *MockController) GetPos(axis string) (float64, error)
- func (c *MockController) GetVelocity(axis string) (float64, error)
- func (c *MockController) Home(axis string) error
- func (c *MockController) Homed(axis string) (bool, error)
- func (c *MockController) MoveAbs(axis string, pos float64) error
- func (c *MockController) MoveRel(axis string, dPos float64) error
- func (c *MockController) Raw(s string) (string, error)
- func (c *MockController) SetVelocity(axis string, v float64) error
- func (c *MockController) Stop(axis string) error
- type Picomotor
- type PicomotorError
- type XPS
- func (xps *XPS) Disable(axis string) error
- func (xps *XPS) Enable(axis string) error
- func (xps *XPS) GetEnabled(axis string) (bool, error)
- func (xps *XPS) GetPos(axis string) (float64, error)
- func (xps *XPS) GetStatus(axis string) (XPSStatus, error)
- func (xps *XPS) GetVelocity(axis string) (float64, error)
- func (xps *XPS) Home(axis string) error
- func (xps *XPS) Homed(axis string) (bool, error)
- func (xps *XPS) Initialize(axis string) error
- func (xps *XPS) MoveAbs(axis string, pos float64) error
- func (xps *XPS) MoveRel(axis string, pos float64) error
- func (xps *XPS) Raw(s string) (string, error)
- func (xps *XPS) SetVelocity(axis string, vel float64) error
- func (xps *XPS) Stop(axis string) error
- type XPSError
- type XPSStatus
Constants ¶
const ( // TxTerm is the outgoing terminator CarriageReturn = '\r' Newline = '\n' )
Variables ¶
var ( // ErrBufferWouldOverflow is generated when the buffer on the ESP controller // would overflow if the message was transmitted ErrBufferWouldOverflow = errors.New("buffer too long, maximum command length is 80 characters") // ESPErrorCodesWithoutAxes maps error codes to error strings when the errors // are not axis specific ESPErrorCodesWithoutAxes = map[int]string{ 0: "NO ERROR DETECTED", 3: "OVER TEMPERATURE SHUTDOWN", 4: "EMERGENCY STOP ACTIVATED", 6: "COMMAND DOES NOT EXIST", 7: "PARAMETER OUT OF RANGE", 8: "CABLE INTERLOCK ERROR", 9: "AXIS NUMBER OUT OF RANGE", 10: "EEPROM WRITE FAILED", 11: "EEPROM READ FAILED", 13: "GROUP NUMBER MISSING", 14: "GROUP NUMBER OUT OF RANGE", 15: "GROUP NUMBER NOT ASSIGNED", 16: "GROUP NUMBER ALREADY ASSIGNED", 17: "GROUP AXIS OUT OF RANGE", 18: "GROUP AXIS ALREADY ASSIGNED", 19: "GROUP AXIS DUPLICATED", 20: "DATA ACQUISITION IS BUSY", 21: "DATA ACQUISITION SETUP ERROR", 22: "DATA ACQUISITION NOT ENABLED", 23: "SERVO CYCLE (400μS) TICK FAILURE", 25: "DOWNLOAD IN PROGRESS", 26: "STORED PROGRAM NOT STARTED", 27: "COMMAND NOT ALLOWED", 28: "STORED PROGRAM FLASH AREA FULL", 29: "GROUP PARAMETER MISSING", 30: "GROUP PARAMETER OUT OF RANGE", 31: "GROUP MAXIMUM VELOCITY EXCEEDED", 32: "GROUP MAXIMUM ACCELERATION EXCEEDED", 33: "GROUP MAXIMUM DECELERATION EXCEEDED", 34: "GROUP MOVE NOT ALLOWED DURING MOTION", 35: "PROGRAM NOT FOUND", 37: "AXIS NUMBER MISSING", 38: "COMMAND PARAMETER MISSING", 40: "LAST COMMAND CANNOT BE REPEATED", 41: "MAX NUMBER OF LABELS PER PROGRAM EXCEEDED", 46: "RS-485 EXT FAULT DETECTED", 47: "RS-485 CRC FAULT DETECTED", 48: "CONTROLLER NUMBER OUT OF RANGE", 49: "SCAN IN PROGRESS", } // ESPErrorCodesWithAxes maps the final two digits of an axis-specific // error code to a string. The axis number is excluded from the key. ESPErrorCodesWithAxes = map[int]string{ 0: "MOTOR TYPE NOT DEFINED", 1: "PARAMETER OUT OF RANGE", 2: "AMPLIFIER FAULT DETECTED", 3: "FOLLOWING ERROR THRESHLD EXCEEDED", 4: "POSITIVE HARDWARE LIMIT REACHED", 5: "NEGATIVE HARDWARE LIMIT REACHED", 6: "POSITIVE SOFTWARE LIMIT REACHED", 7: "NEGATIVE SOFTWARE LIMIT REACHED", 8: "MOTOR / STAGE NOT CONNECTED", 9: "FEEDBACK SIGNAL FAULT DETECTED", 10: "MAXIMUM VELOCITY EXCEEDED", 11: "MAXIMUM ACCELERATION EXCEEDED", 13: "MOTOR NOT ENABLED", 14: "MOTION IN PROGRESS", 15: "MAXIMUM JERK EXCEEDED", 16: "MAXIMUM DAC OFFSET EXCEEDED", 17: "ESP CRITICAL SETTINGS ARE PROTECTED", 18: "ESP STAGE DEVICE ERROR", 19: "ESP STAGE DATA INVALID", 20: "HOMING ABORTED", 21: "MOTOR CURRENT NOT DEFINED", 22: "UNIDRIVE COMMUNICATIONS ERROR", 23: "UNIDRIVE NOT DETECTED", 24: "SPEED OUT OF RANGE", 25: "INVALID TRAJECTORY MASTER AXIS", 26: "PARAMETER CHARGE NOT ALLOWED", 28: "INVALID ENCODER STEP RATIO", 29: "DIGITAL I/O INTERLOCK DETECTED", 30: "COMMAND NOT ALLOWED DURING HOMING", 31: "COMMAND NOT ALLOWED DUE TO GROUP ASSIGNMENT", 32: "INVALID TRAJECTORY MODE FOR MOVING", } )
var ( // XPSErrorCodes maps XPS error integers to strings XPSErrorCodes = map[int]string{ 0: "SUCCESS", -115: "HARDWARE FUNCTION NOT SUPPORTED", -113: "BOTH ENDS OF RUNS ACTIVATED", -112: "EXCITATION SIGNAL INITIALIZATION", -111: "GATHERING BUFFER FULL", -110: "NOT ALLOWED FOR GANTRY", -109: "NEED TO BE HOMED AT LEAST ONCE", -108: "SOCKET CLOSED BY ADMIN", -107: "NEED ADMINISTRATOR RIGHTS", -106: "WRONG USERNAME OR PASSWORD", -105: "SCALING CALIBRATION", -104: "PID TUNING INITIALIZATION", -103: "SIGNAL POINTS NOT ENOUGH", -102: "RELAY FEEDBACK TEST SIGNAL NOISY", -101: "RELAY FEEDBACK TEST NO OSCILLATION", -100: "INTERNAL ERROR", -99: "FATAL EXTERNAL MODULE LOAD", -98: "OPTIONAL EXTERNAL MODULE UNLOAD", -97: "OPTIONAL EXTERNAL MODULE LOAD", -96: "OPTIONAL EXTERNAL MODULE KILL", -95: "OPTIONAL EXTERNAL MODULE EXECUTE", -94: "OPTIONAL EXTERNAL MODULE FILE", -85: "HOME SEARCH GANTRY TOLERANCE ERROR", -83: "EVENT ID UNDEFINED", -82: "EVENT BUFFER FULL", -81: "ACTIONS NOT CONFIGURED", -80: "EVENTS NOT CONFIGURED", -75: "TRAJ TIME", -74: "READ FILE PARAMETER KEY", -73: "END OF FILE", -72: "TRAJ INIITALIZATION", -71: "MSG QUEUE", -70: "TRAJ FINAL VELOCITY", -69: "TRAJ ACC LIMIT", -68: "TRAJ VEL LIMIT", -66: "TRAJ EMPTY", -65: "TRAJ ELEM LINE", -64: "TRAJ ELEM SWEEP", -63: "TRAJ ELEM RADIUS", -62: "TRAJ ELEM TYPE", -61: "READ FILE", -60: "WRITE FILE", -51: "SPIN OUT OF RANGE", -50: "MOTOR INITIALIZATION ERROR", -49: "GROUP HOME SEARCH ZM ERROR", -48: "BASE VELOCITY", -47: "WRONG TCL TASKNAME", -46: "NOT ALLOWED BACKLASH", -45: "END OF RUN", -44: "SLAVE", -43: "GATHERING RUNNING", -42: "JOB OUT OF RANGE", -41: "SLAVE CONFIGURATION", -40: "MNEMO EVENT", -39: "NMEMO ACTION", -38: "TCL INTERPRETOR", -37: "TCL SCRIPT KILL", -36: "UNKNOWN TCL FILE", -35: "TRAVEL LIMITS", -33: "GROUP MOTION DONE TIMEOUT", -32: "GATHERING NOT CONFIGURED", -31: "HOME OUT OF RANGE", -30: "GATHERING NOT STARTED", -29: "MNEMOTYPEGATHERING", -28: "GROUP HOME SEARCH TIMEOUT", -27: "GROUP ABORT MOTION", -26: "EMERGENCY SIGNAL", -25: "FOLLOWING ERROR", -24: "UNCOMPATIBLE", -23: "POSITION COMPARE NOT SET", -22: "NOT ALLOWED ACTION", -21: "IN INITIALIZATION", -20: "FATAL INIT", -19: "GROUP NAME", -18: "POSITIONER NAME", -17: "PARAMETER OUT OF RANGE", -16: "WRONG TYPE UNSIGNEDINT", -15: "WRONG TYPE INT", -14: "WRONG TYPE DOUBLE", -13: "WRONG TYPE CHAR", -12: "WRONG TYPE BOOL", -11: "WRONG TYPE BIT WORD", -10: "WRONG TYPE", -9: "WRONG PARAMETER NUMBER", -8: "WRONG OBJECT TYPE", -7: "WRONG FORMAT", -5: "POSITIONER ERROR", -4: "UNKNOWN COMMAND", -3: "STRING TOO LONG", -2: "TCP TIMEOUT", -1: "BUSY SOCKET", 1: "TCL INTERPRETOR ERROR", 2: "RESPONSE INCOMPLETE", 3: "ERROR PARSING ERROR CODE", } // XPSGroupStatuses maps status ints to their strings for XPS groups // // if i < 10 || i == 50, things are not initialized. // 10 < i < 20 OK/ready. // 20 <= i < 40, disabled // 10 <= i < 18, homed/ready XPSGroupStatuses = map[int]string{ 0: "Not initialized state", 1: "Not initialized state due to an emergency brake : see positioner status", 2: "Not initialized state due to an emergency stop : see positioner status", 3: "Not initialized state due to a following error during homing", 4: "Not initialized state due to a following error", 5: "Not initialized state due to a homing timeout", 6: "Not initialized state due to a motion done timeout during homing", 7: "Not initialized state due to a KillAll command", 8: "Not initialized state due to an end of run after homing", 9: "Not initialized state due to an encoder calibration error", 10: "Ready state due to an AbortMove command", 11: "Ready state from homing", 12: "Ready state from motion", 13: "Ready state due to a MotionEnable command", 14: "Ready state from slave", 15: "Ready state from jogging", 16: "ready state from analog tracking", 17: "Ready state from trajectory", 18: "Ready state from spinning", 20: "Disable state", 21: "Disabled state due a following error on ready state", 22: "Disabled state due to a following error during motion", 23: "Disabled state due to a motion done timeout during moving", 24: "Disabled state due to a following error on slave state", 25: "Disabled state due to a following error on jogging state", 26: "Disabled state due to a following error during trajectory", 27: "Disabled state due to a motion done timeout during trajectory", 28: "Disabled state due to a following error during analog tracking", 29: "Disabled state due to a slave error during motion", 30: "Disabled state due to a slave error on slave state", 31: "Disabled state due to a slave error on jogging state", 32: "Disabled state due to a slave error during trajectory", 33: "Disabled state due to a slave error during analog tracking", 34: "Disabled state due to a slave error on ready state", 35: "Disabled state due to a following error on spinning state", 36: "Disabled state due to a slave error on spinning state", 37: "Disabled state due to a following error on auto-tuning", 38: "Disabled state due to a slave error on auto-tuning", 40: "Emergency braking", 41: "Motor initialization state", 42: "Not referenced state", 43: "Homing state", 44: "moving state", 45: "Trajectory state", 46: "slave state due to a SlaveEnable command", 47: "Jogging state due to a JogEnable command", 48: "Analog tracking state due to a TrackingEnable command", 49: "Analog interpolated encoder calibration state", 50: "Not initialized state due to a mechanical zero inconsistency during homing", 51: "Spinning state due to a SpinParametersSet command", 63: "Not initialized state due to a motor initialization error", 64: "Referencing state", 66: "Not initialized state due to a perpendicularity error homing", 67: "Not initialized state due to a master/slave error during homing", 68: "Auto-tuning state", 69: "Scaling calibration state", 70: "Ready state from auto-tuning", 71: "Not initialized state from scaling calibration", 72: "Not initialized state due to a scaling calibration error", 73: "Excitation signal generation state", 74: "Disable state due to a following error on excitation signal generation state", 75: "Disable state due to a master/slave error on excitation signal generation state", 76: "Disable state due to an emergency stop on excitation signal generation state", 77: "Ready state from excitation signal generation", } )
var ErrNotImplemented = errors.New("not implemented")
Functions ¶
Types ¶
type Command ¶
type Command struct { Cmd string `json:"cmd"` Alias string `json:"alias"` Description string `json:"description"` UsesAxis bool `json:"usesAxis"` IsReadOnly bool `json:"isReadOnly"` }
Command describes a command
type ESP301 ¶
type ESP301 struct {
// contains filtered or unexported fields
}
ESP301 represents an ESP301 motion controller.
func (*ESP301) GetEnabled ¶
GetEnabled returns if an axis is enabled. This may not be truthy if the controller threw an error, check the errors if you get disabled errors and this reports true
func (*ESP301) GetPos ¶
GetPos gets the absolute position of an axis in controller units (usually mm)
func (*ESP301) GetVelocity ¶
GetVelocity returns the velocity setpoint for an axis
func (*ESP301) MoveAbs ¶
MoveAbs sets the absolute position of an axis in controller units (usually mm)
func (*ESP301) RawCommand ¶
RawCommand sends a command directly to the motion controller (with EOT appended) and returns the response as-is
func (*ESP301) ReadErrors ¶
ReadErrors reads all error from the controller and returns a slice of the error messages, which may be empty if there are no errors. The slice may be partially filled if a communication error is encountered while reading the sequence of errors.
func (*ESP301) SetFollowingErrorConfiguration ¶
func (esp *ESP301) SetFollowingErrorConfiguration(axis string, enableChecking, disableMotorPowerOnError, abortMotionOnError bool) error
SetFollowingErrorConfiguration sets the "following error" configuration
func (*ESP301) SetVelocity ¶
SetVelocity sets the velocity setpoint for an axis
type ErrAliasNotFound ¶
type ErrAliasNotFound struct {
Alias string
}
ErrAliasNotFound is generated when an alias is unknown to the newport module
func (ErrAliasNotFound) Error ¶
func (e ErrAliasNotFound) Error() string
type ErrCommandNotFound ¶
type ErrCommandNotFound struct {
Cmd string
}
ErrCommandNotFound is generated when a command is unknown to the newport module
func (ErrCommandNotFound) Error ¶
func (e ErrCommandNotFound) Error() string
type MockController ¶
func NewControllerMock ¶
func NewControllerMock(addr string) *MockController
func (*MockController) Disable ¶
func (c *MockController) Disable(axis string) error
func (*MockController) Enable ¶
func (c *MockController) Enable(axis string) error
func (*MockController) GetEnabled ¶
func (c *MockController) GetEnabled(axis string) (bool, error)
func (*MockController) GetVelocity ¶
func (c *MockController) GetVelocity(axis string) (float64, error)
func (*MockController) Home ¶
func (c *MockController) Home(axis string) error
func (*MockController) SetVelocity ¶
func (c *MockController) SetVelocity(axis string, v float64) error
func (*MockController) Stop ¶
func (c *MockController) Stop(axis string) error
type Picomotor ¶
type Picomotor struct { // Handshaking controls if commands check for errors. Higher throughput can // be achieved without error checking in exchange for reduced safety Handshaking bool // contains filtered or unexported fields }
Picomotor represents an picomotor controller.
func NewPicomotor ¶
NewESP301 makes a new ESP301 motion controller instance
type PicomotorError ¶
type PicomotorError struct {
Axis, Code int
}
func (PicomotorError) Error ¶
func (pe PicomotorError) Error() string
type XPS ¶
type XPS struct {
// contains filtered or unexported fields
}
XPS represents an XPS series motion controller.
Note that the programming manual has a lot of socket numbers sprinkled around. We do not see any here because the embedded pool manages that for us. The controller supports up to 100 concurrent sockets.
While newport markets the XPS as a more versatile and consistent (vis-a-vis communication) product than the older ESP line, this is not really true in the author of this package's opinion. For example, there is no function that returns the number of positioners in a group, yet to move a positioner it must belong to a group, and when you get the position of the group you must supply the number of positioners to query for. Consequently, a best practice emerges to simply put each positioner in its own group, and not use the group functionality at all. This practice eliminates the ability to work with groups the way they are used in most other motion controllers, which is a shame.
There is also no use of terminators for datagrams; the controller scans inputs for valid entries and sends them back to enable synchronization.
You also send commands formatted as C/++ source code, which is presumably compiled or interpreted by the controller.
func (*XPS) GetEnabled ¶
GetEnabled gets if the axis is enabled
func (*XPS) GetVelocity ¶
GetVelocity retrieves the velocity setpoint for an axis
func (*XPS) Initialize ¶
Initialize initializes the axis
func (*XPS) SetVelocity ¶
SetVelocity sets the velocity setpoint for an axis
type XPSError ¶
type XPSError struct {
// contains filtered or unexported fields
}
XPSError is a formatible error code from the XPS