#include "_timer.h"
#include "_shm.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdarg.h>
#include <string.h>
#include "posemath.h"
#include "emcpos.h"
#include "emcmotcfg.h"
#include "emcmotglb.h"
#include "emcmot.h"
#include "pid.h"
#include "cubic.h"
#include "tc.h"
#include "tp.h"
#include "extintf.h"
#include "mmxavg.h"
#include "emcmotlog.h"
#include <signal.h>
Include dependency graph for emcstepmot.c:
Go to the source code of this file.
Defines | |
#define | LIMIT_SWITCH_DEBOUNCE 10 |
#define | AMP_FAULT_DEBOUNCE 100 |
#define | diagnostics printf |
#define | GET_MOTION_ERROR_FLAG() (emcmotStatus->motionFlag & EMCMOT_MOTION_ERROR_BIT ? 1 : 0) |
#define | SET_MOTION_ERROR_FLAG(fl) if (fl) emcmotStatus->motionFlag |= EMCMOT_MOTION_ERROR_BIT; else emcmotStatus->motionFlag &= ~EMCMOT_MOTION_ERROR_BIT; |
#define | GET_MOTION_COORD_FLAG() (emcmotStatus->motionFlag & EMCMOT_MOTION_COORD_BIT ? 1 : 0) |
#define | SET_MOTION_COORD_FLAG(fl) if (fl) emcmotStatus->motionFlag |= EMCMOT_MOTION_COORD_BIT; else emcmotStatus->motionFlag &= ~EMCMOT_MOTION_COORD_BIT; |
#define | GET_MOTION_INPOS_FLAG() (emcmotStatus->motionFlag & EMCMOT_MOTION_INPOS_BIT ? 1 : 0) |
#define | SET_MOTION_INPOS_FLAG(fl) if (fl) emcmotStatus->motionFlag |= EMCMOT_MOTION_INPOS_BIT; else emcmotStatus->motionFlag &= ~EMCMOT_MOTION_INPOS_BIT; |
#define | GET_MOTION_ENABLE_FLAG() (emcmotStatus->motionFlag & EMCMOT_MOTION_ENABLE_BIT ? 1 : 0) |
#define | SET_MOTION_ENABLE_FLAG(fl) if (fl) emcmotStatus->motionFlag |= EMCMOT_MOTION_ENABLE_BIT; else emcmotStatus->motionFlag &= ~EMCMOT_MOTION_ENABLE_BIT; |
#define | GET_AXIS_ENABLE_FLAG(ax) (emcmotStatus->axisFlag[ax] & EMCMOT_AXIS_ENABLE_BIT ? 1 : 0) |
#define | SET_AXIS_ENABLE_FLAG(ax, fl) if (fl) emcmotStatus->axisFlag[ax] |= EMCMOT_AXIS_ENABLE_BIT; else emcmotStatus->axisFlag[ax] &= ~EMCMOT_AXIS_ENABLE_BIT; |
#define | GET_AXIS_ACTIVE_FLAG(ax) (emcmotStatus->axisFlag[ax] & EMCMOT_AXIS_ACTIVE_BIT ? 1 : 0) |
#define | SET_AXIS_ACTIVE_FLAG(ax, fl) if (fl) emcmotStatus->axisFlag[ax] |= EMCMOT_AXIS_ACTIVE_BIT; else emcmotStatus->axisFlag[ax] &= ~EMCMOT_AXIS_ACTIVE_BIT; |
#define | GET_AXIS_INPOS_FLAG(ax) (emcmotStatus->axisFlag[ax] & EMCMOT_AXIS_INPOS_BIT ? 1 : 0) |
#define | SET_AXIS_INPOS_FLAG(ax, fl) if (fl) emcmotStatus->axisFlag[ax] |= EMCMOT_AXIS_INPOS_BIT; else emcmotStatus->axisFlag[ax] &= ~EMCMOT_AXIS_INPOS_BIT; |
#define | GET_AXIS_ERROR_FLAG(ax) (emcmotStatus->axisFlag[ax] & EMCMOT_AXIS_ERROR_BIT ? 1 : 0) |
#define | SET_AXIS_ERROR_FLAG(ax, fl) if (fl) emcmotStatus->axisFlag[ax] |= EMCMOT_AXIS_ERROR_BIT; else emcmotStatus->axisFlag[ax] &= ~EMCMOT_AXIS_ERROR_BIT; |
#define | GET_AXIS_PSL_FLAG(ax) (emcmotStatus->axisFlag[ax] & EMCMOT_AXIS_MAX_SOFT_LIMIT_BIT ? 1 : 0) |
#define | SET_AXIS_PSL_FLAG(ax, fl) if (fl) emcmotStatus->axisFlag[ax] |= EMCMOT_AXIS_MAX_SOFT_LIMIT_BIT; else emcmotStatus->axisFlag[ax] &= ~EMCMOT_AXIS_MAX_SOFT_LIMIT_BIT; |
#define | GET_AXIS_NSL_FLAG(ax) (emcmotStatus->axisFlag[ax] & EMCMOT_AXIS_MIN_SOFT_LIMIT_BIT ? 1 : 0) |
#define | SET_AXIS_NSL_FLAG(ax, fl) if (fl) emcmotStatus->axisFlag[ax] |= EMCMOT_AXIS_MIN_SOFT_LIMIT_BIT; else emcmotStatus->axisFlag[ax] &= ~EMCMOT_AXIS_MIN_SOFT_LIMIT_BIT; |
#define | GET_AXIS_PHL_FLAG(ax) (emcmotStatus->axisFlag[ax] & EMCMOT_AXIS_MAX_HARD_LIMIT_BIT ? 1 : 0) |
#define | SET_AXIS_PHL_FLAG(ax, fl) if (fl) emcmotStatus->axisFlag[ax] |= EMCMOT_AXIS_MAX_HARD_LIMIT_BIT; else emcmotStatus->axisFlag[ax] &= ~EMCMOT_AXIS_MAX_HARD_LIMIT_BIT; |
#define | GET_AXIS_NHL_FLAG(ax) (emcmotStatus->axisFlag[ax] & EMCMOT_AXIS_MIN_HARD_LIMIT_BIT ? 1 : 0) |
#define | SET_AXIS_NHL_FLAG(ax, fl) if (fl) emcmotStatus->axisFlag[ax] |= EMCMOT_AXIS_MIN_HARD_LIMIT_BIT; else emcmotStatus->axisFlag[ax] &= ~EMCMOT_AXIS_MIN_HARD_LIMIT_BIT; |
#define | GET_AXIS_HOME_SWITCH_FLAG(ax) (emcmotStatus->axisFlag[ax] & EMCMOT_AXIS_HOME_SWITCH_BIT ? 1 : 0) |
#define | SET_AXIS_HOME_SWITCH_FLAG(ax, fl) if (fl) emcmotStatus->axisFlag[ax] |= EMCMOT_AXIS_HOME_SWITCH_BIT; else emcmotStatus->axisFlag[ax] &= ~EMCMOT_AXIS_HOME_SWITCH_BIT; |
#define | GET_AXIS_HOMING_FLAG(ax) (emcmotStatus->axisFlag[ax] & EMCMOT_AXIS_HOMING_BIT ? 1 : 0) |
#define | SET_AXIS_HOMING_FLAG(ax, fl) if (fl) emcmotStatus->axisFlag[ax] |= EMCMOT_AXIS_HOMING_BIT; else emcmotStatus->axisFlag[ax] &= ~EMCMOT_AXIS_HOMING_BIT; |
#define | GET_AXIS_HOMED_FLAG(ax) (emcmotStatus->axisFlag[ax] & EMCMOT_AXIS_HOMED_BIT ? 1 : 0) |
#define | SET_AXIS_HOMED_FLAG(ax, fl) if (fl) emcmotStatus->axisFlag[ax] |= EMCMOT_AXIS_HOMED_BIT; else emcmotStatus->axisFlag[ax] &= ~EMCMOT_AXIS_HOMED_BIT; |
#define | GET_AXIS_FERROR_FLAG(ax) (emcmotStatus->axisFlag[ax] & EMCMOT_AXIS_FERROR_BIT ? 1 : 0) |
#define | SET_AXIS_FERROR_FLAG(ax, fl) if (fl) emcmotStatus->axisFlag[ax] |= EMCMOT_AXIS_FERROR_BIT; else emcmotStatus->axisFlag[ax] &= ~EMCMOT_AXIS_FERROR_BIT; |
#define | GET_AXIS_FAULT_FLAG(ax) (emcmotStatus->axisFlag[ax] & EMCMOT_AXIS_FAULT_BIT ? 1 : 0) |
#define | SET_AXIS_FAULT_FLAG(ax, fl) if (fl) emcmotStatus->axisFlag[ax] |= EMCMOT_AXIS_FAULT_BIT; else emcmotStatus->axisFlag[ax] &= ~EMCMOT_AXIS_FAULT_BIT; |
#define | GET_AXIS_ENABLE_POLARITY(ax) (emcmotConfig->axisPolarity[ax] & EMCMOT_AXIS_ENABLE_BIT ? 1 : 0) |
#define | SET_AXIS_ENABLE_POLARITY(ax, fl) if (fl) emcmotConfig->axisPolarity[ax] |= EMCMOT_AXIS_ENABLE_BIT; else emcmotConfig->axisPolarity[ax] &= ~EMCMOT_AXIS_ENABLE_BIT; |
#define | GET_AXIS_PHL_POLARITY(ax) (emcmotConfig->axisPolarity[ax] & EMCMOT_AXIS_MAX_HARD_LIMIT_BIT ? 1 : 0) |
#define | SET_AXIS_PHL_POLARITY(ax, fl) if (fl) emcmotConfig->axisPolarity[ax] |= EMCMOT_AXIS_MAX_HARD_LIMIT_BIT; else emcmotConfig->axisPolarity[ax] &= ~EMCMOT_AXIS_MAX_HARD_LIMIT_BIT; |
#define | GET_AXIS_NHL_POLARITY(ax) (emcmotConfig->axisPolarity[ax] & EMCMOT_AXIS_MIN_HARD_LIMIT_BIT ? 1 : 0) |
#define | SET_AXIS_NHL_POLARITY(ax, fl) if (fl) emcmotConfig->axisPolarity[ax] |= EMCMOT_AXIS_MIN_HARD_LIMIT_BIT; else emcmotConfig->axisPolarity[ax] &= ~EMCMOT_AXIS_MIN_HARD_LIMIT_BIT; |
#define | GET_AXIS_HOME_SWITCH_POLARITY(ax) (emcmotConfig->axisPolarity[ax] & EMCMOT_AXIS_HOME_SWITCH_BIT ? 1 : 0) |
#define | SET_AXIS_HOME_SWITCH_POLARITY(ax, fl) if (fl) emcmotConfig->axisPolarity[ax] |= EMCMOT_AXIS_HOME_SWITCH_BIT; else emcmotConfig->axisPolarity[ax] &= ~EMCMOT_AXIS_HOME_SWITCH_BIT; |
#define | GET_AXIS_HOMING_POLARITY(ax) (emcmotConfig->axisPolarity[ax] & EMCMOT_AXIS_HOMING_BIT ? 1 : 0) |
#define | SET_AXIS_HOMING_POLARITY(ax, fl) if (fl) emcmotConfig->axisPolarity[ax] |= EMCMOT_AXIS_HOMING_BIT; else emcmotConfig->axisPolarity[ax] &= ~EMCMOT_AXIS_HOMING_BIT; |
#define | GET_AXIS_FAULT_POLARITY(ax) (emcmotConfig->axisPolarity[ax] & EMCMOT_AXIS_FAULT_BIT ? 1 : 0) |
#define | SET_AXIS_FAULT_POLARITY(ax, fl) if (fl) emcmotConfig->axisPolarity[ax] |= EMCMOT_AXIS_FAULT_BIT; else emcmotConfig->axisPolarity[ax] &= ~EMCMOT_AXIS_FAULT_BIT; |
#define | FREE_AXIS_QUEUE_SIZE 4 |
#define | AXRANGE(axis) ((emcmotConfig->maxLimit[axis] - emcmotConfig->minLimit[axis])) |
Functions | |
char | __attribute__ ((unused)) ident[]="$Id |
void | MARK_EMCMOT_CONFIG_CHANGE (void) |
void | reportError (const char *fmt,...) |
int | isHoming (void) |
int | inRange (EmcPose pos) |
int | checkLimits (void) |
int | checkJog (int axis, double vel) |
void | setTrajCycleTime (double secs) |
void | setServoCycleTime (double secs) |
int | emcmotCommandHandler (void) |
void | emcmotController (int arg) |
int | init_module (void) |
void | cleanup_module (void) |
void | emcmot_quit (int sig) |
int | getArgs (int argc, char *argv[]) |
int | main (int argc, char *argv[]) |
Variables | |
EMCMOT_STRUCT * | emcmotStruct |
shm_t * | shmem = NULL |
EMCMOT_COMMAND * | emcmotCommand |
EMCMOT_STATUS * | emcmotStatus |
EMCMOT_CONFIG * | emcmotConfig |
EMCMOT_DEBUG * | emcmotDebug |
EMCMOT_ERROR * | emcmotError |
EMCMOT_LOG * | emcmotLog |
EMCMOT_COMP * | emcmotComp [EMCMOT_MAX_AXIS] |
EMCMOT_LOG_STRUCT | ls |
int | logSkip = 0 |
int | loggingAxis = 0 |
int | logIt = 0 |
int | wdEnabling = 0 |
int | wdEnabled = 0 |
int | wdWait = 0 |
int | wdCount = 0 |
unsigned char | wdToggle = 0 |
unsigned char | allHomed = 0 |
double | jointHome [EMCMOT_MAX_AXIS] |
EmcPose | worldHome |
KINEMATICS_FORWARD_FLAGS | fflags = 0 |
KINEMATICS_INVERSE_FLAGS | iflags = 0 |
int | kinType = 0 |
int | maxLimitSwitchCount [EMCMOT_MAX_AXIS] |
int | minLimitSwitchCount [EMCMOT_MAX_AXIS] |
int | ampFaultCount [EMCMOT_MAX_AXIS] |
TP_STRUCT | queue |
TP_STRUCT | freeAxis [EMCMOT_MAX_AXIS] |
EmcPose | freePose = {{0.0, 0.0, 0.0}, 0.0, 0.0, 0.0} |
CUBIC_STRUCT | cubic [EMCMOT_MAX_AXIS] |
TC_STRUCT | queueTcSpace [DEFAULT_TC_QUEUE_SIZE+10] |
TC_STRUCT | freeAxisTcSpace [EMCMOT_MAX_AXIS][FREE_AXIS_QUEUE_SIZE] |
double | rawInput [EMCMOT_MAX_AXIS] |
double | rawOutput [EMCMOT_MAX_AXIS] |
double | coarseJointPos [EMCMOT_MAX_AXIS] |
double | jointPos [EMCMOT_MAX_AXIS] |
double | jointVel [EMCMOT_MAX_AXIS] |
double | oldJointPos [EMCMOT_MAX_AXIS] |
double | oldInput [EMCMOT_MAX_AXIS] |
double | inverseInputScale [EMCMOT_MAX_AXIS] |
double | inverseOutputScale [EMCMOT_MAX_AXIS] |
EmcPose | oldPos |
EmcPose | oldVel |
EmcPose | newVel |
EmcPose | newAcc |
double | bigVel = 1.0 |
int | waitingForLatch [EMCMOT_MAX_AXIS] |
int | latchFlag [EMCMOT_MAX_AXIS] |
double | saveLatch [EMCMOT_MAX_AXIS] |
int | enabling = 0 |
int | coordinating = 0 |
int | wasOnLimit = 0 |
int | onLimit = 0 |
int | overriding = 0 |
int | stepping = 0 |
int | idForStep = 0 |
int | interpolationCounter = 0 |
int | EMCMOT_NO_FORWARD_KINEMATICS = 0 |
int | emcmot_done = 0 |
|
Definition at line 487 of file emcstepmot.c. |
|
Definition at line 758 of file emcstepmot.c. |
|
Definition at line 626 of file emcstepmot.c. |
|
Definition at line 537 of file emcstepmot.c. |
|
Definition at line 533 of file emcstepmot.c. |
|
Definition at line 587 of file emcstepmot.c. |
|
Definition at line 545 of file emcstepmot.c. |
|
Definition at line 581 of file emcstepmot.c. |
|
Definition at line 607 of file emcstepmot.c. |
|
Definition at line 577 of file emcstepmot.c. |
|
Definition at line 573 of file emcstepmot.c. |
|
Definition at line 565 of file emcstepmot.c. |
|
Definition at line 599 of file emcstepmot.c. |
|
Definition at line 569 of file emcstepmot.c. |
|
Definition at line 603 of file emcstepmot.c. |
|
Definition at line 541 of file emcstepmot.c. |
|
Definition at line 561 of file emcstepmot.c. |
|
Definition at line 595 of file emcstepmot.c. |
|
Definition at line 553 of file emcstepmot.c. |
|
Definition at line 557 of file emcstepmot.c. |
|
Definition at line 591 of file emcstepmot.c. |
|
Definition at line 549 of file emcstepmot.c. |
|
Definition at line 519 of file emcstepmot.c. |
|
Definition at line 527 of file emcstepmot.c. |
|
Definition at line 515 of file emcstepmot.c. |
|
Definition at line 523 of file emcstepmot.c. |
|
Definition at line 484 of file emcstepmot.c. |
|
Definition at line 539 of file emcstepmot.c. |
|
Definition at line 535 of file emcstepmot.c. |
|
Definition at line 589 of file emcstepmot.c. |
|
Definition at line 547 of file emcstepmot.c. |
|
Definition at line 583 of file emcstepmot.c. |
|
Definition at line 609 of file emcstepmot.c. |
|
Definition at line 579 of file emcstepmot.c. |
|
Definition at line 575 of file emcstepmot.c. |
|
Definition at line 567 of file emcstepmot.c. |
|
Definition at line 601 of file emcstepmot.c. |
|
Definition at line 571 of file emcstepmot.c. |
|
Definition at line 605 of file emcstepmot.c. |
|
Definition at line 543 of file emcstepmot.c. |
|
Definition at line 563 of file emcstepmot.c. |
|
Definition at line 597 of file emcstepmot.c. |
|
Definition at line 555 of file emcstepmot.c. |
|
Definition at line 559 of file emcstepmot.c. |
|
Definition at line 593 of file emcstepmot.c. |
|
Definition at line 551 of file emcstepmot.c. |
|
Definition at line 521 of file emcstepmot.c. |
|
Definition at line 529 of file emcstepmot.c. |
|
Definition at line 517 of file emcstepmot.c. |
|
Definition at line 525 of file emcstepmot.c. |
|
Definition at line 498 of file emcstepmot.c. |
|
Definition at line 502 of file emcstepmot.c. 00503 { 00504 if(emcmotConfig->head == emcmotConfig->tail) { 00505 emcmotConfig->config_num++; 00506 emcmotStatus->config_num = emcmotConfig->config_num; 00507 emcmotConfig->head++; 00508 } 00509 } |
|
Definition at line 355 of file emcstepmot.c. 00355 : emcstepmot.c,v 1.18 2001/10/18 15:29:09 wshackle Exp $"; 00356 00357 void extMotDout(unsigned char byte) // P.C. Added this to fix a broken call 00358 { // when the functioning call has been 00359 return; // included for steppermotors, this 00360 } // can be deleted. |
|
Definition at line 818 of file emcstepmot.c. Referenced by emcmotCommandHandler().
00819 { 00820 if (emcmotStatus->overrideLimits) { 00821 return 1; /* okay to jog when limits overridden */ 00822 } 00823 00824 if (axis < 0 || 00825 axis >= EMCMOT_MAX_AXIS) { 00826 return 0; /* can't jog out-of-range axis */ 00827 } 00828 00829 if (vel > 0.0 && 00830 (GET_AXIS_PSL_FLAG(axis) || 00831 GET_AXIS_PHL_FLAG(axis))) { 00832 return 0; /* can't jog further past max limit */ 00833 } 00834 00835 if (vel < 0.0 && 00836 (GET_AXIS_NSL_FLAG(axis) || 00837 GET_AXIS_NHL_FLAG(axis))) { 00838 return 0; /* can't jog further past min limit */ 00839 } 00840 00841 /* okay to jog */ 00842 return 1; 00843 } |
|
Definition at line 793 of file emcstepmot.c. 00794 { 00795 int axis; 00796 00797 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 00798 if (! GET_AXIS_ACTIVE_FLAG(axis)) { 00799 /* if axis is not active, don't even look at its limits */ 00800 continue; 00801 } 00802 00803 if (GET_AXIS_PSL_FLAG(axis) || 00804 GET_AXIS_NSL_FLAG(axis) || 00805 GET_AXIS_PHL_FLAG(axis) || 00806 GET_AXIS_NHL_FLAG(axis)) { 00807 return 0; 00808 } 00809 } 00810 00811 return 1; 00812 } |
|
Definition at line 3702 of file emcstepmot.c. 03703 { 03704 int axis; 03705 03706 /* release traj planner space */ 03707 tpDelete(&queue); 03708 03709 /* disable amps */ 03710 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 03711 extAmpEnable(axis, 03712 ! GET_AXIS_ENABLE_POLARITY(axis)); 03713 } 03714 03715 /* quit board */ 03716 extAioQuit(); 03717 extDioQuit(); 03718 extMotQuit(); 03719 03720 #ifdef rtlinux 03721 03722 #ifdef RT_FIFO 03723 rtf_destroy(EMCMOT_COMMAND_RTF); 03724 rtf_destroy(EMCMOT_STATUS_RTF); 03725 rtf_destroy(EMCMOT_ERROR_RTF); 03726 #endif 03727 03728 /* delete control task */ 03729 #ifdef USE_RTL2 03730 pthread_delete_np(emcmotTask); 03731 #else 03732 rt_task_delete(&emcmotTask); 03733 #endif 03734 03735 #ifdef STEPPER_MOTORS 03736 03737 /* delete stepper motor task */ 03738 #ifdef USE_RTL2 03739 pthread_delete_np(smTask); 03740 #else 03741 rt_task_delete(&smTask); 03742 #endif 03743 03744 #endif 03745 03746 /* free shared memory */ 03747 #ifdef USE_RTL2 03748 mbuff_free("emcmotStruct",emcmotStruct); 03749 #else 03750 #ifdef rtlinux2 03751 iounmap(emcmotStruct); 03752 #else 03753 vfree(emcmotStruct); 03754 #endif 03755 #endif 03756 03757 03758 /* FIXME */ 03759 diagnostics("exited emcmot\n"); 03760 #ifdef STEPPER_MOTORS 03761 diagnostics("sm cycle time %d\n", (int) (smCycleTime * 1000000.0)); 03762 diagnostics("sm cycles per axis %d\n", smCyclesPerAxis); 03763 #endif 03764 03765 #else 03766 03767 /* detach from shmem */ 03768 if (NULL != shmem) { 03769 rcs_shm_close(shmem); 03770 shmem = NULL; 03771 } 03772 03773 #endif 03774 } |
|
Definition at line 920 of file emcstepmot.c. 00921 { 00922 int axis; /* loop counter */ 00923 #ifdef rtlinux 00924 #ifdef RT_FIFO 00925 int err; 00926 #endif 00927 #endif 00928 int valid; 00929 #ifdef STEPPER_MOTORS 00930 double mag; /* temporary value for magnitudes, to 00931 avoid calling fabs() all the time */ 00932 #endif 00933 00934 /* copy command from outside into local buffers */ 00935 00936 #if defined (rtlinux) && defined (RT_FIFO) 00937 while ((err = 00938 rtf_get(EMCMOT_COMMAND_RTF, &emcmotCommandBuffer, 00939 sizeof(EMCMOT_COMMAND))) == sizeof(EMCMOT_COMMAND)) { 00940 00941 #endif /* rtlinux and RT_FIFO */ 00942 00943 /* check for split read */ 00944 if (emcmotCommand->head != emcmotCommand->tail) { 00945 emcmotDebug->split++; 00946 return 0; /* not really an error */ 00947 } 00948 00949 if (emcmotCommand->commandNum != emcmotStatus->commandNumEcho) { 00950 /* increment head count-- we'll be modifying emcmotStatus */ 00951 emcmotStatus->head++; 00952 emcmotDebug->head++; 00953 00954 /* got a new command-- echo command and number... */ 00955 emcmotStatus->commandEcho = emcmotCommand->command; 00956 emcmotStatus->commandNumEcho = emcmotCommand->commandNum; 00957 00958 /* clear status value by default */ 00959 emcmotStatus->commandStatus = EMCMOT_COMMAND_OK; 00960 00961 /* log it, if appropriate */ 00962 if (emcmotStatus->logStarted && 00963 emcmotStatus->logType == EMCMOT_LOG_TYPE_CMD) { 00964 ls.item.cmd.time = etime(); 00965 ls.item.cmd.command = emcmotCommand->command; 00966 ls.item.cmd.commandNum = emcmotCommand->commandNum; 00967 #if defined (rtlinux) && defined (RT_FIFO) 00968 rtf_put(EMCMOT_LOG_RTF, &ls, sizeof(EMCMOT_LOG_STRUCT)); 00969 #else /* not rtlinux or not RT_FIFO */ 00970 emcmotLogAdd(emcmotLog, ls); 00971 emcmotStatus->logPoints = emcmotLog->howmany; 00972 #endif /* else not rtlinux nor RT_FIFO */ 00973 } 00974 00975 /* ...and process command */ 00976 switch (emcmotCommand->command) { 00977 case EMCMOT_FREE: 00978 /* change the mode to free axis motion */ 00979 /* can be done at any time */ 00980 /* reset the coordinating flag to defer transition to 00981 controller cycle */ 00982 coordinating = 0; 00983 break; 00984 00985 case EMCMOT_COORD: 00986 /* change the mode to coordinated axis motion */ 00987 /* can be done at any time */ 00988 /* set the coordinating flag to defer transition to 00989 controller cycle */ 00990 coordinating = 1; 00991 break; 00992 00993 case EMCMOT_SET_NUM_AXES: 00994 MARK_EMCMOT_CONFIG_CHANGE(); 00995 /* set the global NUM_AXES, which must be between 1 and 00996 EMCMOT_MAX_AXIS, inclusive */ 00997 axis = emcmotCommand->axis; 00998 /* note that this comparison differs from the check on the 00999 range of 'axis' in most other places, since those checks 01000 are for a value to be used as an index and here it's a value 01001 to be used as a counting number. The indenting is different 01002 here so as not to match macro editing on that other bunch. */ 01003 if 01004 ( 01005 axis <= 0 || 01006 axis > EMCMOT_MAX_AXIS 01007 ) { 01008 break; 01009 } 01010 NUM_AXES = axis; 01011 break; 01012 01013 case EMCMOT_SET_WORLD_HOME: 01014 worldHome = emcmotCommand->pos; 01015 break; 01016 01017 case EMCMOT_SET_JOINT_HOME: 01018 axis = emcmotCommand->axis; 01019 if (axis < 0 || 01020 axis >= EMCMOT_MAX_AXIS) { 01021 break; 01022 } 01023 jointHome[axis] = emcmotCommand->offset; /* FIXME-- use 'home' instead */ 01024 break; 01025 01026 case EMCMOT_SET_HOME_OFFSET: 01027 axis = emcmotCommand->axis; 01028 if (axis < 0 || 01029 axis >= EMCMOT_MAX_AXIS) { 01030 break; 01031 } 01032 emcmotConfig->homeOffset[axis] = emcmotCommand->offset; 01033 break; 01034 01035 case EMCMOT_OVERRIDE_LIMITS: 01036 if (emcmotCommand->axis < 0) { 01037 /* don't override limits */ 01038 emcmotStatus->overrideLimits = 0; 01039 } 01040 else { 01041 emcmotStatus->overrideLimits = 1; 01042 } 01043 overriding = 0; 01044 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 01045 SET_AXIS_ERROR_FLAG(axis, 0); 01046 } 01047 break; 01048 01049 case EMCMOT_SET_TRAJ_CYCLE_TIME: 01050 MARK_EMCMOT_CONFIG_CHANGE(); 01051 /* set the cycle time for trajectory calculations */ 01052 /* really should be done only at startup before 01053 controller is run, but at least it requires 01054 no active motions and the interpolators need 01055 to be cleared */ 01056 setTrajCycleTime(emcmotCommand->cycleTime); 01057 break; 01058 01059 case EMCMOT_SET_SERVO_CYCLE_TIME: 01060 MARK_EMCMOT_CONFIG_CHANGE(); 01061 /* set the cycle time for servo calculations, which is the 01062 period for emcmotController execution */ 01063 /* really should be done only at startup before 01064 controller is run, but at least it requires 01065 no active motions and the interpolators need 01066 to be cleared */ 01067 setServoCycleTime(emcmotCommand->cycleTime); 01068 #ifdef rtlinux 01069 #ifdef USE_RTL2 01070 pthread_make_periodic_np(emcmotTask, 01071 gethrtime(), 01072 (hrtime_t) (HRTICKS_PER_SEC * 01073 emcmotConfig->servoCycleTime)); 01074 #else 01075 rt_task_make_periodic(&emcmotTask, 01076 rt_get_time(), 01077 (RTIME) (RT_TICKS_PER_SEC * 01078 emcmotConfig->servoCycleTime)); 01079 #endif 01080 #endif /* rtlinux */ 01081 break; 01082 01083 case EMCMOT_SET_POSITION_LIMITS: 01084 MARK_EMCMOT_CONFIG_CHANGE(); 01085 /* set the position limits for the axis */ 01086 /* can be done at any time */ 01087 axis = emcmotCommand->axis; 01088 if (axis < 0 || 01089 axis >= EMCMOT_MAX_AXIS) { 01090 break; 01091 } 01092 emcmotConfig->minLimit[axis] = emcmotCommand->minLimit; 01093 emcmotConfig->maxLimit[axis] = emcmotCommand->maxLimit; 01094 break; 01095 01096 case EMCMOT_SET_OUTPUT_LIMITS: 01097 MARK_EMCMOT_CONFIG_CHANGE(); 01098 /* set the output limits for the axis */ 01099 /* can be done at any time */ 01100 axis = emcmotCommand->axis; 01101 if (axis < 0 || 01102 axis >= EMCMOT_MAX_AXIS) { 01103 break; 01104 } 01105 01106 emcmotConfig->minOutput[axis] = emcmotCommand->minLimit; 01107 emcmotConfig->maxOutput[axis] = emcmotCommand->maxLimit; 01108 break; 01109 01110 case EMCMOT_SET_OUTPUT_SCALE: 01111 axis = emcmotCommand->axis; 01112 if (axis < 0 || 01113 axis >= EMCMOT_MAX_AXIS || 01114 emcmotCommand->scale == 0) { 01115 break; 01116 } 01117 emcmotStatus->outputScale[axis] = emcmotCommand->scale; 01118 emcmotStatus->outputOffset[axis] = emcmotCommand->offset; 01119 inverseOutputScale[axis] = 1.0 / emcmotStatus->outputScale[axis]; 01120 break; 01121 01122 case EMCMOT_SET_INPUT_SCALE: 01123 /* 01124 change the scale factor for the position input, e.g., 01125 encoder counts per unit. Note that this is not a good idea 01126 once things have gotten underway, since the axis will 01127 jump servo to the "new" position, the gains will no longer 01128 be appropriate, etc. 01129 */ 01130 axis = emcmotCommand->axis; 01131 if (axis < 0 || 01132 axis >= EMCMOT_MAX_AXIS || 01133 emcmotCommand->scale == 0.0) { 01134 break; 01135 } 01136 01137 /* adjust last saved input value to match this one, so we 01138 don't get a spurious following error */ 01139 oldInput[axis] = oldInput[axis] * emcmotStatus->inputScale[axis] + 01140 emcmotStatus->inputOffset[axis]; /* temp calc */ 01141 oldInput[axis] = (oldInput[axis] - emcmotCommand->offset) / 01142 emcmotCommand->scale; 01143 01144 /* now make them active */ 01145 emcmotStatus->inputScale[axis] = emcmotCommand->scale; 01146 emcmotStatus->inputOffset[axis] = emcmotCommand->offset; 01147 inverseInputScale[axis] = 1.0 / emcmotStatus->inputScale[axis]; 01148 01149 #ifdef STEPPER_MOTORS 01150 /* change the units on the stepper counts; note that this 01151 is a signed value. De-sign it if you want to consider 01152 just its magnitude. */ 01153 smStepsPerUnit[axis] = emcmotCommand->scale; 01154 mag = fabs(smStepsPerUnit[axis]); 01155 smMagUnitsPerStep[axis] = 1.0 / mag; 01156 /* update smVPmax so that stepper task runs at proper rate */ 01157 if (mag > smMaxStepsPerUnit) { 01158 smVPmax = smVPmax * mag / smMaxStepsPerUnit; 01159 smMaxStepsPerUnit = mag; 01160 } 01161 /* set the period to twice the max pulse rate. It need only 01162 be the same as the pulse rate, but this makes it the same 01163 as before */ 01164 smCycleTime = 0.5/smVPmax; 01165 smCyclesPerAxis = (int) (emcmotConfig->servoCycleTime / smCycleTime); 01166 #ifdef USE_RTL2 01167 pthread_make_periodic_np(smTask, 01168 gethrtime(), 01169 ((hrtime_t) (HRTICKS_PER_SEC * smCycleTime))); 01170 #else 01171 rt_task_make_periodic(&smTask, 01172 rt_get_time(), 01173 ((RTIME) (RT_TICKS_PER_SEC * smCycleTime))); 01174 #endif 01175 #endif 01176 break; 01177 01178 /* 01179 Max and min ferror work like this: 01180 limiting ferror is determined by slope of ferror line, 01181 = maxFerror/limitVel 01182 -> limiting ferror = maxFerror/limitVel * vel. 01183 If ferror < minFerror then OK else 01184 if ferror < limiting ferror then OK else ERROR 01185 */ 01186 01187 case EMCMOT_SET_MAX_FERROR: 01188 MARK_EMCMOT_CONFIG_CHANGE(); 01189 axis = emcmotCommand->axis; 01190 if (axis < 0 || 01191 axis >= EMCMOT_MAX_AXIS || 01192 emcmotCommand->maxFerror < 0.0) { 01193 break; 01194 } 01195 emcmotConfig->maxFerror[axis] = emcmotCommand->maxFerror; 01196 break; 01197 01198 case EMCMOT_SET_MIN_FERROR: 01199 MARK_EMCMOT_CONFIG_CHANGE(); 01200 axis = emcmotCommand->axis; 01201 if (axis < 0 || 01202 axis >= EMCMOT_MAX_AXIS || 01203 emcmotCommand->minFerror < 0.0) { 01204 break; 01205 } 01206 emcmotConfig->minFerror[axis] = emcmotCommand->minFerror; 01207 break; 01208 01209 case EMCMOT_JOG_CONT: 01210 /* do a continuous jog, implemented as an incremental 01211 jog to the software limit, or the full range of travel 01212 if software limits don't yet apply because we're not homed */ 01213 01214 /* check axis range */ 01215 axis = emcmotCommand->axis; 01216 if (axis < 0 || 01217 axis >= EMCMOT_MAX_AXIS) { 01218 break; 01219 } 01220 01221 /* requires no motion, in free mode, enable on */ 01222 if (GET_MOTION_COORD_FLAG() || 01223 ! GET_MOTION_INPOS_FLAG() || 01224 ! GET_MOTION_ENABLE_FLAG()) { 01225 SET_AXIS_ERROR_FLAG(axis, 1); 01226 break; 01227 } 01228 01229 /* don't jog further onto limits */ 01230 if (! checkJog(axis, emcmotCommand->vel)) { 01231 SET_AXIS_ERROR_FLAG(axis, 1); 01232 break; 01233 } 01234 01235 if (emcmotCommand->vel > 0.0) { 01236 if (GET_AXIS_HOMED_FLAG(axis)) { 01237 freePose.tran.x = emcmotConfig->maxLimit[axis]; 01238 } 01239 else { 01240 freePose.tran.x = AXRANGE(axis); 01241 } 01242 } 01243 else { 01244 if (GET_AXIS_HOMED_FLAG(axis)) { 01245 freePose.tran.x = emcmotConfig->minLimit[axis]; 01246 } 01247 else { 01248 freePose.tran.x = - AXRANGE(axis); 01249 } 01250 } 01251 01252 tpSetVmax(&freeAxis[axis], fabs(emcmotCommand->vel)); 01253 tpAddLine(&freeAxis[axis], freePose); 01254 SET_AXIS_ERROR_FLAG(axis, 0); 01255 01256 break; 01257 01258 case EMCMOT_JOG_INCR: 01259 /* do an incremental jog */ 01260 01261 /* check axis range */ 01262 axis = emcmotCommand->axis; 01263 if (axis < 0 || 01264 axis >= EMCMOT_MAX_AXIS) { 01265 break; 01266 } 01267 01268 /* requires no motion, in free mode, enable on */ 01269 if (GET_MOTION_COORD_FLAG() || 01270 ! GET_MOTION_INPOS_FLAG() || 01271 ! GET_MOTION_ENABLE_FLAG()) { 01272 SET_AXIS_ERROR_FLAG(axis, 1); 01273 break; 01274 } 01275 01276 /* don't jog further onto limits */ 01277 if (! checkJog(axis, emcmotCommand->vel)) { 01278 SET_AXIS_ERROR_FLAG(axis, 1); 01279 break; 01280 } 01281 01282 if (emcmotCommand->vel > 0.0) { 01283 freePose.tran.x = jointPos[axis] + emcmotCommand->offset; /* FIXME-- use 'goal' instead */ 01284 if (GET_AXIS_HOMED_FLAG(axis)) { 01285 if (freePose.tran.x > emcmotConfig->maxLimit[axis]) { 01286 freePose.tran.x = emcmotConfig->maxLimit[axis]; 01287 } 01288 } 01289 } 01290 else { 01291 freePose.tran.x = jointPos[axis] - emcmotCommand->offset; /* FIXME-- use 'goal' instead */ 01292 if (GET_AXIS_HOMED_FLAG(axis)) { 01293 if (freePose.tran.x < emcmotConfig->minLimit[axis]) { 01294 freePose.tran.x = emcmotConfig->minLimit[axis]; 01295 } 01296 } 01297 } 01298 01299 tpSetVmax(&freeAxis[axis], fabs(emcmotCommand->vel)); 01300 tpAddLine(&freeAxis[axis], freePose); 01301 SET_AXIS_ERROR_FLAG(axis, 0); 01302 01303 break; 01304 01305 case EMCMOT_JOG_ABS: 01306 /* do an absolute jog */ 01307 01308 /* check axis range */ 01309 axis = emcmotCommand->axis; 01310 if (axis < 0 || 01311 axis >= EMCMOT_MAX_AXIS) { 01312 break; 01313 } 01314 01315 /* requires no motion, in free mode, enable on */ 01316 if (GET_MOTION_COORD_FLAG() || 01317 ! GET_MOTION_INPOS_FLAG() || 01318 ! GET_MOTION_ENABLE_FLAG()) { 01319 SET_AXIS_ERROR_FLAG(axis, 1); 01320 break; 01321 } 01322 01323 /* don't jog further onto limits */ 01324 if (! checkJog(axis, emcmotCommand->vel)) { 01325 SET_AXIS_ERROR_FLAG(axis, 1); 01326 break; 01327 } 01328 01329 freePose.tran.x = emcmotCommand->offset; /* FIXME-- use 'goal' instead */ 01330 if (GET_AXIS_HOMED_FLAG(axis)) { 01331 if (freePose.tran.x > emcmotConfig->maxLimit[axis]) { 01332 freePose.tran.x = emcmotConfig->maxLimit[axis]; 01333 } 01334 else if (freePose.tran.x < emcmotConfig->minLimit[axis]) { 01335 freePose.tran.x = emcmotConfig->minLimit[axis]; 01336 } 01337 } 01338 01339 tpSetVmax(&freeAxis[axis], fabs(emcmotCommand->vel)); 01340 tpAddLine(&freeAxis[axis], freePose); 01341 SET_AXIS_ERROR_FLAG(axis, 0); 01342 01343 break; 01344 01345 case EMCMOT_SET_TERM_COND: 01346 /* sets termination condition for motion queue */ 01347 tpSetTermCond(&queue, emcmotCommand->termCond); 01348 break; 01349 01350 case EMCMOT_SET_LINE: 01351 /* queue up a linear move */ 01352 /* requires coordinated mode, enable off, not on limits */ 01353 if (! GET_MOTION_COORD_FLAG() || 01354 ! GET_MOTION_ENABLE_FLAG()) { 01355 reportError("Need to be enabled, in coord mode for linear move"); 01356 emcmotStatus->commandStatus = EMCMOT_COMMAND_INVALID_COMMAND; 01357 SET_MOTION_ERROR_FLAG(1); 01358 break; 01359 } 01360 else if (! inRange(emcmotCommand->pos)) { 01361 reportError("Linear move %d out of range", 01362 emcmotCommand->id); 01363 emcmotStatus->commandStatus = EMCMOT_COMMAND_INVALID_PARAMS; 01364 tpAbort(&queue); 01365 SET_MOTION_ERROR_FLAG(1); 01366 break; 01367 } 01368 else if (! checkLimits()) { 01369 reportError("Can't do linear move with limits exceeded"); 01370 emcmotStatus->commandStatus = EMCMOT_COMMAND_INVALID_PARAMS; 01371 tpAbort(&queue); 01372 SET_MOTION_ERROR_FLAG(1); 01373 break; 01374 } 01375 01376 /* append it to the queue */ 01377 tpSetId(&queue, emcmotCommand->id); 01378 if (-1 == tpAddLine(&queue, emcmotCommand->pos)) { 01379 reportError("Can't add linear move"); 01380 emcmotStatus->commandStatus = EMCMOT_COMMAND_BAD_EXEC; 01381 tpAbort(&queue); 01382 SET_MOTION_ERROR_FLAG(1); 01383 break; 01384 } 01385 else { 01386 SET_MOTION_ERROR_FLAG(0); 01387 } 01388 break; 01389 01390 case EMCMOT_SET_CIRCLE: 01391 /* queue up a circular move */ 01392 /* requires coordinated mode, enable on, not on limits */ 01393 if (! GET_MOTION_COORD_FLAG() || 01394 ! GET_MOTION_ENABLE_FLAG()) { 01395 reportError("Need to be enabled, in coord mode for circular move"); 01396 emcmotStatus->commandStatus = EMCMOT_COMMAND_INVALID_COMMAND; 01397 SET_MOTION_ERROR_FLAG(1); 01398 break; 01399 } 01400 else if (! inRange(emcmotCommand->pos)) { 01401 reportError("Circular move %d out of range", 01402 emcmotCommand->id); 01403 emcmotStatus->commandStatus = EMCMOT_COMMAND_INVALID_PARAMS; 01404 tpAbort(&queue); 01405 SET_MOTION_ERROR_FLAG(1); 01406 break; 01407 } 01408 else if (! checkLimits()) { 01409 reportError("Can't do circular move with limits exceeded"); 01410 emcmotStatus->commandStatus = EMCMOT_COMMAND_INVALID_PARAMS; 01411 tpAbort(&queue); 01412 SET_MOTION_ERROR_FLAG(1); 01413 break; 01414 } 01415 01416 /* append it to the queue */ 01417 tpSetId(&queue, emcmotCommand->id); 01418 if (-1 == 01419 tpAddCircle(&queue, emcmotCommand->pos, 01420 emcmotCommand->center, emcmotCommand->normal, 01421 emcmotCommand->turn)) { 01422 reportError("Can't add circular move"); 01423 emcmotStatus->commandStatus = EMCMOT_COMMAND_BAD_EXEC; 01424 tpAbort(&queue); 01425 SET_MOTION_ERROR_FLAG(1); 01426 break; 01427 } 01428 else { 01429 SET_MOTION_ERROR_FLAG(0); 01430 } 01431 break; 01432 01433 case EMCMOT_SET_VEL: 01434 /* set the velocity for subsequent moves */ 01435 /* can do it at any time */ 01436 emcmotStatus->vel = emcmotCommand->vel; 01437 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 01438 tpSetVmax(&freeAxis[axis], emcmotStatus->vel); 01439 } 01440 tpSetVmax(&queue, emcmotStatus->vel); 01441 break; 01442 01443 01444 case EMCMOT_SET_AXIS_VEL_LIMIT: 01445 /* check axis range */ 01446 axis = emcmotCommand->axis; 01447 if (axis < 0 || 01448 axis >= EMCMOT_MAX_AXIS) { 01449 break; 01450 } 01451 tpSetVlimit(&freeAxis[axis], emcmotCommand->vel); 01452 emcmotConfig->axisLimitVel[axis] = emcmotCommand->vel; 01453 // bigVel[axis = 10 * emcmotCommand->vel; 01454 break; 01455 01456 case EMCMOT_SET_VEL_LIMIT: 01457 /* set the absolute max velocity for all subsequent moves */ 01458 /* can do it at any time */ 01459 #ifdef STEPPER_MOTORS 01460 /* update smVPmax so that stepper task runs at proper rate, 01461 before we lose emcmotStatus->vel from overwrite by new value */ 01462 smVPmax = smVPmax * emcmotCommand->vel / emcmotConfig->limitVel; 01463 /* set the period to twice the max pulse rate. It need only 01464 be the same as the pulse rate, but this makes it the same 01465 as before */ 01466 smCycleTime = 0.5/smVPmax; 01467 smCyclesPerAxis = (int) (emcmotConfig->servoCycleTime / smCycleTime); 01468 #ifdef USE_RTL2 01469 pthread_make_periodic_np(smTask, 01470 gethrtime(), 01471 ((hrtime_t) (HRTICKS_PER_SEC * smCycleTime))); 01472 #else 01473 rt_task_make_periodic(&smTask, 01474 rt_get_time(), 01475 ((RTIME) (RT_TICKS_PER_SEC * smCycleTime))); 01476 #endif 01477 #endif 01478 emcmotConfig->limitVel = emcmotCommand->vel; 01479 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 01480 tpSetVlimit(&freeAxis[axis], emcmotConfig->limitVel); 01481 } 01482 tpSetVlimit(&queue, emcmotConfig->limitVel); 01483 /* set the debounce vel */ 01484 bigVel = 10.0 * emcmotConfig->limitVel; 01485 break; 01486 01487 case EMCMOT_SET_HOMING_VEL: 01488 /* set the homing velocity */ 01489 /* can do it at any time */ 01490 /* sign of vel should set polarity, and mag-sign are recorded */ 01491 01492 /* check axis range */ 01493 axis = emcmotCommand->axis; 01494 if (axis < 0 || 01495 axis >= EMCMOT_MAX_AXIS) { 01496 break; 01497 } 01498 01499 if (emcmotCommand->vel < 0.0) { 01500 emcmotConfig->homingVel[axis] = - emcmotCommand->vel; 01501 SET_AXIS_HOMING_POLARITY(axis, 0); 01502 } 01503 else { 01504 emcmotConfig->homingVel[axis] = emcmotCommand->vel; 01505 SET_AXIS_HOMING_POLARITY(axis, 1); 01506 } 01507 break; 01508 01509 case EMCMOT_SET_ACC: 01510 /* set the max acceleration */ 01511 /* can do it at any time */ 01512 emcmotStatus->acc = emcmotCommand->acc; 01513 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 01514 tpSetAmax(&freeAxis[axis], emcmotStatus->acc); 01515 } 01516 tpSetAmax(&queue, emcmotStatus->acc); 01517 break; 01518 01519 case EMCMOT_PAUSE: 01520 /* pause the motion */ 01521 /* can happen at any time */ 01522 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 01523 tpPause(&freeAxis[axis]); 01524 } 01525 tpPause(&queue); 01526 emcmotStatus->paused = 1; 01527 break; 01528 01529 case EMCMOT_RESUME: 01530 /* resume paused motion */ 01531 /* can happen at any time */ 01532 stepping = 0; 01533 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 01534 tpResume(&freeAxis[axis]); 01535 } 01536 tpResume(&queue); 01537 emcmotStatus->paused = 0; 01538 break; 01539 01540 case EMCMOT_STEP: 01541 /* resume paused motion until id changes */ 01542 /* can happen at any time */ 01543 idForStep = emcmotStatus->id; 01544 stepping = 1; 01545 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 01546 tpResume(&freeAxis[axis]); 01547 } 01548 tpResume(&queue); 01549 emcmotStatus->paused = 0; 01550 break; 01551 01552 case EMCMOT_SCALE: 01553 /* override speed */ 01554 /* can happen at any time */ 01555 if (emcmotCommand->scale < 0.0) { 01556 emcmotCommand->scale = 0.0; /* clamp it */ 01557 } 01558 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 01559 tpSetVscale(&freeAxis[axis], emcmotCommand->scale); 01560 emcmotStatus->axVscale[axis] = emcmotCommand->scale; 01561 } 01562 tpSetVscale(&queue, emcmotCommand->scale); 01563 emcmotStatus->qVscale = emcmotCommand->scale; 01564 break; 01565 01566 case EMCMOT_ABORT: 01567 /* abort motion */ 01568 /* can happen at any time */ 01569 /* check for coord or free space motion active */ 01570 if (GET_MOTION_COORD_FLAG()) { 01571 tpAbort(&queue); 01572 SET_MOTION_ERROR_FLAG(0); 01573 } 01574 else { 01575 /* check axis range */ 01576 axis = emcmotCommand->axis; 01577 if (axis < 0 || 01578 axis >= EMCMOT_MAX_AXIS) { 01579 break; 01580 } 01581 tpAbort(&freeAxis[axis]); 01582 SET_AXIS_HOMING_FLAG(axis, 0); 01583 SET_AXIS_ERROR_FLAG(axis, 0); 01584 } 01585 break; 01586 01587 case EMCMOT_DISABLE: 01588 /* go into disable */ 01589 /* can happen at any time */ 01590 /* reset the enabling flag to defer disable until 01591 controller cycle (it *will* be honored) */ 01592 enabling = 0; 01593 break; 01594 01595 case EMCMOT_ENABLE: 01596 /* come out of disable */ 01597 /* can happen at any time */ 01598 /* set the enabling flag to defer enable 01599 until controller cycle */ 01600 enabling = 1; 01601 break; 01602 01603 case EMCMOT_SET_PID: 01604 /* configure the PID gains */ 01605 axis = emcmotCommand->axis; 01606 if (axis < 0 || 01607 axis >= EMCMOT_MAX_AXIS) { 01608 break; 01609 } 01610 /* force it, instead of callind pidSetGains(), which would require 01611 that we link in pid.o, which we don't really need to do */ 01612 emcmotConfig->pid[axis].p = emcmotCommand->pid.p; 01613 emcmotConfig->pid[axis].i = emcmotCommand->pid.i; 01614 emcmotConfig->pid[axis].d = emcmotCommand->pid.d; 01615 emcmotConfig->pid[axis].ff0 = emcmotCommand->pid.ff0; 01616 emcmotConfig->pid[axis].ff1 = emcmotCommand->pid.ff1; 01617 emcmotConfig->pid[axis].ff2 = emcmotCommand->pid.ff2; 01618 emcmotConfig->pid[axis].backlash = emcmotCommand->pid.backlash; 01619 emcmotConfig->pid[axis].bias = emcmotCommand->pid.bias; 01620 emcmotConfig->pid[axis].maxError = emcmotCommand->pid.maxError; 01621 emcmotConfig->pid[axis].deadband = emcmotCommand->pid.deadband; 01622 break; 01623 01624 case EMCMOT_ACTIVATE_AXIS: 01625 /* make axis active, so that amps will be enabled when 01626 system is enabled or disabled */ 01627 /* can be done at any time */ 01628 axis = emcmotCommand->axis; 01629 if (axis < 0 || 01630 axis >= EMCMOT_MAX_AXIS) { 01631 break; 01632 } 01633 SET_AXIS_ACTIVE_FLAG(axis, 1); 01634 break; 01635 01636 case EMCMOT_DEACTIVATE_AXIS: 01637 /* make axis inactive, so that amps won't be affected when 01638 system is enabled or disabled */ 01639 /* can be done at any time */ 01640 axis = emcmotCommand->axis; 01641 if (axis < 0 || 01642 axis >= EMCMOT_MAX_AXIS) { 01643 break; 01644 } 01645 SET_AXIS_ACTIVE_FLAG(axis, 0); 01646 break; 01647 01648 case EMCMOT_ENABLE_AMPLIFIER: 01649 /* enable the amplifier directly, but don't enable calculations */ 01650 /* can be done at any time */ 01651 axis = emcmotCommand->axis; 01652 if (axis < 0 || 01653 axis >= EMCMOT_MAX_AXIS) { 01654 break; 01655 } 01656 extAmpEnable(axis, GET_AXIS_ENABLE_POLARITY(axis)); 01657 break; 01658 01659 case EMCMOT_DISABLE_AMPLIFIER: 01660 /* disable the axis calculations and amplifier, but don't 01661 disable calculations */ 01662 /* can be done at any time */ 01663 axis = emcmotCommand->axis; 01664 if (axis < 0 || 01665 axis >= EMCMOT_MAX_AXIS) { 01666 break; 01667 } 01668 extAmpEnable(axis, ! GET_AXIS_ENABLE_POLARITY(axis)); 01669 break; 01670 01671 case EMCMOT_OPEN_LOG: 01672 /* open a data log */ 01673 axis = emcmotCommand->axis; 01674 valid = 0; 01675 if (emcmotCommand->logSize > 0 && 01676 emcmotCommand->logSize <= EMCMOT_LOG_MAX) { 01677 /* handle log-specific data */ 01678 switch (emcmotCommand->logType) { 01679 case EMCMOT_LOG_TYPE_AXIS_POS: 01680 case EMCMOT_LOG_TYPE_AXIS_VEL: 01681 case EMCMOT_LOG_TYPE_POS_VOLTAGE: 01682 if (axis >= 0 && 01683 axis < EMCMOT_MAX_AXIS) { 01684 loggingAxis = axis; 01685 valid = 1; 01686 } 01687 break; 01688 01689 default: 01690 valid = 1; 01691 break; 01692 } 01693 } 01694 01695 if (valid) { 01696 /* success */ 01697 #if defined (rtlinux) && defined (RT_FIFO) 01698 if (-1 == 01699 rtf_create(EMCMOT_LOG_RTF, 01700 emcmotCommand->logSize * 01701 sizeof(EMCMOT_LOG_STRUCT))) { 01702 /* error-- can't open log */ 01703 break; 01704 } 01705 #else /* not rtlinux or not RT_FIFO */ 01706 emcmotLogInit(emcmotLog, 01707 emcmotCommand->logType, 01708 emcmotCommand->logSize); 01709 #endif /* else not rtlinux or not RT_FIFO */ 01710 emcmotStatus->logOpen = 1; 01711 emcmotStatus->logStarted = 0; 01712 emcmotStatus->logSize = emcmotCommand->logSize; 01713 emcmotStatus->logSkip = emcmotCommand->logSkip; 01714 emcmotStatus->logType = emcmotCommand->logType; 01715 } 01716 break; 01717 01718 case EMCMOT_START_LOG: 01719 /* start logging */ 01720 /* first ignore triggered log types */ 01721 if (emcmotStatus->logType == EMCMOT_LOG_TYPE_POS_VOLTAGE) { 01722 break; 01723 } 01724 if (emcmotStatus->logOpen) { 01725 emcmotStatus->logStarted = 1; 01726 logSkip = 0; 01727 } 01728 break; 01729 01730 case EMCMOT_STOP_LOG: 01731 /* stop logging */ 01732 emcmotStatus->logStarted = 0; 01733 break; 01734 01735 case EMCMOT_CLOSE_LOG: 01736 #if defined (rtlinux) && defined (RT_FIFO) 01737 rtf_destroy(EMCMOT_LOG_RTF); 01738 #endif /* rtlinux and RT_FIFO */ 01739 emcmotStatus->logOpen = 0; 01740 emcmotStatus->logStarted = 0; 01741 emcmotStatus->logSize = 0; 01742 emcmotStatus->logSkip = 0; 01743 emcmotStatus->logType = 0; 01744 break; 01745 01746 case EMCMOT_DAC_OUT: 01747 /* write output to dacs directly */ 01748 /* will only persist if amplifiers are disabled */ 01749 axis = emcmotCommand->axis; 01750 if (axis < 0 || 01751 axis >= EMCMOT_MAX_AXIS) { 01752 break; 01753 } 01754 /* trigger log, if active */ 01755 if (emcmotStatus->logType == EMCMOT_LOG_TYPE_POS_VOLTAGE && 01756 loggingAxis == axis && 01757 emcmotStatus->logOpen != 0) { 01758 emcmotStatus->logStarted = 1; 01759 logSkip = 0; 01760 } 01761 emcmotStatus->output[axis] = emcmotCommand->dacOut; 01762 break; 01763 01764 case EMCMOT_HOME: 01765 /* home the specified axis */ 01766 /* need to be in free mode, enable on */ 01767 /* homing is basically a slow incremental jog to full range */ 01768 axis = emcmotCommand->axis; 01769 if (axis < 0 || 01770 axis >= EMCMOT_MAX_AXIS) { 01771 break; 01772 } 01773 if (GET_MOTION_COORD_FLAG() || 01774 ! GET_MOTION_ENABLE_FLAG()) { 01775 break; 01776 } 01777 01778 if (GET_AXIS_HOMING_POLARITY(axis)) { 01779 freePose.tran.x = + 2.0 * AXRANGE(axis); 01780 } 01781 else { 01782 freePose.tran.x = - 2.0 * AXRANGE(axis); 01783 } 01784 01785 tpSetVmax(&freeAxis[axis], emcmotConfig->homingVel[axis]); 01786 tpAddLine(&freeAxis[axis], freePose); 01787 waitingForLatch[axis] = 1; 01788 SET_AXIS_HOMING_FLAG(axis, 1); 01789 SET_AXIS_HOMED_FLAG(axis, 0); 01790 break; 01791 01792 case EMCMOT_ENABLE_WATCHDOG: 01793 wdEnabling = 1; 01794 wdWait = emcmotCommand->wdWait; 01795 if (wdWait < 0) { 01796 wdWait = 0; 01797 } 01798 break; 01799 01800 case EMCMOT_DISABLE_WATCHDOG: 01801 wdEnabling = 0; 01802 break; 01803 01804 case EMCMOT_SET_POLARITY: 01805 axis = emcmotCommand->axis; 01806 if (axis < 0 || 01807 axis >= EMCMOT_MAX_AXIS) { 01808 break; 01809 } 01810 if (emcmotCommand->level) { 01811 /* normal */ 01812 emcmotConfig->axisPolarity[axis] |= emcmotCommand->axisFlag; 01813 } 01814 else { 01815 /* inverted */ 01816 emcmotConfig->axisPolarity[axis] &= ~emcmotCommand->axisFlag; 01817 } 01818 break; 01819 01820 #ifdef ENABLE_PROBING 01821 case EMCMOT_SET_PROBE_INDEX: 01822 emcmotConfig->probeIndex = emcmotCommand->probeIndex; 01823 break; 01824 01825 case EMCMOT_SET_PROBE_POLARITY: 01826 emcmotConfig->probePolarity = emcmotCommand->level; 01827 break; 01828 01829 case EMCMOT_CLEAR_PROBE_FLAGS: 01830 emcmotStatus->probeTripped = 0; 01831 emcmotStatus->probing = 1; 01832 break; 01833 01834 case EMCMOT_PROBE: 01835 /* most of this is taken from EMCMOT_SET_LINE */ 01836 /* queue up a linear move */ 01837 /* requires coordinated mode, enable off, not on limits */ 01838 if (! GET_MOTION_COORD_FLAG() || 01839 ! GET_MOTION_ENABLE_FLAG()) { 01840 reportError("Need to be enabled, in coord mode for linear move"); 01841 emcmotStatus->commandStatus = EMCMOT_COMMAND_INVALID_COMMAND; 01842 SET_MOTION_ERROR_FLAG(1); 01843 break; 01844 } 01845 else if (! inRange(emcmotCommand->pos)) { 01846 reportError("Linear move %d out of range", 01847 emcmotCommand->id); 01848 emcmotStatus->commandStatus = EMCMOT_COMMAND_INVALID_PARAMS; 01849 tpAbort(&queue); 01850 SET_MOTION_ERROR_FLAG(1); 01851 break; 01852 } 01853 else if (! checkLimits()) { 01854 reportError("Can't do linear move with limits exceeded"); 01855 emcmotStatus->commandStatus = EMCMOT_COMMAND_INVALID_PARAMS; 01856 tpAbort(&queue); 01857 SET_MOTION_ERROR_FLAG(1); 01858 break; 01859 } 01860 01861 /* append it to the queue */ 01862 tpSetId(&queue, emcmotCommand->id); 01863 if (-1 == tpAddLine(&queue, emcmotCommand->pos)) { 01864 reportError("Can't add linear move"); 01865 emcmotStatus->commandStatus = EMCMOT_COMMAND_BAD_EXEC; 01866 tpAbort(&queue); 01867 SET_MOTION_ERROR_FLAG(1); 01868 break; 01869 } 01870 else { 01871 emcmotStatus->probeTripped = 0; 01872 emcmotStatus->probing = 1; 01873 SET_MOTION_ERROR_FLAG(0); 01874 } 01875 break; 01876 #endif /* ENABLE_PROBING */ 01877 01878 default: 01879 reportError("Unrecognized command %d", emcmotCommand->command); 01880 emcmotStatus->commandStatus = EMCMOT_COMMAND_UNKNOWN_COMMAND; 01881 break; 01882 } /* end of: command switch */ 01883 01884 /* synch tail count */ 01885 emcmotStatus->tail = emcmotStatus->head; 01886 emcmotConfig->tail = emcmotConfig->head; 01887 emcmotDebug->tail = emcmotDebug->head; 01888 01889 } /* end of: if-new-command */ 01890 01891 #if defined (rtlinux) && defined (RT_FIFO) 01892 } /* end of: while-msg loop for RT FIFO */ 01893 01894 if (err != 0) { 01895 return -1; 01896 } 01897 01898 #endif /* rtlinux and RT_FIFO */ 01899 01900 return 0; 01901 } |
|
Definition at line 1916 of file emcstepmot.c. Referenced by main().
01918 { 01919 double start, end, delta; /* time stamping */ 01920 int homeFlag; /* result of ext read to home switch */ 01921 int axis; /* axis loop counter */ 01922 int t; /* loop counter if we're in axis loop */ 01923 int isLimit; /* result of ext read to limit sw */ 01924 int whichCycle; /* 0=none, 1=servo, 2=traj */ 01925 int fault; 01926 double numres; 01927 double thisFerror[EMCMOT_MAX_AXIS]; 01928 double limitFerror; /* current scaled ferror */ 01929 double magFerror; 01930 #ifdef STEPPER_MOTORS 01931 double bcomp[EMCMOT_MAX_AXIS]; /* backlash comp value */ 01932 char bcompdir[EMCMOT_MAX_AXIS]; /* 0=none, 1=pos, -1=neg */ 01933 double bcompincr[EMCMOT_MAX_AXIS]; /* incremental backlash comp value */ 01934 double dsteps; /* steps value (double) for stepper task */ 01935 double oldbcomp; 01936 /* various parameters for acc/dec backlash comp */ 01937 char bac_done[EMCMOT_MAX_AXIS]; 01938 double bac_d[EMCMOT_MAX_AXIS]; 01939 double bac_di[EMCMOT_MAX_AXIS]; 01940 double bac_D[EMCMOT_MAX_AXIS]; 01941 double bac_halfD[EMCMOT_MAX_AXIS]; 01942 double bac_incrincr[EMCMOT_MAX_AXIS]; 01943 double bac_incr[EMCMOT_MAX_AXIS]; 01944 #endif 01945 char finalHome[EMCMOT_MAX_AXIS]; 01946 01947 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 01948 #ifdef STEPPER_MOTORS 01949 bcomp[axis] = 0.0; 01950 bcompdir[axis] = 0; 01951 bcompincr[axis] = 0.0; 01952 bac_done[axis] = 1; 01953 bac_d[axis] = 0.0; 01954 bac_di[axis] = 0.0; 01955 bac_D[axis] = 0.0; 01956 bac_halfD[axis] = 0.0; 01957 bac_incrincr[axis] = 0.0; 01958 bac_incr[axis] = 0.0; 01959 #endif 01960 finalHome[axis] = 0; 01961 } 01962 01963 #ifdef rtlinux 01964 for (;;) { 01965 #endif /* rtlinux */ 01966 01967 #ifdef rtlinux 01968 /* toggle sound port watchdog */ 01969 01970 if (wdEnabling && ! wdEnabled) { 01971 /* just turned WD on */ 01972 wdCount = wdWait; 01973 wdToggle = 0; 01974 wdEnabled = 1; 01975 } 01976 if (! wdEnabling && wdEnabled) { 01977 /* just turned WD off */ 01978 /* clear the bit */ 01979 soundByte = inb(SOUND_PORT); 01980 soundByte &= ~SOUND_MASK; 01981 outb(soundByte, SOUND_PORT); 01982 wdEnabled = 0; 01983 } 01984 01985 if (wdEnabled && wdCount-- <= 0) { 01986 soundByte = inb(SOUND_PORT); 01987 wdToggle = ! wdToggle; 01988 if (wdToggle) { 01989 soundByte |= SOUND_MASK; 01990 } 01991 else { 01992 soundByte &= ~SOUND_MASK; 01993 } 01994 outb(soundByte, SOUND_PORT); 01995 wdCount = wdWait; 01996 } 01997 #endif /* rtlinux */ 01998 01999 /* record start time */ 02000 start = etime(); 02001 02002 /* READ COMMAND: */ 02003 02004 #ifndef RT_FIFO 02005 emcmotCommandHandler(); 02006 02007 #endif /* not RT_FIFO */ 02008 02009 /* increment head count */ 02010 emcmotStatus->head++; 02011 emcmotDebug->head++; 02012 02013 /* READ INPUTS: */ 02014 02015 #ifndef STEPPER_MOTORS 02016 /* latch all encoder feedback into raw input array, done outside 02017 of for-loop on joints below, since it's a single call for all 02018 joints */ 02019 extEncoderReadAll(EMCMOT_MAX_AXIS, rawInput); 02020 #endif 02021 02022 /* process input and read limit switches */ 02023 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 02024 #ifdef STEPPER_MOTORS 02025 /* READ INPUTS, deferred from above */ 02026 rawInput[axis] = (double) emcmotDebug->stepperCount[axis] - 02027 bcompincr[axis] * smStepsPerUnit[axis]; 02028 #endif 02029 02030 /* save old cycle's values */ 02031 oldInput[axis] = emcmotStatus->input[axis]; 02032 /* set input, scaled according to input = (raw - offset) / scale */ 02033 emcmotStatus->input[axis] = 02034 (rawInput[axis] - emcmotStatus->inputOffset[axis]) * 02035 inverseInputScale[axis]; 02036 02037 #ifndef STEPPER_MOTORS 02038 /* debounce bad feedback */ 02039 if (fabs(emcmotStatus->input[axis] - oldInput[axis]) / 02040 emcmotConfig->servoCycleTime > bigVel) { 02041 /* bad input value-- debounce with the last value */ 02042 emcmotStatus->input[axis] = oldInput[axis]; 02043 } 02044 #endif 02045 02046 /* read limit switches and amp fault from external 02047 interface, and set 'enabling' to zero if tripped 02048 to cause immediate stop */ 02049 02050 /* handle limits */ 02051 if (GET_AXIS_ACTIVE_FLAG(axis)) { 02052 extMaxLimitSwitchRead(axis, &isLimit); 02053 if (isLimit == GET_AXIS_PHL_POLARITY(axis)) { 02054 if (++maxLimitSwitchCount[axis] > LIMIT_SWITCH_DEBOUNCE) { 02055 SET_AXIS_PHL_FLAG(axis, 1); 02056 maxLimitSwitchCount[axis] = LIMIT_SWITCH_DEBOUNCE; 02057 if (emcmotStatus->overrideLimits || 02058 isHoming()) { 02059 } 02060 else { 02061 SET_AXIS_ERROR_FLAG(axis, 1); 02062 enabling = 0; 02063 } 02064 } 02065 } 02066 else { 02067 SET_AXIS_PHL_FLAG(axis, 0); 02068 maxLimitSwitchCount[axis] = 0; 02069 } 02070 } 02071 if (GET_AXIS_ACTIVE_FLAG(axis)) { 02072 extMinLimitSwitchRead(axis, &isLimit); 02073 if (isLimit == GET_AXIS_NHL_POLARITY(axis)) { 02074 if (++minLimitSwitchCount[axis] > LIMIT_SWITCH_DEBOUNCE) { 02075 SET_AXIS_NHL_FLAG(axis, 1); 02076 minLimitSwitchCount[axis] = LIMIT_SWITCH_DEBOUNCE; 02077 if (emcmotStatus->overrideLimits || 02078 isHoming()) { 02079 } 02080 else { 02081 SET_AXIS_ERROR_FLAG(axis, 1); 02082 enabling = 0; 02083 } 02084 } 02085 } 02086 else { 02087 SET_AXIS_NHL_FLAG(axis, 0); 02088 minLimitSwitchCount[axis] = 0; 02089 } 02090 } 02091 02092 if (GET_AXIS_ACTIVE_FLAG(axis) && 02093 GET_AXIS_ENABLE_FLAG(axis)) { 02094 extAmpFault(axis, &fault); 02095 if (fault == GET_AXIS_FAULT_POLARITY(axis)) { 02096 if (++ampFaultCount[axis] > AMP_FAULT_DEBOUNCE) { 02097 SET_AXIS_ERROR_FLAG(axis, 1); 02098 SET_AXIS_FAULT_FLAG(axis, 1); 02099 ampFaultCount[axis] = AMP_FAULT_DEBOUNCE; 02100 enabling = 0; 02101 } 02102 } 02103 else { 02104 SET_AXIS_FAULT_FLAG(axis, 0); 02105 ampFaultCount[axis] = 0; 02106 } 02107 } 02108 02109 /* read home switch and set flag if tripped. Handling of home 02110 sequence is done later. */ 02111 if (GET_AXIS_ACTIVE_FLAG(axis)) { 02112 extHomeSwitchRead(axis, &homeFlag); 02113 if (homeFlag == GET_AXIS_HOME_SWITCH_POLARITY(axis)) { 02114 SET_AXIS_HOME_SWITCH_FLAG(axis, 1); 02115 } 02116 else { 02117 SET_AXIS_HOME_SWITCH_FLAG(axis, 0); 02118 } 02119 } 02120 02121 } /* end of: loop on axes, for reading inputs, setting limit and 02122 home switch flags */ 02123 02124 /* now we're outside the axis loop, having just read input, scaled it, 02125 read the limit and home switches and amp faults. We need to abort 02126 all motion if we're on limits, handle homing sequence, and handle 02127 mode and state transitions. */ 02128 02129 /* RUN STATE LOGIC: */ 02130 02131 /* check for disabling */ 02132 if (! enabling && GET_MOTION_ENABLE_FLAG()) { 02133 /* clear out the motion queue and interpolators */ 02134 tpClear(&queue); 02135 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 02136 tpClear(&freeAxis[axis]); 02137 cubicDrain(&cubic[axis]); 02138 if (GET_AXIS_ACTIVE_FLAG(axis)) { 02139 extAmpEnable(axis, ! GET_AXIS_ENABLE_POLARITY(axis)); 02140 SET_AXIS_ENABLE_FLAG(axis, 0); 02141 SET_AXIS_HOMING_FLAG(axis, 0); 02142 emcmotStatus->output[axis] = 0.0; 02143 } 02144 /* don't clear the axis error flag, since that may signify why 02145 we just went into disabled state */ 02146 } 02147 /* reset the trajectory interpolation counter, so that the kinematics 02148 functions called during the disabled state run at the nominal 02149 trajectory rate rather than the servo rate. It's loaded with 02150 emcmotConfig->interpolationRate when it goes to zero. */ 02151 interpolationCounter = 0; 02152 #ifdef STEPPER_MOTORS 02153 smInhibit = 1; 02154 #endif 02155 SET_MOTION_ENABLE_FLAG(0); 02156 /* don't clear the motion error flag, since that may signify why 02157 we just went into disabled state */ 02158 } 02159 02160 /* check for enabling */ 02161 if (enabling && ! GET_MOTION_ENABLE_FLAG()) { 02162 tpSetPos(&queue, emcmotStatus->pos); 02163 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 02164 freePose.tran.x = jointPos[axis]; 02165 tpSetPos(&freeAxis[axis], freePose); 02166 #ifndef STEPPER_MOTORS 02167 pidReset(&emcmotConfig->pid[axis]); 02168 #endif 02169 if (GET_AXIS_ACTIVE_FLAG(axis)) { 02170 extAmpEnable(axis, GET_AXIS_ENABLE_POLARITY(axis)); 02171 SET_AXIS_ENABLE_FLAG(axis, 1); 02172 SET_AXIS_HOMING_FLAG(axis, 0); 02173 } 02174 /* clear any outstanding axis errors when going into enabled state */ 02175 SET_AXIS_ERROR_FLAG(axis, 0); 02176 } 02177 #ifdef STEPPER_MOTORS 02178 smInhibit = 0; 02179 #endif 02180 SET_MOTION_ENABLE_FLAG(1); 02181 /* clear any outstanding motion errors when going into enabled state */ 02182 SET_MOTION_ERROR_FLAG(0); 02183 } 02184 02185 /* check for entering coordinated mode */ 02186 if (coordinating && ! GET_MOTION_COORD_FLAG()) { 02187 if (GET_MOTION_INPOS_FLAG()) { 02188 /* update coordinated queue position */ 02189 tpSetPos(&queue, emcmotStatus->pos); 02190 /* drain the cubics so they'll synch up */ 02191 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 02192 cubicDrain(&cubic[axis]); 02193 } 02194 /* clear the override limits flags */ 02195 overriding = 0; 02196 emcmotStatus->overrideLimits = 0; 02197 SET_MOTION_COORD_FLAG(1); 02198 SET_MOTION_ERROR_FLAG(0); 02199 } 02200 else { 02201 /* not in position-- don't honor mode change */ 02202 coordinating = 0; 02203 } 02204 } 02205 02206 /* check entering free space mode */ 02207 if (! coordinating && GET_MOTION_COORD_FLAG()) { 02208 if (GET_MOTION_INPOS_FLAG()) { 02209 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 02210 /* update free planner positions */ 02211 freePose.tran.x = jointPos[axis]; 02212 tpSetPos(&freeAxis[axis], freePose); 02213 /* drain the cubics so they'll synch up */ 02214 cubicDrain(&cubic[axis]); 02215 } 02216 SET_MOTION_COORD_FLAG(0); 02217 SET_MOTION_ERROR_FLAG(0); 02218 } 02219 else { 02220 /* not in position-- don't honor mode change */ 02221 coordinating = 1; 02222 } 02223 } 02224 02225 /* check for homing sequences */ 02226 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 02227 if (GET_AXIS_HOMING_FLAG(axis)) { 02228 if (tpIsDone(&freeAxis[axis])) { 02229 /* check for decel or final move */ 02230 if (finalHome[axis]) { 02231 /* reset flag-- we're back at home */ 02232 finalHome[axis] = 0; 02233 02234 /* rework the home kinematics values-- this could be done 02235 after each message to set world or joint kinematics, but 02236 we'll defer it to here so it happens just prior to when 02237 it's needed. Note that the nominal value of these may be 02238 changed, if the kinematics need to. */ 02239 kinematicsHome(&worldHome, jointHome, &fflags, &iflags); 02240 02241 /* set input offset to value such that resulting input 02242 is the jointHome[] value, with: 02243 input = (raw - offset) / scale -> 02244 offset = raw - input * scale -> 02245 offset = raw - jointHome * scale */ 02246 02247 emcmotStatus->inputOffset[axis] = rawInput[axis] - 02248 jointHome[axis] * emcmotStatus->inputScale[axis]; 02249 02250 /* recompute inputs to match so we don't have a 02251 momentary jump */ 02252 emcmotStatus->input[axis] = jointHome[axis]; 02253 oldInput[axis] = emcmotStatus->input[axis]; 02254 02255 /* reset interpolator so that it doesn't jump */ 02256 cubicOffset(&cubic[axis], jointHome[axis] - coarseJointPos[axis]); 02257 02258 /* set axis position to jointHome upon homing */ 02259 jointPos[axis] = jointHome[axis]; 02260 freePose.tran.x = jointHome[axis]; 02261 tpSetPos(&freeAxis[axis], freePose); 02262 02263 SET_AXIS_HOMING_FLAG(axis, 0); 02264 SET_AXIS_HOMED_FLAG(axis, 1); 02265 02266 /* set allHomed flag if all active axes are homed; this 02267 will signify that kinematics functions can be called */ 02268 allHomed = 1; 02269 for (t = 0; t < EMCMOT_MAX_AXIS; t++) { 02270 if (GET_AXIS_ACTIVE_FLAG(t) && 02271 ! GET_AXIS_HOMED_FLAG(t)) { 02272 /* one active axis is not homed */ 02273 allHomed = 0; 02274 break; 02275 } 02276 } 02277 /* FIXME-- this only works with no forward kins */ 02278 if (allHomed) { 02279 emcmotStatus->pos = worldHome; 02280 emcmotStatus->actualPos = worldHome; 02281 } 02282 } 02283 else { 02284 /* just finished decel, now we'll do final home */ 02285 finalHome[axis] = 1; 02286 /* add move back to latched position + backoff */ 02287 freePose.tran.x = 02288 (saveLatch[axis] - emcmotStatus->inputOffset[axis]) * 02289 inverseInputScale[axis] + 02290 emcmotConfig->homeOffset[axis]; 02291 tpAddLine(&freeAxis[axis], freePose); 02292 } 02293 } /* end of: if axis is done either decel or final home */ 02294 } /* end of: if axis is homing */ 02295 } /* end of: axis loop that checks for homing */ 02296 02297 /* RUN MOTION CALCULATIONS: */ 02298 02299 /* run axis interpolations and outputs, but only if we're 02300 enabled. This section is "suppressed" if we're not 02301 enabled, although the read/write of encoders/dacs is still 02302 done. */ 02303 whichCycle = 0; 02304 if (GET_MOTION_ENABLE_FLAG()) { 02305 /* set whichCycle to be at least a servo cycle, for calc time logging */ 02306 whichCycle = 1; 02307 02308 /* check to see if the interpolators are empty */ 02309 while (cubicNeedNextPoint(&cubic[0])) { 02310 /* they're empty, so pull next point(s) off Cartesian or 02311 joint planner, depending upon coord or free mode. */ 02312 02313 /* check to see whether we're in coordinated or free mode, to 02314 decide which motion planner to call */ 02315 if (GET_MOTION_COORD_FLAG()) { 02316 /* we're in coordinated mode-- pull a pose off the Cartesian 02317 trajectory planner, run it through the inverse kinematics, 02318 and spline up the joint points for interpolation in 02319 servo cycles. */ 02320 02321 /* set whichCycle to be a Cartesian trajectory cycle, 02322 for calc time logging */ 02323 whichCycle = 2; 02324 02325 /* run coordinated trajectory planning cycle */ 02326 tpRunCycle(&queue); 02327 02328 /* set new commanded traj pos */ 02329 emcmotStatus->pos = tpGetPos(&queue); 02330 02331 /* convert to joints */ 02332 kinematicsInverse(&emcmotStatus->pos, coarseJointPos, &iflags, &fflags); 02333 02334 /* spline joints up-- note that we may be adding points that 02335 fail soft limits, but we'll abort at the end of this cycle 02336 so it doesn't really matter */ 02337 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 02338 cubicAddPoint(&cubic[axis], coarseJointPos[axis]); 02339 } 02340 02341 /* call forward kinematics on input points for actual pos, 02342 at trajectory rate to save bandwidth */ 02343 /* FIXME */ 02344 if (EMCMOT_NO_FORWARD_KINEMATICS) { 02345 /* fake it by setting actual pos to commanded pos */ 02346 emcmotStatus->actualPos = emcmotStatus->pos; 02347 } 02348 else { 02349 kinematicsForward(emcmotStatus->input, &emcmotStatus->actualPos, &fflags, &iflags); 02350 } 02351 02352 /* now emcmotStatus->actualPos, emcmotStatus->pos, and 02353 coarseJointPos[] are set */ 02354 02355 } /* end of: coord mode */ 02356 else { 02357 /* we're in free mode-- run joint planning cycles */ 02358 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 02359 /* set whichCycle to be a joint trajectory cycle, 02360 for calc time logging */ 02361 /* note that this may include one or more joint trajectory 02362 cycles, so calc time may be inherently variable */ 02363 whichCycle = 2; 02364 02365 /* run joint trajectory planning cycle */ 02366 tpRunCycle(&freeAxis[axis]); 02367 02368 /* set new coarse joint position. FIXME-- this uses only 02369 the tran.x field of the TP_STRUCT, which is overkill. 02370 We need a TP_STRUCT with a single scalar element. */ 02371 coarseJointPos[axis] = tpGetPos(&freeAxis[axis]).tran.x; 02372 02373 /* spline joint up-- note that we may be adding a point that 02374 fails soft limit, but we'll abort at the end of this cycle 02375 so it doesn't really matter */ 02376 cubicAddPoint(&cubic[axis], coarseJointPos[axis]); 02377 02378 } /* end of: axis for loop for joint planning cycle */ 02379 02380 if (EMCMOT_NO_FORWARD_KINEMATICS) { 02381 /* can't do anything */ 02382 } 02383 else { 02384 /* call forward kinematics on input points for actual pos, 02385 at trajectory rate to save bandwidth */ 02386 kinematicsForward(emcmotStatus->input, &emcmotStatus->actualPos, &fflags, &iflags); 02387 02388 /* push coarseJointPos[] through the forward kins to 02389 set emcmotStatus->pos, which are not computed in free 02390 mode as they are in coord mode */ 02391 /* Note: in systems where the forward kins are costly to compute, 02392 emcmotStatus->pos can be set to emcmotStatus->actualPos to 02393 save one call to the forward kins */ 02394 kinematicsForward(coarseJointPos, &emcmotStatus->pos, &fflags, &iflags); 02395 } 02396 02397 /* now emcmotStatus->actualPos, emcmotStatus->pos, and 02398 coarseJointPos[] are set */ 02399 02400 } /* end of: free mode trajectory planning */ 02401 } /* end of: while (cubicNeedNextPoint(0)) */ 02402 02403 /* we're still in motion enabled section. For coordinated mode, 02404 the Cartesian trajectory cycle has been computed, if necessary, 02405 run through the inverse kinematics, and the joints have been 02406 splined up for interpolation. For free mode, the joint trajectory 02407 cycles have been computed, if necessary, and the joints have 02408 been splined up for interpolation. We still need to push the 02409 actual input through the forward kinematics, for actual pos. 02410 02411 Effects: 02412 02413 For coord mode, emcmotStatus->pos contains the commanded 02414 Cartesian pose, coarseJointPos[] contains the results of the 02415 inverse kinematics at the coarse (trajectory) rate, and the 02416 interpolators are not empty. 02417 02418 For free mode, emcmotStatus->pos is unchanged, and needs to 02419 be updated via the forward kinematics. FIXME-- make sure this 02420 happens, and note where in this comment. coarseJointPos[] 02421 contains the results of the joint trajectory calculations 02422 at the coarse (trajectory) rate, and the interpolators are 02423 not empty. 02424 */ 02425 02426 /* check for soft joint limits. If so, abort all motion. The 02427 interpolators will pick this up further down and begin 02428 planning abort and stop. */ 02429 onLimit = 0; 02430 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 02431 SET_AXIS_PSL_FLAG(axis, 0); 02432 SET_AXIS_NSL_FLAG(axis, 0); 02433 if (GET_AXIS_HOMED_FLAG(axis)) { 02434 if (coarseJointPos[axis] > emcmotConfig->maxLimit[axis]) { 02435 SET_AXIS_ERROR_FLAG(axis, 1); 02436 SET_AXIS_PSL_FLAG(axis, 1); 02437 onLimit = 1; 02438 } 02439 else if (coarseJointPos[axis] < emcmotConfig->minLimit[axis]) { 02440 SET_AXIS_ERROR_FLAG(axis, 1); 02441 SET_AXIS_NSL_FLAG(axis, 1); 02442 } 02443 } 02444 } 02445 02446 /* reset wasOnLimit flag iff all joints are free of 02447 soft limits, as seen in the flag bits set last cycle. 02448 No need to do this for hard limits, since wasOnLimit 02449 only prevents flurry of aborts while on a soft limit 02450 and hard limits don't abort, they disable. */ 02451 if (onLimit) { 02452 if (! wasOnLimit) { 02453 /* abort everything, regardless of coord or free mode */ 02454 tpAbort(&queue); 02455 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 02456 tpAbort(&freeAxis[axis]); 02457 wasOnLimit = 1; 02458 } 02459 } 02460 /* else we were on a limit, so inhibit firing of aborts */ 02461 } 02462 else { 02463 /* not on a limit, so clear wasOnLimit so aborts fire next 02464 time we are on a limit */ 02465 wasOnLimit = 0; 02466 } 02467 02468 if (whichCycle == 2) { 02469 /* we're on a trajectory cycle, either Cartesian or joint planning, so 02470 log per-traj-cycle data if logging active */ 02471 logIt = 0; 02472 02473 if (emcmotStatus->logStarted && 02474 emcmotStatus->logSkip >= 0) { 02475 02476 /* calculate current vel, accel, for logging */ 02477 newVel.tran.x = (emcmotStatus->pos.tran.x - oldPos.tran.x) / 02478 emcmotConfig->trajCycleTime; 02479 newVel.tran.y = (emcmotStatus->pos.tran.y - oldPos.tran.y) / 02480 emcmotConfig->trajCycleTime; 02481 newVel.tran.z = (emcmotStatus->pos.tran.z - oldPos.tran.z) / 02482 emcmotConfig->trajCycleTime; 02483 oldPos = emcmotStatus->pos; 02484 newAcc.tran.x = (newVel.tran.x - oldVel.tran.x) / 02485 emcmotConfig->trajCycleTime; 02486 newAcc.tran.y = (newVel.tran.y - oldVel.tran.y) / 02487 emcmotConfig->trajCycleTime; 02488 newAcc.tran.z = (newVel.tran.z - oldVel.tran.z) / 02489 emcmotConfig->trajCycleTime; 02490 oldVel = newVel; 02491 02492 /* save the type with the log item */ 02493 ls.type = emcmotStatus->logType; 02494 02495 /* now log type-specific data */ 02496 switch (emcmotStatus->logType) { 02497 02498 case EMCMOT_LOG_TYPE_TRAJ_POS: 02499 if (logSkip-- <= 0) { 02500 ls.item.trajPos.time = start; 02501 ls.item.trajPos.pos = emcmotStatus->pos.tran; 02502 logSkip = emcmotStatus->logSkip; 02503 logIt = 1; 02504 } 02505 break; 02506 02507 case EMCMOT_LOG_TYPE_TRAJ_VEL: 02508 if (logSkip-- <= 0) { 02509 ls.item.trajVel.time = start; 02510 ls.item.trajVel.vel = newVel.tran; 02511 pmCartMag(newVel.tran, &ls.item.trajVel.mag); 02512 logSkip = emcmotStatus->logSkip; 02513 logIt = 1; 02514 } 02515 break; 02516 02517 case EMCMOT_LOG_TYPE_TRAJ_ACC: 02518 if (logSkip-- <= 0) { 02519 ls.item.trajAcc.time = start; 02520 ls.item.trajAcc.acc = newAcc.tran; 02521 pmCartMag(newAcc.tran, &ls.item.trajAcc.mag); 02522 logSkip = emcmotStatus->logSkip; 02523 logIt = 1; 02524 } 02525 break; 02526 02527 default: 02528 break; 02529 } /* end of: switch on log type */ 02530 02531 /* now log it */ 02532 #if defined (rtlinux) && defined (RT_FIFO) 02533 if (logIt) { 02534 rtf_put(EMCMOT_LOG_RTF, &ls, sizeof(EMCMOT_LOG_STRUCT)); 02535 /* FIXME-- update emcmotStatus->logPoints */ 02536 logIt = 0; 02537 } 02538 #else 02539 if (logIt) { 02540 emcmotLogAdd(emcmotLog, ls); 02541 emcmotStatus->logPoints = emcmotLog->howmany; 02542 logIt = 0; 02543 } 02544 #endif 02545 } /* end of: if (emcmotStatus->logStarted && 02546 emcmotStatus->logSkip >= 0) */ 02547 } /* end of: if (whichCycle == 2), for trajectory cycle logging */ 02548 02549 /* run interpolation and compensation */ 02550 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 02551 /* interpolate */ 02552 oldJointPos[axis] = jointPos[axis]; 02553 jointPos[axis] = cubicInterpolate(&cubic[axis], 0, 0, 0, 0); 02554 /* round position to input resolution */ 02555 numres = jointPos[axis] * emcmotStatus->inputScale[axis]; 02556 if (numres < 0.0) { 02557 jointPos[axis] = inverseInputScale[axis] * ((int) (numres - 0.5)); 02558 } 02559 else { 02560 jointPos[axis] = inverseInputScale[axis] * ((int) (numres + 0.5)); 02561 } 02562 jointVel[axis] = (jointPos[axis] - oldJointPos[axis]) / 02563 emcmotConfig->servoCycleTime; 02564 02565 /* run output calculations */ 02566 if (GET_AXIS_ACTIVE_FLAG(axis)) { 02567 #ifdef STEPPER_MOTORS 02568 /* backlash compensation for steppers*/ 02569 /* This is pretty screwed up, since backlash was originally 02570 part of the PID structure. We need to duplicate the 02571 correction method here, and use the backlash value from 02572 the PID structure since that's where it ends up. 02573 FIXME-- make backlash part of the EMC status proper, not 02574 the PID structure */ 02575 if (jointPos[axis] - oldJointPos[axis] > 0.0) { 02576 oldbcomp = bcomp[axis]; 02577 bcomp[axis] = + emcmotConfig->pid[axis].backlash / 2.0; 02578 if (bcompdir[axis] != + 1) { 02579 bac_done[axis] = 0; 02580 bac_di[axis] = bcompincr[axis]; 02581 bac_d[axis] = 0; 02582 bac_D[axis] = bcomp[axis] - oldbcomp; 02583 bac_halfD[axis] = 0.5 * bac_D[axis]; 02584 bac_incrincr[axis] = emcmotStatus->acc * 02585 emcmotConfig->servoCycleTime * emcmotConfig->servoCycleTime; 02586 bac_incr[axis] = - 0.5 * bac_incrincr[axis]; 02587 bcompdir[axis] = + 1; 02588 } 02589 } 02590 else if (jointPos[axis] - oldJointPos[axis] < 0.0) { 02591 oldbcomp = bcomp[axis]; 02592 bcomp[axis] = - emcmotConfig->pid[axis].backlash / 2.0; 02593 if (bcompdir[axis] != - 1) { 02594 bac_done[axis] = 0; 02595 bac_di[axis] = bcompincr[axis]; 02596 bac_d[axis] = 0; 02597 bac_D[axis] = bcomp[axis] - oldbcomp; 02598 bac_halfD[axis] = 0.5 * bac_D[axis]; 02599 bac_incrincr[axis] = emcmotStatus->acc * 02600 emcmotConfig->servoCycleTime * emcmotConfig->servoCycleTime; 02601 bac_incr[axis] = - 0.5 * bac_incrincr[axis]; 02602 bcompdir[axis] = - 1; 02603 } 02604 } 02605 /* else no motion, so leave bcomp what it was */ 02606 02607 /* mete out the backlash according to an acc/dec profile */ 02608 if (! bac_done[axis]) { 02609 if (bac_D[axis] > 0.0) { 02610 bcompincr[axis] = bac_di[axis] + bac_d[axis]; 02611 if (bac_d[axis] < bac_halfD[axis]) { 02612 bac_incr[axis] += bac_incrincr[axis]; 02613 bac_d[axis] += bac_incr[axis]; 02614 } 02615 else if (bac_d[axis] < bac_D[axis]) { 02616 bac_incr[axis] -= bac_incrincr[axis]; 02617 bac_d[axis] += bac_incr[axis]; 02618 } 02619 if (bac_d[axis] >= bac_D[axis] || bac_incr[axis] <= 0.0) { 02620 bac_done[axis] = 1; 02621 } 02622 } 02623 else { 02624 bcompincr[axis] = bac_di[axis] + bac_d[axis]; 02625 if (bac_d[axis] > bac_halfD[axis]) { 02626 bac_incr[axis] += bac_incrincr[axis]; 02627 bac_d[axis] -= bac_incr[axis]; 02628 } 02629 else if (bac_d[axis] > bac_D[axis]) { 02630 bac_incr[axis] -= bac_incrincr[axis]; 02631 bac_d[axis] -= bac_incr[axis]; 02632 } 02633 if (bac_d[axis] <= bac_D[axis] || bac_incr[axis] <= 0.0) { 02634 bac_done[axis] = 1; 02635 } 02636 } 02637 } /* end of: if not bac_done[axis] */ 02638 02639 /* fill in global smSteps[] for stepper task */ 02640 /* first get steps, as a floating point */ 02641 dsteps = (jointPos[axis] + bcompincr[axis]) * 02642 smStepsPerUnit[axis] + emcmotStatus->inputOffset[axis]; 02643 /* round to nearest integer */ 02644 if (dsteps < 0.0) { 02645 smSteps[axis] = (int) (dsteps - 0.5); 02646 } 02647 else { 02648 smSteps[axis] = (int) (dsteps + 0.5); 02649 } 02650 02651 /* flag this as the start of a new chunk for the stepper task */ 02652 smNewCycle[axis] = 1; 02653 #else 02654 /* COMPENSATE: */ 02655 02656 /* 02657 compensation means compute output 02658 'emcmotStatus->output[]' based on desired position 02659 'jointPos[]' and input 'emcmotStatus->input[]'. 02660 02661 Currently the source calls for PID compensation. 02662 FIXME-- add wrapper for compensator, with ptr to 02663 emcmotStatus struct, with semantics that ->output[] 02664 needs to be filled. 02665 */ 02666 02667 /* here is PID compensation */ 02668 emcmotStatus->output[axis] = 02669 pidRunCycle(&emcmotConfig->pid[axis], 02670 emcmotStatus->input[axis], 02671 jointPos[axis]); 02672 #endif 02673 02674 /* COMPUTE FOLLOWING ERROR: */ 02675 02676 /* compute signed following error and magnitude */ 02677 thisFerror[axis] = jointPos[axis] - emcmotStatus->input[axis]; 02678 emcmotDebug->ferrorCurrent[axis] = thisFerror[axis]; 02679 magFerror = fabs(thisFerror[axis]); 02680 02681 /* record the max ferror for this axis */ 02682 if (emcmotDebug->ferrorHighMark[axis] < magFerror) { 02683 emcmotDebug->ferrorHighMark[axis] = magFerror; 02684 } 02685 02686 /* compute the scaled ferror for a move of this speed */ 02687 limitFerror = emcmotConfig->maxFerror[axis] / 02688 emcmotConfig->limitVel * 02689 jointVel[axis]; 02690 if (limitFerror < emcmotConfig->minFerror[axis]) { 02691 limitFerror = emcmotConfig->minFerror[axis]; 02692 } 02693 02694 /* abort if this ferror is greater than the scaled ferror */ 02695 if (magFerror > limitFerror) { 02696 /* abort! abort! following error exceeded */ 02697 SET_AXIS_ERROR_FLAG(axis, 1); 02698 SET_AXIS_FERROR_FLAG(axis, 1); 02699 if (enabling) { 02700 // report the following error just this once 02701 reportError("Axis %d following error", axis); 02702 } 02703 enabling = 0; 02704 } 02705 else { 02706 SET_AXIS_FERROR_FLAG(axis, 0); 02707 } 02708 } /* end of: if (GET_AXIS_ACTIVE_FLAG(axis)) */ 02709 else { 02710 /* axis is not active-- leave the pid output where it is-- 02711 if axis is not active one can still write to the dac */ 02712 } 02713 02714 #ifndef STEPPER_MOTORS 02715 /* CLAMP OUTPUT: */ 02716 02717 /* 02718 clamp output means take 'emcmotStatus->output[]' and 02719 limit to range 02720 'emcmotConfig->minOutput[] .. emcmotConfig->maxOutput[]' 02721 */ 02722 if (emcmotStatus->output[axis] < emcmotConfig->minOutput[axis]) { 02723 emcmotStatus->output[axis] = emcmotConfig->minOutput[axis]; 02724 } 02725 else if (emcmotStatus->output[axis] > emcmotConfig->maxOutput[axis]) { 02726 emcmotStatus->output[axis] = emcmotConfig->maxOutput[axis]; 02727 } 02728 #endif 02729 02730 /* CHECK FOR LATCH CONDITION: */ 02731 02732 /* 02733 check for latch condition means if we're waiting for a 02734 latched index pulse, and we see the pulse and the home 02735 switch, we read the raw input and abort. The offset is set 02736 above in the homing section by noting that if we're homing, 02737 and waitingForLatch[] is cleared, we latched. 02738 02739 This presumes an encoder index pulse. 02740 FIXME-- remove explicit calls to encoder index pulse, to 02741 allow for open-loop control latching via switches only. 02742 */ 02743 if (waitingForLatch[axis]) { 02744 if (GET_AXIS_HOME_SWITCH_FLAG(axis) || 02745 GET_AXIS_PHL_FLAG(axis) || 02746 GET_AXIS_NHL_FLAG(axis)) { 02747 /* read encoder index */ 02748 #ifdef STEPPER_MOTORS 02749 /* force an "encoder latch" */ 02750 latchFlag[axis] = 1; 02751 #else 02752 extEncoderResetIndex(axis); 02753 extEncoderReadLatch(axis, &latchFlag[axis]); 02754 #endif 02755 if (latchFlag[axis]) { 02756 /* get latched position in RAW UNITS */ 02757 saveLatch[axis] = rawInput[axis]; 02758 waitingForLatch[axis] = 0; 02759 /* call for an abort-- when it's finished, code 02760 above sets inputOffset[] to saveLatch[] */ 02761 finalHome[axis] = 0; 02762 tpAbort(&freeAxis[axis]); 02763 } 02764 } /* end of: if (GET_AXIS_HOME_SWITCH_FLAG(axis)) */ 02765 }/* end of: if (waitingForLatch[axis]) */ 02766 } /* end of: for (axis = 0; ...) */ 02767 } /* end of: if (GET_MOTION_ENABLE_FLAG()) */ 02768 else { 02769 /* we're not enabled, so no motion planning or interpolation has 02770 been done. jointPos[] is set to emcmotStatus->input[], and 02771 likewise with coarseJointPos[], which is normally updated at 02772 the traj rate but it's convenient to do them here at the same 02773 time at the servo rate. emcmotStatus->pos, ->actualPos need to 02774 be run through forward kinematics. 02775 Note that we are running at the servo rate, so we may need 02776 to slow down by the interpolation factor to avoid soaking 02777 the CPU. If we were enabled, ->pos was set by calcs (coord mode) 02778 or forward kins (free mode), and ->actualPos was set by forward 02779 kins on ->input[], all at the trajectory rate. */ 02780 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 02781 coarseJointPos[axis] = emcmotStatus->input[axis]; 02782 jointPos[axis] = coarseJointPos[axis]; 02783 } 02784 /* synthesize the trajectory interpolation, via a counter that 02785 decrements from the interpolation rate. This causes the statements 02786 to execute at the trajectory rate instead of the servo rate at which 02787 this enclosing code is called. */ 02788 if (--interpolationCounter <= 0) { 02789 if (! EMCMOT_NO_FORWARD_KINEMATICS) { 02790 /* call the forward kinematics, at the effective trajectory rate */ 02791 if (allHomed || 02792 kinType == KINEMATICS_IDENTITY) { 02793 kinematicsForward(emcmotStatus->input, &emcmotStatus->actualPos, &fflags, &iflags); 02794 } 02795 emcmotStatus->pos = emcmotStatus->actualPos; 02796 } 02797 /* reload the interpolation counter that simulates the interpolation 02798 done when enabled */ 02799 interpolationCounter = emcmotConfig->interpolationRate; 02800 } 02801 } 02802 02803 #ifdef ENABLE_PROBING 02804 extDioRead(emcmotConfig->probeIndex, &emcmotStatus->probeval); 02805 if (emcmotStatus->probing && emcmotStatus->probeTripped) { 02806 tpClear(&queue); 02807 emcmotStatus->probing = 0; 02808 } 02809 else if (emcmotStatus->probing && GET_MOTION_INPOS_FLAG() && 02810 tpQueueDepth(&queue) == 0) { 02811 emcmotStatus->probing = 0; 02812 } 02813 else if (emcmotStatus->probing) { 02814 if (emcmotStatus->probeval == emcmotConfig->probePolarity) { 02815 emcmotStatus->probeTripped = 1; 02816 emcmotStatus->probedPos = emcmotStatus->actualPos; 02817 if (GET_MOTION_COORD_FLAG()) { 02818 tpAbort(&queue); 02819 SET_MOTION_ERROR_FLAG(0); 02820 } 02821 else { 02822 /* check axis range */ 02823 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 02824 tpAbort(&freeAxis[axis]); 02825 SET_AXIS_HOMING_FLAG(axis, 0); 02826 SET_AXIS_ERROR_FLAG(axis, 0); 02827 } 02828 } 02829 } 02830 } 02831 #endif /* ENABLE_PROBING */ 02832 02833 #ifndef STEPPER_MOTORS 02834 02835 /* SCALE OUTPUTS: */ 02836 02837 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 02838 rawOutput[axis] = 02839 (emcmotStatus->output[axis] - emcmotStatus->outputOffset[axis]) * 02840 inverseOutputScale[axis]; 02841 } 02842 02843 /* WRITE OUTPUTS: */ 02844 02845 /* write DACs-- note that this is done even when not 02846 enabled, although in this case the pidOutputs are 02847 all zero unless manually overridden. They will not 02848 be set by any calculations if we're not enabled. */ 02849 extDacWriteAll(EMCMOT_MAX_AXIS, rawOutput); 02850 #endif 02851 02852 /* UPDATE THE REST OF THE DYNAMIC STATUS: */ 02853 02854 /* copy computed axis positions to status. Note that if motion is 02855 disabled, this is the same as ->input[]. */ 02856 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 02857 emcmotStatus->axisPos[axis] = jointPos[axis]; 02858 } 02859 02860 /* health heartbeat */ 02861 emcmotStatus->heartbeat++; 02862 02863 /* motion queue status */ 02864 emcmotStatus->depth = tpQueueDepth(&queue); 02865 emcmotStatus->activeDepth = tpActiveDepth(&queue); 02866 emcmotStatus->id = tpGetExecId(&queue); 02867 emcmotStatus->queueFull = tcqFull(&queue.queue); 02868 SET_MOTION_INPOS_FLAG(0); 02869 if (tpIsDone(&queue)) { 02870 SET_MOTION_INPOS_FLAG(1); 02871 } 02872 02873 /* axis status */ 02874 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 02875 SET_AXIS_INPOS_FLAG(axis, 0); 02876 if (tpIsDone(&freeAxis[axis])) { 02877 SET_AXIS_INPOS_FLAG(axis, 1); 02878 } 02879 else { 02880 /* this axis, at least, is moving, so set overriding flag */ 02881 if (emcmotStatus->overrideLimits) { 02882 overriding = 1; 02883 } 02884 } 02885 } 02886 02887 /* reset overrideLimits flag if we have started a move and now 02888 are in position */ 02889 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 02890 if (! GET_AXIS_INPOS_FLAG(axis)) { 02891 break; 02892 } 02893 } 02894 if (axis == EMCMOT_MAX_AXIS) { 02895 /* ran through all axes, and all are in position */ 02896 if (overriding) { 02897 overriding = 0; 02898 emcmotStatus->overrideLimits = 0; 02899 } 02900 } 02901 02902 /* check to see if we should pause in order to implement 02903 single stepping */ 02904 if (stepping && idForStep != emcmotStatus->id) { 02905 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 02906 tpPause(&freeAxis[axis]); 02907 } 02908 tpPause(&queue); 02909 stepping = 0; 02910 emcmotStatus->paused = 1; 02911 } 02912 02913 /* calculate elapsed time and min/max/avg */ 02914 end = etime(); 02915 delta = end - start; 02916 emcmotStatus->computeTime = delta; 02917 if (2 == whichCycle) { 02918 /* traj calcs done this cycle-- use tMin,Max,Avg */ 02919 mmxavgAdd(&emcmotDebug->tMmxavg, delta); 02920 emcmotDebug->tMin = mmxavgMin(&emcmotDebug->tMmxavg); 02921 emcmotDebug->tMax = mmxavgMax(&emcmotDebug->tMmxavg); 02922 emcmotDebug->tAvg = mmxavgAvg(&emcmotDebug->tMmxavg); 02923 } 02924 else if (1 == whichCycle) { 02925 /* servo calcs only this cycle-- use sMin,Max,Avg */ 02926 mmxavgAdd(&emcmotDebug->sMmxavg, delta); 02927 emcmotDebug->sMin = mmxavgMin(&emcmotDebug->sMmxavg); 02928 emcmotDebug->sMax = mmxavgMax(&emcmotDebug->sMmxavg); 02929 emcmotDebug->sAvg = mmxavgAvg(&emcmotDebug->sMmxavg); 02930 } 02931 else { 02932 /* calcs disabled this cycle-- use nMin,Max,Avg */ 02933 mmxavgAdd(&emcmotDebug->nMmxavg, delta); 02934 emcmotDebug->nMin = mmxavgMin(&emcmotDebug->nMmxavg); 02935 emcmotDebug->nMax = mmxavgMax(&emcmotDebug->nMmxavg); 02936 emcmotDebug->nAvg = mmxavgAvg(&emcmotDebug->nMmxavg); 02937 } 02938 02939 /* log per-servo-cycle data if logging active */ 02940 logIt = 0; 02941 if (emcmotStatus->logStarted && 02942 emcmotStatus->logSkip >= 0) { 02943 02944 /* record type here, since all will set this */ 02945 ls.type = emcmotStatus->logType; 02946 02947 /* now log type-specific data */ 02948 switch (ls.type) { 02949 02950 case EMCMOT_LOG_TYPE_AXIS_POS: 02951 if (logSkip-- <= 0) { 02952 ls.item.axisPos.time = end; 02953 ls.item.axisPos.input = emcmotStatus->input[loggingAxis]; 02954 ls.item.axisPos.output = jointPos[loggingAxis]; 02955 logSkip = emcmotStatus->logSkip; 02956 logIt = 1; 02957 } 02958 break; 02959 02960 case EMCMOT_LOG_TYPE_ALL_INPOS: 02961 if (logSkip-- <= 0) { 02962 ls.item.allInpos.time = end; 02963 for (axis = 0; 02964 axis < EMCMOT_LOG_NUM_AXES && 02965 axis < EMCMOT_MAX_AXIS; 02966 axis++) { 02967 ls.item.allInpos.input[axis] = emcmotStatus->input[axis]; 02968 } 02969 logSkip = emcmotStatus->logSkip; 02970 logIt = 1; 02971 } 02972 break; 02973 02974 case EMCMOT_LOG_TYPE_ALL_OUTPOS: 02975 if (logSkip-- <= 0) { 02976 ls.item.allOutpos.time = end; 02977 for (axis = 0; 02978 axis < EMCMOT_LOG_NUM_AXES && 02979 axis < EMCMOT_MAX_AXIS; 02980 axis++) { 02981 ls.item.allOutpos.output[axis] = jointPos[axis]; 02982 } 02983 logSkip = emcmotStatus->logSkip; 02984 logIt = 1; 02985 } 02986 break; 02987 02988 case EMCMOT_LOG_TYPE_AXIS_VEL: 02989 if (logSkip-- <= 0) { 02990 ls.item.axisVel.time = end; 02991 ls.item.axisVel.cmdVel = jointPos[loggingAxis] - 02992 oldJointPos[loggingAxis]; 02993 ls.item.axisVel.actVel = emcmotStatus->input[loggingAxis] - 02994 oldInput[loggingAxis]; 02995 logSkip = emcmotStatus->logSkip; 02996 logIt = 1; 02997 } 02998 break; 02999 03000 case EMCMOT_LOG_TYPE_ALL_FERROR: 03001 if (logSkip-- <= 0) { 03002 ls.item.allFerror.time = end; 03003 for (axis = 0; 03004 axis < EMCMOT_LOG_NUM_AXES && 03005 axis < EMCMOT_MAX_AXIS; 03006 axis++) { 03007 ls.item.allFerror.ferror[axis] = thisFerror[axis]; 03008 } 03009 logSkip = emcmotStatus->logSkip; 03010 logIt = 1; 03011 } 03012 break; 03013 03014 case EMCMOT_LOG_TYPE_POS_VOLTAGE: 03015 /* don't do a circular log-- suppress if full */ 03016 if (emcmotLog->howmany >= emcmotStatus->logSize) { 03017 emcmotStatus->output[loggingAxis] = 0.0; /* drop the DAC to zero */ 03018 emcmotStatus->logStarted = 0; /* stop logging */ 03019 logIt = 0; /* should still be zero, reset anyway */ 03020 break; 03021 } 03022 if (logSkip-- <= 0) { 03023 ls.item.posVoltage.time = end; 03024 for (axis = 0; 03025 axis < EMCMOT_LOG_NUM_AXES && 03026 axis < EMCMOT_MAX_AXIS; 03027 axis++) { 03028 ls.item.posVoltage.pos = emcmotStatus->input[loggingAxis]; 03029 ls.item.posVoltage.voltage = rawOutput[loggingAxis]; 03030 } 03031 logSkip = emcmotStatus->logSkip; 03032 logIt = 1; 03033 } 03034 break; 03035 03036 default: 03037 break; 03038 } /* end of: switch on log type */ 03039 03040 /* now log it */ 03041 #if defined (rtlinux) && defined (RT_FIFO) 03042 if (logIt) { 03043 rtf_put(EMCMOT_LOG_RTF, &ls, sizeof(EMCMOT_LOG_STRUCT)); 03044 /* FIXME-- update emcmotStatus->logPoints */ 03045 logIt = 0; 03046 } 03047 #else 03048 if (logIt) { 03049 emcmotLogAdd(emcmotLog, ls); 03050 emcmotStatus->logPoints = emcmotLog->howmany; 03051 logIt = 0; 03052 } 03053 #endif 03054 } /* end of: if logging */ 03055 03056 /* set tail to head, which has already been incremented */ 03057 emcmotStatus->tail = emcmotStatus->head; 03058 emcmotDebug->tail = emcmotDebug->head; 03059 emcmotConfig->tail = emcmotConfig->head; 03060 03061 /* WRITE STATUS DATA */ 03062 03063 #if defined (rtlinux) && defined (RT_FIFO) 03064 /* write to rtlinux FIFO */ 03065 rtf_put(EMCMOT_STATUS_RTF, &emcmotStatusBuffer, sizeof(EMCMOT_STATUS)); 03066 03067 #endif /* rtlinux and RT_FIFO */ 03068 03069 #ifdef rtlinux 03070 /* wait for next cycle */ 03071 #ifdef USE_RTL2 03072 pthread_wait_np(); 03073 #else 03074 rt_task_wait(); 03075 #endif 03076 } /* end of: forever loop for RT task */ 03077 #endif /* rtlinux */ 03078 #ifdef USE_RTL2 03079 return(NULL); 03080 #endif 03081 } /* end of: emcmotController() function */ |
|
Definition at line 3780 of file emcstepmot.c. 03781 { 03782 emcmot_done = 1; 03783 } |
|
Definition at line 3790 of file emcstepmot.c. Referenced by main().
03791 { 03792 int t; 03793 int len; 03794 03795 for (t = 1; t < argc; t++) { 03796 /* try -ini */ 03797 /* NOTE: motion controller cannot normally read an INI file. 03798 This is provided for main() simulation, which can read 03799 an INI file and needs it for the plant simulation parameters */ 03800 if (!strcmp(argv[t], "-ini")) { 03801 if (t == argc - 1) { 03802 diagnostics("missing -ini parameter\n"); 03803 return -1; 03804 } 03805 else { 03806 strcpy(EMCMOT_INIFILE, argv[t+1]); 03807 t++; /* step over following arg */ 03808 continue; 03809 } 03810 } 03811 03812 /* try SHMEM_BASE_ADDRESS */ 03813 len = strlen("SHMEM_BASE_ADDRESS"); 03814 if (! strncmp(argv[t], "SHMEM_BASE_ADDRESS", len)) { 03815 if (argv[t][len] != '=' || 03816 1 != sscanf(&argv[t][len + 1], "%i", &SHMEM_BASE_ADDRESS)) { 03817 diagnostics("syntax: %s SHMEM_BASE_ADDRESS=integer\n", argv[0]); 03818 return -1; 03819 } 03820 else { 03821 continue; 03822 } 03823 } 03824 03825 /* try SHMEM_KEY */ 03826 len = strlen("SHMEM_KEY"); 03827 if (! strncmp(argv[t], "SHMEM_KEY", len)) { 03828 if (argv[t][len] != '=' || 03829 1 != sscanf(&argv[t][len + 1], "%i", &SHMEM_KEY)) { 03830 diagnostics("syntax: %s SHMEM_KEY=integer\n", argv[0]); 03831 return -1; 03832 } 03833 else { 03834 continue; 03835 } 03836 } 03837 03838 /* FIXME */ 03839 /* try -noforward */ 03840 if (!strcmp(argv[t], "-noforward")) { 03841 EMCMOT_NO_FORWARD_KINEMATICS = 1; 03842 continue; 03843 } 03844 03845 /* no match-- bad arg */ 03846 diagnostics("bad argument to %s: %s\n", argv[0], argv[t]); 03847 return -1; 03848 } 03849 03850 return 0; 03851 } |
|
Definition at line 762 of file emcstepmot.c. Referenced by emcmotCommandHandler().
00763 { 00764 double joint[EMCMOT_MAX_AXIS]; 00765 int axis; 00766 00767 /* fill in all joints with 0 */ 00768 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 00769 joint[axis] = 0.0; 00770 } 00771 00772 /* now fill in with real values, for joints that are used */ 00773 kinematicsInverse(&pos, joint, &iflags, &fflags); 00774 00775 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 00776 if (! GET_AXIS_ACTIVE_FLAG(axis)) { 00777 /* if axis is not active, don't even look at its limits */ 00778 continue; 00779 } 00780 00781 if (joint[axis] > emcmotConfig->maxLimit[axis] || 00782 joint[axis] < emcmotConfig->minLimit[axis]) { 00783 return 0; /* can't move further past limit */ 00784 } 00785 } 00786 00787 /* okay to move */ 00788 return 1; 00789 } |
|
Definition at line 3260 of file emcstepmot.c. 03261 { 03262 int axis; 03263 int t; 03264 #ifdef rtlinux 03265 #ifdef USE_RTL2 03266 hrtime_t now; 03267 pthread_attr_t attr; 03268 struct sched_param sched_param; 03269 clockid_t local_clock; 03270 #else 03271 RTIME now; 03272 #endif 03273 #endif 03274 PID_STRUCT pid; 03275 03276 #ifdef rtlinux 03277 03278 #ifdef RT_FIFO 03279 rtf_create(EMCMOT_COMMAND_RTF, sizeof(EMCMOT_COMMAND) + 1); 03280 rtf_create(EMCMOT_STATUS_RTF, sizeof(EMCMOT_STATUS) + 1); 03281 rtf_create(EMCMOT_ERROR_RTF, EMCMOT_ERROR_NUM * EMCMOT_ERROR_LEN + 1); 03282 /* log is created, deleted dynamically */ 03283 03284 /* fifo puts and gets work on buffer structs, so point to these */ 03285 emcmotCommand = &emcmotCommandBuffer; 03286 emcmotStatus = &emcmotStatusBuffer; 03287 emcmotConfig = &emcmotConfigBuffer; 03288 emcmotDebug = &emcmotDebugBuffer; 03289 03290 #else /* not RT_FIFO */ 03291 03292 03293 #ifdef USE_RTL2 03294 /* set shared memory pointer using mbuff which does not require that memory be resevered in lilo.conf */ 03295 printk(KERN_INFO "calling mbuff_alloc(%s,%d)\n", 03296 "emcmotStruct", 03297 (int) sizeof(EMCMOT_STRUCT)); 03298 emcmotStruct = (EMCMOT_STRUCT *) mbuff_alloc("emcmotStruct",sizeof(EMCMOT_STRUCT)); 03299 printk(KERN_INFO "mbuff_alloc returned %d\n",((int) emcmotStruct)); 03300 03301 #else 03302 #ifdef rtlinux2 03303 /* set shared memory pointer using ioremap for 2.1+ kernels */ 03304 emcmotStruct = (EMCMOT_STRUCT *) ioremap(SHMEM_BASE_ADDRESS, sizeof(EMCMOT_STRUCT)); 03305 03306 #else 03307 /* set shared memory pointer */ 03308 emcmotStruct = (EMCMOT_STRUCT *) vremap(SHMEM_BASE_ADDRESS, sizeof(EMCMOT_STRUCT)); 03309 #endif 03310 #endif 03311 03312 #endif /* else not RT_FIFO */ 03313 03314 #else /* not rtlinux */ 03315 /* get command shmem */ 03316 shmem = rcs_shm_open(SHMEM_KEY, sizeof(EMCMOT_STRUCT), 1, 0666); 03317 if (NULL == shmem || 03318 NULL == shmem->addr) 03319 { 03320 diagnostics("can't get shared memory\n"); 03321 return -1; 03322 } 03323 03324 memset(shmem->addr, 0, sizeof(EMCMOT_STRUCT)); 03325 /* map shmem area into local address space */ 03326 emcmotStruct = (EMCMOT_STRUCT *) shmem->addr; 03327 03328 #endif /* else not rtlinux */ 03329 03330 #ifndef RT_FIFO 03331 /* we'll reference emcmotStruct directly */ 03332 emcmotCommand = (EMCMOT_COMMAND *) &emcmotStruct->command; 03333 emcmotStatus = (EMCMOT_STATUS *) &emcmotStruct->status; 03334 emcmotConfig = (EMCMOT_CONFIG *) &emcmotStruct->config; 03335 emcmotDebug = (EMCMOT_DEBUG *) &emcmotStruct->debug; 03336 emcmotError = (EMCMOT_ERROR *) &emcmotStruct->error; 03337 emcmotLog = (EMCMOT_LOG *) &emcmotStruct->log; 03338 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 03339 emcmotComp[axis] = (EMCMOT_COMP *) &emcmotStruct->comp[axis]; 03340 } 03341 03342 /* zero shared memory */ 03343 for (t = 0; t < sizeof(EMCMOT_STRUCT); t++) { 03344 ((char *) emcmotStruct)[t] = 0; 03345 } 03346 #endif /* not RT_FIFO */ 03347 03348 /* init locals */ 03349 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 03350 maxLimitSwitchCount[axis] = 0; 03351 minLimitSwitchCount[axis] = 0; 03352 ampFaultCount[axis] = 0; 03353 #ifdef STEPPER_MOTORS 03354 smStepsPerUnit[axis] = INPUT_SCALE; 03355 smMagUnitsPerStep[axis] = fabs(1.0 / INPUT_SCALE); 03356 emcmotDebug->stepperCount[axis] = 0; 03357 smNewCycle[axis] = 1; 03358 #endif 03359 } 03360 03361 #ifndef RT_FIFO 03362 /* init compensation struct */ 03363 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 03364 emcmotComp[axis]->total = 0; 03365 emcmotComp[axis]->alter = 0.0; 03366 /* leave out the avgint, nominal, forward, and reverse, since 03367 these can't be zero and the total flag prevents their use anyway */ 03368 } 03369 03370 /* init error struct */ 03371 emcmotErrorInit(emcmotError); 03372 #endif /* not RT_FIFO */ 03373 03374 /* init command struct */ 03375 emcmotCommand->head = 0; 03376 emcmotCommand->command = 0; 03377 emcmotCommand->commandNum = 0; 03378 emcmotCommand->tail = 0; 03379 03380 /* init status struct */ 03381 03382 emcmotStatus->head = 0; 03383 emcmotConfig->head = 0; 03384 emcmotDebug->head = 0; 03385 03386 emcmotStatus->motionFlag = 0; 03387 SET_MOTION_ERROR_FLAG(0); 03388 SET_MOTION_COORD_FLAG(0); 03389 emcmotDebug->split = 0; 03390 emcmotStatus->commandEcho = 0; 03391 emcmotStatus->commandNumEcho = 0; 03392 emcmotStatus->commandStatus = 0; 03393 emcmotStatus->heartbeat = 0; 03394 emcmotStatus->computeTime = 0.0; 03395 emcmotConfig->numAxes = EMCMOT_MAX_AXIS; 03396 emcmotConfig->trajCycleTime = TRAJ_CYCLE_TIME; 03397 emcmotConfig->servoCycleTime = SERVO_CYCLE_TIME; 03398 emcmotStatus->pos.tran.x = 0.0; 03399 emcmotStatus->pos.tran.y = 0.0; 03400 emcmotStatus->pos.tran.z = 0.0; 03401 emcmotStatus->actualPos.tran.x = 0.0; 03402 emcmotStatus->actualPos.tran.y = 0.0; 03403 emcmotStatus->actualPos.tran.z = 0.0; 03404 emcmotStatus->vel = VELOCITY; 03405 emcmotConfig->limitVel = VELOCITY; 03406 emcmotStatus->acc = ACCELERATION; 03407 emcmotStatus->qVscale = 1.0; 03408 emcmotStatus->id = 0; 03409 emcmotStatus->depth = 0; 03410 emcmotStatus->activeDepth = 0; 03411 emcmotStatus->paused = 0; 03412 emcmotStatus->overrideLimits = 0; 03413 SET_MOTION_INPOS_FLAG(1); 03414 emcmotStatus->logOpen = 0; 03415 emcmotStatus->logStarted = 0; 03416 emcmotStatus->logSize = 0; 03417 emcmotStatus->logSkip = 0; 03418 emcmotStatus->logPoints = 0; 03419 SET_MOTION_ENABLE_FLAG(0); 03420 03421 oldPos = emcmotStatus->pos; 03422 oldVel.tran.x = 0.0; 03423 oldVel.tran.y = 0.0; 03424 oldVel.tran.z = 0.0; 03425 03426 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 03427 emcmotConfig->homingVel[axis] = VELOCITY; 03428 emcmotConfig->homeOffset[axis] = 0.0; 03429 emcmotStatus->axisFlag[axis] = 0; 03430 emcmotConfig->maxLimit[axis] = MAX_LIMIT; 03431 emcmotConfig->minLimit[axis] = MIN_LIMIT; 03432 emcmotConfig->maxOutput[axis] = MAX_OUTPUT; 03433 emcmotConfig->minOutput[axis] = MIN_OUTPUT; 03434 emcmotConfig->minFerror[axis] = 0.0; /* gives a true linear ferror */ 03435 emcmotConfig->maxFerror[axis] = MAX_FERROR; 03436 emcmotDebug->ferrorCurrent[axis] = 0.0; 03437 emcmotDebug->ferrorHighMark[axis] = 0.0; 03438 emcmotStatus->outputScale[axis] = OUTPUT_SCALE; 03439 emcmotStatus->outputOffset[axis] = OUTPUT_OFFSET; 03440 emcmotStatus->inputScale[axis] = INPUT_SCALE; 03441 inverseInputScale[axis] = 1.0 / INPUT_SCALE; 03442 emcmotStatus->inputOffset[axis] = INPUT_OFFSET; 03443 inverseOutputScale[axis] = 1.0 / OUTPUT_SCALE; 03444 emcmotStatus->axVscale[axis] = 1.0; 03445 SET_AXIS_ENABLE_FLAG(axis, 0); 03446 SET_AXIS_ACTIVE_FLAG(axis, 0); /* default is not to use it; need an 03447 explicit activate */ 03448 SET_AXIS_NSL_FLAG(axis, 0); 03449 SET_AXIS_PSL_FLAG(axis, 0); 03450 SET_AXIS_NHL_FLAG(axis, 0); 03451 SET_AXIS_PHL_FLAG(axis, 0); 03452 SET_AXIS_INPOS_FLAG(axis, 1); 03453 SET_AXIS_HOMING_FLAG(axis, 0); 03454 SET_AXIS_HOMED_FLAG(axis, 0); 03455 SET_AXIS_FERROR_FLAG(axis, 0); 03456 SET_AXIS_FAULT_FLAG(axis, 0); 03457 SET_AXIS_ERROR_FLAG(axis, 0); 03458 emcmotConfig->axisPolarity[axis] = (EMCMOT_AXIS_FLAG) 0xFFFFFFFF; 03459 /* will read encoders directly, so don't set them here */ 03460 } 03461 03462 /* FIXME-- add emcmotError */ 03463 03464 /* init min-max-avg stats */ 03465 mmxavgInit(&emcmotDebug->tMmxavg, emcmotDebug->tMmxavgSpace, MMXAVG_SIZE); 03466 mmxavgInit(&emcmotDebug->sMmxavg, emcmotDebug->sMmxavgSpace, MMXAVG_SIZE); 03467 mmxavgInit(&emcmotDebug->nMmxavg, emcmotDebug->nMmxavgSpace, MMXAVG_SIZE); 03468 emcmotDebug->tMin = 0.0; 03469 emcmotDebug->tMax = 0.0; 03470 emcmotDebug->tAvg = 0.0; 03471 emcmotDebug->sMin = 0.0; 03472 emcmotDebug->sMax = 0.0; 03473 emcmotDebug->sAvg = 0.0; 03474 emcmotDebug->nMin = 0.0; 03475 emcmotDebug->nMax = 0.0; 03476 emcmotDebug->nAvg = 0.0; 03477 03478 /* init motion queue */ 03479 if (-1 == tpCreate(&queue, DEFAULT_TC_QUEUE_SIZE, queueTcSpace)) { 03480 diagnostics("can't create motion queue\n"); 03481 return -1; 03482 } 03483 tpInit(&queue); 03484 tpSetCycleTime(&queue, emcmotConfig->trajCycleTime); 03485 tpSetPos(&queue, emcmotStatus->pos); 03486 tpSetVmax(&queue, emcmotStatus->vel); 03487 tpSetAmax(&queue, emcmotStatus->acc); 03488 03489 /* init the axis components */ 03490 pid.p = P_GAIN; 03491 pid.i = I_GAIN; 03492 pid.d = D_GAIN; 03493 pid.ff0 = FF0_GAIN; 03494 pid.ff1 = FF1_GAIN; 03495 pid.ff2 = FF2_GAIN; 03496 pid.backlash = BACKLASH; 03497 pid.bias = BIAS; 03498 pid.maxError = MAX_ERROR; 03499 03500 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 03501 if (-1 == tpCreate(&freeAxis[axis], FREE_AXIS_QUEUE_SIZE, freeAxisTcSpace[axis])) { 03502 diagnostics("can't create axis queue %d\n", axis); 03503 return -1; 03504 } 03505 tpInit(&freeAxis[axis]); 03506 tpSetCycleTime(&freeAxis[axis], emcmotConfig->trajCycleTime); 03507 /* freePose is inited to 0's in decl */ 03508 tpSetPos(&freeAxis[axis], freePose); 03509 tpSetVmax(&freeAxis[axis], emcmotStatus->vel); 03510 tpSetAmax(&freeAxis[axis], emcmotStatus->acc); 03511 #ifndef STEPPER_MOTORS 03512 pidInit(&emcmotConfig->pid[axis]); 03513 pidSetGains(&emcmotConfig->pid[axis], pid); 03514 #endif 03515 cubicInit(&cubic[axis]); 03516 } 03517 03518 /* init the time and rate using functions to affect traj, the 03519 pids, and the cubics properly, since they're coupled */ 03520 setTrajCycleTime(TRAJ_CYCLE_TIME); 03521 setServoCycleTime(SERVO_CYCLE_TIME); 03522 03523 /* init board */ 03524 if (-1 == extMotInit((const char *) 0)) { 03525 diagnostics("can't initialize motion hardware\n"); 03526 return -1; 03527 } 03528 if (-1 == extDioInit((const char *) 0)) { 03529 diagnostics("can't initialize DIO hardware\n"); 03530 return -1; 03531 } 03532 if (-1 == extAioInit((const char *) 0)) { 03533 diagnostics("can't initialize AIO hardware\n"); 03534 return -1; 03535 } 03536 03537 /* record the kinematics type of the machine */ 03538 kinType = kinematicsType(); 03539 03540 extEncoderSetIndexModel(EXT_ENCODER_INDEX_MODEL_MANUAL); 03541 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 03542 rawInput[axis] = 0.0; 03543 rawOutput[axis] = 0.0; 03544 coarseJointPos[axis] = 0.0; 03545 jointPos[axis] = 0.0; 03546 jointVel[axis] = 0.0; 03547 emcmotStatus->axisPos[axis] = 0.0; 03548 oldJointPos[axis] = 0.0; 03549 03550 waitingForLatch[axis] = 0; 03551 latchFlag[axis] = 0; 03552 saveLatch[axis] = 0.0; 03553 03554 emcmotStatus->input[axis] = 0.0; 03555 oldInput[axis] = 0.0; 03556 emcmotStatus->output[axis] = 0.0; 03557 03558 jointHome[axis] = 0.0; 03559 03560 extAmpEnable(axis, 03561 ! GET_AXIS_ENABLE_POLARITY(axis)); 03562 } 03563 03564 emcmotStatus->tail = 0; 03565 03566 #ifdef rtlinux 03567 03568 03569 #ifdef USE_RTL2 03570 local_clock = rtl_getschedclock(); 03571 03572 #if 0 03573 if(!rtl_setclockmode(local_clock, RTL_CLOCK_MODE_PERIODIC, 20000)) 03574 { 03575 diagnostics("can't set periodic mode\n"); 03576 } 03577 #else 03578 rtl_setclockmode(local_clock, RTL_CLOCK_MODE_ONESHOT,0); 03579 #endif 03580 03581 #else // RTL before version 2 03582 #if 0 03583 if (RT_TIME_END == rtl_set_periodic_mode(20)) { 03584 diagnostics("can't set periodic mode\n"); 03585 } 03586 #else 03587 rtl_set_oneshot_mode(); 03588 #endif 03589 03590 #endif 03591 03592 #ifdef USE_RTL2 03593 pthread_attr_init (&attr); 03594 sched_param.sched_priority = RT_TASK_PRIORITY; 03595 pthread_attr_setschedparam (&attr, &sched_param); 03596 attr.use_fp = 1; 03597 attr.stack_size = RT_TASK_STACK_SIZE; 03598 pthread_create( &emcmotTask, &attr, emcmotController, (void *) 1); 03599 03600 /* get current time as base for starting tasks */ 03601 now =gethrtime(); 03602 03603 pthread_setfp_np(emcmotTask,1); 03604 pthread_make_periodic_np(emcmotTask, 03605 now + 0.010*HRTICKS_PER_SEC, 03606 (hrtime_t) (HRTICKS_PER_SEC * 03607 emcmotConfig->servoCycleTime)); 03608 #else 03609 03610 /* init control task */ 03611 rt_task_init(&emcmotTask, /* RT_TASK * */ 03612 emcmotController, /* task code */ 03613 0, /* startup arg to task code */ 03614 RT_TASK_STACK_SIZE, /* task stack size */ 03615 RT_TASK_PRIORITY); /* priority */ 03616 03617 /* make sure we save FP context */ 03618 rt_task_use_fp(&emcmotTask, 1); 03619 03620 /* get current time as base for starting tasks */ 03621 now = rt_get_time(); 03622 03623 /* schedule control task to run */ 03624 rt_task_make_periodic(&emcmotTask, 03625 now + SECS_TO_RTIME(0.010), 03626 (RTIME) (RT_TICKS_PER_SEC * 03627 emcmotConfig->servoCycleTime)); 03628 03629 03630 #endif 03631 03632 03633 03634 #ifdef STEPPER_MOTORS 03635 03636 03637 /* schedule stepper task to run at 1/(V*P), where V is max velocity 03638 and P is the max stepper pulses per unit among all axes, i.e., 03639 inputScale. Note that this is also done whenever limit vel or input 03640 scales are changed */ 03641 smVPmax = VELOCITY * INPUT_SCALE; /* use defaults at first */ 03642 smMaxStepsPerUnit = INPUT_SCALE; 03643 /* set the period to twice the max pulse rate. It need only 03644 be the same as the pulse rate, but this makes it the same 03645 as before */ 03646 smCycleTime = 0.5/smVPmax; 03647 smCyclesPerAxis = (int) (emcmotConfig->servoCycleTime / smCycleTime); 03648 03649 03650 #ifdef USE_RTL2 03651 pthread_attr_init (&attr); 03652 sched_param.sched_priority = SM_TASK_PRIORITY; 03653 pthread_attr_setschedparam (&attr, &sched_param); 03654 attr.use_fp = 1; 03655 attr.stack_size = SM_TASK_STACK_SIZE; 03656 pthread_create( &smTask, &attr, smController, NULL); 03657 03658 /* get current time as base for starting tasks */ 03659 now =gethrtime(); 03660 03661 pthread_setfp_np(emcmotTask,1); 03662 pthread_make_periodic_np(emcmotTask, 03663 now + 0.010*HRTICKS_PER_SEC, 03664 (hrtime_t) (HRTICKS_PER_SEC * 03665 smCycleTime)); 03666 03667 #else 03668 03669 /* init stepper motor task */ 03670 rt_task_init(&smTask, /* RT_TASK * */ 03671 smController, /* task code */ 03672 0, /* startup arg to task code */ 03673 SM_TASK_STACK_SIZE, /* task stack size */ 03674 SM_TASK_PRIORITY); /* priority */ 03675 03676 /* make sure we save FP context */ 03677 rt_task_use_fp(&smTask, 1); 03678 03679 rt_task_make_periodic(&smTask, 03680 now + SECS_TO_RTIME(0.010), 03681 ((RTIME) (RT_TICKS_PER_SEC * smCycleTime))); 03682 03683 #endif 03684 #endif 03685 03686 /* FIXME */ 03687 diagnostics("inited emcmot\n"); 03688 03689 #endif /* rtlinux */ 03690 03691 #if defined (rtlinux) && defined (RT_FIFO) 03692 /* create user process handler on control channel */ 03693 rtf_create_handler(EMCMOT_COMMAND_RTF, /* fifo number */ 03694 emcmotCommandHandler /* control message handler */ 03695 ); 03696 03697 #endif /* rtlinux and RT_FIFO */ 03698 03699 return 0; 03700 } |
|
Definition at line 743 of file emcstepmot.c. 00744 { 00745 int axis; 00746 00747 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) { 00748 if (GET_AXIS_HOMING_FLAG(axis)) { 00749 return 1; 00750 } 00751 } 00752 00753 /* got here, so none are homing */ 00754 return 0; 00755 } |
|
Definition at line 3861 of file emcstepmot.c. 03865 { 03866 double delta; /* elapsed time */ 03867 03868 #ifndef UNDER_CE 03869 /* trap ^C */ 03870 signal(SIGINT, emcmot_quit); 03871 03872 /* process command line args */ 03873 if (0 != getArgs(argc, argv)) { 03874 diagnostics("can't init module-- bad arguments\n"); 03875 exit(1); 03876 } 03877 #endif 03878 03879 /* set up data structs */ 03880 if (-1 == init_module()) { 03881 diagnostics("can't init module-- execution permission problems?\n"); 03882 #ifndef UNDER_CE 03883 exit(1); 03884 #else 03885 return 1; 03886 #endif 03887 } 03888 03889 while (! emcmot_done) { 03890 delta = etime(); 03891 emcmotController(0); 03892 delta = etime() - delta; 03893 delta = emcmotConfig->servoCycleTime - delta; 03894 03895 if (delta > 0.0) { 03896 esleep(delta); 03897 } 03898 } 03899 03900 cleanup_module(); 03901 #ifndef UNDER_CE 03902 exit(0); 03903 #else 03904 return 0; 03905 #endif 03906 } |
|
Definition at line 720 of file emcstepmot.c. Referenced by checkJog(), emcmotCommandHandler(), and emcmotController().
00721 { 00722 va_list args; 00723 char error[EMCMOT_ERROR_LEN]; 00724 00725 va_start(args, fmt); 00726 #ifndef UNDER_CE 00727 vsprintf(error, fmt, args); 00728 #else 00729 RCS_CE_VSPRINTF(error,fmt,args); 00730 #endif 00731 va_end(args); 00732 00733 #if defined (rtlinux) && defined (RT_FIFO) 00734 rtf_put(EMCMOT_ERROR_RTF, error, EMCMOT_ERROR_LEN); 00735 00736 #else 00737 emcmotErrorPut(emcmotError, error); 00738 00739 #endif 00740 } |
|
Definition at line 884 of file emcstepmot.c. Referenced by emcmotCommandHandler(), and init_module().
00885 { 00886 static int t; 00887 00888 /* make sure it's not zero */ 00889 if (secs <= 0.0) { 00890 return; 00891 } 00892 00893 MARK_EMCMOT_CONFIG_CHANGE(); 00894 00895 /* compute the interpolation rate as nearest integer to traj/servo*/ 00896 emcmotConfig->interpolationRate = 00897 (int) (emcmotConfig->trajCycleTime / secs + 0.5); 00898 00899 /* set the cubic interpolation rate and PID cycle time */ 00900 for (t = 0; t < EMCMOT_MAX_AXIS; t++) { 00901 cubicSetInterpolationRate(&cubic[t], emcmotConfig->interpolationRate); 00902 cubicSetSegmentTime(&cubic[t], secs); 00903 #ifndef STEPPER_MOTORS 00904 pidSetCycleTime(&emcmotConfig->pid[t], secs); 00905 #endif 00906 } 00907 00908 /* copy into status out */ 00909 emcmotConfig->servoCycleTime = secs; 00910 00911 #ifdef STEPPER_MOTORS 00912 smCyclesPerAxis = (int) (emcmotConfig->servoCycleTime / smCycleTime); 00913 #endif 00914 } |
|
Definition at line 855 of file emcstepmot.c. Referenced by emcmotCommandHandler(), and init_module().
00856 { 00857 static int t; 00858 00859 /* make sure it's not zero */ 00860 if (secs <= 0.0) { 00861 return; 00862 } 00863 MARK_EMCMOT_CONFIG_CHANGE(); 00864 00865 00866 /* compute the interpolation rate as nearest integer to traj/servo*/ 00867 emcmotConfig->interpolationRate = 00868 (int) (secs / emcmotConfig->servoCycleTime + 0.5); 00869 00870 /* set traj planner */ 00871 tpSetCycleTime(&queue, secs); 00872 00873 /* set the free planners, cubic interpolation rate and segment time */ 00874 for (t = 0; t < EMCMOT_MAX_AXIS; t++) { 00875 tpSetCycleTime(&freeAxis[t], secs); 00876 cubicSetInterpolationRate(&cubic[t], emcmotConfig->interpolationRate); 00877 } 00878 00879 /* copy into status out */ 00880 emcmotConfig->trajCycleTime = secs; 00881 } |
|
Definition at line 1904 of file emcstepmot.c. |
|
Definition at line 467 of file emcstepmot.c. |
|
Definition at line 488 of file emcstepmot.c. |
|
Definition at line 646 of file emcstepmot.c. |
|
Definition at line 632 of file emcstepmot.c. |
|
Definition at line 653 of file emcstepmot.c. |
|
Definition at line 621 of file emcstepmot.c. |
|
Definition at line 442 of file emcstepmot.c. |
|
Definition at line 451 of file emcstepmot.c. |
|
Definition at line 444 of file emcstepmot.c. |
|
Definition at line 445 of file emcstepmot.c. |
|
Definition at line 449 of file emcstepmot.c. |
|
Definition at line 450 of file emcstepmot.c. |
|
Definition at line 443 of file emcstepmot.c. |
|
Definition at line 431 of file emcstepmot.c. |
|
Definition at line 3779 of file emcstepmot.c. |
|
Definition at line 652 of file emcstepmot.c. |
|
Definition at line 477 of file emcstepmot.c. |
|
Definition at line 616 of file emcstepmot.c. |
|
Definition at line 627 of file emcstepmot.c. |
|
Definition at line 620 of file emcstepmot.c. |
|
Definition at line 667 of file emcstepmot.c. |
|
Definition at line 478 of file emcstepmot.c. |
|
Definition at line 852 of file emcstepmot.c. |
|
Definition at line 639 of file emcstepmot.c. |
|
Definition at line 640 of file emcstepmot.c. |
|
Definition at line 470 of file emcstepmot.c. |
|
Definition at line 633 of file emcstepmot.c. |
|
Definition at line 634 of file emcstepmot.c. |
|
Definition at line 481 of file emcstepmot.c. |
|
Definition at line 649 of file emcstepmot.c. |
|
Definition at line 457 of file emcstepmot.c. |
|
Definition at line 455 of file emcstepmot.c. |
|
Definition at line 456 of file emcstepmot.c. |
|
Definition at line 454 of file emcstepmot.c. |
|
Definition at line 485 of file emcstepmot.c. |
|
Definition at line 486 of file emcstepmot.c. |
|
Definition at line 643 of file emcstepmot.c. |
|
Definition at line 642 of file emcstepmot.c. |
|
Definition at line 636 of file emcstepmot.c. |
|
Definition at line 635 of file emcstepmot.c. |
|
Definition at line 641 of file emcstepmot.c. |
|
Definition at line 642 of file emcstepmot.c. |
|
Definition at line 660 of file emcstepmot.c. |
|
Definition at line 663 of file emcstepmot.c. |
|
Definition at line 611 of file emcstepmot.c. |
|
Definition at line 625 of file emcstepmot.c. |
|
Definition at line 629 of file emcstepmot.c. |
|
Definition at line 630 of file emcstepmot.c. |
|
Definition at line 650 of file emcstepmot.c. |
|
Definition at line 435 of file emcstepmot.c. |
|
Definition at line 666 of file emcstepmot.c. |
|
Definition at line 648 of file emcstepmot.c. |
|
Definition at line 655 of file emcstepmot.c. |
|
Definition at line 463 of file emcstepmot.c. |
|
Definition at line 461 of file emcstepmot.c. |
|
Definition at line 460 of file emcstepmot.c. |
|
Definition at line 464 of file emcstepmot.c. |
|
Definition at line 462 of file emcstepmot.c. |
|
Initial value: {{0.0, 0.0, 0.0}, 0.0, 0.0, 0.0} Definition at line 473 of file emcstepmot.c. |