Files
smargopolo/c_algorithms/Automation1/ConsoleExample.c
2025-10-27 14:21:06 +01:00

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);
}