The Heist crane is one of the best mech in all of pinball.
The Heist section of the support wiki has a lot of information detailing how to troubleshoot and repair the crane.
On the programming side, the documentation is the file ~/.multimorphic/P3/ModuleDrivers/Heist/1.2.0.0/HeistModuleCapabilities.cs
This tech tip describes the crane and how to control it in software.
Note: the discovery of undocumented events was made possible by the comprehensive event log technique described in the Events tech tip.
The crane can move left-to-right, up and down and extend forward. There is a magnet in the head that can pick up the ball. In the center of the magnet, there is a pin to sense the ball. There is a front target that can be bashed. There is also an RGB LED in the front.
The right wireform has a lever that can lock the ball. An opto near the lever can detect when a ball is locked.
The module definition file ~/.multimorphic/P3/ModuleDrivers/Heist/1.2.0.0/Heist.json describes the components of the playfield, including the crane.
The crane can sweep left-to-right with the servo named craneRotation located underneath the playfield.
The crane can pitch up and down with the servo named cranePitch located to the right of the mast. This servo is connected to a round piece called the horn which lifts or lowers a lever underneath the crane. Higher values move the crane up but if you go too high, the rotation overshoots and the crane starts to move down.
The crane can extend or retract with the stepper motor named crane (labeled Crane Extension in diagnostics). The stepper is located in the top left of the crane. It drives a belt that moves a carriage that pushes or pulls the crane extension.
The coil stepperEnable must be enabled for the crane stepper to work. The module driver takes care of that.
When not in motion, you can safely manually pull or push the crane extension. Never try to sweep or pitch the crane manually since that could force the servos.
The magnet is a coil named craneMagnet. The coil is magnetized when it is energized.
The crane has a micro switch in the back of the extension to detect when it is fully retracted. The switch is named CraneHome but it is labeled “Crane Retracted” in diagnostics.
The front target has a switch named Crane to detect when it is bashed. This switch is named “Crane Target” in diagnostics. The switch is implemented by an opto underneath a small board in the crane head. When the front target is hit, it rotates, rising just high enough to block a light beam underneath the board.
The switch that detects when the magnet touches the ball is named CraneMagnet. This switch is implemented by another opto underneath the board in the crane head. When the ball hits the free moving pin passing through the middle of the magnet, this lifts the pin, blocking the opto light beam.
The crane has another switch named CraneStop. This switch is named “Crane Contact” in diagnostics. This switch detects when the crane frame touches something metallic like the wireform. This switch is currently not used by the Heist module driver nor any application running on the Heist module. You can ignore it.
The LED in the crane head is named crane.
The ball lock lever on the wireform is controlled by the servo named ballLock. This is a two-position servo. It can be either up or down.
The switch that detects if there is a ball locked on the wireform is named WireLock0 but it appears as “Wireform Lock” in diagnostics. This switch is implemented with an opto in front of the lock lever.
There is an extra switch named WireLock1 listed in HeistModuleSwitches in HeistModuleCapabilities. Maybe there was a second wire lock switch in an early prototype but it does not exist in the production version. You will not find it in diagnostics either.
The crane LED is like any other LED on the module. You can control it with a LEDScript.
For example, this will make the crane LED blink in red:
private LEDScript craneScript;
craneScript = new LEDScript(p3.LEDs["crane"], this.Priority);
craneScript.AddCommand(Multimorphic.P3.Colors.Color.red, 0, 1);
craneScript.AddCommand(Multimorphic.P3.Colors.Color.black, 0, 0.5);
p3.LEDController.AddScript(craneScript, -1);
Don’t forget to remove the script when done or when the mode is stopped:
p3.LEDController.RemoveScript(craneScript);
The LED simulator does not emulate the crane LED, so you won't find it on Display #8. While tracking the crane movement is complex, displaying the crane LED in a static location would have been straightforward.
When the crane is low enough, the front can be bashed with the ball. The application can detect a bash hit with a handler for the front switch:
…
return SWITCH_CONTINUE;
}
The Heist module driver is unusual because it forwards many switch events as mode to mode events. It is therefore possible to implement the bash detection with a regular event handler:
// when the handler is needed
AddModeEventHandler("sw_Crane_active", CraneBashHitEventHandler, this.Priority);
// when the handler is no longer needed
RemoveModeEventHandler("sw_Crane_active", CraneBashHitEventHandler, this.Priority);
private bool CraneBashHitEventHandler(string eventName, object eventData) {
…
return EVENT_CONTINUE;
}
Some people may find the event code easier to read if you need to dynamically register and remove the handler. The call to dynamically register switch handlers is less known.
The Heist module driver defines the following “Playfield Module Local GameAttributes”. They will appear in the service menu at Settings/Mech/Crane. The application automatically inherits those settings when running with the Heist module. To access this menu when the application is running, open the coin door and press the Launch button.
GameAttribute Name | Description | Default | Min | Max | |
EnableCrane | Crane must be enabled to function | Yes | No | Yes | |
* | CranePitchMax | Max height the crane will rise, higher value is higher towards glass | 255 | 60 | 255 |
* | CranePitchMin | Min height the crane will lower, lower value is lower towards playfield | 180 | 60 | 255 |
* | CranePitchPickup | Height the crane moves to for ball pickup | 200 | 60 | 255 |
* | CraneSweepRightMax | Max distance the crane will move right, lower value is further right towards the lock | 60 | 50 | 255 |
* | CraneSweepLeftMax | Max distance the crane will move left, higher value is further away from the lock | 185 | 60 | 255 |
* | CraneSweepHome | Distance the crane moves right for ball pickup, lower value is further right, should be the same as CraneSweepRightMax | 62 | 50 | 255 |
* | StepperMaxSteps | Maximum the crane will extend, higher value is further towards the flippers | 1000 | 200 | 6000 |
* | CraneExtensionHome | Distance the crane will extend to for ball pickup, 0 is fully retracted, higher is more extended | 0 | 0 | 100 |
CranePickupRetryMax | How many pickup attempts before giving up | 5 | 1 | 10 |
GameAttributes marked with * are automatically calculated during crane validation. The values should be fairly accurate and there is usually no need to change them. With that said, you may want to manually adjust the pickup location slightly after crane calibration for improved results (i.e. CranePitchPickup, CraneSweepRightMax, CraneSweepHome, CraneExtensionHome).
CraneSweepRightMax is the maximum the crane can sweep right, so this is the minimum sweep value. They could have called it CraneSweepMin for symmetry with CranePitchMin but then it would not have been clear if the min is left or right of the playfield.
The application can read those settings like this:
int cranePitchMax = data.GetGameAttributeValue("PlayfieldModuleLocalSettings", "CranePitchMax").ToInt();
This is not common in the application because the module driver can usually handle these crane details.
The Heist application extends the Settings/Mech/Crane menu with one more GameAttribute:
GameAttribute Display Name | Description |
Calibrate Crane | Run the interactive crane calibration process now |
There is no value for this GameAttribute because it triggers an action after confirmation. This is achieved with the GameAttribute options (GameAttributeOptions.Action | GameAttributeOptions.Confirm).
The CraneCalibrationMode is part of the Heist application instead of the module driver, so no other application will inherit this menu action. Users must run the Heist application if they want to run crane calibration.
An application might want to define other application-specific GameAttributes for things like the crane bash height, crane ball knock-off height, crane move speed. For example, the Heist application has this GameAttribute under Service Menu/Settings/Gameplay/Crane.
GameAttribute Display Name | Description |
Crane Ball Flipper Knockoff Height | Height in ball diameters above the playfield for flipper knockoff |
The documentation for the Heist module programming interface is in ~/.multimorphic/P3/ModuleDrivers/Heist/1.2.0.0/HeistModuleCapabilities.cs
This file is in C# for historical reasons. Look for the information in comments.
In the following sections, we describe the crane API and expand on that documentation.
We do not cover the CraneHoverRequest class because some documentation is missing (like the name of the event). In any case, that feature is implemented in the Heist application, not in the module driver, therefore no other application can use it.
BallPaths, two-position servos and locking a ball are not covered here. See the Heist BallPaths Tech Tip for these topics.
The crane API defines a coordinate system based on 3 independent axes: pitch, sweep and extend. This is not a cartesian or polar coordinate system.
Pitch is a ushort from 0 to 255, but it is only valid from CranePitchMin to CranePitchMax (default from 180 to 255). The maximum height is typically achieved around 220. A request to pitch outside the valid region logs an error message and the command is ignored.
Sweep is a ushort from 0 to 255, but it is only valid from CraneSweepRightMax to CraneSweepLeftMax (default from 60 to 185). Note 0 is the wireform position, not all the way right on the playfield. A request to sweep outside the valid region logs an error message and the command is ignored.
Extend is a ushort from 0 to StepperMaxSteps (typically 1000). A request to extend to less than or equal to 0 fully retracts the crane. A request to extend to StepperMaxSteps or more extends to StepperMaxSteps exactly. There is no error message if the value is out of bounds.
It is also possible to specify a float value as a percentage between 0 and 1. The value 0 means the lowest valid value. The value 1 means the highest valid value. Any other fraction is the percentage between the lowest and highest value. For example, the value 0.5 is the middle point between the low and high values.
Surprisingly, sweep 0.5 is not the middle of the playfield. It is about 2 inches to the right of what you expect. This is not a bug. The value is indeed the middle of the range but there is no requirement that the range be centered.
Using percentages is preferred over ushort units.
The application can compute percentages programmatically like this if needed:
int pitchMin = data.GetGameAttributeValue("PlayfieldModuleLocalSettings", "CranePitchMin").ToInt();
int pitchMax = data.GetGameAttributeValue("PlayfieldModuleLocalSettings", "CranePitchMax").ToInt();
float pitchPercent = (float)(pitch – pitchMin) / (pitchMax – pitchMin);
int sweepMin = data.GetGameAttributeValue("PlayfieldModuleLocalSettings", "CraneSweepLeftMax").ToInt();
int sweepMax = data.GetGameAttributeValue("PlayfieldModuleLocalSettings", "CraneSweepLeftMax").ToInt();
float sweepPercent = (float)(sweep – sweepMin) / (sweepMax – sweepMin);
// extendMin is always 0
int extendMax = data.GetGameAttributeValue("PlayfieldModuleLocalSettings", "StepperMaxSteps").ToInt();
float extendPercent = (float)extend / extendMax;
In practice, the percentage is likely already known as part of the game design. In that case, there is no need to compute the percentage from the GameAttributes. This is doubly beneficial since the application does not have to implement handlers to detect when the GameAttribute values change in the Service Menu.
These mode to modes events move the crane along one of the axes:
Evt_CranePitchMoveTo
Evt_CraneSweepMoveTo
Evt_CraneExtendTo
The event argument can be specified in any of the following ways:
The duration in the KeyValuePair is how long the crane will take to reach its destination in seconds.
Passing a ushort or a float argument uses the default duration as follows.
There is no software limit on how fast or how slow the pitch or sweep servos can move.
The minimum stepper speed is about 465 units per second. If you try to move the stepper slower, the duration will be adjusted to 465 units per second with a warning. The maximum stepper speed is 755 units per second. If you try to move the extend stepper faster than 755 units per second, it will be slowed down to 755 units per second with a warning.
These examples show the various argument types (they don’t do anything particularly useful as a group):
ushort pitch = 200;
ushort extend = 800;
PostModeEventToModes("Evt_CranePitchMoveTo", pitch);
PostModeEventToModes("Evt_CraneSweepMoveTo", 0.5f);
PostModeEventToModes("Evt_CraneExtendTo", new KeyValuePair<ushort, double>(extend, 1.32));
PostModeEventToModes("Evt_CraneSweepMoveTo", new KeyValuePair<float, double>(0.5f, 2.0));
This example combines multiple movements to move the crane in bash position near the center of the playfield in 5 seconds.
double craneMoveDuration = 5d;
float cranePitch = 1.0f;
float craneSweep = 0.5f;
float craneExtension = 1.0f;
PostModeEventToModes("Evt_CraneSweepMoveTo",
new KeyValuePair<float, double>(craneSweep, craneMoveDuration));
PostModeEventToModes("Evt_CranePitchMoveTo",
new KeyValuePair<float, double>(cranePitch, craneMoveDuration));
PostModeEventToModes("Evt_CraneExtendTo",
new KeyValuePair<float, double>(craneExtension, craneMoveDuration));
This code assumes the crane starts over the playfield and has already cleared the wireform. If you run this code when the crane is in the home position, you run the risk of pitching into the wireform or extending into the lock lever. The order in which the movements are performed matter and you need to sometimes delay a movement before another one starts.
When a crane move is initiated, the module driver sends notification events.
When executing Evt_CranePitchMoveTo, the module driver sends these status events in order:
Evt_CraneMove_Pitch_Started
Evt_CurrentCranePitch (both mode to modes and mode to GUI at regular intervals)
Evt_TextDriverPitch (at regular intervals)
Evt_CraneMove_Pitch_Done
Evt_ServoParked_cranePitch
When executing Evt_CraneSweepMoveTo, the module driver sends these status events in order:
Evt_CraneMove_Sweep_Started
Evt_CurrentCraneSweep (both mode to modes and mode to GUI at regular intervals)
Evt_TextDriverSweep (at regular intervals)
Evt_CraneMove_Sweep_Done
Evt_ServoParked_craneRotation
When executing Evt_CraneExtendTo, the module driver sends these status events in order:
Evt_CraneMove_Extension_Started
Evt_CurrentCraneExtension (both mode to modes and mode to GUI at regular intervals)
Evt_TextDriverExtension (at regular intervals)
There is no equivalent of the Done or Parked events for the crane extension. The application must estimate an appropriate delay based on the corrected duration.
The predefined crane routines combine multiple crane movements to perform a specific function. It is much easier to call these routines than to try to reimplement them yourself.
There are 3 routines: send home, pickup and drop.
The following sections describe one routine at a time.
The Evt_CraneSendHome event moves the crane to the home position, ready for pickup. The event argument is not used.
PostModeEventToModes("Evt_CraneSendHome", null);
This routine starts by retracting the crane. The routine will retry multiple times if the “Crane Retracted” switch is not activated.
Once the crane is fully retracted, the routine lifts and sweeps the crane to the pickup location. There is no retry for these movements.
It is also possible to send the crane home on each axis independently. This does not retry and requires some precaution to avoid hitting the crane against the wireform.
PostModeEventToModes("Evt_CraneExtendTo", 0);
...add a delay here to wait for the crane to retract...
PostModeEventToModes("Evt_CranePitchSendHome", null);
PostModeEventToModes("Evt_CraneSweepMoveToPickup", null);
The module driver sends these status events when it thinks the crane is in the home position on an axis:
PostModeEventToModes("Evt_CraneStepperIsHome", null);
PostModeEventToModes("Evt_CranePitchHome", pitchAsUshort);
PostModeEventToModes("Evt_CraneSweepHome", sweepAsUshort);
For the pitch axis, this happens when the target position is either CranePitchMax or CranePitchPickup.
For the sweep axis, this happens when the target position is CraneSweepHome.
The routine sends these status events in order:
… see status events for Evt_CraneExtendTo in earlier section …
Evt_CraneStepperIsHome
Evt_CraneSendHomeWhenStepperDone
… see status events for Evt_CranePitchMoveTo and Evt_CraneSweepMoveTo in earlier section …
Evt_CraneSweepHome
Evt_CranePitchHome
The application knows the routine has finished when it receives both Evt_CraneSweepHome and Evt_CranePitchHome.
The Evt_CranePickup event loads the ball onto the crane if a ball is available in lock position. The event argument is not used.
PostModeEventToModes("Evt_CranePickup", null);
This routine combines moving the crane to the home position, dipping the crane, magnetizing, lifting then sweeping to the middle of playfield with the ball still held by the crane.
If everything goes well, the routine sends the following status events. The routine logs a message each time it progresses to the next stage (these log messages are represented by C# comments in the trace below).
// Crane Load requested
// Start Homing For Pickup - awaiting CraneSweepHome
Evt_CraneSendHome
… see status events for Evt_CraneSendHome routine in earlier section …
// Crane Load State Proceeding: Homing; event trigger : Evt_CraneMove_Sweep_Done
// Crane Load State: Finishing Homing
// Crane Load State: Dipping
Evt_CranePitchMoveToPickup
Evt_CraneSweepMoveToPickup
… see status events for Evt_CranePitchMoveTo and Evt_CraneSweepMoveTo in earlier section …
// Crane Load State: Finishing Dipping
// Ball On Crane: False
Evt_BallLeftLock
Evt_BallOnMagnet
Evt_BallOnCrane
// Crane Load State Proceeding: Magnetizing; event trigger : Evt_BallOnCrane
// Crane Load State: Lifting
Evt_CraneSweepMoveToPickup
Evt_CraneExtendToAlmostPickup
Evt_CranePitchSendHome
… see status events for Evt_CranePitchMoveTo, Evt_CraneSweepMoveTo, Evt_CraneExtendTo in earlier section
// Crane Load State Proceeding: Lifting; event trigger : Evt_CraneMove_Pitch_Done
// Crane Load State: Finish Lifting
Evt_CraneSweepMoveToPickup
// Crane Load State: Delivering
Evt_CraneSweepMoveTo
Evt_CraneDeliveringBallAfterPickup
… see status events for Evt_CraneSweepMoveTo in earlier section …
// Crane Load State Proceeding: Delivering; event trigger : Evt_CraneMove_Sweep_Done
// Crane Load State: Finish Delivering
// Sending CraneLoaded
Evt_CraneLoaded
When running in the simulator, the routine triggers the Evt_SimulationWaitingForBallOnCrane event when finishing dipping. In response, the CraneMagnetMode sends Evt_BallLeftLock, Evt_BallOnMagnet and Evt_BallOnCrane tricking the application into believing that the ball has raised above the wireform opto and is now held by the magnet.
The application knows the routine completed successfully when it receives the Evt_CraneLoaded event. The event argument is always true.
Conversely, the application must be ready to handle errors.
If the crane is already attempting to pickup the ball, the routine logs an error and ignores the request. The earlier request continues to execute. The application will interpret the result of the earlier request as the result of this request.
If the crane is already holding the ball, the routine logs an error and sends the event Evt_CraneLoadFailed. The event argument is the string "AlreadyHadBall". This is probably a logic error in the application.
If the crane fails to pickup the ball, it sends the error event Evt_CraneDeliveringNoBallAfterPickup and it continues with the delivery sweep without a ball. At the end of the delivery sweep, it sends the Evt_CraneLoadFailed event with string argument "NoBall". One possibility is the ball never made it to the lock position to begin with. Another possibility is the ball is still sitting in the lock position but the crane could not lift it for some reason. The application should take mitigation action to continue the gameplay.
The Evt_CraneDrop event drops the ball held by the crane. The argument data is not used.
PostModeEventToModes("Evt_CraneDrop", null);
The routine ignores the request if there is a pickup in progress, otherwise it demagnetizes the crane.
The routine sends these status events:
// Disabling crane magnet due to CraneDrop event
Evt_BallOffMagnet
Evt_BallOffCrane (both mode to modes and mode to GUI)
// CraneMechMode sees BallOffCrane during None
When running in the simulator, the routine sends the Evt_SimulationWaitingForBallOffCrane event. In response, the CraneMagnetMode emulates the deactivation of the CraneMagnet switch, tricking the application into believing that the ball has indeed dropped from the crane.
The ball in play can knock off the ball suspended on the magnet provided the crane is loaded and low enough. Be careful when pitching down not to crash the suspended ball into the screen. The exact height might also depend whether it matters if the infrared grid detects the suspended ball or not.
After the crane is loaded, the application can detect the ball is knocked off the magnet by implementing an event handler for Evt_BallOffCrane.
// when the handler is needed
AddModeEventHandler("Evt_BallOffCrane", BallOffCraneEventHandler, this.Priority);
// when the handler is no longer needed
RemoveModeEventHandler("Evt_BallOffCrane", BallOffCraneEventHandler, this.Priority);
private bool BallOffCraneEventHandler(string eventName, object eventData) {
…
return EVENT_CONTINUE;
}
The module driver documentation highlights some best practices necessary to guarantee smooth operation of the crane. These practices are so important that we copy them below.
The following table lists the Mode to Modes events related to the crane.
A * indicates an undocumented event in HeistModuleCapabilities.cs
Mode to Modes Event | Argument | Description | |
* | Evt_BallLeftLock | int | The ball has left the lock area on the right wireform. Argument is number of remaining locked balls. |
* | Evt_BallOffCrane | true | The magnet switch deactivated. Sent to modes and GUI. |
* | Evt_BallOffMagnet | true | The magnet switch deactivated. Same as Evt_BallOffCrane but sent to modes only. |
* | Evt_BallOnCrane | true | The magnet switch activated. Sent to modes and GUI. |
* | Evt_BallOnMagnet | true | The magnet switch activated. Same as Evt_BallOnCrane, but sent to modes only. |
* | Evt_CraneDeliveringBallAfterPickup | null | During the pickup routine, the crane successfully picked up the ball and is initiating the delivery sweep. |
* | Evt_CraneDeliveringNoBallAfterPickup | null | During the pickup routine, the crane failed to pick up the ball and is initiating the delivery sweep with no ball. |
Evt_CraneDrop | null | Request to initiate the drop routine. | |
Evt_CraneExtendTo | 4 options | Request the crane extension to move to the target value. Argument is the target extension and an optional duration. | |
* | Evt_CraneExtendToAlmostPickup | double | Move the crane to 0.9 of the home position. The argument is the move duration. |
* | Evt_CraneLoadFailed | string | The pickup routine completed unsuccessfully and the crane is over the playfield without a ball. The argument is a reason like "NoBall" or "AlreadyHadBall". |
* | Evt_CraneLoaded | true | The pickup routine completed successfully and the crane is holding the ball over the playfield. |
Evt_CraneMove_Extension_Started | ushort | Status event sent when an extension is initiated. The argument is the target extension value. | |
Evt_CraneMove_Pitch_Done | ushort | Status event sent when a pitch move is complete. Argument is the current pitch value. | |
Evt_CraneMove_Pitch_Started | ushort | Status event sent when a pitch is initiated. Argument is the target pitch value. | |
Evt_CraneMove_Sweep_Started | ushort | Status event sent when a sweep is initiated. Argument is the target sweep value. | |
Evt_CraneMove_Sweep_Done | ushort | Status event sent when a sweep move is complete. Argument is the current sweep value. | |
Evt_CranePickup | Null | Request to initiate the pickup routine: send home, dip, magnetizing, lift, sweep to middle of playfield. Responds with Evt_CraneLoaded when successful, or Evt_CraneLoadFailed upon error. | |
Evt_CranePitchHome | ushort | Status event sent when the pitch is in its home position or its pickup position. Argument is the current pitch value. | |
Evt_CranePitchMoveTo | 4 options | Request the crane pitch to move to the target value. Argument is the target pitch and an optional duration. | |
* | Evt_CranePitchMoveToPickup | double | Lower the crane to pickup the ball. The argument is the move duration. |
* | Evt_CranePitchSendHome | double | Raise the crane to “Crane Pitch Max” height. The argument is the move duration. |
Evt_CraneSendHome | null | Request to move the crane to the home position. | |
* | Evt_CraneSendHomeWhenStepperDone | true | Internal event sent during the send home routine when the extension reaches home, it signals the sweep and pitch home can start. |
Evt_CraneStepperIsHome | null | Status event sent when the crane extension is in its home position. | |
Evt_CraneSweepHome | ushort | Status event sent when the crane sweep is in its home position. Argument is the current sweep value. | |
Evt_CraneSweepMoveTo | 4 options | Request the crane sweep to move to the target value. Argument is the target sweep and an optional duration. | |
* | Evt_CraneSweepMoveToPickup | null | Sweep the crane to the home position. |
* | Evt_CurrentCraneExtension | float | Status event sent at regular intervals during an extension. The argument is the current extension percentage. |
* | Evt_CurrentCranePitch | float | Status event sent at regular intervals during a pitch. Argument is the current pitch percentage. |
* | Evt_CurrentCraneSweep | float | Status event sent at regular intervals during a sweep. Argument is the current sweep percentage. |
* | Evt_ServoParked_cranePitch | null | Status even sent when the pitch servo goes into idle mode. |
* | Evt_ServoParked_craneRotation | null | Status event sent when the sweep servo goes into idle mode. |
* | Evt_SimulationWaitingForBallOffCrane | true | Internal message sent during the drop routine when running in the simulator. It sends the necessary events to trick the application to think the ball has dropped off the crane. |
* | Evt_SimulationWaitingForBallOnCrane | true | Internal message sent during the pickup routine when running in the simulator. It sends the necessary events to trick the application to think the ball has been picked up by the crane. |
The 4 options are:
The following table lists the Mode to GUI events related to the crane.
Event Name | Argument | Description | |
* | Evt_BallOffCrane | true | The magnet switch deactivated. |
* | Evt_BallOnCrane | true | The magnet switch activated. |
* | Evt_CurrentCraneExtension | float | Status event sent to the GUI at regular intervals during an extension. The argument is the current extension percentage. |
* | Evt_CurrentCranePitch | float | Status event sent to the GUI at regular intervals during a pitch. The argument is the current pitch percentage. |
* | Evt_CurrentCraneSweep | float | Status event sent to the GUI at regular intervals during a sweep. The argument is the current sweep percentage. |
* | Evt_TextCraneMechLog | string | Status event containing the last 10 log messages logged by the crane mech. The application can show the log messages on the screen for debugging. |
* | Evt_TextDriverExtension | string | Status event sent to the GUI at regular intervals during an extension. The argument is the current ushort extension as a string. |
* | Evt_TextDriverPitch | string | Status event sent to the GUI at regular intervals during a pitch. The argument is the current ushort pitch value as a string. |
* | Evt_TextDriverSweep | string | Status event sent to the GUI at regular intervals during a sweep. The argument is the current ushort sweep value as a string |