libsting
Step Timing and INformation Gathering Library
|
As its name suggests, libsting was created for two purposes: to limit the temperature rise of actuators by limiting motor steps taken over time, and to accumulate and store lifetime operating information about individual actuators. Of these, only the former functionality has been implemented and tested as of this writing (June 2019). The design and usage are described below.
In summary, libsting is unfinished as of June 2019. Even within its currently reduced scope (thermal management), libsmoco implementation has been limited to the subset of functionality required for smocod in the SCS 2.0 release. This includes the core timing thread and the single actuator operation API call sting_act_move_relative().
libsting was created to address problems noted in practice with actuators used for manipulating HET mirror segments as a part of the Segment Control System (SCS).
The performance of some actuators was found to degrade over time due to overheat events, in which motor coil insulation would fail at various points causing coil windings to short. This would reduce the impedance of the motor, drawing more current and causing such events to be more likely in the future. Due to the poor provision for cooling in the actuator housing design and the lack of temperature sensors in the assembly, a means was needed to limit the temperature rise by implementing a duty cycle – limiting the distance an actuator could travel in a given span of time while not limiting its actual travel speed, as travel at full speed provides higher efficiency and lower power consumption.
By observing temperature rise in the actuator at its normal operating speed, it is possible to represent the thermal dissipation characteristic of the actuator housing at a selected safe maximum operating temperature, in terms of a fraction of that speed, or duty cycle percentage. In terms of the actuators used for SCS, the operating speed is 6000 steps per second, and through rough calculations adjusted after testing, an average speed of 2500 steps per second was identified as a speed at which thermal equilibrium could be achieved at a safe temperature, less than 50F above ambient. The library operates a background timing thread that provides commands to motors on behalf of the calling application, to move and pause as needed to maintain the average speed configured in the library initialization.
The library has been tested not only for its correct operation, but also in its ability to successfully limit temperature rise of SCS's Diamond Motion actuators during extended operation.
The second planned purpose for libsting was as a central collection point for the operating history of motors and actuator assemblies in SCS, for the purposes of planned maintenance, inspection and overhaul. To this end the library would provide a registration step for actuators which would include hardware information such as barcodes or other identifying details which could be configured as a part of segment swaps and segment frame setups. In this way, actuator assemblies could be tracked throughout their history regardless of their location in the primary mirror array, and an "age" in terms of lifetime step count could be accumulated for each actuator in a database.
Especially given the significantly different SAMS-driven movement behavior of segments at the outer edges of the array compared to those at the center, this tracking could be very useful in determining and comparing the impacts of movement step and accel/decel cycle counts on motor performance over time.
These information gathering features have not been implemented in libsting, though opportunities may be presented in the future to add them.
The development of libsting as a separate library stems from the design goals of libsmoco, as it was spun off from the creation of smocod. libsmoco was intended as a library providing the specific command set of the SMOCO hardware and its CAN protocol in the form of a C API. This implies a direct one-to-one mapping of commands exposed by libsmoco to those command identifiers utilized by SMOCO firmware.
The needed movement step timing functionality, in contrast, requires an abstracted command set in which generalized movement commands can result in possibly several low-level commands sent to the controller hardware. For this reason, the routines were placed in their own library with its own API.
While it might be reasonable to implement this set of routines as a layer above libsmoco such that libsting makes direct use of libsmoco to do its work, libsting was instead designed to be hardware-agnostic, a final decision that led to the architecture of libsting as it currently exists. As a result, an application can use libsmoco (or any other motor control code) to control stepper motors, and separately can use libsting to track motors and limit movement and temperature rise. Put another way, an application's dependency on libsting does not imply a dependency or a use of any particular motor control library or system.
When writing an application to use libsting, keep a key premise in mind: libsting does not know how to control actuators. It only knows when to control actuators.
The above statement is significant in its details. Taking its use with SMOCO and SCS as an example, the sentences above make no mention of mirror segments or SMOCO nodes; nothing about locations in the primary mirror, axes, I, J and K positions or three actuators per SMOCO controller. libsting knows nothing about these – only about individual actuators, about which it maintains a simple list provided by registrations from the calling application. (In future enhancements, this list may be persisted in a database.) This has two fundamental implications to the design of an application using libsting.
So the application must maintain some association to libsting's actuator resources, either by storing the STING_ACT handle with its own internal actuator data, or by giving libsting the pointer to such data, or both.
In the call to sting_init(), three values are submitted, which determine libsting's movement-limiting behavior. These parameters are documented in the reference material, but we'll cover the practical selection of these values in more detail here:
It is recommended to supply these parameters from a configuration file or other resource, such that they can be updated if environmental changes require it.
#include "mydefs.h" #include <motorctrl_lib.h> typedef struct actuator { uint32_t motor_hwid; uint16_t controller_hwid; uint32_t actuator_assy_barcode; //... STING_ACT st_act; } my_actuator_t; /* Callback function, for performing hardware operations as required by libsting */ STING_OPERATION_RESULT my_sting_op(st_cb_operation_t *p_op, void *p_data) { /* Get our actuator data */ my_actuator_t *p_act = (my_actuator_t *)p_data; switch(p_op->optype) { case ST_OPTYPE_MVUP: mtrctl_movemotor(p_act->motor_hwid, p_act->controller_hwid, p_op->value); break; case ST_OPTYPE_MVDN: mtrctl_movemotor(p_act->motor_hwid, p_act->controller_hwid, p_op->value * -1); break; case ST_OPTYPE_MVABS: mtrctl_movemotor(p_act->motor_hwid, p_act->controller_hwid, p_op->value - mtrctl_get_position(p_act->motor_hwid, p_act->controller_hwid)); case ST_OPTYPE_GETPOS: p_op->value = mtrctl_get_position(p_act->motor_hwid, p_act->controller_hwid); break; case ST_OPTYPE_SETPOS: mtrctl_set_position(p_act->motor_hwid, p_act->controller_hwid, p_op->value); break; case ST_OPTYPE_FINDLIMIT: switch(p_op->fl_type) { case STFLT_UPPER: /* Move to upper travel limit */ //... break; case STFLT_LOWER: /* Move to lower travel limit */ //... break; case STFLT_HOME: /* Home the stepper/actuator */ //... break; } break; } /* No error handling in this example */ return ST_OPRES_SUCCESS; } int main(int argc, char *argv[]) { STING_CTX stctx = sting_init(my_sting_op, MAX_MOVE, MIN_MOVE, AVGSPEED); /* Initialize motor control system */ //... /* Set up our actuator resource */ my_actuator_t act1; act1.hwid = 100; //... /* Register the actuator with libsting session, and save the STING_ACT value */ act1.st_act = sting_act_register(stctx, (void *)&act1); /* Get motor's current position from motor control API (support not yet available in libsting), home motion axes, etc */ //... /* Move motor 1000 steps, using libsting */ sting_act_move_relative(stctx, act1.st_act, 1000); /* Move it back */ sting_act_move_relative(stctx, act1.st_act, -1000); /* Terminate libsting session */ sting_terminate(stctx); return 0; }
This simplified example uses a hypothetical motor control API, and leaves out a lot of detail.