100#include "ClearCore.h"
105#define ioPort ConnectorUsb
107#define ioPortBaudRate 115200
111#define ioFlowControl false
114struct FeedbackMessage{
120#define FB_COMMAND_OK ( 0)
121#define FB_ERR_BUFFER_OVERRUN ( 1)
122#define FB_ERR_INPUT_INVALID_NONLETTER ( 2)
123#define FB_ERR_MOTOR_NUM_INVALID ( 3)
124#define FB_ERR_CONNECTOR_NUM_INVALID ( 4)
125#define FB_ERR_CONNECTOR_MODE_INCOMPATIBLE ( 5)
126#define FB_ENABLED_WAITING_ON_HLFB ( 6)
127#define FB_ENABLE_FAILURE ( 7)
128#define FB_ERR_IO_OUTPUT ( 8)
129#define FB_ERR_MOVE_NOT_ENABLED ( 9)
130#define FB_ERR_MOVE_IN_ALERT (10)
131#define FB_ERR_INVALID_QUERY_REQUEST (11)
132#define FB_ERR_LIMIT_OUT_OF_BOUNDS (12)
133#define FB_ERR_INVALID_LIMIT_REQUEST (13)
134#define FB_ERR_INVALID_FEEDBACK_OPTION (14)
135#define FB_ERR_UNRECOGNIZED_COMMAND (15)
139char *msg_command_ok =
141char *msg_err_buffer_overrun =
142 "Error: input buffer overrun.";
143char *msg_err_input_invalid_nonletter =
144 "Error: invalid input. Commands begin with a single letter character.";
145char *msg_err_motor_num_invalid =
146 "Error: a required motor was not specified or specified incorrectly. Acceptable motor numbers are 0, 1, 2, and 3.";
147char *msg_err_connector_num_invalid =
148 "Error: a required connector was not specified or specified incorrectly. Acceptable connector numbers are 0 through 12, inclusive.";
149char *msg_err_io_output =
150 "Error: an I/O output parameter is invalid. Ensure the output value is appropriate for the type of output pin.";
151char *msg_err_connector_mode_incompatible =
152 "Error: a specified connector is of an inappropriate mode. Verify the I/O connector is configured as necessary.";
153char *msg_enabled_waiting_on_hlfb =
154 "Motor enabled; waiting on HLFB to assert before accepting other commands.";
155char *msg_enable_failure =
156 "Motor failed to enable due to motor fault, loss of power, or loss/absence of connection. Motor disabled.";
157char *msg_err_move_not_enabled =
158 "Error: motion commanded while motor not enabled. Command e# to enable motor number #.";
159char *msg_err_move_in_alert =
160 "Error: motion commanded while motor in fault. Command c# to clear alerts on motor number #.";
161char *msg_err_invalid_query_request =
162 "Error: invalid query request. Command h for more information.";
163char *msg_err_limit_out_of_bounds =
164 "Error: commanded limit falls outside the acceptable bounds for this limit.";
165char *msg_err_invalid_limit_request =
166 "Error: invalid limit request. Command h for more information.";
167char *msg_err_invalid_feedback_option =
168 "Error: invalid feedback request. Command h for more information.";
169char *msg_err_unrecognized_command =
170 "Error: unrecognized command. Command h for more information.";
172 "ClearCore Command Protocol\n"
173 "Acceptable commands, where # specifies a motor number* (0, 1, 2, or 3): \n"
174 " e# | enable specified motor\n"
175 " d# | disable specified motor\n"
176 " m# distance | if(ABSOLUTE_MOVE==1) move to the specified position\n"
177 " if(ABSOLUTE_MOVE==0) move the specified number of steps\n"
178 " v# velocity | move at the specified velocity (steps/s)\n"
179 " q#<p/v/s> | query specified motor's position/velocity/status\n"
180 " l#<v/a> limit | set specified motor's velocity/acceleration limit\n"
181 " c# | clear alerts\n"
182 " z# | set the zero position for motor # to the current commanded position\n"
183 " i# | read input on pin #\n"
184 " Digital pins return 1 or 0; analog pins return [0,4095] corresponding to [0,10]V\n"
185 " (*note that # for this command can be 0 through 5)\n"
186 " o# outputVal | write output on pin #\n"
187 " Digital pins allow 1 or 0; analog pins allow [409,2047] corresponding to [4,20]mA\n"
188 " (*note that # for this command can be 0 through 12)\n"
189 " f fdbkType | specify the type of feedback printed:\n"
190 " 0 : send message number only\n"
191 " 1 : send verbose message\n"
192 " h | print this help message\n";
195FeedbackMessage FeedbackMessages[17] = {
196 {FB_COMMAND_OK , msg_command_ok },
197 {FB_ERR_BUFFER_OVERRUN , msg_err_buffer_overrun },
198 {FB_ERR_INPUT_INVALID_NONLETTER , msg_err_input_invalid_nonletter },
199 {FB_ERR_MOTOR_NUM_INVALID , msg_err_motor_num_invalid },
200 {FB_ERR_CONNECTOR_NUM_INVALID , msg_err_connector_num_invalid },
201 {FB_ERR_CONNECTOR_MODE_INCOMPATIBLE,
202 msg_err_connector_mode_incompatible },
203 {FB_ENABLED_WAITING_ON_HLFB , msg_enabled_waiting_on_hlfb },
204 {FB_ENABLE_FAILURE , msg_enable_failure },
205 {FB_ERR_IO_OUTPUT , msg_err_io_output },
206 {FB_ERR_MOVE_NOT_ENABLED , msg_err_move_not_enabled },
207 {FB_ERR_MOVE_IN_ALERT , msg_err_move_in_alert },
208 {FB_ERR_INVALID_QUERY_REQUEST , msg_err_invalid_query_request },
209 {FB_ERR_LIMIT_OUT_OF_BOUNDS , msg_err_limit_out_of_bounds },
210 {FB_ERR_INVALID_LIMIT_REQUEST , msg_err_invalid_limit_request },
211 {FB_ERR_INVALID_FEEDBACK_OPTION , msg_err_invalid_feedback_option },
212 {FB_ERR_UNRECOGNIZED_COMMAND , msg_err_unrecognized_command },
213 {FB_HELP , msg_help }
217bool verboseFeedback =
true;
221#define ABSOLUTE_MOVE (1)
226#define IN_BUFFER_LEN 32
227char input[IN_BUFFER_LEN+1];
235Connector *
const connectors[13] = {
243#define DEFAULT_ACCEL_LIMIT (100000)
244#define MAX_ACCEL_LIMIT (1000000000)
245#define MIN_ACCEL_LIMIT (1)
246#define DEFAULT_VEL_LIMIT (10000)
247#define MAX_VEL_LIMIT (500000)
248#define MIN_VEL_LIMIT (1)
252void SendFeedback(int32_t messageNumber);
253void SendVerboseStatus(int32_t motorNumber);
259 ioPort.Mode(Connector::USB_CDC);
260 ioPort.Speed(ioPortBaudRate);
277 DEFAULT_ACCEL_LIMIT, DEFAULT_ACCEL_LIMIT, DEFAULT_ACCEL_LIMIT, DEFAULT_ACCEL_LIMIT
280 DEFAULT_VEL_LIMIT, DEFAULT_VEL_LIMIT, DEFAULT_VEL_LIMIT, DEFAULT_VEL_LIMIT
289 motors[i]->HlfbMode(MotorDriver::HLFB_MODE_HAS_BIPOLAR_PWM);
290 motors[i]->HlfbCarrier(MotorDriver::HLFB_CARRIER_482_HZ);
291 motors[i]->VelMax(velocityLimits[i]);
292 motors[i]->AccelMax(accelerationLimits[i]);
316 bool connectorNumValid;
317 bool motorEnabledBeforeClearingAlerts;
321 int32_t connectorNum_in;
322 int32_t moveDistance_in;
325 int32_t queriedValue;
326 int16_t inputConnectorValue;
327 int16_t outputConnectorValue_in;
329 ioPort.SendLine(
"Setup successful");
330 ioPort.SendLine(
"Send 'h' to receive a list of valid commands");
336 for (i = 0; i<IN_BUFFER_LEN+1; i++){
337 input[i] = (char) NULL;
345 while(i<IN_BUFFER_LEN && ioPort.CharPeek() != -1){
346 input[i] = (char) ioPort.CharGet();
359 if(verboseFeedback && i!=0){
360 ioPort.SendLine(input);
366 }
else if (ioPort.CharPeek()!=-1){
369 SendFeedback(FB_ERR_BUFFER_OVERRUN);
371 while(ioPort.CharPeek()!=-1){
379 if ((
'A' <= input[0] && input[0] <=
'Z') || (
'a' <= input[0] && input[0] <=
'z')){
381 if (
'A' <= input[0] && input[0] <=
'Z'){
387 SendFeedback(FB_ERR_INPUT_INVALID_NONLETTER);
396 motorNum_in = atoi(&input[1]);
397 motorNumValid = (0<=motorNum_in && motorNum_in<=3 && input[1]!=NULL);
400 connectorNum_in = atoi(&input[1]);
401 connectorNumValid = (0<=connectorNum_in && connectorNum_in<=12 && input[1]!=NULL);
404 volatile const MotorDriver::StatusRegMotor &statusReg = motors[motorNum_in]->StatusReg();
405 volatile const MotorDriver::AlertRegMotor &alertReg = motors[motorNum_in]->AlertReg();
415 SendFeedback(FB_ERR_MOTOR_NUM_INVALID);
418 motors[motorNum_in]->EnableRequest(
true);
419 SendFeedback(FB_ENABLED_WAITING_ON_HLFB);
423 while (statusReg.bit.HlfbState != MotorDriver::HLFB_ASSERTED &&
424 !statusReg.bit.MotorInFault){
427 if(statusReg.bit.MotorInFault){
429 motors[motorNum_in]->EnableRequest(
false);
430 SendFeedback(FB_ENABLE_FAILURE);
432 SendFeedback(FB_COMMAND_OK);
441 SendFeedback(FB_ERR_MOTOR_NUM_INVALID);
444 motors[motorNum_in]->EnableRequest(
false);
445 SendFeedback(FB_COMMAND_OK);
453 SendFeedback(FB_ERR_MOTOR_NUM_INVALID);
454 }
else if ( statusReg.bit.ReadyState==MotorDriver::MOTOR_DISABLED ||
455 statusReg.bit.ReadyState==MotorDriver::MOTOR_ENABLING){
456 SendFeedback(FB_ERR_MOVE_NOT_ENABLED);
457 }
else if (motors[motorNum_in]->StatusReg().bit.AlertsPresent) {
458 SendFeedback(FB_ERR_MOVE_IN_ALERT);
465 moveDistance_in = atoi(&input[2]);
467 motors[motorNum_in]->Move(moveDistance_in, MotorDriver::MOVE_TARGET_ABSOLUTE);
469 motors[motorNum_in]->Move(moveDistance_in);
471 SendFeedback(FB_COMMAND_OK);
479 SendFeedback(FB_ERR_MOTOR_NUM_INVALID);
480 }
else if ( statusReg.bit.ReadyState==MotorDriver::MOTOR_DISABLED ||
481 statusReg.bit.ReadyState==MotorDriver::MOTOR_ENABLING){
482 SendFeedback(FB_ERR_MOVE_NOT_ENABLED);
483 }
else if (motors[motorNum_in]->StatusReg().bit.AlertsPresent) {
484 SendFeedback(FB_ERR_MOVE_IN_ALERT);
487 velocity_in = atoi(&input[2]);
488 motors[motorNum_in]->MoveVelocity(velocity_in);
489 SendFeedback(FB_COMMAND_OK);
497 SendFeedback(FB_ERR_MOTOR_NUM_INVALID);
507 queriedValue = (int32_t) motors[motorNum_in]->PositionRefCommanded();
508 if (verboseFeedback){
509 ioPort.Send(
"Motor ");
510 ioPort.Send(motorNum_in);
511 ioPort.Send(
" is in position (steps) ");
513 ioPort.SendLine(queriedValue);
520 queriedValue = motors[motorNum_in]->VelocityRefCommanded();
521 if (verboseFeedback){
522 ioPort.Send(
"Motor ");
523 ioPort.Send(motorNum_in);
524 ioPort.Send(
" is at velocity (steps/s) ");
526 ioPort.SendLine(queriedValue);
533 if (verboseFeedback){
534 SendVerboseStatus(motorNum_in);
536 ioPort.SendLine(statusReg.reg, 2);
537 if (statusReg.bit.AlertsPresent){
538 ioPort.SendLine(alertReg.reg, 2);
545 SendFeedback(FB_ERR_INVALID_QUERY_REQUEST);
552 if ( !motorNumValid){
553 SendFeedback(FB_ERR_MOTOR_NUM_INVALID);
557 limit_in = atoi(&input[3]);
564 if (MIN_VEL_LIMIT<=limit_in && limit_in<=MAX_VEL_LIMIT){
565 velocityLimits[motorNum_in] = limit_in;
566 motors[motorNum_in]->VelMax(velocityLimits[motorNum_in]);
567 SendFeedback(FB_COMMAND_OK);
569 SendFeedback(FB_ERR_LIMIT_OUT_OF_BOUNDS);
577 if (MIN_ACCEL_LIMIT<=limit_in && limit_in<=MAX_ACCEL_LIMIT){
578 accelerationLimits[motorNum_in] = limit_in;
579 motors[motorNum_in]->AccelMax(velocityLimits[motorNum_in]);
580 SendFeedback(FB_COMMAND_OK);
582 SendFeedback(FB_ERR_LIMIT_OUT_OF_BOUNDS);
588 SendFeedback(FB_ERR_INVALID_LIMIT_REQUEST);
597 SendFeedback(FB_ERR_MOTOR_NUM_INVALID);
603 motorEnabledBeforeClearingAlerts = motors[motorNum_in]->EnableRequest();
609 if (statusReg.bit.MotorInFault){
610 motors[motorNum_in]->EnableRequest(
false);
612 if(motorEnabledBeforeClearingAlerts){
613 motors[motorNum_in]->EnableRequest(
true);
616 motors[motorNum_in]->ClearAlerts();
617 SendFeedback(FB_COMMAND_OK);
624 SendFeedback(FB_ERR_MOTOR_NUM_INVALID);
628 motors[motorNum_in]->PositionRefSet(0);
629 SendFeedback(FB_COMMAND_OK);
635 if (!connectorNumValid){
636 SendFeedback(FB_ERR_CONNECTOR_NUM_INVALID);
640 if (connectors[connectorNum_in]->Mode() != Connector::INPUT_DIGITAL &&
641 connectors[connectorNum_in]->Mode() != Connector::INPUT_ANALOG){
642 SendFeedback(FB_ERR_CONNECTOR_MODE_INCOMPATIBLE);
645 inputConnectorValue = connectors[connectorNum_in]->State();
647 ioPort.Send(
"Connector ");
648 ioPort.Send(connectorNum_in);
649 ioPort.Send(
" value: ");
651 ioPort.SendLine(inputConnectorValue);
658 if (!connectorNumValid){
659 SendFeedback(FB_ERR_CONNECTOR_NUM_INVALID);
663 if (connectors[connectorNum_in]->Mode() != Connector::OUTPUT_DIGITAL &&
664 connectors[connectorNum_in]->Mode() != Connector::OUTPUT_ANALOG){
665 SendFeedback(FB_ERR_CONNECTOR_MODE_INCOMPATIBLE);
669 outputConnectorValue_in = atoi(&input[3]);
670 if(!connectors[connectorNum_in]->State(outputConnectorValue_in)){
671 SendFeedback(FB_ERR_IO_OUTPUT);
673 SendFeedback(FB_COMMAND_OK);
680 switch(atoi(&input[1])){
684 verboseFeedback =
false;
685 SendFeedback(FB_COMMAND_OK);
690 verboseFeedback =
true;
691 SendFeedback(FB_COMMAND_OK);
696 SendFeedback(FB_ERR_INVALID_FEEDBACK_OPTION);
703 SendFeedback(FB_HELP);
708 SendFeedback(FB_ERR_UNRECOGNIZED_COMMAND);
728 void SendFeedback(int32_t messageNumber){
730 if (verboseFeedback){
731 ioPort.SendLine(FeedbackMessages[messageNumber].message);
733 ioPort.SendLine(FeedbackMessages[messageNumber].number);
751void SendVerboseStatus(int32_t motorNumber) {
753 volatile const MotorDriver::StatusRegMotor &statusReg = motors[motorNumber]->StatusReg();
754 volatile const MotorDriver::AlertRegMotor &alertReg = motors[motorNumber]->AlertReg();
756 ioPort.Send(
"Motor status register for motor M");
757 ioPort.Send(motorNumber);
759 ioPort.SendLine(statusReg.reg, 2);
761 ioPort.Send(
"AtTargetPosition: ");
762 ioPort.SendLine(statusReg.bit.AtTargetPosition);
764 ioPort.Send(
"StepsActive: ");
765 ioPort.SendLine(statusReg.bit.StepsActive);
767 ioPort.Send(
"AtTargetVelocity: ");
768 ioPort.SendLine(statusReg.bit.AtTargetVelocity);
770 ioPort.Send(
"MoveDirection: ");
771 ioPort.SendLine(statusReg.bit.MoveDirection);
773 ioPort.Send(
"MotorInFault: ");
774 ioPort.SendLine(statusReg.bit.MotorInFault);
776 ioPort.Send(
"Enabled: ");
777 ioPort.SendLine(statusReg.bit.Enabled);
779 ioPort.Send(
"PositionalMove: ");
780 ioPort.SendLine(statusReg.bit.PositionalMove);
782 ioPort.Send(
"HLFB State: ");
783 switch (statusReg.bit.HlfbState) {
785 ioPort.SendLine(
"HLFB_DEASSERTED");
788 ioPort.SendLine(
"HLFB_ASSERTED");
791 ioPort.SendLine(
"HLFB_HAS_MEASUREMENT");
794 ioPort.SendLine(
"HLFB_UNKNOWN");
798 ioPort.SendLine(
"???");
801 ioPort.Send(
"AlertsPresent: ");
802 ioPort.SendLine(statusReg.bit.AlertsPresent);
804 ioPort.Send(
"Ready state: ");
805 switch (statusReg.bit.ReadyState) {
806 case MotorDriver::MOTOR_DISABLED:
807 ioPort.SendLine(
"Disabled");
809 case MotorDriver::MOTOR_ENABLING:
810 ioPort.SendLine(
"Enabling");
812 case MotorDriver::MOTOR_FAULTED:
813 ioPort.SendLine(
"Faulted");
815 case MotorDriver::MOTOR_READY:
816 ioPort.SendLine(
"Ready");
818 case MotorDriver::MOTOR_MOVING:
819 ioPort.SendLine(
"Moving");
823 ioPort.SendLine(
"???");
826 ioPort.Send(
"Triggering: ");
827 ioPort.SendLine(statusReg.bit.Triggering);
829 ioPort.Send(
"InPositiveLimit: ");
830 ioPort.SendLine(statusReg.bit.InPositiveLimit);
832 ioPort.Send(
"InNegativeLimit: ");
833 ioPort.SendLine(statusReg.bit.InNegativeLimit);
835 ioPort.Send(
"InEStopSensor: ");
836 ioPort.SendLine(statusReg.bit.InEStopSensor);
838 ioPort.SendLine(
"--------------------------------");
841 if (statusReg.bit.AlertsPresent){
842 ioPort.Send(
"Alert register: ");
843 ioPort.SendLine(alertReg.reg, 2);
845 ioPort.Send(
"MotionCanceledInAlert: ");
846 ioPort.SendLine(alertReg.bit.MotionCanceledInAlert);
848 ioPort.Send(
"MotionCanceledPositiveLimit: ");
849 ioPort.SendLine(alertReg.bit.MotionCanceledPositiveLimit);
851 ioPort.Send(
"MotionCanceledNegativeLimit: ");
852 ioPort.SendLine(alertReg.bit.MotionCanceledNegativeLimit);
854 ioPort.Send(
"MotionCanceledSensorEStop: ");
855 ioPort.SendLine(alertReg.bit.MotionCanceledSensorEStop);
857 ioPort.Send(
"MotionCanceledMotorDisabled: ");
858 ioPort.SendLine(alertReg.bit.MotionCanceledMotorDisabled);
860 ioPort.Send(
"MotorFaulted: ");
861 ioPort.SendLine(alertReg.bit.MotorFaulted);
863 ioPort.SendLine(
"--------------------------------");
#define MOTOR_CON_CNT
Definition SysConnectors.h:42
void Delay_ms(uint32_t ms)
Blocks operations for ms milliseconds.
Definition SysTiming.h:287
virtual ConnectorModes Mode() override
Get the connector's operational mode.
Definition DigitalInAnalogIn.h:89
virtual ConnectorModes Mode() override
Get the connector's operational mode.
Definition DigitalIn.h:161
virtual ConnectorModes Mode() override
Get the connector's operational mode.
Definition DigitalInOutAnalogOut.h:70
virtual ConnectorModes Mode() override
Get the connector's operational mode.
Definition DigitalInOutHBridge.h:124
virtual ConnectorModes Mode() override
Get the connector's operational mode.
Definition DigitalInOut.h:85
bool MotorInputClocking(MotorClockRates newRate)
Sets the output step rate for the motor step generators.
bool MotorModeSet(MotorPair motorPair, Connector::ConnectorModes newMode)
Sets the operational mode for the specified MotorDriver connectors.
DigitalInAnalogIn ConnectorA10
A-10 connector instance.
DigitalInOutAnalogOut ConnectorIO0
IO-0 connector instance.
DigitalInAnalogIn ConnectorA12
A-12 connector instance.
MotorDriver ConnectorM2
M-2 connector instance.
DigitalIn ConnectorDI6
DI-6 connector instance.
DigitalInOut ConnectorIO3
IO-3 connector instance.
DigitalInAnalogIn ConnectorA9
A-9 connector instance.
DigitalInOut ConnectorIO1
IO-1 connector instance.
MotorDriver ConnectorM0
M-0 connector instance.
DigitalInOutHBridge ConnectorIO4
IO-4 connector instance.
MotorDriver ConnectorM1
M-1 connector instance.
MotorManager & MotorMgr
Motor connector manager.
DigitalInOutHBridge ConnectorIO5
IO-5 connector instance.
MotorDriver ConnectorM3
M-3 connector instance.
DigitalInAnalogIn ConnectorA11
A-11 connector instance.
DigitalInOut ConnectorIO2
IO-2 connector instance.
DigitalIn ConnectorDI7
DI-7 connector instance.
DigitalIn ConnectorDI8
DI-8 connector instance.