852 lines
32 KiB
C
852 lines
32 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include "Automation1.h"
|
|
|
|
void connectToController();
|
|
void disconnectFromController();
|
|
void startController();
|
|
void stopController();
|
|
void enableAxis(int32_t axis);
|
|
void disableAxis(int32_t axis);
|
|
void homeAxis(int32_t axis);
|
|
void abortAxis(int32_t axis);
|
|
void showAxisStatus(int32_t axis);
|
|
void moveAxisLinear(int32_t axis, double distance, double speed);
|
|
void runProgram(const char* aeroscriptProgramPath);
|
|
void showProgramStatus();
|
|
void stopProgram();
|
|
void getGlobalInteger(int32_t index);
|
|
void setGlobalInteger(int32_t index, int64_t newValue);
|
|
void showAxisParameters(int32_t axis);
|
|
void printHelp();
|
|
void printError();
|
|
|
|
/// <summary>
|
|
/// The handle to the connected Automation1 controller. All controller interaction will be done using this variable.
|
|
/// This handle is null if we are not connected. See connectToController() and startController() in this source file for
|
|
/// more details on how to connect to and start the controller.
|
|
/// </summary>
|
|
Automation1Controller controller = NULL;
|
|
|
|
/// <summary>
|
|
/// The Automation1 console example for C/C++.
|
|
///
|
|
/// This example has a simple command line interface to demonstrate the basics of interacting
|
|
/// with an Automation1 controller from a user's perspective. The code for each command line command will
|
|
/// demonstrate how to perform these actions through the C API.
|
|
///
|
|
/// The IntelliSense information on the types, enums, and functions found in the header files document much of the API and how to use it.
|
|
///
|
|
/// This project links against Automation1C64.dll and Automation1Compiler64.dll. These are
|
|
/// required to compile and run the application.
|
|
///
|
|
/// You might not be able to open or build this project from the installation directory under "C:\Program Files\Aerotech".
|
|
/// If that is the case, copy this example and the dlls listed above to your user files directory and build from there.
|
|
///
|
|
/// Be sure to read the Readme.txt file in the APIs/C folder.
|
|
/// </summary>
|
|
int32_t main(int32_t argc, char** argv)
|
|
{
|
|
char inputBuffer[2048];
|
|
char command[64];
|
|
int32_t arg0;
|
|
double arg1;
|
|
double arg2;
|
|
int numParsed;
|
|
char programPath[1024];
|
|
int64_t newGlobalInteger;
|
|
|
|
printf("Enter a command(or \"quit\" to exit or \"help\" for a list of commands)\n");
|
|
printf("> ");
|
|
|
|
// This loop checks for input over and over for simple command line commands and then executes the commands with the user
|
|
// supplied arguments. See the individual functions in this source file for more details on each command.
|
|
while (true)
|
|
{
|
|
// If input is detected from stdin, it will be read into the buffer and the function will return a non-null pointer.
|
|
if (fgets(inputBuffer, 2048, stdin))
|
|
{
|
|
// This function will attempt to parse the input into the formats specified by the second argument.
|
|
// On failure, this function returns 0 or EOF (generally -1).
|
|
numParsed = sscanf_s(inputBuffer, "%s %d %lf %lf", command, (unsigned)_countof(command), &arg0, &arg1, &arg2);
|
|
if (numParsed <= 0)
|
|
{
|
|
printf("Could not parse input\n");
|
|
printHelp();
|
|
printf("> ");
|
|
continue;
|
|
}
|
|
|
|
for (int character = 0; character < 64; character++)
|
|
{
|
|
command[character] = tolower(command[character]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (!strcmp(command, "connect"))
|
|
{
|
|
connectToController();
|
|
}
|
|
else if (!strcmp(command, "disconnect"))
|
|
{
|
|
disconnectFromController();
|
|
}
|
|
else if (!strcmp(command, "start"))
|
|
{
|
|
startController();
|
|
}
|
|
else if (!strcmp(command, "stop"))
|
|
{
|
|
stopController();
|
|
}
|
|
else if (!strcmp(command, "enable"))
|
|
{
|
|
if (numParsed == 2)
|
|
{
|
|
enableAxis(arg0);
|
|
}
|
|
else
|
|
{
|
|
printf("Invalid command: you must specify an axis to enable\n");
|
|
}
|
|
}
|
|
else if (!strcmp(command, "disable"))
|
|
{
|
|
if (numParsed == 2)
|
|
{
|
|
disableAxis(arg0);
|
|
}
|
|
else
|
|
{
|
|
printf("Invalid command: you must specify an axis to disable\n");
|
|
}
|
|
}
|
|
else if (!strcmp(command, "home"))
|
|
{
|
|
if (numParsed == 2)
|
|
{
|
|
homeAxis(arg0);
|
|
}
|
|
else
|
|
{
|
|
printf("Invalid command: you must specify an axis to home\n");
|
|
}
|
|
}
|
|
else if (!strcmp(command, "abort"))
|
|
{
|
|
if (numParsed == 2)
|
|
{
|
|
abortAxis(arg0);
|
|
}
|
|
else
|
|
{
|
|
printf("Invalid command: you must specify an axis to abort motion on\n");
|
|
}
|
|
}
|
|
else if (!strcmp(command, "axisstatus"))
|
|
{
|
|
if (numParsed == 2)
|
|
{
|
|
showAxisStatus(arg0);
|
|
}
|
|
else
|
|
{
|
|
printf("Invalid command: you must specify an axis to get status from\n");
|
|
}
|
|
}
|
|
else if (!strcmp(command, "movelinear"))
|
|
{
|
|
if (numParsed == 4)
|
|
{
|
|
moveAxisLinear(arg0, arg1, arg2);
|
|
}
|
|
else
|
|
{
|
|
printf("Invalid command: you must specify an axis, distance, and speed for the linear move\n");
|
|
}
|
|
}
|
|
else if (!strcmp(command, "runprogram"))
|
|
{
|
|
// Run program is an edge case in terms of input parsing, so we parse the input again with different formatting.
|
|
numParsed = sscanf_s(inputBuffer, "%s %s", command, (unsigned)_countof(command), programPath, (unsigned)_countof(programPath));
|
|
if (numParsed == 2)
|
|
{
|
|
runProgram(programPath);
|
|
}
|
|
else
|
|
{
|
|
printf("Invalid command: you must specify the path to an AeroScript program to run\n");
|
|
}
|
|
}
|
|
else if (!strcmp(command, "programstatus"))
|
|
{
|
|
showProgramStatus();
|
|
}
|
|
else if (!strcmp(command, "stopprogram"))
|
|
{
|
|
stopProgram();
|
|
}
|
|
else if (!strcmp(command, "getglobalinteger"))
|
|
{
|
|
if (numParsed == 2)
|
|
{
|
|
getGlobalInteger(arg0);
|
|
}
|
|
else
|
|
{
|
|
printf("Invalid command: you must specify an index to get\n");
|
|
}
|
|
}
|
|
else if (!strcmp(command, "setglobalinteger"))
|
|
{
|
|
// Set global integer is another edge case, so we parse the input again with different formatting.
|
|
numParsed = sscanf_s(inputBuffer, "%s %d %lld", command, (unsigned)_countof(command), &arg0, &newGlobalInteger);
|
|
if (numParsed == 3)
|
|
{
|
|
setGlobalInteger(arg0, (int64_t)arg1);
|
|
}
|
|
else
|
|
{
|
|
printf("Invalid command: you must specify an index and a new integer value to set\n");
|
|
}
|
|
}
|
|
else if (!strcmp(command, "showaxisparameters"))
|
|
{
|
|
if (numParsed == 2)
|
|
{
|
|
showAxisParameters(arg0);
|
|
}
|
|
else
|
|
{
|
|
printf("Invalid command: you must specify an axis to show parameters for\n");
|
|
}
|
|
}
|
|
else if (!strcmp(command, "help"))
|
|
{
|
|
printHelp();
|
|
}
|
|
else if (!strcmp(command, "quit"))
|
|
{
|
|
// Because connecting to the controller allocates memory, we should always disconnect before
|
|
// exiting the program to avoid leaking memory.
|
|
if (controller)
|
|
{
|
|
disconnectFromController();
|
|
}
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
printf("Unknown Command\n");
|
|
printHelp();
|
|
}
|
|
printf("> ");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Connects to the Automation1 controller.
|
|
/// </summary>
|
|
void connectToController()
|
|
{
|
|
// Make sure we aren't connected before trying to do anything.
|
|
if (controller)
|
|
{
|
|
printf("Already connected\n");
|
|
return;
|
|
}
|
|
|
|
// Calling Automation1_Connect(&controller) will connect to the controller installed on the local machine. If
|
|
// we wanted to connect to a controller installed on a different machine with the IP address 192.168.1.15,
|
|
// we could instead call Automation1_ConnectWithHost("192.168.1.15", &controller).
|
|
//
|
|
// Connecting to the controller will not change its running state, meaning that we might have to also
|
|
// call Automation1_Controller_Start(controller) on our controller variable before we can run AeroScript programs
|
|
// or perform motion. We must start the controller before using most of the functions in the C API. See the
|
|
// startController(controller) function in this source file for more information on starting the controller.
|
|
//
|
|
// To avoid leaking memory, be sure to call Automation1_Disconnect(controller) before quitting. See
|
|
// disconnectFromController(controller) for more information.
|
|
if (!Automation1_Connect(&controller))
|
|
{
|
|
printError();
|
|
return;
|
|
}
|
|
|
|
printf("Connected to Automation1 controller\n");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Disconnects from the Automation1 controller.
|
|
/// </summary>
|
|
void disconnectFromController()
|
|
{
|
|
// Make sure we are connected before trying to do anything.
|
|
if (!controller)
|
|
{
|
|
printf("Already disconnected\n");
|
|
return;
|
|
}
|
|
|
|
// Disconnecting from a controller will not change its running state, meaning that the controller
|
|
// might still be running after we disconnect. Call Automation1_Controller_Stop(controller) before disconnecting
|
|
// to stop the controller from running AeroScript programs or performing motion. See the stopController(controller)
|
|
// function in this source file for more information. Use this function when your application no longer needs to interact
|
|
// with the controller but you want the controller to continue running.
|
|
//
|
|
// Calling Automation1_Disconnect(controller) frees memory associated with the controller handle.
|
|
if (!Automation1_Disconnect(controller))
|
|
{
|
|
printError();
|
|
}
|
|
|
|
controller = NULL;
|
|
printf("Disconnected from Automation1 controller\n");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Starts the Automation1 controller.
|
|
/// </summary>
|
|
void startController()
|
|
{
|
|
// Make sure we are connected before trying to do anything.
|
|
if (!controller)
|
|
{
|
|
printf("You must connect to the controller before you can start it\n");
|
|
return;
|
|
}
|
|
|
|
// The act of connecting to the controller on its own will not change the running state of the controller
|
|
// so we have to explicitly start it by calling Automation1_Controller_Start(controller). We could check
|
|
// Automation1_Controller_IsRunning(controller) to see if the controller is already running, but since
|
|
// Automation1_Controller_Start(controller) will just do nothing if the controller is already running we
|
|
// can call it regardless. We must start the controller before calling any other C API functionality.
|
|
if (!Automation1_Controller_Start(controller))
|
|
{
|
|
printError();
|
|
return;
|
|
}
|
|
|
|
printf("Controller started\n");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Stops the Automation1 controller.
|
|
/// </summary>
|
|
void stopController()
|
|
{
|
|
// Make sure we are connected before trying to do anything.
|
|
if (!controller)
|
|
{
|
|
printf("You must connect to the controller before you can stop it\n");
|
|
return;
|
|
}
|
|
|
|
// Calling Automation1_Controller_Stop(controller) will stop the Automation1 controller but not disconnect us.
|
|
// We could check Automation1_Controller_IsRunning(controller) to see if the controller is already running,
|
|
// but since Automation1_Controller_Stop(controller) will just do nothing if the controller is already running
|
|
// we can call it regardless.
|
|
if (!Automation1_Controller_Stop(controller))
|
|
{
|
|
printError();
|
|
return;
|
|
}
|
|
|
|
printf("Controller stopped\n");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Enables an axis.
|
|
/// </summary>
|
|
/// <param name="axis">The index of the axis to enable.</param>
|
|
void enableAxis(int32_t axis)
|
|
{
|
|
// Make sure we are connected before trying to do anything.
|
|
if (!controller)
|
|
{
|
|
printf("You must connect to the controller before enabling an axis\n");
|
|
return;
|
|
}
|
|
|
|
// We can enable an axis using the Automation1_Command_Enable(controller, taskIndex, axes, axesLength)
|
|
// in the Automation1Command.h header. The Automation1Command.h header provides access to many of the AeroScript
|
|
// commands that are used to perform actions on the controller. This function accepts an array but we can give it a single
|
|
// value by passing it by-reference and hardcoding the array length to "1".
|
|
// You can also enable multiple axes at once.
|
|
//
|
|
// If an error occurs while executing a command, like if the controller is not started or an axis fault
|
|
// has occurred, the error can be accessed via functionality provided in the Automation1Error.h header file.
|
|
// See the function printError() for more information.
|
|
if (!Automation1_Command_Enable(controller, 1, &axis, 1))
|
|
{
|
|
printError();
|
|
return;
|
|
}
|
|
|
|
printf("Axis %d enabled\n", axis);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Disables an axis.
|
|
/// </summary>
|
|
/// <param name="axis">The index of the axis to disable.</param>
|
|
void disableAxis(int32_t axis)
|
|
{
|
|
// Make sure we are connected before trying to do anything.
|
|
if (!controller)
|
|
{
|
|
printf("You must connect to the controller before disabling an axis\n");
|
|
return;
|
|
}
|
|
|
|
// We can disable an axis using the Automation1_Command_Disable(controller, axes, axesLength) function
|
|
// in the Automation1Command.h header. The Automation1Command.h header provides access to many of the AeroScript
|
|
// commands that are used to perform actions on the controller. This function accepts arrays but we can give it a single
|
|
// value by passing it by-reference and hardcoding the array length to "1".
|
|
// You can also disable multiple axes at once.
|
|
//
|
|
// If an error occurs while executing a command, like if the controller is not started or an axis fault
|
|
// has occurred, the error can be accessed via functionality provided in the Automation1Error.h header file.
|
|
// See the function printError() for more information.
|
|
if (!Automation1_Command_Disable(controller, &axis, 1))
|
|
{
|
|
printError();
|
|
return;
|
|
}
|
|
|
|
printf("Axis %d disabled\n", axis);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Homes an axis.
|
|
/// </summary>
|
|
/// <param name="axis">The index of the axis to home.</param>
|
|
void homeAxis(int32_t axis)
|
|
{
|
|
// Make sure we are connected before trying to do anything.
|
|
if (!controller)
|
|
{
|
|
printf("You must connect to the controller before homing an axis\n");
|
|
return;
|
|
}
|
|
|
|
// We can home an axis using the Automation1_Command_Home(controller, taskIndex, axes, axesLength) function
|
|
// in the Automation1Command.h header. The Automation1Command.h header provides access to many of the AeroScript
|
|
// commands that are used to perform actions on the controller. This function accepts an array but we can give it a single
|
|
// value by passing it by-reference and hardcoding the array length to "1".
|
|
// You can also home multiple axes at once.
|
|
//
|
|
// If an error occurs while executing a command, like if the controller is not started or an axis fault
|
|
// has occurred, the error can be accessed via functionality provided in the Automation1Error.h header file.
|
|
// See the function printError() for more information.
|
|
if (!Automation1_Command_Home(controller, 1, &axis, 1))
|
|
{
|
|
printError();
|
|
return;
|
|
}
|
|
|
|
printf("Axis %d homed\n", axis);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Aborts motion on an axis.
|
|
/// </summary>
|
|
/// <param name="axis">The index of the axis to abort motion on.</param>
|
|
void abortAxis(int32_t axis)
|
|
{
|
|
// Make sure we are connected before trying to do anything.
|
|
if (!controller)
|
|
{
|
|
printf("You must connect to the controller before aborting\n");
|
|
return;
|
|
}
|
|
|
|
// We can abort motion on an axis using theAutomation1_Command_Abort(controller, axes, axesLength) function
|
|
// in the Automation1Command.h header. The Automation1Command.h header provides access to many of the AeroScript
|
|
// commands that are used to perform actions on the controller. This function accepts an array but we can give it a single
|
|
// value by passing it by-reference and hardcoding the array length to "1".
|
|
// You can also abort multiple axes at once.
|
|
//
|
|
// If an error occurs while executing a command, like if the controller is not started or an axis fault
|
|
// has occurred, the error can be accessed via functionality provided in the Automation1Error.h header file.
|
|
// See the function printError() for more information.
|
|
if (!Automation1_Command_Abort(controller, &axis, 1))
|
|
{
|
|
printError();
|
|
return;
|
|
}
|
|
|
|
printf("Motion aborted on axis %d\n", axis);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets common and important informaiton about an axis.
|
|
/// </summary>
|
|
/// <param name="axis">The index of the axis to get information about.</param>
|
|
void showAxisStatus(int32_t axis)
|
|
{
|
|
Automation1StatusConfig statusConfig;
|
|
double result[3];
|
|
bool isEnabled;
|
|
bool isHomed;
|
|
bool calibrationEnabled1D;
|
|
bool calibrationEnabled2D;
|
|
|
|
// Make sure we are connected before trying to do anything.
|
|
if (!controller)
|
|
{
|
|
printf("You must connect to the controller before getting an axis's status.\n");
|
|
return;
|
|
}
|
|
|
|
// We can get information about the current state of the controller, tasks, and axes via status items. To do so, we must first
|
|
// specify the items we want to query by creating an Automation1StatusConfig struct. We then add each status item to the axis
|
|
// category using the Automation1_StatusConfig_AddAxisStatusItem(statusConfig, axis, axisStatusItem, argument) function. To
|
|
// actually get the values of these items, we call GetStatusItem(statusConfig), which populates an array of doubles with the
|
|
// requested values.
|
|
Automation1_StatusConfig_Create(&statusConfig);
|
|
// Status items are defined in enums in the C API. ProgramPosition is the position specified in program-space, before being
|
|
// transformed and sent to the drive. See the Controller Motion Signals help file topic for more details.
|
|
Automation1_StatusConfig_AddAxisStatusItem(statusConfig, axis, Automation1AxisStatusItem_ProgramPositionFeedback, 0);
|
|
// DriveStatus is a series of bits that can be masked. We will use it to get the axis enabled bit.
|
|
Automation1_StatusConfig_AddAxisStatusItem(statusConfig, axis, Automation1AxisStatusItem_DriveStatus, 0);
|
|
// AxisStatus is another series of bits that can be masked. We will use it to get the axis homed bit, calibration enabled 1D bit,
|
|
// and calibration enabled 2D bit. In this case, homed indicates whether or not the axis in question has been homed since the last
|
|
// controller reset. The calibration bits indicate if the axis is currently calibrated.
|
|
Automation1_StatusConfig_AddAxisStatusItem(statusConfig, axis, Automation1AxisStatusItem_AxisStatus, 0);
|
|
// If we fail to get all status items, we should not use the results. Instead we should free up the memory used by the statusConfig
|
|
// and return.
|
|
if (!Automation1_Status_GetResults(controller, statusConfig, result, 3))
|
|
{
|
|
printf("Failed to get axis %d status\n", axis);
|
|
printError();
|
|
Automation1_StatusConfig_Destroy(statusConfig);
|
|
return;
|
|
}
|
|
|
|
printf("Axis %d Status\n", axis);
|
|
printf("--------------\n");
|
|
|
|
// ProgramPosition is acquired directly as a double, which is what we need.
|
|
printf("Position: %lf\n", result[0]);
|
|
|
|
// DriveStatus is a series of status bits that can be masked to get various information about the state of the drive.
|
|
// It is acquired as a double, but we need to interperet it as a series of maskable bits. To do so, we cast it to
|
|
// a 64-bit integer. We next apply the "Enabled" mask from the enum and check if the result equals the mask to
|
|
// determine if the drive axis is enabled.
|
|
isEnabled = (Automation1DriveStatus_Enabled & (int64_t)result[1]) == Automation1DriveStatus_Enabled;
|
|
printf("Enabled: %s\n", isEnabled ? "true" : "false");
|
|
|
|
// AxisStatus is similar to DriveStatus in that it can be masked to get information about the state of the axis.
|
|
// It is also acquired as a double, but we again need to interperet it as a series of maskable bits. To do so, we repeat
|
|
// the process outlined for DriveStatus with AxisStatus.
|
|
isHomed = (Automation1AxisStatus_Homed & (int64_t)result[2]) == Automation1AxisStatus_Homed;
|
|
printf("Homed: %s\n", isHomed ? "true" : "false");
|
|
|
|
// AxisStatus also contains status bits relating to the calibration state of the axis. To get these, we simply need to
|
|
// apply different masks and "or" the results.
|
|
calibrationEnabled1D = (Automation1AxisStatus_CalibrationEnabled1D & (int64_t)result[2]) == Automation1AxisStatus_CalibrationEnabled1D;
|
|
calibrationEnabled2D = (Automation1AxisStatus_CalibrationEnabled2D & (int64_t)result[2]) == Automation1AxisStatus_CalibrationEnabled2D;
|
|
printf("Calibration State: %s\n", (calibrationEnabled1D || calibrationEnabled2D) ? "true" : "false");
|
|
|
|
// Destorying the statusConfig frees up any memory associated with it.
|
|
Automation1_StatusConfig_Destroy(statusConfig);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Executes a linear move on an axis.
|
|
/// </summary>
|
|
/// <param name="axis">The index of the axis to move.</param>
|
|
/// <param name="distance">The distance to move the axis.</param>
|
|
/// <param name="speed">The speed at which to move the axis.</param>
|
|
void moveAxisLinear(int32_t axis, double distance, double speed)
|
|
{
|
|
// Make sure we are connected before trying to do anything.
|
|
if (!controller)
|
|
{
|
|
printf("You must connect to the controller before moving an axis\n");
|
|
return;
|
|
}
|
|
|
|
// The Automation1_Command_MoveLinear(controller, taskIndex, axes, axesLength, distances, distancesLength, speed)
|
|
// function will not return until the move is complete. This function accepts arrays but we can give it a single
|
|
// value by passing it by-reference and hardcoding the array length to "1".
|
|
// You can also move multiple axes at once.
|
|
//
|
|
// We can keep this application responsive during the move if we do the move on a background thread.
|
|
// You should be familiar with multi-threaded programming before doing this.
|
|
printf("Moving axis %d\n", axis);
|
|
if (!Automation1_Command_MoveLinear(controller, 1, &axis, 1, &distance, 1, speed))
|
|
{
|
|
printError();
|
|
return;
|
|
}
|
|
|
|
printf("Move complete\n");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Runs an AeroScript program on the Automation1 controller.
|
|
/// </summary>
|
|
/// <param name="aeroscriptProgramPath">The path to the .ascript file to run.</param>
|
|
void runProgram(const char* aeroscriptProgramPath)
|
|
{
|
|
// Make sure we are connected before trying to do anything.
|
|
if (!controller)
|
|
{
|
|
printf("You must connect to the controller before running an AeroScript program\n");
|
|
return;
|
|
}
|
|
|
|
// When we call Automation1_Task_ProgramRun(controller, taskIndex, aeroscriptProgramPath), it will
|
|
// load the program on the controller task and begin execution, but it will not wait for the program
|
|
// to complete before returning. The AeroScript source file will be compiled before running. If there
|
|
// is a compile error, this function will return false and the error can be acquired via the functionality
|
|
// provided via the Automation1Error.h header (see printError() in this file for more details). We can use
|
|
// the functionality from the Automation1Task.h header to check on the status of our program as it runs,
|
|
// and to find out when it completes.
|
|
printf("Starting AeroScript program\n");
|
|
if (!Automation1_Task_ProgramRun(controller, 1, aeroscriptProgramPath))
|
|
{
|
|
printError();
|
|
return;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Shows the status of the currently running AeroScript program.
|
|
/// </summary>
|
|
void showProgramStatus()
|
|
{
|
|
Automation1TaskStatus taskStatus[2];
|
|
|
|
// Make sure we are connected before trying to do anything.
|
|
if (!controller)
|
|
{
|
|
printf("You must connect to the controller before getting an AeroScript program's status\n");
|
|
return;
|
|
}
|
|
|
|
// We can check the state of the task we are running the AeroScript program on (Task 1 in this example)
|
|
// to find out the status of our running AeroScript program. We can check this task state regularly
|
|
// to track our AeroScript program if it runs, make sure no errors occur, etc.
|
|
// Calling Automation1_Task_GetStatus(controller, taskStatus, taskStatusLength) gets a moment in time for
|
|
// the first taskStatusLength number of tasks on the controller. To get new status you must access the
|
|
// Status property again.
|
|
if (!Automation1_Task_GetStatus(controller, taskStatus, 2))
|
|
{
|
|
printError();
|
|
return;
|
|
}
|
|
switch (taskStatus[1].TaskState)
|
|
{
|
|
case Automation1TaskState_Error:
|
|
printf("An AeroScript error occurred: %s\n", taskStatus[1].ErrorMessage);
|
|
break;
|
|
case Automation1TaskState_Idle:
|
|
printf("No AeroScript program is loaded or running\n");
|
|
break;
|
|
case Automation1TaskState_ProgramReady:
|
|
printf("The AeroScript program has not started yet\n");
|
|
break;
|
|
case Automation1TaskState_ProgramRunning:
|
|
printf("The AeroScript program is running\n");
|
|
break;
|
|
case Automation1TaskState_ProgramPaused:
|
|
printf("The AeroScript program is paused\n");
|
|
break;
|
|
case Automation1TaskState_ProgramComplete:
|
|
printf("The AeroScript program has completed\n");
|
|
break;
|
|
// We should not encounter these task states in this example program.
|
|
case Automation1TaskState_ProgramFeedhold:
|
|
case Automation1TaskState_Inactive:
|
|
case Automation1TaskState_Unavailable:
|
|
case Automation1TaskState_QueueRunning:
|
|
case Automation1TaskState_QueuePaused:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Stops the currently running AeroScript program.
|
|
/// </summary>
|
|
void stopProgram()
|
|
{
|
|
// Make sure we are connected before trying to do anything.
|
|
if (!controller)
|
|
{
|
|
printf("You must connect to the controller before stopping a program\n");
|
|
return;
|
|
}
|
|
|
|
// To stop a running AeroScript program, we stop the controller task it is running on (Task 1 in this example)
|
|
// The call to Automation1_Task_ProgramStop(controller, taskIndex, millisecondTimeout) will terminate the
|
|
// program and wait for it to stop (or for the timeout to trigger) before returning.
|
|
if (!Automation1_Task_ProgramStop(controller, 1, 500))
|
|
{
|
|
printError();
|
|
return;
|
|
}
|
|
|
|
printf("Program stopped\n");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets a value from the global integer array variable.
|
|
/// </summary>
|
|
/// <param name="index">The index of the integer to get.</param>
|
|
void getGlobalInteger(int32_t index)
|
|
{
|
|
int64_t integerOut = 0;
|
|
|
|
// Make sure we are connected before trying to do anything.
|
|
if (!controller)
|
|
{
|
|
printf("You must connect to the controller before setting a global integer\n");
|
|
return;
|
|
}
|
|
|
|
// The controller has a set of global variable arrays that are accessible from every task on the controller and from every API.
|
|
// These variables can be used to communicate data between tasks or between the controller and a custom application.
|
|
// There are three global arrays for each data type: AeroScript integer values ($iglobal), AeroScript real values ($rglobal), and
|
|
// and AeroScript string values ($sglobal).
|
|
//
|
|
// To get a global integer value, we use the Variables functions to return a single, specific global integer index.
|
|
// This function accepts an array but we can give it a single value by passing it by-reference and hardcoding the array length to "1".
|
|
// You can also get multiple global variables at once.
|
|
if (!Automation1_Variables_GetGlobalIntegers(controller, index, &integerOut, 1))
|
|
{
|
|
printError();
|
|
return;
|
|
}
|
|
|
|
printf("$iglobal[%d] is %lld\n", index, integerOut);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets a value of an index of the global integer array variable.
|
|
/// </summary>
|
|
/// <param name="index">The index of the integer to set.</param>
|
|
/// <param name="newValue">The new value of the integer.</param>
|
|
void setGlobalInteger(int32_t index, int64_t newValue)
|
|
{
|
|
// Make sure we are connected before trying to do anything.
|
|
if (!controller)
|
|
{
|
|
printf("You must connect to the controller before setting a global integer\n");
|
|
return;
|
|
}
|
|
|
|
// The controller has a set of global variable arrays that are accessible from every task on the controller and from every API.
|
|
// These variables can be used to communicate data between tasks or between the controller and a custom application.
|
|
// There are three global arrays for each data type: AeroScript integer values ($iglobal), AeroScript real values ($rglobal), and
|
|
// and AeroScript string values ($sglobal).
|
|
//
|
|
// To change a global integer value, we use the Variables functions to set a single, specific global integer index.
|
|
// This function accepts an array but we can give it a single value by passing it by-reference and hardcoding the array length to "1".
|
|
// You can also set multiple global variables at once.
|
|
if (!Automation1_Variables_SetGlobalIntegers(controller, index, &newValue, 1))
|
|
{
|
|
printError();
|
|
return;
|
|
}
|
|
|
|
printf("$iglobal[%d] is now set to: %lld\n", index, newValue);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Shows common parameter values for an axis.
|
|
/// </summary>
|
|
/// <param name="axis">The axis to show parameter values for.</param>
|
|
void showAxisParameters(int32_t axis)
|
|
{
|
|
// Controller parameters can be accessed through the Automation1_Parameter_Get* functions. They are divided into three categories:
|
|
// Axis, Task, and System parameters. Parameters are then divided into numeric and string parameters, and each have their own
|
|
// function for getting and setting.
|
|
//
|
|
// The FaultMask, DefaultAxisSpeed, and DefaultAxisRampRate parameters are numeric axis parameters, so we use the
|
|
// Automation1_Parameter_GetAxisValue function to get their values.
|
|
//
|
|
// For a string axis parameter, use the Automation1_Parameter_GetAxisStringValue() function to get its value.
|
|
double axisFaultMask;
|
|
double defaultAxisSpeed;
|
|
double defaultAxisRampRate;
|
|
if (!Automation1_Parameter_GetAxisValue(controller, axis, Automation1AxisParameterId_FaultMask, &axisFaultMask) ||
|
|
!Automation1_Parameter_GetAxisValue(controller, axis, Automation1AxisParameterId_DefaultAxisSpeed, &defaultAxisSpeed) ||
|
|
!Automation1_Parameter_GetAxisValue(controller, axis, Automation1AxisParameterId_DefaultAxisRampRate, &defaultAxisRampRate))
|
|
{
|
|
printError();
|
|
return;
|
|
}
|
|
|
|
// The FaultMask axis parameter is a series of bits that can be masked to get/set the protection status of
|
|
// a specific axis fault. After casting the parameter value to an "int64_t", we can and the result with
|
|
// our desired Automation1AxisFault enum value and compare it to itself to determine if a specified AxisFault
|
|
// bit is enabled.
|
|
bool isMotorTemperatureFaultProtectionEnabled = ((int64_t)axisFaultMask & Automation1AxisFault_MotorTemperatureFault) == Automation1AxisFault_MotorTemperatureFault;
|
|
char* motorTemperatureFaultProtectionStatus = isMotorTemperatureFaultProtectionEnabled ? "Enabled" : "Disabled";
|
|
|
|
printf("Motor Temperature Fault protection: %s\n", motorTemperatureFaultProtectionStatus);
|
|
printf("Default Axis Speed: %f\n", defaultAxisSpeed);
|
|
printf("Default Axis Ramp Rate: %f\n", defaultAxisRampRate);
|
|
|
|
// To set the values of controller parameters, use the Automation1_Parameter_Set* functions to set a numeric
|
|
// or string value for an axis, task, or system parameter.
|
|
// Example:
|
|
//
|
|
// Automation1_Parameter_SetAxisValue(controller, axis, Automation1AxisParameterId_DefaultAxisSpeed, newDefaultAxisSpeed);
|
|
// Automation1_Parameter_SetAxisValue(controller, axis, Automation1AxisParameterId_DefaultAxisRampRate, newDefaultAxisRampRate);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Prints the list of commands available to the user.
|
|
/// </summary>
|
|
void printHelp()
|
|
{
|
|
printf("Available commands:\n");
|
|
printf(" Connect\n");
|
|
printf(" Disconnect\n");
|
|
printf(" Start\n");
|
|
printf(" Stop\n");
|
|
printf(" Enable [Axis Index]\n");
|
|
printf(" Disable [Axis Index]\n");
|
|
printf(" Home [Axis Index]\n");
|
|
printf(" Abort [Axis Index]\n");
|
|
printf(" AxisStatus [Axis Index]\n");
|
|
printf(" MoveLinear [Axis Index] [Distance] [Speed]\n");
|
|
printf(" RunProgram [AeroScript Program Path]\n");
|
|
printf(" ProgramStatus\n");
|
|
printf(" StopProgram\n");
|
|
printf(" GetGlobalInteger [Integer Index]\n");
|
|
printf(" SetGlobalInteger [Integer Index] [New Value]\n");
|
|
printf(" ShowAxisParameters [Axis Index]\n");
|
|
printf(" Quit\n");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the most recent error from the controller and prints it for the user.
|
|
/// </summary>
|
|
void printError()
|
|
{
|
|
// When a function from the C API fails, an error code and message are stored. We can use
|
|
// Automation1_GetLastError() to get the most recent error code from the controller. Note
|
|
// that a subsequent error will overwrite the currently stored code and message.
|
|
int32_t lastError = Automation1_GetLastError();
|
|
|
|
// We can then use Automation1_GetLastErrorMessage(buffer, bufferLength) to populate a char array with
|
|
// the error message.
|
|
char lastErrorMessage[2048];
|
|
Automation1_GetLastErrorMessage(lastErrorMessage, 2048);
|
|
|
|
printf(" error (%d): %s\n", lastError, lastErrorMessage);
|
|
} |