#include "_timer.h"#include "_shm.h"#include <stdio.h>#include <stdlib.h>#include <math.h>#include <stdarg.h>#include <string.h>#include <float.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 emcmot.c:

Go to the source code of this file.
Defines | |
| #define | NO_ROUNDING |
| #define | COMPING |
| #define | DEFAULT_EMCMOT_TASK_PRIORITY 2 |
| #define | DEFAULT_EMCMOT_TASK_STACK_SIZE 8192 |
| #define | SOUND_PORT 0x61 |
| #define | SOUND_MASK 0x02 |
| #define | LIMIT_SWITCH_DEBOUNCE 10 |
| #define | AMP_FAULT_DEBOUNCE 100 |
| #define | POSITION_INPUT_DEBOUNCE 10 |
| #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_TELEOP_FLAG() (emcmotStatus->motionFlag & EMCMOT_MOTION_TELEOP_BIT ? 1 : 0) |
| #define | SET_MOTION_TELEOP_FLAG(fl) if (fl) emcmotStatus->motionFlag |= EMCMOT_MOTION_TELEOP_BIT; else emcmotStatus->motionFlag &= ~EMCMOT_MOTION_TELEOP_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) MARK_EMCMOT_CONFIG_CHANGE(); 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 | AXRANGE(axis) ((emcmotConfig->maxLimit[axis] - emcmotConfig->minLimit[axis])) |
| #define | MOT_DOUT_PORT 0x278 |
| #define | MOT_DOUT_ABORT_VAL 0 |
Functions | |
| char | __attribute__ ((unused)) ident[]="$Id |
| void | MARK_EMCMOT_CONFIG_CHANGE (void) |
| void | reportError (const char *fmt,...) |
| int | isHoming (void) |
| void | clearHomes (int axis) |
| int | inRange (EmcPose pos) |
| int | checkLimits (void) |
| int | checkJog (int axis, double vel) |
| void | setTrajCycleTime (double secs) |
| void | setServoCycleTime (double secs) |
| void | extMotDout (unsigned char byte) |
| int | emcmotCommandHandler (void) |
| double | axisComp (int axis, int dir, double nominput) |
| 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 | |
| KINEMATICS_FORWARD_FLAGS | fflags = 0 |
| KINEMATICS_INVERSE_FLAGS | iflags = 0 |
| int | kinType = 0 |
| int | rehomeAll = 0 |
| double | positionInputDebounce [EMCMOT_MAX_AXIS] = {0.0} |
| int | EMCMOT_NO_FORWARD_KINEMATICS = 0 |
| int | interpolationCounter = 0 |
| int | debouncecount [EMCMOT_MAX_AXIS] = {0} |
| int | STEPPING_TYPE |
| int | emcmot_done = 0 |
|
|
|
|
|
Definition at line 895 of file emcmot.c. Referenced by emcmotCommandHandler(), and emcmotController().
|
|
|
|
|
|
|
|
|
|
|
|
Definition at line 683 of file emcmot.c. Referenced by checkLimits(), emcmotController(), and inRange().
|
|
|
Definition at line 679 of file emcmot.c. Referenced by emcmotController().
|
|
|
Definition at line 733 of file emcmot.c. Referenced by cleanup_module(), emcmotCommandHandler(), emcmotController(), and init_module().
|
|
|
|
|
|
|
|
|
Definition at line 753 of file emcmot.c. Referenced by emcmotController().
|
|
|
|
|
|
Definition at line 719 of file emcmot.c. Referenced by emcmotCommandHandler(), and emcmotController().
|
|
|
Definition at line 711 of file emcmot.c. Referenced by emcmotController().
|
|
|
Definition at line 745 of file emcmot.c. Referenced by emcmotController().
|
|
|
Definition at line 715 of file emcmot.c. Referenced by emcmotController(), and isHoming().
|
|
|
Definition at line 749 of file emcmot.c. Referenced by emcmotCommandHandler(), and emcmotController().
|
|
|
Definition at line 687 of file emcmot.c. Referenced by emcmotController().
|
|
|
Definition at line 707 of file emcmot.c. Referenced by checkJog(), checkLimits(), and emcmotController().
|
|
|
Definition at line 741 of file emcmot.c. Referenced by emcmotController().
|
|
|
Definition at line 699 of file emcmot.c. Referenced by checkJog(), and checkLimits().
|
|
|
Definition at line 703 of file emcmot.c. Referenced by checkJog(), checkLimits(), and emcmotController().
|
|
|
Definition at line 737 of file emcmot.c. Referenced by emcmotController().
|
|
|
Definition at line 695 of file emcmot.c. Referenced by checkJog(), and checkLimits().
|
|
|
Definition at line 661 of file emcmot.c. Referenced by emcmotCommandHandler(), and emcmotController().
|
|
|
Definition at line 673 of file emcmot.c. Referenced by emcmotCommandHandler(), and emcmotController().
|
|
|
|
|
|
Definition at line 669 of file emcmot.c. Referenced by emcmotCommandHandler(), and emcmotController().
|
|
|
Definition at line 665 of file emcmot.c. Referenced by emcmotCommandHandler(), and emcmotController().
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Definition at line 685 of file emcmot.c. Referenced by emcmotCommandHandler(), and init_module().
|
|
|
Definition at line 681 of file emcmot.c. Referenced by emcmotController(), and init_module().
|
|
|
|
|
|
Definition at line 693 of file emcmot.c. Referenced by emcmotCommandHandler(), emcmotController(), and init_module().
|
|
|
Definition at line 729 of file emcmot.c. Referenced by emcmotController(), and init_module().
|
|
|
|
|
|
Definition at line 725 of file emcmot.c. Referenced by emcmotController(), and init_module().
|
|
|
Definition at line 721 of file emcmot.c. Referenced by clearHomes(), emcmotCommandHandler(), emcmotController(), and init_module().
|
|
|
Definition at line 713 of file emcmot.c. Referenced by emcmotController().
|
|
|
|
|
|
Definition at line 717 of file emcmot.c. Referenced by emcmotCommandHandler(), emcmotController(), and init_module().
|
|
|
Definition at line 751 of file emcmot.c. Referenced by emcmotCommandHandler().
|
|
|
Definition at line 689 of file emcmot.c. Referenced by emcmotController(), and init_module().
|
|
|
Definition at line 709 of file emcmot.c. Referenced by emcmotController(), and init_module().
|
|
|
|
|
|
Definition at line 701 of file emcmot.c. Referenced by emcmotController(), and init_module().
|
|
|
Definition at line 705 of file emcmot.c. Referenced by emcmotController(), and init_module().
|
|
|
|
|
|
Definition at line 697 of file emcmot.c. Referenced by emcmotController(), and init_module().
|
|
|
Definition at line 663 of file emcmot.c. Referenced by emcmotController(), and init_module().
|
|
|
Definition at line 675 of file emcmot.c. Referenced by emcmotController(), and init_module().
|
|
|
Definition at line 659 of file emcmot.c. Referenced by emcmotCommandHandler(), emcmotController(), and init_module().
|
|
|
Definition at line 671 of file emcmot.c. Referenced by emcmotController(), and init_module().
|
|
|
Definition at line 667 of file emcmot.c. Referenced by emcmotController(), and init_module().
|
|
|
|
|
|
|
|
|
Definition at line 640 of file emcmot.c. Referenced by cleanup_module(), getArgs(), init_module(), main(), sqAbort(), sqAddCircle(), sqAddLine(), sqBackwardLinkSegment(), sqClearQueue(), sqForwardLinkSegment(), sqGetDepth(), sqGetID(), sqGetMaxAcc(), sqGetPosition(), sqGetVel(), sqGiveCornerVelocity(), sqGiveMaxInc(), sqGiveMinAmaxTan(), sqInitQueue(), sqIsDone(), sqIsPaused(), sqIsQueueFull(), sqIsStepping(), sqLinkCriterion(), sqLinkSegments(), sqPause(), sqPlanSegment(), sqPreprocessSegment(), sqResume(), sqRunCycle(), sqSetCycleTime(), sqSetFeed(), sqSetFeedOverride(), sqSetMaxAcc(), sqSetMaxFeedOverride(), sqSetPos(), sqSetVmax(), sqStep(), and sqTrashQueue().
|
|
|
Definition at line 644 of file emcmot.c. Referenced by emcmotCommandHandler(), init_module(), setServoCycleTime(), and setTrajCycleTime().
00645 {
00646 if(emcmotConfig->head == emcmotConfig->tail) {
00647 emcmotConfig->config_num++;
00648 emcmotStatus->config_num = emcmotConfig->config_num;
00649 emcmotConfig->head++;
00650 }
00651 }
|
|
|
Definition at line 437 of file emcmot.c. 00437 : emcmot.c,v 1.56 2001/11/08 23:55:47 paul_c Exp $";
00438
00439 #ifdef rtai
00440 static RTIME rtaiTickPeriod,now;
00441 static long rtaiTickPeriod_long;
00442 #endif
00443
00444 #ifdef STEPPER_MOTORS
00445
00446 /* FIXME-- shouldn't hard code parallel port, use ext intf instead */
00447 #include "parport.h"
00448
00449 /* value of compensator output below which it's effectively off, so that
00450 the frequency generator can be turned off */
00451 #define OUTPUT_DELTA 1.0e-6
00452
00453 #endif /* STEPPER_MOTORS */
00454
00455 #if ((defined(rtlinux2) || defined(RTLINUX_V2)) && !defined(CONFIG_RTL_USE_V1_API)) || defined(RTLINUX_V3)
00456 #define USE_RTL2
00457 #endif
00458
00459 #ifdef USE_RTL2
00460 #include <rtl.h>
00461 #include <time.h>
00462 #include "mbuff.h"
00463 #endif
00464
00465 #ifdef SIMULATED_MOTORS
00466 #include "sim.h" /* simMotInit() */
00467 #endif
00468
00469 /* lpg changed period from 20000 to avoid flattening a P133 */
00470 /* this is programmable in the .ini file, so faster boxes can use 16us */
00471 static int PERIOD = 48000; /* fundamental period for timer interrupts */
00472
00473 #ifndef STEPPER_MOTORS
00474 extern unsigned short STG_BASE_ADDRESS;
00475 extern int FIND_STG_BASE_ADDRESS;
00476 #else
00477 extern unsigned long int PARPORT_IO_ADDRESS;
00478
00479 #define DEFAULT_FREQ_TASK_PRIORITY 1
00480 #define DEFAULT_FREQ_TASK_STACK_SIZE 4096
00481
00482 static int FREQ_TASK_PRIORITY = DEFAULT_FREQ_TASK_PRIORITY;
00483 static int FREQ_TASK_STACK_SIZE = DEFAULT_FREQ_TASK_STACK_SIZE;
00484 #endif
00485
00486 #ifdef rtlinux
00487 #ifdef USE_RTL2
00488 static hrtime_t rtperiod;
00489 #else
00490
00491 static RTIME rtstart;
00492 static RTIME rtperiod;
00493
00494 /* useful conversion from secs to RTIME */
00495 /* RT_TICKS_PER_SEC is 1193180, BTW */
00496 #define SECS_TO_RTIME(secs) ((RTIME) (RT_TICKS_PER_SEC * secs))
00497
00498 #endif
00499 #endif
00500
00501 #if defined(rtlinux) || defined(rtai)
00502 static int iperiod;
00503 #endif
00504
00505 #ifdef rtai
00506 static RTIME iperiod_rtime;
00507 #endif
00508
00509 /* task struct */
00510 #if defined(rtlinux)|| defined(rtai)
00511 #ifdef rtai
00512 static RT_TASK emcmotTask;
00513 #else
00514 #ifdef USE_RTL2
00515 static pthread_t emcmotTask;
00516 #else
00517 static RT_TASK emcmotTask;
00518 #endif
00519 #endif
00520
00521 #ifdef STEPPER_MOTORS
00522 #ifdef rtai
00523 static RT_TASK freqTask;
00524 #else
00525 #ifdef USE_RTL2
00526 static pthread_t freqTask;
00527 #else
00528 static RT_TASK freqTask;
00529 #endif
00530 #endif
00531 #endif
00532 #endif
00533
00534 static int emcmotTask_created = 0;
00535 static int freqTask_created = 0;
00536
00537 #define DEFAULT_EMCMOT_TASK_PRIORITY 2 /* the highest is 1, the lowest is
00538 RT_LOWEST_PRIORITY */
00539 #define DEFAULT_EMCMOT_TASK_STACK_SIZE 8192
00540 static int EMCMOT_TASK_PRIORITY=DEFAULT_EMCMOT_TASK_PRIORITY;
00541 static int EMCMOT_TASK_STACK_SIZE=DEFAULT_EMCMOT_TASK_STACK_SIZE;
00542
00543 /* for RT-Linux, can have watchdog sound port, parallel port bit toggling */
00544 #define SOUND_PORT 0x61
00545 #define SOUND_MASK 0x02
00546 #if defined(rtlinux) || defined(rtai)
00547 static unsigned char soundByte;
00548 #endif
00549
00550 /*
00551 Principles of communication:
00552
00553 Data is copied in or out from the various types of comm mechanisms:
00554 mbuff mapped memory for Linux/RT-Linux, or OS shared memory for Unixes.
00555
00556 emcmotStruct is ptr to this memory.
00557
00558 emcmotCommand points to emcmotStruct->command,
00559 emcmotStatus points to emcmotStruct->status,
00560 emcmotError points to emcmotStruct->error, and
00561 emcmotLog points to emcmotStruct->log.
00562 emcmotComp[] points to emcmotStruct->comp[].
00563 */
00564
00565 /* need to point to command, status, error, and log */
00566 EMCMOT_STRUCT *emcmotStruct;
00567
00568 #ifdef rtlinux
00569 #ifndef realtimeonly
00570 #define realtimeonly
00571 #endif
00572 #endif
00573
00574 #ifdef rtai
00575 #ifndef realtimeonly
00576 #define realtimeonly
00577 #endif
00578 #endif
00579
00580 #ifndef realtimeonly
00581 /* also need to get shared memory id */
00582 static shm_t *shmem = NULL;
00583 #endif
00584
00585 /* ptrs to either buffered copies or direct memory for
00586 command and status */
00587 static EMCMOT_COMMAND *emcmotCommand;
00588 static EMCMOT_STATUS *emcmotStatus;
00589 static EMCMOT_STATUS *emcmotStatus;
00590 static EMCMOT_CONFIG *emcmotConfig;
00591 static EMCMOT_DEBUG *emcmotDebug;
00592 static EMCMOT_ERROR *emcmotError; /* unused for RT_FIFO */
00593 static EMCMOT_LOG *emcmotLog; /* unused for RT_FIFO */
00594 static EMCMOT_COMP *emcmotComp[EMCMOT_MAX_AXIS]; /* unused for RT_FIFO */
00595
00596 static EMCMOT_LOG_STRUCT ls;
00597 static int logSkip = 0; /* how many to skip, for per-cycle logging */
00598 static int loggingAxis = 0; /* record of which axis to log */
00599 static int logIt = 0;
00600 static int logStartTime; /* set when logging is started, and subtracted
00601 off each log time for better resolution */
00602
00603 /* value for world home position */
00604 static EmcPose worldHome = {{0.0, 0.0, 0.0},
00605 0.0, 0.0, 0.0};
|
|
||||||||||||||||
|
Definition at line 2170 of file emcmot.c. Referenced by emcmotController().
02171 {
02172 int index;
02173 double avgint;
02174 double compin;
02175 int lower, upper;
02176 int total;
02177 double *nominal;
02178 double *ptr;
02179 double denom;
02180
02181 /* first adjust nominput by the alter value, before looking it up */
02182 nominput += emcmotComp[axis]->alter;
02183
02184 total = emcmotComp[axis]->total;
02185 if (total < 2) {
02186 return nominput;
02187 }
02188 avgint = emcmotComp[axis]->avgint;
02189 index = (int) (nominput / avgint);
02190 nominal = emcmotComp[axis]->nominal;
02191 if (dir < 0) {
02192 ptr = emcmotComp[axis]->reverse;
02193 }
02194 else {
02195 ptr = emcmotComp[axis]->forward;
02196 }
02197
02198 /* set the comp input to the nominput, by default */
02199 compin = nominput;
02200 lower = upper = 0;
02201 while (index >= 0 && index < total) {
02202 if (nominput > nominal[index]) {
02203 if (index == total - 1) {
02204 /* off the top */
02205 break;
02206 }
02207 else if (nominput <= nominal[index + 1]) {
02208 /* in range */
02209 lower = index;
02210 upper = index + 1;
02211 denom = nominal[upper] - nominal[lower];
02212 if (denom < DBL_MIN) {
02213 compin = nominput;
02214 /* error */
02215 }
02216 else {
02217 compin = ptr[lower] + (nominput - nominal[lower]) * (ptr[upper] - ptr[lower]) / denom;
02218 }
02219 break;
02220 }
02221 else {
02222 /* index too low */
02223 index++;
02224 continue;
02225 }
02226 }
02227 else if (nominput < nominal[index]) {
02228 if (index == 0) {
02229 /* off the bottom */
02230 break;
02231 }
02232 else if (nominput >= nominal[index - 1]) {
02233 /* in range */
02234 lower = index - 1;
02235 upper = index;
02236 denom = nominal[upper] - nominal[lower];
02237 if (denom < DBL_MIN) {
02238 compin = nominput;
02239 /* error */
02240 }
02241 else {
02242 compin = ptr[lower] + (nominput - nominal[lower]) * (ptr[upper] - ptr[lower]) / denom;
02243 }
02244 break;
02245 }
02246 else {
02247 /* index too high */
02248 index--;
02249 continue;
02250 }
02251 }
02252 else {
02253 /* nominput == nominal[index], so return ptr[index] */
02254 compin = ptr[index];
02255 lower = index;
02256 upper = index;
02257 break;
02258 }
02259 }
02260
02261 return compin;
02262 }
|
|
||||||||||||
|
Definition at line 955 of file emcmot.c. 00956 {
00957 if (emcmotStatus->overrideLimits) {
00958 return 1; /* okay to jog when limits overridden */
00959 }
00960
00961 if (axis < 0 ||
00962 axis >= EMCMOT_MAX_AXIS) {
00963 reportError("Can't jog out of range axis %d.",axis);
00964 return 0; /* can't jog out-of-range axis */
00965 }
00966
00967 if (vel > 0.0 &&
00968 GET_AXIS_PSL_FLAG(axis) )
00969 {
00970 reportError("Can't jog axis %d further past max soft limit.",axis);
00971 return 0;
00972 }
00973
00974 if (vel > 0.0 &&
00975 GET_AXIS_PHL_FLAG(axis) )
00976 {
00977 reportError("Can't jog axis %d further past max hard limit.",axis);
00978 return 0;
00979 }
00980
00981 if (vel < 0.0 &&
00982 GET_AXIS_NSL_FLAG(axis) )
00983 {
00984 reportError("Can't jog axis %d further past min soft limit.",axis);
00985 return 0;
00986 }
00987
00988 if (vel < 0.0 &&
00989 GET_AXIS_NHL_FLAG(axis) )
00990 {
00991 reportError("Can't jog axis %d further past min hard limit.",axis);
00992 return 0;
00993 }
00994
00995 /* okay to jog */
00996 return 1;
00997 }
|
|
|
Definition at line 930 of file emcmot.c. Referenced by emcmotCommandHandler().
00931 {
00932 int axis;
00933
00934 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
00935 if (! GET_AXIS_ACTIVE_FLAG(axis)) {
00936 /* if axis is not active, don't even look at its limits */
00937 continue;
00938 }
00939
00940 if (GET_AXIS_PSL_FLAG(axis) ||
00941 GET_AXIS_NSL_FLAG(axis) ||
00942 GET_AXIS_PHL_FLAG(axis) ||
00943 GET_AXIS_NHL_FLAG(axis)) {
00944 return 0;
00945 }
00946 }
00947
00948 return 1;
00949 }
|
|
|
Definition at line 4996 of file emcmot.c. Referenced by main().
04997 {
04998 int axis;
04999
05000 diagnostics("emcmot: cleanup started.\n");
05001
05002 #if 0
05003 /* WPS - There is no mutex mechanism to allow us to modify
05004 this memory without possibly interfering with the running
05005 tasks.
05006 After the tasks are deleted but before the the memory is freed we
05007 will disable amps and run the quits.*/
05008 /* release traj planner space */
05009 if( 0 != emcmotStruct)
05010 {
05011 if(0 != emcmotDebug )
05012 {
05013 tpDelete(&emcmotDebug->queue);
05014 }
05015
05016 /* disable amps */
05017 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
05018 extAmpEnable(axis,
05019 ! GET_AXIS_ENABLE_POLARITY(axis));
05020 }
05021
05022 /* quit board */
05023 extAioQuit();
05024 extDioQuit();
05025 extMotQuit();
05026 }
05027 #endif
05028
05029 #ifdef rtai
05030 stop_rt_timer();
05031 if(emcmotTask_created)
05032 {
05033 diagnostics("emcmot: deleting emcmotTask.\n");
05034 rt_task_delete(&emcmotTask);
05035 emcmotTask_created=0;
05036 }
05037 #ifdef STEPPER_MOTORS
05038 if(freqTask_created)
05039 {
05040 diagnostics("emcmot: deleting freqTask.\n");
05041 rt_task_delete(&freqTask);
05042 freqTask_created=0;
05043 }
05044 #endif
05045 #endif
05046
05047 /* delete control task */
05048 #ifdef rtlinux
05049 #ifdef USE_RTL2
05050 pthread_delete_np(emcmotTask);
05051 #else
05052 rt_task_delete(&emcmotTask);
05053 #endif
05054
05055 #ifdef STEPPER_MOTORS
05056 /* delete stepper motor task */
05057 #ifdef USE_RTL2
05058 pthread_delete_np(freqTask);
05059 #else
05060 rt_task_delete(&freqTask);
05061 #endif
05062 #endif
05063 #endif
05064
05065 /* WPS these were moved from above to avoid a possible mutex problem.*/
05066 /* There is no point in clearing the trajectory queue since the
05067 planner should be dead by now anyway. */
05068 if( emcmotStruct != 0 && emcmotDebug != 0 && emcmotConfig != 0)
05069 {
05070 diagnostics("emcmot: disabling amps\n");
05071 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
05072 extAmpEnable(axis,
05073 ! GET_AXIS_ENABLE_POLARITY(axis));
05074 }
05075
05076 /* quit board */
05077 diagnostics("emcmot: quitting analog, digital and motor interfaces\n");
05078 extAioQuit();
05079 extDioQuit();
05080 extMotQuit();
05081 }
05082
05083 /* free shared memory */
05084 #ifdef rtai
05085 if(emcmotStruct != 0)
05086 {
05087 diagnostics("emcmot: releasing rtai shared memory.\n");
05088 rtai_kfree(SHMEM_KEY);
05089 emcmotStruct = 0;
05090 }
05091 #endif
05092
05093 #ifdef rtlinux
05094 #ifdef USE_RTL2
05095 mbuff_free("emcmotStruct", emcmotStruct);
05096 #else
05097 #if defined(rtlinux2)
05098 iounmap(emcmotStruct);
05099 #else
05100 vfree(emcmotStruct);
05101 #endif
05102 #endif
05103
05104 /* restore oneshot mode */
05105 #ifdef USE_RTL2
05106 rtl_setclockmode(local_clock, RTL_CLOCK_MODE_ONESHOT,0);
05107 #else
05108 rtl_set_oneshot_mode();
05109 #endif
05110 #endif
05111
05112 #if !defined(rtlinux) && !defined(rtai)
05113 /* detach from shmem */
05114 if (NULL != shmem) {
05115 rcs_shm_close(shmem);
05116 shmem = NULL;
05117 }
05118
05119 #endif
05120
05121 #ifdef rtai
05122 rt_umount_rtai();
05123 #endif
05124
05125 /* FIXME-- testing */
05126 diagnostics("emcmot: debounce counts: ");
05127 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
05128 diagnostics("%d ", debouncecount[axis]);
05129 }
05130 diagnostics("\n");
05131
05132 diagnostics("emcmot: cleanup finished.\n");
05133 }
|
|
|
Definition at line 875 of file emcmot.c. Referenced by emcmotCommandHandler().
00876 {
00877 int t;
00878
00879 if (kinType == KINEMATICS_INVERSE_ONLY) {
00880 if (rehomeAll) {
00881 for (t = 0; t < EMCMOT_MAX_AXIS; t++) {
00882 SET_AXIS_HOMED_FLAG(t, 0);
00883 }
00884 }
00885 else {
00886 SET_AXIS_HOMED_FLAG(axis, 0);
00887 }
00888 }
00889 if (NULL != emcmotDebug) {
00890 emcmotDebug->allHomed = 0;
00891 }
00892 }
|
|
|
Definition at line 1078 of file emcmot.c. Referenced by emcmotController().
01079 {
01080 int axis;
01081 int valid;
01082
01083 /* check for split read */
01084 if (emcmotCommand->head != emcmotCommand->tail) {
01085 emcmotDebug->split++;
01086 return 0; /* not really an error */
01087 }
01088
01089 if (emcmotCommand->commandNum != emcmotStatus->commandNumEcho) {
01090 /* increment head count-- we'll be modifying emcmotStatus */
01091 emcmotStatus->head++;
01092 emcmotDebug->head++;
01093
01094 /* got a new command-- echo command and number... */
01095 emcmotStatus->commandEcho = emcmotCommand->command;
01096 emcmotStatus->commandNumEcho = emcmotCommand->commandNum;
01097
01098 /* clear status value by default */
01099 emcmotStatus->commandStatus = EMCMOT_COMMAND_OK;
01100
01101 /* log it, if appropriate */
01102 if (emcmotStatus->logStarted &&
01103 emcmotStatus->logType == EMCMOT_LOG_TYPE_CMD) {
01104 ls.item.cmd.time = etime(); /* don't subtract off logStartTime,
01105 since we want an absolute time value */
01106 ls.item.cmd.command = emcmotCommand->command;
01107 ls.item.cmd.commandNum = emcmotCommand->commandNum;
01108 emcmotLogAdd(emcmotLog, ls);
01109 emcmotStatus->logPoints = emcmotLog->howmany;
01110 }
01111
01112 /* ...and process command */
01113 switch (emcmotCommand->command) {
01114 case EMCMOT_FREE:
01115 /* change the mode to free axis motion */
01116 /* can be done at any time */
01117 /* reset the emcmotDebug->coordinating flag to defer transition to
01118 controller cycle */
01119 emcmotDebug->coordinating = 0;
01120 emcmotDebug->teleoperating = 0;
01121 break;
01122
01123 case EMCMOT_COORD:
01124 /* change the mode to coordinated axis motion */
01125 /* can be done at any time */
01126 /* set the emcmotDebug->coordinating flag to defer transition to
01127 controller cycle */
01128 emcmotDebug->coordinating = 1;
01129 emcmotDebug->teleoperating = 0;
01130 if (kinType != KINEMATICS_IDENTITY) {
01131 if (!emcmotDebug->allHomed) {
01132 reportError("all axes must be homed before going into coordinated mode");
01133 emcmotDebug->coordinating = 0;
01134 break;
01135 }
01136 }
01137 break;
01138
01139 case EMCMOT_TELEOP:
01140 /* change the mode to teleop motion */
01141 /* can be done at any time */
01142 /* set the emcmotDebug->teleoperating flag to defer transition to
01143 controller cycle */
01144 emcmotDebug->teleoperating = 1;
01145 if (kinType != KINEMATICS_IDENTITY) {
01146 if (! emcmotDebug->allHomed) {
01147 reportError("all axes must be homed before going into teleop mode");
01148 emcmotDebug->teleoperating = 0;
01149 break;
01150 }
01151
01152 }
01153 break;
01154
01155 case EMCMOT_SET_NUM_AXES:
01156 /* set the global NUM_AXES, which must be between 1 and
01157 EMCMOT_MAX_AXIS, inclusive */
01158 axis = emcmotCommand->axis;
01159 /* note that this comparison differs from the check on the
01160 range of 'axis' in most other places, since those checks
01161 are for a value to be used as an index and here it's a value
01162 to be used as a counting number. The indenting is different
01163 here so as not to match macro editing on that other bunch. */
01164 if (axis <= 0 ||
01165 axis > EMCMOT_MAX_AXIS) {
01166 break;
01167 }
01168 NUM_AXES = axis;
01169 break;
01170
01171 case EMCMOT_SET_WORLD_HOME:
01172 worldHome = emcmotCommand->pos;
01173 break;
01174
01175 case EMCMOT_SET_JOINT_HOME:
01176 axis = emcmotCommand->axis;
01177 if (axis < 0 ||
01178 axis >= EMCMOT_MAX_AXIS) {
01179 break;
01180 }
01181 emcmotDebug->jointHome[axis] = emcmotCommand->offset; /* FIXME-- use 'home' instead */
01182 break;
01183
01184 case EMCMOT_SET_HOME_OFFSET:
01185 MARK_EMCMOT_CONFIG_CHANGE();
01186 axis = emcmotCommand->axis;
01187 if (axis < 0 ||
01188 axis >= EMCMOT_MAX_AXIS) {
01189 break;
01190 }
01191 emcmotConfig->homeOffset[axis] = emcmotCommand->offset;
01192 break;
01193
01194 case EMCMOT_OVERRIDE_LIMITS:
01195 if (emcmotCommand->axis < 0) {
01196 /* don't override limits */
01197 emcmotStatus->overrideLimits = 0;
01198 }
01199 else {
01200 emcmotStatus->overrideLimits = 1;
01201 }
01202 emcmotDebug->overriding = 0;
01203 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
01204 SET_AXIS_ERROR_FLAG(axis, 0);
01205 }
01206 break;
01207
01208 case EMCMOT_SET_TRAJ_CYCLE_TIME:
01209 /* set the cycle time for trajectory calculations */
01210 /* really should be done only at startup before
01211 controller is run, but at least it requires
01212 no active motions and the interpolators need
01213 to be cleared */
01214 setTrajCycleTime(emcmotCommand->cycleTime);
01215 break;
01216
01217 case EMCMOT_SET_SERVO_CYCLE_TIME:
01218 /* set the cycle time for servo calculations, which is the
01219 period for emcmotController execution */
01220 /* really should be done only at startup before
01221 controller is run, but at least it requires
01222 no active motions and the interpolators need
01223 to be cleared */
01224 #ifdef rtai
01225 if(rtaiTickPeriod > 0)
01226 {
01227 rtaiTickPeriod_long= (long) rtaiTickPeriod;
01228 iperiod = nano2count((int) (1e9* emcmotCommand->cycleTime));
01229
01230 if ( iperiod < rtaiTickPeriod_long)
01231 {
01232 iperiod = rtaiTickPeriod_long;
01233 }
01234 iperiod /= rtaiTickPeriod_long;
01235 iperiod *= rtaiTickPeriod_long;
01236 iperiod_rtime = (RTIME) iperiod;
01237 now = rt_get_time();
01238 rt_task_make_periodic(&emcmotTask,now+rtaiTickPeriod,iperiod_rtime);
01239 setServoCycleTime(count2nano(iperiod)*1e-9);
01240 }
01241 #else
01242
01243 #ifdef rtlinux
01244 #ifdef USE_RTL2
01245 iperiod = (HRTICKS_PER_SEC * emcmotCommand->cycleTime);
01246 #else
01247 iperiod = (RT_TICKS_PER_SEC * emcmotCommand->cycleTime);
01248 #endif
01249
01250 /* make it an even multiple of fundamental period */
01251 iperiod = iperiod / PERIOD;
01252 iperiod = iperiod * PERIOD;
01253 if (iperiod < PERIOD) {
01254 iperiod = PERIOD;
01255 }
01256 #ifdef USE_RTL2
01257 rtperiod = (hrtime_t) iperiod;
01258 #else
01259 rtperiod = (RTIME) iperiod;
01260 #endif
01261
01262 #ifdef USE_RTL2
01263 pthread_make_periodic_np(emcmotTask,
01264 gethrtime() + rtperiod,
01265 rtperiod);
01266 #else
01267 rt_task_make_periodic(&emcmotTask,
01268 rt_get_time() + rtperiod,
01269 rtperiod);
01270 #endif
01271
01272 #ifdef USE_RTL2
01273 setServoCycleTime(((double) iperiod) / ((double) HRTICKS_PER_SEC));
01274 #else
01275 setServoCycleTime(((double) iperiod) / ((double) RT_TICKS_PER_SEC));
01276 #endif
01277 #else
01278 setServoCycleTime(emcmotCommand->cycleTime);
01279 #endif /* rtlinux */
01280 #endif /* rtai*/
01281 break;
01282
01283 case EMCMOT_SET_POSITION_LIMITS:
01284 MARK_EMCMOT_CONFIG_CHANGE();
01285 /* set the position limits for the axis */
01286 /* can be done at any time */
01287 axis = emcmotCommand->axis;
01288 if (axis < 0 ||
01289 axis >= EMCMOT_MAX_AXIS) {
01290 break;
01291 }
01292 emcmotConfig->minLimit[axis] = emcmotCommand->minLimit;
01293 emcmotConfig->maxLimit[axis] = emcmotCommand->maxLimit;
01294 break;
01295
01296 case EMCMOT_SET_OUTPUT_LIMITS:
01297 MARK_EMCMOT_CONFIG_CHANGE();
01298 /* set the output limits for the axis */
01299 /* can be done at any time */
01300 axis = emcmotCommand->axis;
01301 if (axis < 0 ||
01302 axis >= EMCMOT_MAX_AXIS) {
01303 break;
01304 }
01305
01306 emcmotConfig->minOutput[axis] = emcmotCommand->minLimit;
01307 emcmotConfig->maxOutput[axis] = emcmotCommand->maxLimit;
01308 break;
01309
01310 case EMCMOT_SET_OUTPUT_SCALE:
01311 axis = emcmotCommand->axis;
01312 if (axis < 0 ||
01313 axis >= EMCMOT_MAX_AXIS ||
01314 emcmotCommand->scale == 0) {
01315 break;
01316 }
01317 emcmotStatus->outputScale[axis] = emcmotCommand->scale;
01318 emcmotStatus->outputOffset[axis] = emcmotCommand->offset;
01319 emcmotDebug->inverseOutputScale[axis] = 1.0 / emcmotStatus->outputScale[axis];
01320 break;
01321
01322 case EMCMOT_SET_INPUT_SCALE:
01323 /*
01324 change the scale factor for the position input, e.g.,
01325 encoder counts per unit. Note that this is not a good idea
01326 once things have gotten underway, since the axis will
01327 jump servo to the "new" position, the gains will no longer
01328 be appropriate, etc.
01329 */
01330 axis = emcmotCommand->axis;
01331 if (axis < 0 ||
01332 axis >= EMCMOT_MAX_AXIS ||
01333 emcmotCommand->scale == 0.0) {
01334 break;
01335 }
01336 #if 0
01337 /* adjust last saved input value to match this one, so we
01338 don't get a spurious following error */
01339 emcmotDebug->oldInput[axis] = emcmotDebug->oldInput[axis] * emcmotStatus->inputScale[axis] +
01340 emcmotStatus->inputOffset[axis]; /* temp calc */
01341 emcmotDebug->oldInput[axis] = (emcmotDebug->oldInput[axis] - emcmotCommand->offset) /
01342 emcmotCommand->scale;
01343 #endif
01344 emcmotDebug->oldInputValid[axis] = 0;
01345
01346 /* now make them active */
01347 emcmotStatus->inputScale[axis] = emcmotCommand->scale;
01348 emcmotStatus->inputOffset[axis] = emcmotCommand->offset;
01349 emcmotDebug->inverseInputScale[axis] = 1.0 / emcmotStatus->inputScale[axis];
01350
01351 break;
01352
01353 /*
01354 Max and min ferror work like this:
01355 limiting ferror is determined by slope of ferror line,
01356 = maxFerror/limitVel
01357 -> limiting ferror = maxFerror/limitVel * vel.
01358 If ferror < minFerror then OK else
01359 if ferror < limiting ferror then OK else ERROR
01360 */
01361
01362 case EMCMOT_SET_MAX_FERROR:
01363 MARK_EMCMOT_CONFIG_CHANGE();
01364 axis = emcmotCommand->axis;
01365 if (axis < 0 ||
01366 axis >= EMCMOT_MAX_AXIS ||
01367 emcmotCommand->maxFerror < 0.0) {
01368 break;
01369 }
01370 emcmotConfig->maxFerror[axis] = emcmotCommand->maxFerror;
01371 break;
01372
01373 case EMCMOT_SET_MIN_FERROR:
01374 MARK_EMCMOT_CONFIG_CHANGE();
01375 axis = emcmotCommand->axis;
01376 if (axis < 0 ||
01377 axis >= EMCMOT_MAX_AXIS ||
01378 emcmotCommand->minFerror < 0.0) {
01379 break;
01380 }
01381 emcmotConfig->minFerror[axis] = emcmotCommand->minFerror;
01382 break;
01383
01384 case EMCMOT_JOG_CONT:
01385 /* do a continuous jog, implemented as an incremental
01386 jog to the software limit, or the full range of travel
01387 if software limits don't yet apply because we're not homed */
01388
01389 /* check axis range */
01390 axis = emcmotCommand->axis;
01391 if (axis < 0 ||
01392 axis >= EMCMOT_MAX_AXIS) {
01393 break;
01394 }
01395
01396 /* requires no motion, in free mode, enable on */
01397 if (GET_MOTION_COORD_FLAG() )
01398 {
01399 reportError("Can't jog axis in coordinated mode.");
01400 SET_AXIS_ERROR_FLAG(axis, 1);
01401 break;
01402 }
01403
01404 if( ! GET_MOTION_INPOS_FLAG() )
01405 {
01406 reportError("Can't jog axis when not in position.");
01407 SET_AXIS_ERROR_FLAG(axis, 1);
01408 break;
01409 }
01410
01411 if( ! GET_MOTION_ENABLE_FLAG()) {
01412 reportError("Can't jog axis when not enabled.");
01413 SET_AXIS_ERROR_FLAG(axis, 1);
01414 break;
01415 }
01416
01417 /* don't jog further onto limits */
01418 if (! checkJog(axis, emcmotCommand->vel)) {
01419 SET_AXIS_ERROR_FLAG(axis, 1);
01420 break;
01421 }
01422
01423 if (emcmotCommand->vel > 0.0) {
01424 if (GET_AXIS_HOMED_FLAG(axis)) {
01425 emcmotDebug->freePose.tran.x = emcmotConfig->maxLimit[axis];
01426 }
01427 else {
01428 emcmotDebug->freePose.tran.x = AXRANGE(axis);
01429 }
01430 }
01431 else {
01432 if (GET_AXIS_HOMED_FLAG(axis)) {
01433 emcmotDebug->freePose.tran.x = emcmotConfig->minLimit[axis];
01434 }
01435 else {
01436 emcmotDebug->freePose.tran.x = - AXRANGE(axis);
01437 }
01438 }
01439
01440 tpSetVmax(&emcmotDebug->freeAxis[axis], fabs(emcmotCommand->vel));
01441 tpAddLine(&emcmotDebug->freeAxis[axis], emcmotDebug->freePose);
01442 SET_AXIS_ERROR_FLAG(axis, 0);
01443 /* clear axis homed flag(s) if we don't have forward kins.
01444 Otherwise, a transition into coordinated mode will incorrectly
01445 assume the homed position. Do all if they've all been moved
01446 since homing, otherwise just do this one */
01447 clearHomes(axis);
01448 break;
01449
01450 case EMCMOT_JOG_INCR:
01451 /* do an incremental jog */
01452
01453 /* check axis range */
01454 axis = emcmotCommand->axis;
01455 if (axis < 0 ||
01456 axis >= EMCMOT_MAX_AXIS) {
01457 break;
01458 }
01459
01460 /* requires no motion, in free mode, enable on */
01461 if (GET_MOTION_COORD_FLAG() ||
01462 ! GET_MOTION_INPOS_FLAG() ||
01463 ! GET_MOTION_ENABLE_FLAG()) {
01464 SET_AXIS_ERROR_FLAG(axis, 1);
01465 break;
01466 }
01467
01468 /* don't jog further onto limits */
01469 if (! checkJog(axis, emcmotCommand->vel)) {
01470 SET_AXIS_ERROR_FLAG(axis, 1);
01471 break;
01472 }
01473
01474 if (emcmotCommand->vel > 0.0) {
01475 emcmotDebug->freePose.tran.x = emcmotDebug->jointPos[axis] + emcmotCommand->offset; /* FIXME-- use 'goal' instead */
01476 if (GET_AXIS_HOMED_FLAG(axis)) {
01477 if (emcmotDebug->freePose.tran.x > emcmotConfig->maxLimit[axis]) {
01478 emcmotDebug->freePose.tran.x = emcmotConfig->maxLimit[axis];
01479 }
01480 }
01481 }
01482 else {
01483 emcmotDebug->freePose.tran.x = emcmotDebug->jointPos[axis] - emcmotCommand->offset; /* FIXME-- use 'goal' instead */
01484 if (GET_AXIS_HOMED_FLAG(axis)) {
01485 if (emcmotDebug->freePose.tran.x < emcmotConfig->minLimit[axis]) {
01486 emcmotDebug->freePose.tran.x = emcmotConfig->minLimit[axis];
01487 }
01488 }
01489 }
01490
01491 tpSetVmax(&emcmotDebug->freeAxis[axis], fabs(emcmotCommand->vel));
01492 tpAddLine(&emcmotDebug->freeAxis[axis], emcmotDebug->freePose);
01493 SET_AXIS_ERROR_FLAG(axis, 0);
01494 /* clear axis homed flag(s) if we don't have forward kins.
01495 Otherwise, a transition into coordinated mode will incorrectly
01496 assume the homed position. Do all if they've all been moved
01497 since homing, otherwise just do this one */
01498 clearHomes(axis);
01499
01500 break;
01501
01502 case EMCMOT_JOG_ABS:
01503 /* do an absolute jog */
01504
01505 /* check axis range */
01506 axis = emcmotCommand->axis;
01507 if (axis < 0 ||
01508 axis >= EMCMOT_MAX_AXIS) {
01509 break;
01510 }
01511
01512 /* requires no motion, in free mode, enable on */
01513 if (GET_MOTION_COORD_FLAG() ||
01514 ! GET_MOTION_INPOS_FLAG() ||
01515 ! GET_MOTION_ENABLE_FLAG()) {
01516 SET_AXIS_ERROR_FLAG(axis, 1);
01517 break;
01518 }
01519
01520 /* don't jog further onto limits */
01521 if (! checkJog(axis, emcmotCommand->vel)) {
01522 SET_AXIS_ERROR_FLAG(axis, 1);
01523 break;
01524 }
01525
01526 emcmotDebug->freePose.tran.x = emcmotCommand->offset; /* FIXME-- use 'goal' instead */
01527 if (GET_AXIS_HOMED_FLAG(axis)) {
01528 if (emcmotDebug->freePose.tran.x > emcmotConfig->maxLimit[axis]) {
01529 emcmotDebug->freePose.tran.x = emcmotConfig->maxLimit[axis];
01530 }
01531 else if (emcmotDebug->freePose.tran.x < emcmotConfig->minLimit[axis]) {
01532 emcmotDebug->freePose.tran.x = emcmotConfig->minLimit[axis];
01533 }
01534 }
01535
01536 tpSetVmax(&emcmotDebug->freeAxis[axis], fabs(emcmotCommand->vel));
01537 tpAddLine(&emcmotDebug->freeAxis[axis], emcmotDebug->freePose);
01538 SET_AXIS_ERROR_FLAG(axis, 0);
01539 /* clear axis homed flag(s) if we don't have forward kins.
01540 Otherwise, a transition into coordinated mode will incorrectly
01541 assume the homed position. Do all if they've all been moved
01542 since homing, otherwise just do this one */
01543 clearHomes(axis);
01544
01545 break;
01546
01547 case EMCMOT_SET_TERM_COND:
01548 /* sets termination condition for motion emcmotDebug->queue */
01549 tpSetTermCond(&emcmotDebug->queue, emcmotCommand->termCond);
01550 break;
01551
01552 case EMCMOT_SET_LINE:
01553 /* emcmotDebug->queue up a linear move */
01554 /* requires coordinated mode, enable off, not on limits */
01555 if (! GET_MOTION_COORD_FLAG() ||
01556 ! GET_MOTION_ENABLE_FLAG()) {
01557 reportError("need to be enabled, in coord mode for linear move");
01558 emcmotStatus->commandStatus = EMCMOT_COMMAND_INVALID_COMMAND;
01559 SET_MOTION_ERROR_FLAG(1);
01560 break;
01561 }
01562 else if (! inRange(emcmotCommand->pos)) {
01563 reportError("linear move %d out of range",
01564 emcmotCommand->id);
01565 emcmotStatus->commandStatus = EMCMOT_COMMAND_INVALID_PARAMS;
01566 tpAbort(&emcmotDebug->queue);
01567 SET_MOTION_ERROR_FLAG(1);
01568 break;
01569 }
01570 else if (! checkLimits()) {
01571 reportError("can't do linear move with limits exceeded");
01572 emcmotStatus->commandStatus = EMCMOT_COMMAND_INVALID_PARAMS;
01573 tpAbort(&emcmotDebug->queue);
01574 SET_MOTION_ERROR_FLAG(1);
01575 break;
01576 }
01577
01578 /* append it to the emcmotDebug->queue */
01579 tpSetId(&emcmotDebug->queue, emcmotCommand->id);
01580 if (-1 == tpAddLine(&emcmotDebug->queue, emcmotCommand->pos)) {
01581 reportError("can't add linear move");
01582 emcmotStatus->commandStatus = EMCMOT_COMMAND_BAD_EXEC;
01583 tpAbort(&emcmotDebug->queue);
01584 SET_MOTION_ERROR_FLAG(1);
01585 break;
01586 }
01587 else {
01588 SET_MOTION_ERROR_FLAG(0);
01589 /* set flag that indicates all axes need rehoming, if any axis
01590 is moved in joint mode, for machines with no forward kins */
01591 rehomeAll = 1;
01592 }
01593 break;
01594
01595 case EMCMOT_SET_CIRCLE:
01596 /* emcmotDebug->queue up a circular move */
01597 /* requires coordinated mode, enable on, not on limits */
01598 if (! GET_MOTION_COORD_FLAG() ||
01599 ! GET_MOTION_ENABLE_FLAG()) {
01600 reportError("need to be enabled, in coord mode for circular move");
01601 emcmotStatus->commandStatus = EMCMOT_COMMAND_INVALID_COMMAND;
01602 SET_MOTION_ERROR_FLAG(1);
01603 break;
01604 }
01605 else if (! inRange(emcmotCommand->pos)) {
01606 reportError("circular move %d out of range",
01607 emcmotCommand->id);
01608 emcmotStatus->commandStatus = EMCMOT_COMMAND_INVALID_PARAMS;
01609 tpAbort(&emcmotDebug->queue);
01610 SET_MOTION_ERROR_FLAG(1);
01611 break;
01612 }
01613 else if (! checkLimits()) {
01614 reportError("can't do circular move with limits exceeded");
01615 emcmotStatus->commandStatus = EMCMOT_COMMAND_INVALID_PARAMS;
01616 tpAbort(&emcmotDebug->queue);
01617 SET_MOTION_ERROR_FLAG(1);
01618 break;
01619 }
01620
01621 /* append it to the emcmotDebug->queue */
01622 tpSetId(&emcmotDebug->queue, emcmotCommand->id);
01623 if (-1 ==
01624 tpAddCircle(&emcmotDebug->queue, emcmotCommand->pos,
01625 emcmotCommand->center, emcmotCommand->normal,
01626 emcmotCommand->turn)) {
01627 reportError("can't add circular move");
01628 emcmotStatus->commandStatus = EMCMOT_COMMAND_BAD_EXEC;
01629 tpAbort(&emcmotDebug->queue);
01630 SET_MOTION_ERROR_FLAG(1);
01631 break;
01632 }
01633 else {
01634 SET_MOTION_ERROR_FLAG(0);
01635 /* set flag that indicates all axes need rehoming, if any axis
01636 is moved in joint mode, for machines with no forward kins */
01637 rehomeAll = 1;
01638 }
01639 break;
01640
01641 case EMCMOT_SET_VEL:
01642 /* set the velocity for subsequent moves */
01643 /* can do it at any time */
01644 emcmotStatus->vel = emcmotCommand->vel;
01645 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
01646 tpSetVmax(&emcmotDebug->freeAxis[axis], emcmotStatus->vel);
01647 }
01648 tpSetVmax(&emcmotDebug->queue, emcmotStatus->vel);
01649 break;
01650
01651 case EMCMOT_SET_VEL_LIMIT:
01652 MARK_EMCMOT_CONFIG_CHANGE();
01653 /* set the absolute max velocity for all subsequent moves */
01654 /* can do it at any time */
01655 emcmotConfig->limitVel = emcmotCommand->vel;
01656 tpSetVlimit(&emcmotDebug->queue, emcmotConfig->limitVel);
01657 break;
01658
01659 case EMCMOT_SET_AXIS_VEL_LIMIT:
01660 MARK_EMCMOT_CONFIG_CHANGE();
01661 /* check axis range */
01662 axis = emcmotCommand->axis;
01663 if (axis < 0 ||
01664 axis >= EMCMOT_MAX_AXIS) {
01665 break;
01666 }
01667 tpSetVlimit(&emcmotDebug->freeAxis[axis], emcmotCommand->vel);
01668 emcmotConfig->axisLimitVel[axis] = emcmotCommand->vel;
01669 emcmotDebug->bigVel[axis] = 10 * emcmotCommand->vel;
01670 break;
01671
01672 case EMCMOT_SET_HOMING_VEL:
01673 MARK_EMCMOT_CONFIG_CHANGE();
01674 /* set the homing velocity */
01675 /* can do it at any time */
01676 /* sign of vel should set polarity, and mag-sign are recorded */
01677
01678 /* check axis range */
01679 axis = emcmotCommand->axis;
01680 if (axis < 0 ||
01681 axis >= EMCMOT_MAX_AXIS) {
01682 break;
01683 }
01684
01685 if (emcmotCommand->vel < 0.0) {
01686 emcmotConfig->homingVel[axis] = - emcmotCommand->vel;
01687 SET_AXIS_HOMING_POLARITY(axis, 0);
01688 }
01689 else {
01690 emcmotConfig->homingVel[axis] = emcmotCommand->vel;
01691 SET_AXIS_HOMING_POLARITY(axis, 1);
01692 }
01693 break;
01694
01695 case EMCMOT_SET_ACC:
01696 /* set the max acceleration */
01697 /* can do it at any time */
01698 emcmotStatus->acc = emcmotCommand->acc;
01699 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
01700 tpSetAmax(&emcmotDebug->freeAxis[axis], emcmotStatus->acc);
01701 }
01702 tpSetAmax(&emcmotDebug->queue, emcmotStatus->acc);
01703 break;
01704
01705 case EMCMOT_PAUSE:
01706 /* pause the motion */
01707 /* can happen at any time */
01708 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
01709 tpPause(&emcmotDebug->freeAxis[axis]);
01710 }
01711 tpPause(&emcmotDebug->queue);
01712 emcmotStatus->paused = 1;
01713 break;
01714
01715 case EMCMOT_RESUME:
01716 /* resume paused motion */
01717 /* can happen at any time */
01718 emcmotDebug->stepping = 0;
01719 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
01720 tpResume(&emcmotDebug->freeAxis[axis]);
01721 }
01722 tpResume(&emcmotDebug->queue);
01723 emcmotStatus->paused = 0;
01724 break;
01725
01726 case EMCMOT_STEP:
01727 /* resume paused motion until id changes */
01728 /* can happen at any time */
01729 emcmotDebug->idForStep = emcmotStatus->id;
01730 emcmotDebug->stepping = 1;
01731 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
01732 tpResume(&emcmotDebug->freeAxis[axis]);
01733 }
01734 tpResume(&emcmotDebug->queue);
01735 emcmotStatus->paused = 0;
01736 break;
01737
01738 case EMCMOT_SCALE:
01739 /* override speed */
01740 /* can happen at any time */
01741 if (emcmotCommand->scale < 0.0) {
01742 emcmotCommand->scale = 0.0; /* clamp it */
01743 }
01744 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
01745 tpSetVscale(&emcmotDebug->freeAxis[axis], emcmotCommand->scale);
01746 emcmotStatus->axVscale[axis] = emcmotCommand->scale;
01747 }
01748 tpSetVscale(&emcmotDebug->queue, emcmotCommand->scale);
01749 emcmotStatus->qVscale = emcmotCommand->scale;
01750 break;
01751
01752 case EMCMOT_ABORT:
01753 /* abort motion */
01754 /* can happen at any time */
01755 /* check for coord or free space motion active */
01756 if (GET_MOTION_TELEOP_FLAG()) {
01757 emcmotDebug->teleop_data.desiredVel.tran.x = 0.0;
01758 emcmotDebug->teleop_data.desiredVel.tran.y = 0.0;
01759 emcmotDebug->teleop_data.desiredVel.tran.z = 0.0;
01760 emcmotDebug->teleop_data.desiredVel.a = 0.0;
01761 emcmotDebug->teleop_data.desiredVel.b = 0.0;
01762 emcmotDebug->teleop_data.desiredVel.c = 0.0;
01763 }
01764 else if (GET_MOTION_COORD_FLAG()) {
01765 tpAbort(&emcmotDebug->queue);
01766 SET_MOTION_ERROR_FLAG(0);
01767 }
01768 else {
01769 /* check axis range */
01770 axis = emcmotCommand->axis;
01771 if (axis < 0 ||
01772 axis >= EMCMOT_MAX_AXIS) {
01773 break;
01774 }
01775 tpAbort(&emcmotDebug->freeAxis[axis]);
01776 SET_AXIS_HOMING_FLAG(axis, 0);
01777 SET_AXIS_ERROR_FLAG(axis, 0);
01778 }
01779 /* FIXME-- testing dout */
01780 extMotDout(MOT_DOUT_ABORT_VAL);
01781 break;
01782
01783 case EMCMOT_DISABLE:
01784 /* go into disable */
01785 /* can happen at any time */
01786 /* reset the emcmotDebug->enabling flag to defer disable until
01787 controller cycle (it *will* be honored) */
01788 emcmotDebug->enabling = 0;
01789 if (kinType == KINEMATICS_INVERSE_ONLY) {
01790 emcmotDebug->teleoperating = 0;
01791 emcmotDebug->coordinating = 0;
01792 }
01793 break;
01794
01795 case EMCMOT_ENABLE:
01796 /* come out of disable */
01797 /* can happen at any time */
01798 /* set the emcmotDebug->enabling flag to defer enable
01799 until controller cycle */
01800 emcmotDebug->enabling = 1;
01801 if (kinType == KINEMATICS_INVERSE_ONLY) {
01802 emcmotDebug->teleoperating = 0;
01803 emcmotDebug->coordinating = 0;
01804 }
01805 break;
01806
01807 case EMCMOT_SET_PID:
01808 MARK_EMCMOT_CONFIG_CHANGE();
01809 /* configure the PID gains */
01810 axis = emcmotCommand->axis;
01811 if (axis < 0 ||
01812 axis >= EMCMOT_MAX_AXIS) {
01813 break;
01814 }
01815 pidSetGains(&emcmotConfig->pid[axis],
01816 emcmotCommand->pid);
01817 break;
01818
01819 case EMCMOT_ACTIVATE_AXIS:
01820 /* make axis active, so that amps will be enabled when
01821 system is enabled or disabled */
01822 /* can be done at any time */
01823 axis = emcmotCommand->axis;
01824 if (axis < 0 ||
01825 axis >= EMCMOT_MAX_AXIS) {
01826 break;
01827 }
01828 SET_AXIS_ACTIVE_FLAG(axis, 1);
01829 break;
01830
01831 case EMCMOT_DEACTIVATE_AXIS:
01832 /* make axis inactive, so that amps won't be affected when
01833 system is enabled or disabled */
01834 /* can be done at any time */
01835 axis = emcmotCommand->axis;
01836 if (axis < 0 ||
01837 axis >= EMCMOT_MAX_AXIS) {
01838 break;
01839 }
01840 SET_AXIS_ACTIVE_FLAG(axis, 0);
01841 break;
01842
01843 case EMCMOT_ENABLE_AMPLIFIER:
01844 /* enable the amplifier directly, but don't enable calculations */
01845 /* can be done at any time */
01846 axis = emcmotCommand->axis;
01847 if (axis < 0 ||
01848 axis >= EMCMOT_MAX_AXIS) {
01849 break;
01850 }
01851 extAmpEnable(axis, GET_AXIS_ENABLE_POLARITY(axis));
01852 break;
01853
01854 case EMCMOT_DISABLE_AMPLIFIER:
01855 /* disable the axis calculations and amplifier, but don't
01856 disable calculations */
01857 /* can be done at any time */
01858 axis = emcmotCommand->axis;
01859 if (axis < 0 ||
01860 axis >= EMCMOT_MAX_AXIS) {
01861 break;
01862 }
01863 extAmpEnable(axis, ! GET_AXIS_ENABLE_POLARITY(axis));
01864 break;
01865
01866 case EMCMOT_OPEN_LOG:
01867 /* open a data log */
01868 axis = emcmotCommand->axis;
01869 valid = 0;
01870 if (emcmotCommand->logSize > 0 &&
01871 emcmotCommand->logSize <= EMCMOT_LOG_MAX) {
01872 /* handle log-specific data */
01873 switch (emcmotCommand->logType) {
01874 case EMCMOT_LOG_TYPE_AXIS_POS:
01875 case EMCMOT_LOG_TYPE_AXIS_VEL:
01876 case EMCMOT_LOG_TYPE_POS_VOLTAGE:
01877 if (axis >= 0 &&
01878 axis < EMCMOT_MAX_AXIS) {
01879 valid = 1;
01880 }
01881 break;
01882
01883 default:
01884 valid = 1;
01885 break;
01886 }
01887 }
01888
01889 if (valid) {
01890 /* success */
01891 loggingAxis = axis;
01892 emcmotLogInit(emcmotLog,
01893 emcmotCommand->logType,
01894 emcmotCommand->logSize);
01895 emcmotStatus->logOpen = 1;
01896 emcmotStatus->logStarted = 0;
01897 emcmotStatus->logSize = emcmotCommand->logSize;
01898 emcmotStatus->logSkip = emcmotCommand->logSkip;
01899 emcmotStatus->logType = emcmotCommand->logType;
01900 emcmotStatus->logTriggerType = emcmotCommand->logTriggerType;
01901 emcmotStatus->logTriggerVariable = emcmotCommand->logTriggerVariable;
01902 emcmotStatus->logTriggerThreshold = emcmotCommand->logTriggerThreshold;
01903 if (axis >= 0 &&
01904 axis < EMCMOT_MAX_AXIS &&
01905 emcmotStatus->logTriggerType == EMCLOG_DELTA_TRIGGER)
01906 {
01907 switch(emcmotStatus->logTriggerVariable)
01908 {
01909 case EMCLOG_TRIGGER_ON_FERROR:
01910 emcmotStatus->logStartVal = emcmotDebug->ferrorCurrent[loggingAxis];
01911 break;
01912
01913 case EMCLOG_TRIGGER_ON_VOLT:
01914 emcmotStatus->logStartVal = emcmotDebug->rawOutput[loggingAxis];
01915 break;
01916 case EMCLOG_TRIGGER_ON_POS:
01917 emcmotStatus->logStartVal = emcmotDebug->jointPos[loggingAxis];
01918 break;
01919 case EMCLOG_TRIGGER_ON_VEL:
01920 emcmotStatus->logStartVal = emcmotDebug->jointPos[loggingAxis] - emcmotDebug->oldJointPos[loggingAxis];
01921 break;
01922
01923 default:
01924 break;
01925 }
01926 }
01927 }
01928 break;
01929
01930 case EMCMOT_START_LOG:
01931 /* start logging */
01932 /* first ignore triggered log types */
01933 if (emcmotStatus->logType == EMCMOT_LOG_TYPE_POS_VOLTAGE) {
01934 break;
01935 }
01936 /* set the global baseTime, to be subtracted off log times, otherwise
01937 time values are too large for the small increments to appear */
01938 if (emcmotStatus->logOpen &&
01939 emcmotStatus->logTriggerType == EMCLOG_MANUAL_TRIGGER) {
01940 logStartTime = etime();
01941 emcmotStatus->logStarted = 1;
01942 logSkip = 0;
01943 }
01944 break;
01945
01946 case EMCMOT_STOP_LOG:
01947 /* stop logging */
01948 emcmotStatus->logStarted = 0;
01949 break;
01950
01951 case EMCMOT_CLOSE_LOG:
01952 emcmotStatus->logOpen = 0;
01953 emcmotStatus->logStarted = 0;
01954 emcmotStatus->logSize = 0;
01955 emcmotStatus->logSkip = 0;
01956 emcmotStatus->logType = 0;
01957 break;
01958
01959 case EMCMOT_DAC_OUT:
01960 /* write output to dacs directly */
01961 /* will only persist if amplifiers are disabled */
01962 axis = emcmotCommand->axis;
01963 if (axis < 0 ||
01964 axis >= EMCMOT_MAX_AXIS) {
01965 break;
01966 }
01967 /* trigger log, if active */
01968 if (emcmotStatus->logType == EMCMOT_LOG_TYPE_POS_VOLTAGE &&
01969 loggingAxis == axis &&
01970 emcmotStatus->logOpen != 0) {
01971 emcmotStatus->logStarted = 1;
01972 logSkip = 0;
01973 }
01974 emcmotStatus->output[axis] = emcmotCommand->dacOut;
01975 break;
01976
01977 case EMCMOT_HOME:
01978 /* home the specified axis */
01979 /* need to be in free mode, enable on */
01980 /* homing is basically a slow incremental jog to full range */
01981 axis = emcmotCommand->axis;
01982 if (axis < 0 ||
01983 axis >= EMCMOT_MAX_AXIS) {
01984 break;
01985 }
01986 if (GET_MOTION_COORD_FLAG() ||
01987 ! GET_MOTION_ENABLE_FLAG()) {
01988 break;
01989 }
01990
01991 if (GET_AXIS_HOMING_POLARITY(axis)) {
01992 emcmotDebug->freePose.tran.x = + 2.0 * AXRANGE(axis);
01993 }
01994 else {
01995 emcmotDebug->freePose.tran.x = - 2.0 * AXRANGE(axis);
01996 }
01997
01998 tpSetVmax(&emcmotDebug->freeAxis[axis], emcmotConfig->homingVel[axis]);
01999 tpAddLine(&emcmotDebug->freeAxis[axis], emcmotDebug->freePose);
02000 emcmotDebug->homingPhase[axis]=1;
02001 SET_AXIS_HOMING_FLAG(axis, 1);
02002 SET_AXIS_HOMED_FLAG(axis, 0);
02003 break;
02004
02005 case EMCMOT_ENABLE_WATCHDOG:
02006 emcmotDebug->wdEnabling = 1;
02007 emcmotDebug->wdWait = emcmotCommand->wdWait;
02008 if (emcmotDebug->wdWait < 0) {
02009 emcmotDebug->wdWait = 0;
02010 }
02011 break;
02012
02013 case EMCMOT_DISABLE_WATCHDOG:
02014 emcmotDebug->wdEnabling = 0;
02015 break;
02016
02017 case EMCMOT_SET_POLARITY:
02018 MARK_EMCMOT_CONFIG_CHANGE();
02019 axis = emcmotCommand->axis;
02020 if (axis < 0 ||
02021 axis >= EMCMOT_MAX_AXIS) {
02022 break;
02023 }
02024 if (emcmotCommand->level) {
02025 /* normal */
02026 emcmotConfig->axisPolarity[axis] |= emcmotCommand->axisFlag;
02027 }
02028 else {
02029 /* inverted */
02030 emcmotConfig->axisPolarity[axis] &= ~emcmotCommand->axisFlag;
02031 }
02032 break;
02033
02034 #ifdef ENABLE_PROBING
02035 case EMCMOT_SET_PROBE_INDEX:
02036 MARK_EMCMOT_CONFIG_CHANGE();
02037 emcmotConfig->probeIndex = emcmotCommand->probeIndex;
02038 break;
02039
02040 case EMCMOT_SET_PROBE_POLARITY:
02041 MARK_EMCMOT_CONFIG_CHANGE();
02042 emcmotConfig->probePolarity = emcmotCommand->level;
02043 break;
02044
02045 case EMCMOT_CLEAR_PROBE_FLAGS:
02046 emcmotStatus->probeTripped = 0;
02047 emcmotStatus->probing = 1;
02048 break;
02049
02050 case EMCMOT_PROBE:
02051 /* most of this is taken from EMCMOT_SET_LINE */
02052 /* emcmotDebug->queue up a linear move */
02053 /* requires coordinated mode, enable off, not on limits */
02054 if (! GET_MOTION_COORD_FLAG() ||
02055 ! GET_MOTION_ENABLE_FLAG()) {
02056 reportError("need to be enabled, in coord mode for probe move");
02057 emcmotStatus->commandStatus = EMCMOT_COMMAND_INVALID_COMMAND;
02058 SET_MOTION_ERROR_FLAG(1);
02059 break;
02060 }
02061 else if (! inRange(emcmotCommand->pos)) {
02062 reportError("probe move %d out of range",
02063 emcmotCommand->id);
02064 emcmotStatus->commandStatus = EMCMOT_COMMAND_INVALID_PARAMS;
02065 tpAbort(&emcmotDebug->queue);
02066 SET_MOTION_ERROR_FLAG(1);
02067 break;
02068 }
02069 else if (! checkLimits()) {
02070 reportError("can't do probe move with limits exceeded");
02071 emcmotStatus->commandStatus = EMCMOT_COMMAND_INVALID_PARAMS;
02072 tpAbort(&emcmotDebug->queue);
02073 SET_MOTION_ERROR_FLAG(1);
02074 break;
02075 }
02076
02077 /* append it to the emcmotDebug->queue */
02078 tpSetId(&emcmotDebug->queue, emcmotCommand->id);
02079 if (-1 == tpAddLine(&emcmotDebug->queue, emcmotCommand->pos)) {
02080 reportError("can't add probe move");
02081 emcmotStatus->commandStatus = EMCMOT_COMMAND_BAD_EXEC;
02082 tpAbort(&emcmotDebug->queue);
02083 SET_MOTION_ERROR_FLAG(1);
02084 break;
02085 }
02086 else {
02087 emcmotStatus->probeTripped = 0;
02088 emcmotStatus->probing = 1;
02089 SET_MOTION_ERROR_FLAG(0);
02090 /* set flag that indicates all axes need rehoming, if any axis
02091 is moved in joint mode, for machines with no forward kins */
02092 rehomeAll = 1;
02093 }
02094 break;
02095 #endif /* ENABLE_PROBING */
02096
02097 case EMCMOT_SET_TELEOP_VECTOR:
02098 if (! GET_MOTION_TELEOP_FLAG() ||
02099 ! GET_MOTION_ENABLE_FLAG()) {
02100 reportError("need to be enabled, in teleop mode for teleop move");
02101 }
02102 else {
02103 double velmag;
02104 emcmotDebug->teleop_data.desiredVel = emcmotCommand->pos;
02105 pmCartMag(emcmotDebug->teleop_data.desiredVel.tran, &velmag);
02106 if (emcmotDebug->teleop_data.desiredVel.a > velmag) {
02107 velmag = emcmotDebug->teleop_data.desiredVel.a;
02108 }
02109 if (emcmotDebug->teleop_data.desiredVel.b > velmag) {
02110 velmag = emcmotDebug->teleop_data.desiredVel.b;
02111 }
02112 if (emcmotDebug->teleop_data.desiredVel.c > velmag) {
02113 velmag = emcmotDebug->teleop_data.desiredVel.c;
02114 }
02115 if (velmag > emcmotConfig->limitVel) {
02116 pmCartScalMult(emcmotDebug->teleop_data.desiredVel.tran,
02117 emcmotConfig->limitVel/velmag,
02118 &emcmotDebug->teleop_data.desiredVel.tran);
02119 emcmotDebug->teleop_data.desiredVel.a *=
02120 emcmotConfig->limitVel/velmag;
02121 emcmotDebug->teleop_data.desiredVel.b *=
02122 emcmotConfig->limitVel/velmag;
02123 emcmotDebug->teleop_data.desiredVel.c *=
02124 emcmotConfig->limitVel/velmag;
02125 }
02126 /* flag that all joints need to be homed, if any joint
02127 is jogged individually later */
02128 rehomeAll = 1;
02129 }
02130 break;
02131
02132 case EMCMOT_SET_DEBUG:
02133 emcmotConfig->debug = emcmotCommand->debug;
02134 MARK_EMCMOT_CONFIG_CHANGE();
02135 break;
02136
02137 case EMCMOT_SET_AOUT:
02138 tpSetAout(&emcmotDebug->queue, emcmotCommand->out, emcmotCommand->minLimit, emcmotCommand->maxLimit);
02139 break;
02140
02141 case EMCMOT_SET_DOUT:
02142 tpSetDout(&emcmotDebug->queue, emcmotCommand->out, emcmotCommand->start, emcmotCommand->end);
02143 break;
02144
02145 default:
02146 reportError("unrecognized command %d", emcmotCommand->command);
02147 emcmotStatus->commandStatus = EMCMOT_COMMAND_UNKNOWN_COMMAND;
02148 break;
02149 } /* end of: command switch */
02150
02151 /* synch tail count */
02152 emcmotStatus->tail = emcmotStatus->head;
02153 emcmotConfig->tail = emcmotConfig->head;
02154 emcmotDebug->tail = emcmotDebug->head;
02155
02156 } /* end of: if-new-command */
02157
02158 return 0;
02159 }
|
|
|
Definition at line 2277 of file emcmot.c. 02279 {
02280 int first = 1; /* true the first time thru, for initing */
02281 double start, end, delta; /* time stamping */
02282 int homeFlag; /* result of ext read to home switch */
02283 int axis; /* axis loop counter */
02284 int t; /* loop counter if we're in axis loop */
02285 int isLimit; /* result of ext read to limit sw */
02286 int whichCycle; /* 0=none, 1=servo, 2=traj */
02287 int fault;
02288 #ifndef NO_ROUNDING
02289 double numres;
02290 #endif
02291 double thisFerror[EMCMOT_MAX_AXIS] = {0.0};
02292 double limitFerror; /* current scaled ferror */
02293 double magFerror;
02294 double oldbcomp;
02295 int retval;
02296 /* end of backlash stuff */
02297 #ifdef STEPPER_MOTORS
02298 double pdmultfloat;
02299 #endif
02300 #ifdef COMPING
02301 int dir[EMCMOT_MAX_AXIS] = {1}; /* flag for direction, used for axis comp */
02302 #endif /* COMPING */
02303
02304 #if defined(rtai) || defined(rtlinux)
02305 for (;;) {
02306 #endif /* rtai || rtlinux */
02307
02308 #ifdef SIMULATED_MOTORS
02309 #if defined(rtlinux) || defined(rtai)
02310 simMotInit(NULL);
02311 #endif
02312 #endif
02313
02314 #if defined(rtlinux) || defined(rtai)
02315 /* toggle sound port watchdog */
02316
02317 if (emcmotDebug->wdEnabling && ! emcmotDebug->wdEnabled) {
02318 /* just turned WD on */
02319 emcmotDebug->wdCount = emcmotDebug->wdWait;
02320 emcmotDebug->wdToggle = 0;
02321 emcmotDebug->wdEnabled = 1;
02322 }
02323 if (! emcmotDebug->wdEnabling && emcmotDebug->wdEnabled) {
02324 /* just turned WD off */
02325 /* clear the bit */
02326 soundByte = inb(SOUND_PORT);
02327 soundByte &= ~SOUND_MASK;
02328 outb(soundByte, SOUND_PORT);
02329 emcmotDebug->wdEnabled = 0;
02330 }
02331
02332 if (emcmotDebug->wdEnabled && emcmotDebug->wdCount-- <= 0) {
02333 soundByte = inb(SOUND_PORT);
02334 emcmotDebug->wdToggle = ! emcmotDebug->wdToggle;
02335 if (emcmotDebug->wdToggle) {
02336 soundByte |= SOUND_MASK;
02337 }
02338 else {
02339 soundByte &= ~SOUND_MASK;
02340 }
02341 outb(soundByte, SOUND_PORT);
02342 emcmotDebug->wdCount = emcmotDebug->wdWait;
02343 }
02344 #endif /* rtlinux || rtai */
02345
02346 /* record start time */
02347 start = etime();
02348
02349 /* READ COMMAND: */
02350 emcmotCommandHandler();
02351
02352 /* increment head count */
02353 emcmotStatus->head++;
02354
02355 /* READ INPUTS: */
02356
02357 /* latch all encoder feedback into raw input array, done outside
02358 of for-loop on joints below, since it's a single call for all
02359 joints */
02360 extEncoderReadAll(EMCMOT_MAX_AXIS, emcmotDebug->rawInput);
02361
02362 /* process input and read limit switches */
02363 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
02364 /* save old cycle's values */
02365 if (! first && emcmotDebug->oldInputValid[axis] ) {
02366 emcmotDebug->oldInput[axis] = emcmotStatus->input[axis];
02367 }
02368 /* set input, scaled according to input = (raw - offset) / scale */
02369 emcmotStatus->input[axis] =
02370 (emcmotDebug->rawInput[axis] - emcmotStatus->inputOffset[axis]) *
02371 emcmotDebug->inverseInputScale[axis] - emcmotDebug->bcompincr[axis];
02372
02373 #ifdef COMPING
02374 /* adjust feedback using compensation tables */
02375 if (GET_AXIS_HOMED_FLAG(axis)) {
02376 emcmotStatus->input[axis] = axisComp(axis, dir[axis], emcmotStatus->input[axis]);
02377 }
02378 #endif
02379 if (first || !emcmotDebug->oldInputValid[axis] ) {
02380 emcmotDebug->oldInput[axis] = emcmotStatus->input[axis];
02381 emcmotDebug->oldInputValid[axis] = 1;
02382 first = 0;
02383 }
02384
02385 /* debounce bad feedback */
02386 #ifndef SIMULATED_MOTORS
02387 if (fabs(emcmotStatus->input[axis] - emcmotDebug->oldInput[axis]) /
02388 emcmotConfig->servoCycleTime > emcmotDebug->bigVel[axis]) {
02389 /* bad input value-- interpolate last value, up to max debounces,
02390 then hold it */
02391 if (++positionInputDebounce[axis] > POSITION_INPUT_DEBOUNCE) {
02392 /* we haven't exceeded max number of debounces allowed, so
02393 interpolate off the velocity estimate */
02394 emcmotStatus->input[axis] = emcmotDebug->oldInput[axis] +
02395 emcmotDebug->jointVel[axis] * emcmotConfig->servoCycleTime;
02396 }
02397 else {
02398 /* we've exceeded the max number of debounces allowed, so
02399 hold position. We should flag an error here, abort the move,
02400 disable motion, etc. but for now we'll rely on following error
02401 to do this */
02402 emcmotStatus->input[axis] = emcmotDebug->oldInput[axis];
02403 }
02404 /* FIXME-- testing */
02405 debouncecount[axis]++;
02406 }
02407 else {
02408 /* no debounce needed, so reset debounce counter */
02409 positionInputDebounce[axis] = 0;
02410 }
02411 #endif
02412
02413 /* read limit switches and amp fault from external
02414 interface, and set 'emcmotDebug->enabling' to zero if tripped
02415 to cause immediate stop */
02416
02417 /* handle limits */
02418 if (GET_AXIS_ACTIVE_FLAG(axis)) {
02419 extMaxLimitSwitchRead(axis, &isLimit);
02420 if (isLimit == GET_AXIS_PHL_POLARITY(axis)) {
02421 if (++emcmotDebug->maxLimitSwitchCount[axis] > LIMIT_SWITCH_DEBOUNCE) {
02422 SET_AXIS_PHL_FLAG(axis, 1);
02423 emcmotDebug->maxLimitSwitchCount[axis] = LIMIT_SWITCH_DEBOUNCE;
02424 if (emcmotStatus->overrideLimits ||
02425 isHoming()) {
02426 }
02427 else {
02428 SET_AXIS_ERROR_FLAG(axis, 1);
02429 emcmotDebug->enabling = 0;
02430 }
02431 }
02432 }
02433 else {
02434 SET_AXIS_PHL_FLAG(axis, 0);
02435 emcmotDebug->maxLimitSwitchCount[axis] = 0;
02436 }
02437 }
02438 if (GET_AXIS_ACTIVE_FLAG(axis)) {
02439 extMinLimitSwitchRead(axis, &isLimit);
02440 if (isLimit == GET_AXIS_NHL_POLARITY(axis)) {
02441 if (++emcmotDebug->minLimitSwitchCount[axis] > LIMIT_SWITCH_DEBOUNCE) {
02442 SET_AXIS_NHL_FLAG(axis, 1);
02443 emcmotDebug->minLimitSwitchCount[axis] = LIMIT_SWITCH_DEBOUNCE;
02444 if (emcmotStatus->overrideLimits ||
02445 isHoming()) {
02446 }
02447 else {
02448 SET_AXIS_ERROR_FLAG(axis, 1);
02449 emcmotDebug->enabling = 0;
02450 }
02451 }
02452 }
02453 else {
02454 SET_AXIS_NHL_FLAG(axis, 0);
02455 emcmotDebug->minLimitSwitchCount[axis] = 0;
02456 }
02457 }
02458
02459 if (GET_AXIS_ACTIVE_FLAG(axis) &&
02460 GET_AXIS_ENABLE_FLAG(axis)) {
02461 extAmpFault(axis, &fault);
02462 if (fault == GET_AXIS_FAULT_POLARITY(axis)) {
02463 if (++emcmotDebug->ampFaultCount[axis] > AMP_FAULT_DEBOUNCE) {
02464 SET_AXIS_ERROR_FLAG(axis, 1);
02465 SET_AXIS_FAULT_FLAG(axis, 1);
02466 emcmotDebug->ampFaultCount[axis] = AMP_FAULT_DEBOUNCE;
02467 emcmotDebug->enabling = 0;
02468 }
02469 }
02470 else {
02471 SET_AXIS_FAULT_FLAG(axis, 0);
02472 emcmotDebug->ampFaultCount[axis] = 0;
02473 }
02474 }
02475
02476 /* read home switch and set flag if tripped. Handling of home
02477 sequence is done later. */
02478 if (GET_AXIS_ACTIVE_FLAG(axis)) {
02479 extHomeSwitchRead(axis, &homeFlag);
02480 if (homeFlag == GET_AXIS_HOME_SWITCH_POLARITY(axis)) {
02481 SET_AXIS_HOME_SWITCH_FLAG(axis, 1);
02482 }
02483 else {
02484 SET_AXIS_HOME_SWITCH_FLAG(axis, 0);
02485 }
02486 }
02487
02488 } /* end of: loop on axes, for reading inputs, setting limit and
02489 home switch flags */
02490
02491 /* check to see if logging should be triggered */
02492 if (emcmotStatus->logOpen &&
02493 ! emcmotStatus->logStarted &&
02494 loggingAxis >= 0 &&
02495 loggingAxis < EMCMOT_MAX_AXIS) {
02496 double val = 0.0;
02497
02498 switch (emcmotStatus->logTriggerVariable) {
02499 case EMCLOG_TRIGGER_ON_FERROR:
02500 val = emcmotDebug->ferrorCurrent[loggingAxis];
02501 break;
02502
02503 case EMCLOG_TRIGGER_ON_VOLT:
02504 val = emcmotDebug->rawOutput[loggingAxis];
02505 break;
02506
02507 case EMCLOG_TRIGGER_ON_POS:
02508 val = emcmotDebug->jointPos[loggingAxis];
02509 break;
02510
02511 case EMCLOG_TRIGGER_ON_VEL:
02512 val = emcmotDebug->jointPos[loggingAxis] - emcmotDebug->oldJointPos[loggingAxis];
02513 break;
02514
02515 default:
02516 break;
02517 }
02518
02519 switch (emcmotStatus->logTriggerType) {
02520 case EMCLOG_MANUAL_TRIGGER:
02521 break;
02522
02523 case EMCLOG_DELTA_TRIGGER:
02524 if (emcmotStatus->logStartVal - val < -emcmotStatus->logTriggerThreshold ||
02525 emcmotStatus->logStartVal - val > emcmotStatus->logTriggerThreshold) {
02526 emcmotStatus->logStarted = 1;
02527 }
02528 break;
02529
02530 case EMCLOG_OVER_TRIGGER:
02531 if (val > emcmotStatus->logTriggerThreshold) {
02532 emcmotStatus->logStarted = 1;
02533 }
02534 break;
02535
02536 case EMCLOG_UNDER_TRIGGER:
02537 if (val < emcmotStatus->logTriggerThreshold) {
02538 emcmotStatus->logStarted = 1;
02539 }
02540 }
02541 }
02542
02543 /* now we're outside the axis loop, having just read input, scaled it,
02544 read the limit and home switches and amp faults. We need to abort
02545 all motion if we're on limits, handle homing sequence, and handle
02546 mode and state transitions. */
02547
02548 /* RUN STATE LOGIC: */
02549
02550 /* check for disabling */
02551 if (! emcmotDebug->enabling && GET_MOTION_ENABLE_FLAG()) {
02552 /* clear out the motion emcmotDebug->queue and interpolators */
02553 tpClear(&emcmotDebug->queue);
02554 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
02555 tpClear(&emcmotDebug->freeAxis[axis]);
02556 cubicDrain(&emcmotDebug->cubic[axis]);
02557 if (GET_AXIS_ACTIVE_FLAG(axis)) {
02558 extAmpEnable(axis, ! GET_AXIS_ENABLE_POLARITY(axis));
02559 SET_AXIS_ENABLE_FLAG(axis, 0);
02560 SET_AXIS_HOMING_FLAG(axis, 0);
02561 emcmotStatus->output[axis] = 0.0;
02562 }
02563 /* don't clear the axis error flag, since that may signify why
02564 we just went into disabled state */
02565 }
02566 /* reset the trajectory interpolation counter, so that the kinematics
02567 functions called during the disabled state run at the nominal
02568 trajectory rate rather than the servo rate. It's loaded with
02569 emcmotConfig->interpolationRate when it goes to zero. */
02570 interpolationCounter = 0;
02571 SET_MOTION_ENABLE_FLAG(0);
02572 /* don't clear the motion error flag, since that may signify why
02573 we just went into disabled state */
02574 }
02575
02576 /* check for emcmotDebug->enabling */
02577 if (emcmotDebug->enabling && ! GET_MOTION_ENABLE_FLAG()) {
02578 tpSetPos(&emcmotDebug->queue, emcmotStatus->pos);
02579 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
02580 emcmotDebug->freePose.tran.x = emcmotDebug->jointPos[axis];
02581 tpSetPos(&emcmotDebug->freeAxis[axis], emcmotDebug->freePose);
02582 pidReset(&emcmotConfig->pid[axis]);
02583 if (GET_AXIS_ACTIVE_FLAG(axis)) {
02584 extAmpEnable(axis, GET_AXIS_ENABLE_POLARITY(axis));
02585 SET_AXIS_ENABLE_FLAG(axis, 1);
02586 SET_AXIS_HOMING_FLAG(axis, 0);
02587 }
02588 /* clear any outstanding axis errors when going into enabled state */
02589 SET_AXIS_ERROR_FLAG(axis, 0);
02590 }
02591 SET_MOTION_ENABLE_FLAG(1);
02592 /* clear any outstanding motion errors when going into enabled state */
02593 SET_MOTION_ERROR_FLAG(0);
02594 }
02595
02596 /* check for entering teleop mode */
02597 if (emcmotDebug->teleoperating && ! GET_MOTION_TELEOP_FLAG()) {
02598 if (GET_MOTION_INPOS_FLAG()) {
02599
02600 /* update coordinated emcmotDebug->queue position */
02601 tpSetPos(&emcmotDebug->queue, emcmotStatus->pos);
02602 /* drain the cubics so they'll synch up */
02603 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
02604 cubicDrain(&emcmotDebug->cubic[axis]);
02605 }
02606 /* Initialize things to do when starting teleop mode.*/
02607 emcmotDebug->teleop_data.currentVel.tran.x = 0.0;
02608 emcmotDebug->teleop_data.currentVel.tran.y = 0.0;
02609 emcmotDebug->teleop_data.currentVel.tran.z = 0.0;
02610 emcmotDebug->teleop_data.currentVel.a = 0.0;
02611 emcmotDebug->teleop_data.currentVel.b = 0.0;
02612 emcmotDebug->teleop_data.currentVel.c = 0.0;
02613 emcmotDebug->teleop_data.desiredVel.tran.x = 0.0;
02614 emcmotDebug->teleop_data.desiredVel.tran.y = 0.0;
02615 emcmotDebug->teleop_data.desiredVel.tran.z = 0.0;
02616 emcmotDebug->teleop_data.desiredVel.a = 0.0;
02617 emcmotDebug->teleop_data.desiredVel.b = 0.0;
02618 emcmotDebug->teleop_data.desiredVel.c = 0.0;
02619 emcmotDebug->teleop_data.currentAccell.tran.x = 0.0;
02620 emcmotDebug->teleop_data.currentAccell.tran.y = 0.0;
02621 emcmotDebug->teleop_data.currentAccell.tran.z = 0.0;
02622 emcmotDebug->teleop_data.currentAccell.a = 0.0;
02623 emcmotDebug->teleop_data.currentAccell.b = 0.0;
02624 emcmotDebug->teleop_data.currentAccell.c = 0.0;
02625 emcmotDebug->teleop_data.desiredAccell.tran.x = 0.0;
02626 emcmotDebug->teleop_data.desiredAccell.tran.y = 0.0;
02627 emcmotDebug->teleop_data.desiredAccell.tran.z = 0.0;
02628 emcmotDebug->teleop_data.desiredAccell.a = 0.0;
02629 emcmotDebug->teleop_data.desiredAccell.b = 0.0;
02630 emcmotDebug->teleop_data.desiredAccell.c = 0.0;
02631 SET_MOTION_TELEOP_FLAG(1);
02632 SET_MOTION_ERROR_FLAG(0);
02633 }
02634 else {
02635 /* not in position-- don't honor mode change */
02636 emcmotDebug->teleoperating = 0;
02637 }
02638 }
02639 else {
02640 if (GET_MOTION_INPOS_FLAG()) {
02641 if (!emcmotDebug->teleoperating && GET_MOTION_TELEOP_FLAG()) {
02642 SET_MOTION_TELEOP_FLAG(0);
02643 if (! emcmotDebug->coordinating) {
02644 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
02645 /* update free planner positions */
02646 emcmotDebug->freePose.tran.x = emcmotDebug->jointPos[axis];
02647 tpSetPos(&emcmotDebug->freeAxis[axis], emcmotDebug->freePose);
02648 /* drain the cubics so they'll synch up */
02649 cubicDrain(&emcmotDebug->cubic[axis]);
02650 }
02651 }
02652 }
02653 }
02654
02655 /* check for entering coordinated mode */
02656 if (emcmotDebug->coordinating && ! GET_MOTION_COORD_FLAG()) {
02657 if (GET_MOTION_INPOS_FLAG()) {
02658 /* update coordinated emcmotDebug->queue position */
02659 tpSetPos(&emcmotDebug->queue, emcmotStatus->pos);
02660 /* drain the cubics so they'll synch up */
02661 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
02662 cubicDrain(&emcmotDebug->cubic[axis]);
02663 }
02664 /* clear the override limits flags */
02665 emcmotDebug->overriding = 0;
02666 emcmotStatus->overrideLimits = 0;
02667 SET_MOTION_COORD_FLAG(1);
02668 SET_MOTION_TELEOP_FLAG(0);
02669 SET_MOTION_ERROR_FLAG(0);
02670 }
02671 else {
02672 /* not in position-- don't honor mode change */
02673 emcmotDebug->coordinating = 0;
02674 }
02675 }
02676
02677 /* check entering free space mode */
02678 if (! emcmotDebug->coordinating && GET_MOTION_COORD_FLAG()) {
02679 if (GET_MOTION_INPOS_FLAG()) {
02680 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
02681 /* update free planner positions */
02682 emcmotDebug->freePose.tran.x = emcmotDebug->jointPos[axis];
02683 tpSetPos(&emcmotDebug->freeAxis[axis], emcmotDebug->freePose);
02684 /* drain the cubics so they'll synch up */
02685 cubicDrain(&emcmotDebug->cubic[axis]);
02686 }
02687 SET_MOTION_COORD_FLAG(0);
02688 SET_MOTION_TELEOP_FLAG(0);
02689 SET_MOTION_ERROR_FLAG(0);
02690 }
02691 else {
02692 /* not in position-- don't honor mode change */
02693 emcmotDebug->coordinating = 1;
02694 }
02695 }
02696
02697 }
02698
02699 /* check for homing sequences */
02700 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
02701 if (GET_AXIS_HOMING_FLAG(axis)) {
02702 if (tpIsDone(&emcmotDebug->freeAxis[axis])) {
02703 /* check for decel or final move */
02704 if (emcmotDebug->homingPhase[axis] == 5) {
02705 /* reset flag-- we're back at home */
02706 emcmotDebug->homingPhase[axis] = 0;
02707
02708 /* rework the home kinematics values-- this could be done
02709 after each message to set world or joint kinematics, but
02710 we'll defer it to here so it happens just prior to when
02711 it's needed. Note that the nominal value of these may be
02712 changed, if the kinematics need to. */
02713 kinematicsHome(&worldHome, emcmotDebug->jointHome, &fflags, &iflags);
02714
02715 /* clear flag that indicates all joints need rehoming if any
02716 joint is moved, for machines with no forward kins */
02717 rehomeAll = 0;
02718
02719 /* set input offset to value such that resulting input
02720 is the emcmotDebug->jointHome[] value, with:
02721 input = (raw - offset) / scale ->
02722 offset = raw - input * scale ->
02723 offset = raw - emcmotDebug->jointHome * scale */
02724
02725 emcmotStatus->inputOffset[axis] = emcmotDebug->rawInput[axis] -
02726 emcmotDebug->jointHome[axis] * emcmotStatus->inputScale[axis];
02727
02728 /* recompute inputs to match so we don't have a
02729 momentary jump */
02730 emcmotStatus->input[axis] = emcmotDebug->jointHome[axis];
02731 emcmotDebug->oldInput[axis] = emcmotStatus->input[axis];
02732
02733 /* reset interpolator so that it doesn't jump */
02734 cubicOffset(&emcmotDebug->cubic[axis], emcmotDebug->jointHome[axis] - emcmotDebug->coarseJointPos[axis]);
02735
02736 /* set axis position to emcmotDebug->jointHome upon homing */
02737 emcmotDebug->jointPos[axis] = emcmotDebug->jointHome[axis];
02738 emcmotDebug->freePose.tran.x = emcmotDebug->jointHome[axis];
02739 tpSetPos(&emcmotDebug->freeAxis[axis], emcmotDebug->freePose);
02740
02741 SET_AXIS_HOMING_FLAG(axis, 0);
02742 SET_AXIS_HOMED_FLAG(axis, 1);
02743
02744 /* set emcmotDebug->allHomed flag if all active axes are homed; this
02745 will signify that kinematics functions can be called */
02746 emcmotDebug->allHomed = 1;
02747 for (t = 0; t < EMCMOT_MAX_AXIS; t++) {
02748 if (GET_AXIS_ACTIVE_FLAG(t) &&
02749 ! GET_AXIS_HOMED_FLAG(t)) {
02750 /* one active axis is not homed */
02751 emcmotDebug->allHomed = 0;
02752 break;
02753 }
02754 }
02755 /* FIXME-- this only works with no forward kins */
02756 if (emcmotDebug->allHomed) {
02757 emcmotStatus->pos = worldHome;
02758 emcmotStatus->actualPos = worldHome;
02759 }
02760 }
02761
02762 if (emcmotDebug->homingPhase[axis] == 4) {
02763 /* just finished decel, now we'll do final home */
02764 /* add move back to latched position + backoff */
02765 emcmotDebug->freePose.tran.x =
02766 (emcmotDebug->saveLatch[axis] -
02767 emcmotStatus->inputOffset[axis]) *
02768 emcmotDebug->inverseInputScale[axis] +
02769 emcmotConfig->homeOffset[axis];
02770 /* Note that I put a multiplication factor of 2 in front of
02771 the homing velocity below. The reason is that, I think,
02772 if you found the index pulse you know your exact position
02773 it is save to travel with higher speeds. In addition to
02774 that, you actually see that the machine has found its
02775 index pulse for the specified axis */
02776 tpSetVmax(&emcmotDebug->freeAxis[axis],
02777 2 * (emcmotConfig->homingVel[axis]));
02778 if ((retval = tpAddLine(&emcmotDebug->freeAxis[axis], emcmotDebug->freePose)) == 0) {
02779 /* Advance homing sequence only if motion is added to the tp */
02780 emcmotDebug->homingPhase[axis] = 5;
02781 }
02782 }
02783 } /* end of: if axis is done either decel or final home */
02784 } /* end of: if axis is homing */
02785 } /* end of: axis loop that checks for homing */
02786
02787 /* RUN MOTION CALCULATIONS: */
02788
02789 /* run axis interpolations and outputs, but only if we're
02790 enabled. This section is "suppressed" if we're not
02791 enabled, although the read/write of encoders/dacs is still
02792 done. */
02793 whichCycle = 0;
02794 if (GET_MOTION_ENABLE_FLAG()) {
02795 /* set whichCycle to be at least a servo cycle, for calc time logging */
02796 whichCycle = 1;
02797
02798 /* check to see if the interpolators are empty */
02799 while (cubicNeedNextPoint(&emcmotDebug->cubic[0])) {
02800 /* they're empty, so pull next point(s) off Cartesian or
02801 joint planner, depending upon coord or free mode. */
02802
02803 /* check to see whether we're in teleop, coordinated or free mode, to
02804 decide which motion planner to call */
02805 if (GET_MOTION_TELEOP_FLAG()) {
02806 double accell_mag;
02807
02808 emcmotDebug->teleop_data.desiredAccell.tran.x = (emcmotDebug->teleop_data.desiredVel.tran.x - emcmotDebug->teleop_data.currentVel.tran.x)/emcmotConfig->trajCycleTime;
02809 emcmotDebug->teleop_data.desiredAccell.tran.y = (emcmotDebug->teleop_data.desiredVel.tran.y - emcmotDebug->teleop_data.currentVel.tran.y)/emcmotConfig->trajCycleTime;
02810 emcmotDebug->teleop_data.desiredAccell.tran.z = (emcmotDebug->teleop_data.desiredVel.tran.z - emcmotDebug->teleop_data.currentVel.tran.z)/emcmotConfig->trajCycleTime;
02811 pmCartMag(emcmotDebug->teleop_data.desiredAccell.tran, &accell_mag);
02812 emcmotDebug->teleop_data.desiredAccell.a = (emcmotDebug->teleop_data.desiredVel.a - emcmotDebug->teleop_data.currentVel.a)/emcmotConfig->trajCycleTime;
02813 emcmotDebug->teleop_data.desiredAccell.b = (emcmotDebug->teleop_data.desiredVel.b - emcmotDebug->teleop_data.currentVel.b)/emcmotConfig->trajCycleTime;
02814 emcmotDebug->teleop_data.desiredAccell.c = (emcmotDebug->teleop_data.desiredVel.c - emcmotDebug->teleop_data.currentVel.c)/emcmotConfig->trajCycleTime;
02815 if (emcmotDebug->teleop_data.desiredAccell.a > accell_mag) {
02816 accell_mag = emcmotDebug->teleop_data.desiredAccell.a;
02817 }
02818 if (emcmotDebug->teleop_data.desiredAccell.b > accell_mag) {
02819 accell_mag = emcmotDebug->teleop_data.desiredAccell.b;
02820 }
02821 if (emcmotDebug->teleop_data.desiredAccell.c > accell_mag) {
02822 accell_mag = emcmotDebug->teleop_data.desiredAccell.c;
02823 }
02824 if (accell_mag > emcmotStatus->acc) {
02825 pmCartScalMult(emcmotDebug->teleop_data.desiredAccell.tran, emcmotStatus->acc/accell_mag,
02826 &emcmotDebug->teleop_data.currentAccell.tran);
02827 emcmotDebug->teleop_data.currentAccell.a =
02828 emcmotDebug->teleop_data.desiredAccell.a * emcmotStatus->acc/accell_mag;
02829 emcmotDebug->teleop_data.currentAccell.b =
02830 emcmotDebug->teleop_data.desiredAccell.b * emcmotStatus->acc/accell_mag;
02831 emcmotDebug->teleop_data.currentAccell.c =
02832 emcmotDebug->teleop_data.desiredAccell.c * emcmotStatus->acc/accell_mag;
02833 emcmotDebug->teleop_data.currentVel.tran.x += emcmotDebug->teleop_data.currentAccell.tran.x*emcmotConfig->trajCycleTime;
02834 emcmotDebug->teleop_data.currentVel.tran.y += emcmotDebug->teleop_data.currentAccell.tran.y*emcmotConfig->trajCycleTime;
02835 emcmotDebug->teleop_data.currentVel.tran.z += emcmotDebug->teleop_data.currentAccell.tran.z*emcmotConfig->trajCycleTime;
02836 emcmotDebug->teleop_data.currentVel.a += emcmotDebug->teleop_data.currentAccell.a*emcmotConfig->trajCycleTime;
02837 emcmotDebug->teleop_data.currentVel.b += emcmotDebug->teleop_data.currentAccell.b*emcmotConfig->trajCycleTime;
02838 emcmotDebug->teleop_data.currentVel.c += emcmotDebug->teleop_data.currentAccell.c*emcmotConfig->trajCycleTime;
02839 }
02840 else {
02841 emcmotDebug->teleop_data.currentAccell = emcmotDebug->teleop_data.desiredAccell;
02842 emcmotDebug->teleop_data.currentVel = emcmotDebug->teleop_data.desiredVel;
02843 }
02844
02845 emcmotStatus->pos.tran.x += emcmotDebug->teleop_data.currentVel.tran.x*emcmotConfig->trajCycleTime;
02846 emcmotStatus->pos.tran.y += emcmotDebug->teleop_data.currentVel.tran.y*emcmotConfig->trajCycleTime;
02847 emcmotStatus->pos.tran.z += emcmotDebug->teleop_data.currentVel.tran.z*emcmotConfig->trajCycleTime;
02848 emcmotStatus->pos.a += emcmotDebug->teleop_data.currentVel.a*emcmotConfig->trajCycleTime;
02849 emcmotStatus->pos.b += emcmotDebug->teleop_data.currentVel.b*emcmotConfig->trajCycleTime;
02850 emcmotStatus->pos.c += emcmotDebug->teleop_data.currentVel.c*emcmotConfig->trajCycleTime;
02851
02852 /* convert to joints */
02853 kinematicsInverse(&emcmotStatus->pos, emcmotDebug->coarseJointPos, &iflags, &fflags);
02854
02855 /* spline joints up-- note that we may be adding points that
02856 fail soft limits, but we'll abort at the end of this cycle
02857 so it doesn't really matter */
02858 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
02859 cubicAddPoint(&emcmotDebug->cubic[axis], emcmotDebug->coarseJointPos[axis]);
02860 }
02861
02862 if (kinType == KINEMATICS_IDENTITY) {
02863 /* call forward kinematics on input points for actual pos,
02864 at trajectory rate to save bandwidth */
02865 kinematicsForward(emcmotStatus->input, &emcmotStatus->actualPos, &fflags, &iflags);
02866 }
02867 else {
02868 /* fake it by setting actual pos to commanded pos */
02869 emcmotStatus->actualPos = emcmotStatus->pos;
02870 }
02871 }
02872 else {
02873 if (GET_MOTION_COORD_FLAG()) {
02874 /* we're in coordinated mode-- pull a pose off the Cartesian
02875 trajectory planner, run it through the inverse kinematics,
02876 and spline up the joint points for interpolation in
02877 servo cycles. */
02878
02879 /* set whichCycle to be a Cartesian trajectory cycle,
02880 for calc time logging */
02881 whichCycle = 2;
02882
02883 /* run coordinated trajectory planning cycle */
02884 tpRunCycle(&emcmotDebug->queue);
02885
02886 /* set new commanded traj pos */
02887 emcmotStatus->pos = tpGetPos(&emcmotDebug->queue);
02888
02889 /* convert to joints */
02890 kinematicsInverse(&emcmotStatus->pos, emcmotDebug->coarseJointPos, &iflags, &fflags);
02891
02892 /* spline joints up-- note that we may be adding points that
02893 fail soft limits, but we'll abort at the end of this cycle
02894 so it doesn't really matter */
02895 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
02896 cubicAddPoint(&emcmotDebug->cubic[axis], emcmotDebug->coarseJointPos[axis]);
02897 }
02898
02899 if (kinType == KINEMATICS_IDENTITY) {
02900 /* call forward kinematics on input points for actual pos,
02901 at trajectory rate to save bandwidth */
02902 kinematicsForward(emcmotStatus->input, &emcmotStatus->actualPos, &fflags, &iflags);
02903 }
02904 else {
02905 /* fake it by setting actual pos to commanded pos */
02906 emcmotStatus->actualPos = emcmotStatus->pos;
02907 }
02908
02909 /* now emcmotStatus->actualPos, emcmotStatus->pos, and
02910 emcmotDebug->coarseJointPos[] are set */
02911
02912 } /* end of: coord mode */
02913 else {
02914 /* we're in free mode-- run joint planning cycles */
02915 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
02916 /* set whichCycle to be a joint trajectory cycle,
02917 for calc time logging */
02918 /* note that this may include one or more joint trajectory
02919 cycles, so calc time may be inherently variable */
02920 whichCycle = 2;
02921
02922 /* run joint trajectory planning cycle */
02923 tpRunCycle(&emcmotDebug->freeAxis[axis]);
02924
02925 /* set new coarse joint position. FIXME-- this uses only
02926 the tran.x field of the TP_STRUCT, which is overkill.
02927 We need a TP_STRUCT with a single scalar element. */
02928 emcmotDebug->coarseJointPos[axis] = tpGetPos(&emcmotDebug->freeAxis[axis]).tran.x;
02929
02930 /* spline joint up-- note that we may be adding a point that
02931 fails soft limit, but we'll abort at the end of this cycle
02932 so it doesn't really matter */
02933 cubicAddPoint(&emcmotDebug->cubic[axis], emcmotDebug->coarseJointPos[axis]);
02934 } /* end of: axis for loop for joint planning cycle */
02935
02936 if (kinType == KINEMATICS_IDENTITY) {
02937 /* set actualPos from actual inputs */
02938 kinematicsForward(emcmotStatus->input, &emcmotStatus->actualPos, &fflags, &iflags);
02939 /* set pos from nominal joints, since we're in joint mode */
02940 kinematicsForward(emcmotDebug->coarseJointPos, &emcmotStatus->pos, &fflags, &iflags);
02941 }
02942 else if (kinType != KINEMATICS_INVERSE_ONLY) {
02943 /* here is where we call the forward kinematics repeatedly,
02944 when we're in free mode, so that the world coordinates are
02945 kept up to date when joints are moving. This is only done
02946 if we have the kinematics. emcmotStatus->pos needs to be set
02947 with an estimate for the kinematics to converge, which is
02948 true when we enter free mode from coordinated mode or after
02949 the machine is homed. */
02950 EmcPose temp = emcmotStatus->pos;
02951 if (0 == kinematicsForward(emcmotStatus->input, &temp, &fflags, &iflags)) {
02952 emcmotStatus->pos = temp;
02953 emcmotStatus->actualPos = temp;
02954 }
02955 /* else leave them alone */
02956 }
02957 else {
02958 /* no foward kins, and we're in joint mode, so we have no
02959 estimate of world coords, and we have to leave them alone */
02960 }
02961
02962 /* now emcmotStatus->actualPos, emcmotStatus->pos, and
02963 emcmotDebug->coarseJointPos[] are set */
02964
02965 } /* end of: free mode trajectory planning */
02966 } /* end of: not teleop mode */
02967 } /* end of: while (cubicNeedNextPoint(0)) */
02968
02969 /* we're still in motion enabled section. For coordinated mode,
02970 the Cartesian trajectory cycle has been computed, if necessary,
02971 run through the inverse kinematics, and the joints have been
02972 splined up for interpolation. For free mode, the joint trajectory
02973 cycles have been computed, if necessary, and the joints have
02974 been splined up for interpolation. We still need to push the
02975 actual input through the forward kinematics, for actual pos.
02976
02977 Effects:
02978
02979 For coord mode, emcmotStatus->pos contains the commanded
02980 Cartesian pose, emcmotDebug->coarseJointPos[] contains the results of the
02981 inverse kinematics at the coarse (trajectory) rate, and the
02982 interpolators are not empty.
02983
02984 For free mode, emcmotStatus->pos is unchanged, and needs to
02985 be updated via the forward kinematics. FIXME-- make sure this
02986 happens, and note where in this comment. emcmotDebug->coarseJointPos[]
02987 contains the results of the joint trajectory calculations
02988 at the coarse (trajectory) rate, and the interpolators are
02989 not empty.
02990 */
02991
02992 /* check for soft joint limits. If so, abort all motion. The
02993 interpolators will pick this up further down and begin
02994 planning abort and stop. */
02995 emcmotDebug->onLimit = 0;
02996 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
02997 SET_AXIS_PSL_FLAG(axis, 0);
02998 SET_AXIS_NSL_FLAG(axis, 0);
02999 if (GET_AXIS_HOMED_FLAG(axis)) {
03000 if (emcmotDebug->coarseJointPos[axis] > emcmotConfig->maxLimit[axis]) {
03001 SET_AXIS_ERROR_FLAG(axis, 1);
03002 SET_AXIS_PSL_FLAG(axis, 1);
03003 emcmotDebug->onLimit = 1;
03004 }
03005 else if (emcmotDebug->coarseJointPos[axis] < emcmotConfig->minLimit[axis]) {
03006 SET_AXIS_ERROR_FLAG(axis, 1);
03007 SET_AXIS_NSL_FLAG(axis, 1);
03008 }
03009 }
03010 }
03011
03012 /* reset emcmotDebug->wasOnLimit flag iff all joints are free of
03013 soft limits, as seen in the flag bits set last cycle.
03014 No need to do this for hard limits, since emcmotDebug->wasOnLimit
03015 only prevents flurry of aborts while on a soft limit
03016 and hard limits don't abort, they disable. */
03017 if (emcmotDebug->onLimit) {
03018 if (! emcmotDebug->wasOnLimit) {
03019 /* abort everything, regardless of coord or free mode */
03020 tpAbort(&emcmotDebug->queue);
03021 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
03022 tpAbort(&emcmotDebug->freeAxis[axis]);
03023 emcmotDebug->wasOnLimit = 1;
03024 }
03025 }
03026 /* else we were on a limit, so inhibit firing of aborts */
03027 }
03028 else {
03029 /* not on a limit, so clear emcmotDebug->wasOnLimit so aborts fire next
03030 time we are on a limit */
03031 emcmotDebug->wasOnLimit = 0;
03032 }
03033
03034 if (whichCycle == 2) {
03035 /* we're on a trajectory cycle, either Cartesian or joint planning, so
03036 log per-traj-cycle data if logging active */
03037 logIt = 0;
03038
03039 if (emcmotStatus->logStarted &&
03040 emcmotStatus->logSkip >= 0) {
03041
03042 /* calculate current vel, accel, for logging */
03043 emcmotDebug->newVel.tran.x = (emcmotStatus->pos.tran.x - emcmotDebug->oldPos.tran.x) /
03044 emcmotConfig->trajCycleTime;
03045 emcmotDebug->newVel.tran.y = (emcmotStatus->pos.tran.y - emcmotDebug->oldPos.tran.y) /
03046 emcmotConfig->trajCycleTime;
03047 emcmotDebug->newVel.tran.z = (emcmotStatus->pos.tran.z - emcmotDebug->oldPos.tran.z) /
03048 emcmotConfig->trajCycleTime;
03049 emcmotDebug->oldPos = emcmotStatus->pos;
03050 emcmotDebug->newAcc.tran.x = (emcmotDebug->newVel.tran.x - emcmotDebug->oldVel.tran.x) /
03051 emcmotConfig->trajCycleTime;
03052 emcmotDebug->newAcc.tran.y = (emcmotDebug->newVel.tran.y - emcmotDebug->oldVel.tran.y) /
03053 emcmotConfig->trajCycleTime;
03054 emcmotDebug->newAcc.tran.z = (emcmotDebug->newVel.tran.z - emcmotDebug->oldVel.tran.z) /
03055 emcmotConfig->trajCycleTime;
03056 emcmotDebug->oldVel = emcmotDebug->newVel;
03057
03058 /* save the type with the log item */
03059 ls.type = emcmotStatus->logType;
03060
03061 /* now log type-specific data */
03062 switch (emcmotStatus->logType) {
03063
03064 case EMCMOT_LOG_TYPE_TRAJ_POS:
03065 if (logSkip-- <= 0) {
03066 ls.item.trajPos.time = start - logStartTime;
03067 ls.item.trajPos.pos = emcmotStatus->pos.tran;
03068 logSkip = emcmotStatus->logSkip;
03069 logIt = 1;
03070 }
03071 break;
03072
03073 case EMCMOT_LOG_TYPE_TRAJ_VEL:
03074 if (logSkip-- <= 0) {
03075 ls.item.trajVel.time = start - logStartTime;
03076 ls.item.trajVel.vel = emcmotDebug->newVel.tran;
03077 pmCartMag(emcmotDebug->newVel.tran, &ls.item.trajVel.mag);
03078 logSkip = emcmotStatus->logSkip;
03079 logIt = 1;
03080 }
03081 break;
03082
03083 case EMCMOT_LOG_TYPE_TRAJ_ACC:
03084 if (logSkip-- <= 0) {
03085 ls.item.trajAcc.time = start - logStartTime;
03086 ls.item.trajAcc.acc = emcmotDebug->newAcc.tran;
03087 pmCartMag(emcmotDebug->newAcc.tran, &ls.item.trajAcc.mag);
03088 logSkip = emcmotStatus->logSkip;
03089 logIt = 1;
03090 }
03091 break;
03092
03093 default:
03094 break;
03095 } /* end of: switch on log type */
03096
03097 /* now log it */
03098 if (logIt) {
03099 emcmotLogAdd(emcmotLog, ls);
03100 emcmotStatus->logPoints = emcmotLog->howmany;
03101 logIt = 0;
03102 }
03103 } /* end of: if (emcmotStatus->logStarted &&
03104 emcmotStatus->logSkip >= 0) */
03105 } /* end of: if (whichCycle == 2), for trajectory cycle logging */
03106
03107 /* run interpolation and compensation */
03108 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
03109 /* interpolate */
03110 emcmotDebug->oldJointPos[axis] = emcmotDebug->jointPos[axis];
03111 emcmotDebug->jointPos[axis] = cubicInterpolate(&emcmotDebug->cubic[axis], 0, 0, 0, 0);
03112 emcmotDebug->jointVel[axis] = (emcmotDebug->jointPos[axis] - emcmotDebug->oldJointPos[axis]) / emcmotConfig->servoCycleTime;
03113 #ifdef COMPING
03114 /* set direction flag iff there's a direction change, otherwise
03115 leave it alone so that stops won't change dir */
03116 if (emcmotDebug->jointVel[axis] > 0.0 && dir[axis] < 0) {
03117 dir[axis] = 1;
03118 }
03119 else if (emcmotDebug->jointVel[axis] < 0.0 && dir[axis] > 0) {
03120 dir[axis] = -1;
03121 }
03122 /* else leave it alone */
03123 #endif /* COMPING */
03124
03125 /* run output calculations */
03126 if (GET_AXIS_ACTIVE_FLAG(axis)) {
03127 /* BACKLASH COMPENSATION */
03128 /* FIXME-- make backlash part of the EMC status proper, not
03129 the PID structure */
03130 if (emcmotDebug->jointPos[axis] - emcmotDebug->oldJointPos[axis] > 0.0) {
03131 oldbcomp = emcmotDebug->bcomp[axis];
03132 emcmotDebug->bcomp[axis] = + emcmotConfig->pid[axis].backlash / 2.0;
03133 if (emcmotDebug->bcompdir[axis] != + 1) {
03134 emcmotDebug->bac_done[axis] = 0;
03135 emcmotDebug->bac_di[axis] = emcmotDebug->bcompincr[axis];
03136 emcmotDebug->bac_d[axis] = 0;
03137 emcmotDebug->bac_D[axis] = emcmotDebug->bcomp[axis] - oldbcomp;
03138 emcmotDebug->bac_halfD[axis] = 0.5 * emcmotDebug->bac_D[axis];
03139 emcmotDebug->bac_incrincr[axis] = emcmotStatus->acc *
03140 emcmotConfig->servoCycleTime * emcmotConfig->servoCycleTime;
03141 emcmotDebug->bac_incr[axis] = - 0.5 * emcmotDebug->bac_incrincr[axis];
03142 emcmotDebug->bcompdir[axis] = + 1;
03143 }
03144 }
03145 else if (emcmotDebug->jointPos[axis] - emcmotDebug->oldJointPos[axis] < 0.0) {
03146 oldbcomp = emcmotDebug->bcomp[axis];
03147 emcmotDebug->bcomp[axis] = - emcmotConfig->pid[axis].backlash / 2.0;
03148 if (emcmotDebug->bcompdir[axis] != - 1) {
03149 emcmotDebug->bac_done[axis] = 0;
03150 emcmotDebug->bac_di[axis] = emcmotDebug->bcompincr[axis];
03151 emcmotDebug->bac_d[axis] = 0;
03152 emcmotDebug->bac_D[axis] = emcmotDebug->bcomp[axis] - oldbcomp;
03153 emcmotDebug->bac_halfD[axis] = 0.5 * emcmotDebug->bac_D[axis];
03154 emcmotDebug->bac_incrincr[axis] = emcmotStatus->acc *
03155 emcmotConfig->servoCycleTime * emcmotConfig->servoCycleTime;
03156 emcmotDebug->bac_incr[axis] = - 0.5 * emcmotDebug->bac_incrincr[axis];
03157 emcmotDebug->bcompdir[axis] = - 1;
03158 }
03159 }
03160 /* else no motion, so leave emcmotDebug->bcomp what it was */
03161
03162 /* mete out the backlash according to an acc/dec profile */
03163 if (! emcmotDebug->bac_done[axis]) {
03164 if (emcmotDebug->bac_D[axis] > 0.0) {
03165 emcmotDebug->bcompincr[axis] = emcmotDebug->bac_di[axis] + emcmotDebug->bac_d[axis];
03166 if (emcmotDebug->bac_d[axis] < emcmotDebug->bac_halfD[axis]) {
03167 emcmotDebug->bac_incr[axis] += emcmotDebug->bac_incrincr[axis];
03168 emcmotDebug->bac_d[axis] += emcmotDebug->bac_incr[axis];
03169 }
03170 else if (emcmotDebug->bac_d[axis] < emcmotDebug->bac_D[axis]) {
03171 emcmotDebug->bac_incr[axis] -= emcmotDebug->bac_incrincr[axis];
03172 emcmotDebug->bac_d[axis] += emcmotDebug->bac_incr[axis];
03173 }
03174 if (emcmotDebug->bac_d[axis] >= emcmotDebug->bac_D[axis] || emcmotDebug->bac_incr[axis] <= 0.0) {
03175 emcmotDebug->bac_done[axis] = 1;
03176 }
03177 }
03178 else {
03179 emcmotDebug->bcompincr[axis] = emcmotDebug->bac_di[axis] + emcmotDebug->bac_d[axis];
03180 if (emcmotDebug->bac_d[axis] > emcmotDebug->bac_halfD[axis]) {
03181 emcmotDebug->bac_incr[axis] += emcmotDebug->bac_incrincr[axis];
03182 emcmotDebug->bac_d[axis] -= emcmotDebug->bac_incr[axis];
03183 }
03184 else if (emcmotDebug->bac_d[axis] > emcmotDebug->bac_D[axis]) {
03185 emcmotDebug->bac_incr[axis] -= emcmotDebug->bac_incrincr[axis];
03186 emcmotDebug->bac_d[axis] -= emcmotDebug->bac_incr[axis];
03187 }
03188 if (emcmotDebug->bac_d[axis] <= emcmotDebug->bac_D[axis] || emcmotDebug->bac_incr[axis] <= 0.0) {
03189 emcmotDebug->bac_done[axis] = 1;
03190 }
03191 }
03192 } /* end of: if not emcmotDebug->bac_done[axis] */
03193
03194 /* ADJUST OUTPUT: */
03195
03196 /*
03197 this computes outJointPos[] from emcmotDebug->jointPos[], by adding backlash
03198 compensation and rounding result to nearest input unit
03199 */
03200 emcmotDebug->outJointPos[axis] = emcmotDebug->jointPos[axis] + emcmotDebug->bcompincr[axis];
03201 #ifndef NO_ROUNDING
03202 numres = outJointPos[axis] * emcmotStatus->inputScale[axis];
03203 if (numres < 0.0) {
03204 outJointPos[axis] = emcmotDebug->inverseInputScale[axis] * ((int) (numres - 0.5));
03205 }
03206 else {
03207 outJointPos[axis] = emcmotDebug->inverseInputScale[axis] * ((int) (numres + 0.5));
03208 }
03209 #endif
03210
03211 /* COMPENSATE: */
03212
03213 /*
03214 compensation means compute output
03215 'emcmotStatus->output[]' based on desired position
03216 'outJointPos[]' and input 'emcmotStatus->input[]'.
03217
03218 Currently the source calls for PID compensation.
03219 FIXME-- add wrapper for compensator, with ptr to
03220 emcmotStatus struct, with semantics that ->output[]
03221 needs to be filled.
03222 */
03223
03224 /* here is PID compensation */
03225 /* note that we have to compare adjusted output 'outJointPos'
03226 with the input, but the input has already had backlash comp
03227 taken out, while the output has just had it added in. So,
03228 we need to add it to the input for this calculation */
03229 emcmotStatus->output[axis] =
03230 pidRunCycle(&emcmotConfig->pid[axis],
03231 emcmotStatus->input[axis] + emcmotDebug->bcompincr[axis],
03232 emcmotDebug->outJointPos[axis]);
03233
03234 /* COMPUTE FOLLOWING ERROR: */
03235
03236 /* compute signed following error and magnitude */
03237 thisFerror[axis] = emcmotDebug->jointPos[axis] - emcmotStatus->input[axis];
03238 magFerror = fabs(thisFerror[axis]);
03239 emcmotDebug->ferrorCurrent[axis] = thisFerror[axis];
03240
03241 /* record the max ferror for this axis */
03242 if (emcmotDebug->ferrorHighMark[axis] < magFerror) {
03243 emcmotDebug->ferrorHighMark[axis] = magFerror;
03244 }
03245
03246 /* compute the scaled ferror for a move of this speed */
03247 limitFerror = emcmotConfig->maxFerror[axis] /
03248 emcmotConfig->limitVel *
03249 emcmotDebug->jointVel[axis];
03250 if (limitFerror < emcmotConfig->minFerror[axis]) {
03251 limitFerror = emcmotConfig->minFerror[axis];
03252 }
03253
03254 /* abort if this ferror is greater than the scaled ferror */
03255 if (magFerror > limitFerror) {
03256 /* abort! abort! following error exceeded */
03257 SET_AXIS_ERROR_FLAG(axis, 1);
03258 SET_AXIS_FERROR_FLAG(axis, 1);
03259 if (emcmotDebug->enabling) {
03260 /* report the following error just this once */
03261 reportError("axis %d following error", axis);
03262 }
03263 emcmotDebug->enabling = 0;
03264 }
03265 else {
03266 SET_AXIS_FERROR_FLAG(axis, 0);
03267 }
03268 } /* end of: if (GET_AXIS_ACTIVE_FLAG(axis)) */
03269 else {
03270 /* axis is not active-- leave the pid output where it is--
03271 if axis is not active one can still write to the dac */
03272 }
03273
03274 /* CLAMP OUTPUT: */
03275
03276 /*
03277 clamp output means take 'emcmotStatus->output[]' and
03278 limit to range
03279 'emcmotConfig->minOutput[] .. emcmotConfig->maxOutput[]'
03280 */
03281 if (emcmotStatus->output[axis] < emcmotConfig->minOutput[axis]) {
03282 emcmotStatus->output[axis] = emcmotConfig->minOutput[axis];
03283 }
03284 else if (emcmotStatus->output[axis] > emcmotConfig->maxOutput[axis]) {
03285 emcmotStatus->output[axis] = emcmotConfig->maxOutput[axis];
03286 }
03287
03288 /* CHECK FOR LATCH CONDITION: */
03289 /*
03290 check for latch condition means if we're waiting for a
03291 latched index pulse, and we see the pulse switch,
03292 we read the raw input and abort. The offset is set
03293 above in the homing section by noting that if we're homing,
03294 and emcmotDebug->homingPhase[] is 3, we latched.
03295
03296 This presumes an encoder index pulse.
03297 FIXME-- remove explicit calls to encoder index pulse, to
03298 allow for open-loop control latching via switches only.
03299 Open-loop control can be achieved, at least for STG boards, by
03300 defining NO_INDEX_PULSE in extstgmot.c
03301 */
03302 if (emcmotDebug->homingPhase[axis] == 3) {
03303 /* read encoder index pulse */
03304 extEncoderReadLatch(axis, &emcmotDebug->latchFlag[axis]);
03305 if (emcmotDebug->latchFlag[axis]) {
03306 /* code below is excuted once the index pulse is found */
03307 /* call for an abort-- when it's finished, code
03308 above sets inputOffset[] to emcmotDebug->saveLatch[] */
03309 if (tpAbort(&emcmotDebug->freeAxis[axis]) == 0) {
03310 /* Only advance the homing sequence if the motion is really aborted */
03311 emcmotDebug->homingPhase[axis] = 4;
03312 /* get latched position in RAW UNITS */
03313 emcmotDebug->saveLatch[axis] = emcmotDebug->rawInput[axis];
03314 }
03315 } /* end of: if (emcmotDebug->latchFlag[axis]) */
03316 } /* end of: if (emcmotDebug->homingPhase[axis] == 3 */
03317
03318 /* CHECK FOR HOMING PHASE 2, COMMAND THE MOVE TO THE INDEX PULSE */
03319 if (emcmotDebug->homingPhase[axis] == 2) {
03320 if (GET_AXIS_HOMING_POLARITY(axis)) {
03321 emcmotDebug->freePose.tran.x = - 2.0 * AXRANGE(axis);
03322 } else {
03323 emcmotDebug->freePose.tran.x = + 2.0 * AXRANGE(axis);
03324 }
03325 if ((retval = tpAddLine(&emcmotDebug->freeAxis[axis], emcmotDebug->freePose)) == 0) {
03326 /* Only advance homing sequence if the motion is
03327 actually put in the traj. planner */
03328 extEncoderResetIndex(axis);
03329 emcmotDebug->homingPhase[axis] = 3;
03330 }
03331 } /* END OF: PHASE 2 */
03332
03333 /* CHECK FOR HOME SWITCH CONDITION AND then tpAbort: */
03334 /* check if any of the home switch, phl, nhl are tripped */
03335 if (emcmotDebug->homingPhase[axis] == 1) {
03336 if (GET_AXIS_HOME_SWITCH_FLAG(axis) ||
03337 GET_AXIS_PHL_FLAG(axis) ||
03338 GET_AXIS_NHL_FLAG(axis)) {
03339 if (tpAbort(&emcmotDebug->freeAxis[axis]) == 0) {
03340 /* Advance homing sequence if motion is aborted */
03341 emcmotDebug->homingPhase[axis] = 2;
03342 }
03343 }
03344 } /* end of: if(emcmotDebug->homingPhase[axis]==1){ */
03345 } /* end of: for (axis = 0; ...) */
03346 } /* end of: if (GET_MOTION_ENABLE_FLAG()) */
03347 else {
03348 /*
03349 we're not enabled, so no motion planning or interpolation has
03350 been done. emcmotDebug->jointPos[] is set to emcmotStatus->input[],
03351 and likewise with emcmotDebug->coarseJointPos[], which is normally
03352 updated at the traj rate but it's convenient to do them here at the
03353 same time at the servo rate. emcmotStatus->pos, ->actualPos need to be
03354 run through forward kinematics. Note that we are running at the servo
03355 rate, so we need to slow down by the interpolation factor to avoid
03356 soaking the CPU. If we were enabled, ->pos was set by calcs (coord
03357 mode) or forward kins (free mode), and ->actualPos was set by forward
03358 kins on ->input[], all at the trajectory rate.
03359 */
03360 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
03361 emcmotDebug->coarseJointPos[axis] = emcmotStatus->input[axis];
03362 emcmotDebug->oldJointPos[axis] = emcmotDebug->jointPos[axis];
03363 emcmotDebug->jointPos[axis] = emcmotDebug->coarseJointPos[axis];
03364 emcmotDebug->jointVel[axis] = (emcmotDebug->jointPos[axis] - emcmotDebug->oldJointPos[axis]) / emcmotConfig->servoCycleTime;
03365 }
03366 /* synthesize the trajectory interpolation, via a counter that
03367 decrements from the interpolation rate. This causes the statements
03368 to execute at the trajectory rate instead of the servo rate at which
03369 this enclosing code is called. */
03370 if (--interpolationCounter <= 0) {
03371 if (kinType != KINEMATICS_INVERSE_ONLY) {
03372 /* call the forward kinematics, at the effective trajectory rate */
03373 EmcPose temp = emcmotStatus->pos;
03374 if (0 == kinematicsForward(emcmotStatus->input, &temp, &fflags, &iflags)) {
03375 emcmotStatus->pos = temp;
03376 emcmotStatus->actualPos = temp;
03377 }
03378 }
03379 /* else can't generate Cartesian position, so leave it alone */
03380
03381 /* reload the interpolation counter that simulates the interpolation
03382 done when enabled */
03383 interpolationCounter = emcmotConfig->interpolationRate;
03384 }
03385 }
03386
03387 #ifdef ENABLE_PROBING
03388 extDioRead(emcmotConfig->probeIndex, &emcmotStatus->probeval);
03389 if (emcmotStatus->probing && emcmotStatus->probeTripped) {
03390 tpClear(&emcmotDebug->queue);
03391 emcmotStatus->probing = 0;
03392 }
03393 else if (emcmotStatus->probing && GET_MOTION_INPOS_FLAG() &&
03394 tpQueueDepth(&emcmotDebug->queue) == 0) {
03395 emcmotStatus->probing = 0;
03396 }
03397 else if (emcmotStatus->probing) {
03398 if (emcmotStatus->probeval == emcmotConfig->probePolarity) {
03399 emcmotStatus->probeTripped = 1;
03400 emcmotStatus->probedPos = emcmotStatus->actualPos;
03401 if (GET_MOTION_COORD_FLAG()) {
03402 tpAbort(&emcmotDebug->queue);
03403 SET_MOTION_ERROR_FLAG(0);
03404 }
03405 else {
03406 /* check axis range */
03407 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
03408 tpAbort(&emcmotDebug->freeAxis[axis]);
03409 SET_AXIS_HOMING_FLAG(axis, 0);
03410 SET_AXIS_ERROR_FLAG(axis, 0);
03411 }
03412 }
03413 }
03414 }
03415 #endif /* ENABLE_PROBING */
03416
03417 /* SCALE OUTPUTS: */
03418
03419 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
03420 #ifndef STEPPER_MOTORS
03421 emcmotDebug->rawOutput[axis] =
03422 (emcmotStatus->output[axis] - emcmotStatus->outputOffset[axis]) *
03423 emcmotDebug->inverseOutputScale[axis];
03424 #else
03425 /* lpg - stepper motors, rawoutput is typically -10->0->+10 with
03426 * zero indicating no correction required. For very small corrections,
03427 * the enable gets shut off so no motion takes place and gets used below
03428 * to avoid divide by zero calc (which would give infinite stepper periods)
03429 */
03430 emcmotDebug->rawOutput[axis] = emcmotStatus->output[axis];
03431 if (emcmotDebug->rawOutput[axis] < +OUTPUT_DELTA &&
03432 emcmotDebug->rawOutput[axis] > -OUTPUT_DELTA) {
03433 emcmotDebug->enable[axis] = 0;
03434 }
03435 else {
03436 #ifdef rtai
03437 pdmultfloat = 1e9 /
03438 (emcmotDebug->rawOutput[axis] *
03439 ((double) emcmotStatus->outputScale[axis]) *
03440 ((double) PERIOD));
03441 #else
03442 #ifdef USE_RTL2
03443 pdmultfloat = ((double) HRTICKS_PER_SEC) /
03444 (emcmotDebug->rawOutput[axis] *
03445 ((double) emcmotStatus->outputScale[axis]) *
03446 ((double) PERIOD));
03447 #else
03448 pdmultfloat = ((double) RT_TICKS_PER_SEC) /
03449 (emcmotDebug->rawOutput[axis] *
03450 ((double) emcmotStatus->outputScale[axis]) *
03451 ((double) PERIOD));
03452 #endif
03453 #endif
03454 /* round it */
03455 if (pdmultfloat < 0.0) {
03456 emcmotDebug->pdmult[axis] = (int) (pdmultfloat - 0.5);
03457 emcmotDebug->enable[axis] = 1;
03458 /* lpg */
03459 /*
03460 rounding may have caused a problem for very high gain/high
03461 error calcs. If negative number close to zero get rounded to 0,
03462 we lose the sign information on pdmult. This seems to be handled
03463 in the 1st phase drive routine, but is harmful to the
03464 lpg_phase_drive().
03465 */
03466 if (emcmotDebug->pdmult[axis] == 0) {
03467 emcmotDebug->pdmult[axis] = -1;
03468 }
03469 }
03470 else {
03471 emcmotDebug->pdmult[axis] = (int) (pdmultfloat + 0.5);
03472 emcmotDebug->enable[axis] = 1;
03473 /* lpg - make sure pdmult > 0 as zero means infinite step rate */
03474 if (emcmotDebug->pdmult[axis] == 0) {
03475 emcmotDebug->pdmult[axis] = 1;
03476 }
03477 }
03478 }
03479 #endif
03480 }
03481
03482 /* WRITE OUTPUTS: */
03483
03484 /* write DACs-- note that this is done even when not
03485 enabled, although in this case the pidOutputs are
03486 all zero unless manually overridden. They will not
03487 be set by any calculations if we're not enabled. */
03488 extDacWriteAll(EMCMOT_MAX_AXIS, emcmotDebug->rawOutput);
03489
03490 /* UPDATE THE REST OF THE DYNAMIC STATUS: */
03491
03492 /* copy computed axis positions to status. Note that if motion is
03493 disabled, this is the same as ->input[]. */
03494 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
03495 emcmotStatus->axisPos[axis] = emcmotDebug->jointPos[axis];
03496 }
03497
03498 /* health heartbeat */
03499 emcmotStatus->heartbeat++;
03500
03501 /* motion emcmotDebug->queue status */
03502 emcmotStatus->depth = tpQueueDepth(&emcmotDebug->queue);
03503 emcmotStatus->activeDepth = tpActiveDepth(&emcmotDebug->queue);
03504 emcmotStatus->id = tpGetExecId(&emcmotDebug->queue);
03505 emcmotStatus->queueFull = tcqFull(&emcmotDebug->queue.queue);
03506 SET_MOTION_INPOS_FLAG(0);
03507 if (tpIsDone(&emcmotDebug->queue)) {
03508 SET_MOTION_INPOS_FLAG(1);
03509 }
03510
03511 /* axis status */
03512 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
03513 SET_AXIS_INPOS_FLAG(axis, 0);
03514 if (tpIsDone(&emcmotDebug->freeAxis[axis])) {
03515 SET_AXIS_INPOS_FLAG(axis, 1);
03516 }
03517 else {
03518 /* this axis, at least, is moving, so set emcmotDebug->overriding flag */
03519 if (emcmotStatus->overrideLimits) {
03520 emcmotDebug->overriding = 1;
03521 }
03522 }
03523 }
03524
03525 /* reset overrideLimits flag if we have started a move and now
03526 are in position */
03527 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
03528 if (! GET_AXIS_INPOS_FLAG(axis)) {
03529 break;
03530 }
03531 }
03532 if (axis == EMCMOT_MAX_AXIS) {
03533 /* ran through all axes, and all are in position */
03534 if (emcmotDebug->overriding) {
03535 emcmotDebug->overriding = 0;
03536 emcmotStatus->overrideLimits = 0;
03537 }
03538 }
03539
03540 /* check to see if we should pause in order to implement
03541 single emcmotDebug->stepping */
03542 if (emcmotDebug->stepping && emcmotDebug->idForStep != emcmotStatus->id) {
03543 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
03544 tpPause(&emcmotDebug->freeAxis[axis]);
03545 }
03546 tpPause(&emcmotDebug->queue);
03547 emcmotDebug->stepping = 0;
03548 emcmotStatus->paused = 1;
03549 }
03550
03551 /* calculate elapsed time and min/max/avg */
03552 end = etime();
03553 delta = end - start;
03554
03555 emcmotDebug->last_time = emcmotDebug->cur_time;
03556 emcmotDebug->cur_time = end;
03557
03558 if (emcmotDebug->last_time != 0.0) {
03559 mmxavgAdd(&emcmotDebug->yMmxavg, (emcmotDebug->cur_time - emcmotDebug->last_time));
03560 emcmotDebug->yMin = mmxavgMin(&emcmotDebug->yMmxavg);
03561 emcmotDebug->yMax = mmxavgMax(&emcmotDebug->yMmxavg);
03562 emcmotDebug->yAvg = mmxavgAvg(&emcmotDebug->yMmxavg);
03563 }
03564
03565 emcmotStatus->computeTime = delta;
03566 if (2 == whichCycle) {
03567 /* traj calcs done this cycle-- use tMin,Max,Avg */
03568 mmxavgAdd(&emcmotDebug->tMmxavg, delta);
03569 emcmotDebug->tMin = mmxavgMin(&emcmotDebug->tMmxavg);
03570 emcmotDebug->tMax = mmxavgMax(&emcmotDebug->tMmxavg);
03571 emcmotDebug->tAvg = mmxavgAvg(&emcmotDebug->tMmxavg);
03572 }
03573 else if (1 == whichCycle) {
03574 /* servo calcs only this cycle-- use sMin,Max,Avg */
03575 mmxavgAdd(&emcmotDebug->sMmxavg, delta);
03576 emcmotDebug->sMin = mmxavgMin(&emcmotDebug->sMmxavg);
03577 emcmotDebug->sMax = mmxavgMax(&emcmotDebug->sMmxavg);
03578 emcmotDebug->sAvg = mmxavgAvg(&emcmotDebug->sMmxavg);
03579 }
03580 else {
03581 /* calcs disabled this cycle-- use nMin,Max,Avg */
03582 mmxavgAdd(&emcmotDebug->nMmxavg, delta);
03583 emcmotDebug->nMin = mmxavgMin(&emcmotDebug->nMmxavg);
03584 emcmotDebug->nMax = mmxavgMax(&emcmotDebug->nMmxavg);
03585 emcmotDebug->nAvg = mmxavgAvg(&emcmotDebug->nMmxavg);
03586 }
03587
03588 /* log per-servo-cycle data if logging active */
03589 logIt = 0;
03590 if (emcmotStatus->logStarted &&
03591 emcmotStatus->logSkip >= 0) {
03592
03593 /* record type here, since all will set this */
03594 ls.type = emcmotStatus->logType;
03595
03596 /* now log type-specific data */
03597 switch (ls.type) {
03598
03599 case EMCMOT_LOG_TYPE_AXIS_POS:
03600 if (logSkip-- <= 0) {
03601 ls.item.axisPos.time = end - logStartTime;
03602 ls.item.axisPos.input = emcmotStatus->input[loggingAxis];
03603 ls.item.axisPos.output = emcmotDebug->jointPos[loggingAxis];
03604 logSkip = emcmotStatus->logSkip;
03605 logIt = 1;
03606 }
03607 break;
03608
03609 case EMCMOT_LOG_TYPE_ALL_INPOS:
03610 if (logSkip-- <= 0) {
03611 ls.item.allInpos.time = end - logStartTime;
03612 for (axis = 0;
03613 axis < EMCMOT_LOG_NUM_AXES &&
03614 axis < EMCMOT_MAX_AXIS;
03615 axis++) {
03616 ls.item.allInpos.input[axis] = emcmotStatus->input[axis];
03617 }
03618 logSkip = emcmotStatus->logSkip;
03619 logIt = 1;
03620 }
03621 break;
03622
03623 case EMCMOT_LOG_TYPE_ALL_OUTPOS:
03624 if (logSkip-- <= 0) {
03625 ls.item.allOutpos.time = end - logStartTime;
03626 for (axis = 0;
03627 axis < EMCMOT_LOG_NUM_AXES &&
03628 axis < EMCMOT_MAX_AXIS;
03629 axis++) {
03630 ls.item.allOutpos.output[axis] = emcmotDebug->jointPos[axis];
03631 }
03632 logSkip = emcmotStatus->logSkip;
03633 logIt = 1;
03634 }
03635 break;
03636
03637 case EMCMOT_LOG_TYPE_AXIS_VEL:
03638 if (logSkip-- <= 0) {
03639 ls.item.axisVel.time = end - logStartTime;
03640 ls.item.axisVel.cmdVel = emcmotDebug->jointPos[loggingAxis] -
03641 emcmotDebug->oldJointPos[loggingAxis];
03642 ls.item.axisVel.actVel = emcmotStatus->input[loggingAxis] -
03643 emcmotDebug->oldInput[loggingAxis];
03644 logSkip = emcmotStatus->logSkip;
03645 logIt = 1;
03646 }
03647 break;
03648
03649 case EMCMOT_LOG_TYPE_ALL_FERROR:
03650 if (logSkip-- <= 0) {
03651 ls.item.allFerror.time = end - logStartTime;
03652 for (axis = 0;
03653 axis < EMCMOT_LOG_NUM_AXES &&
03654 axis < EMCMOT_MAX_AXIS;
03655 axis++) {
03656 ls.item.allFerror.ferror[axis] = emcmotDebug->ferrorCurrent[axis];
03657 }
03658 logSkip = emcmotStatus->logSkip;
03659 logIt = 1;
03660 }
03661 break;
03662
03663 case EMCMOT_LOG_TYPE_POS_VOLTAGE:
03664 /* don't do a circular log-- suppress if full */
03665 if (emcmotLog->howmany >= emcmotStatus->logSize) {
03666 emcmotStatus->output[loggingAxis] = 0.0; /* drop the DAC to zero */
03667 emcmotStatus->logStarted = 0; /* stop logging */
03668 logIt = 0; /* should still be zero, reset anyway */
03669 break;
03670 }
03671 if (logSkip-- <= 0) {
03672 ls.item.posVoltage.time = end - logStartTime;
03673 for (axis = 0;
03674 axis < EMCMOT_LOG_NUM_AXES &&
03675 axis < EMCMOT_MAX_AXIS;
03676 axis++) {
03677 ls.item.posVoltage.pos = emcmotStatus->input[loggingAxis];
03678 ls.item.posVoltage.voltage = emcmotDebug->rawOutput[loggingAxis];
03679 }
03680 logSkip = emcmotStatus->logSkip;
03681 logIt = 1;
03682 }
03683 break;
03684
03685 default:
03686 break;
03687 } /* end of: switch on log type */
03688
03689 /* now log it */
03690 if (logIt) {
03691 emcmotLogAdd(emcmotLog, ls);
03692 emcmotStatus->logPoints = emcmotLog->howmany;
03693 logIt = 0;
03694 }
03695 } /* end of: if logging */
03696
03697 emcmotDebug->running_time = etime() - emcmotDebug->start_time;
03698
03699 /* set tail to head, which has already been incremented */
03700 emcmotStatus->tail = emcmotStatus->head;
03701 emcmotDebug->tail = emcmotDebug->head;
03702 emcmotConfig->tail = emcmotConfig->head;
03703 /* wait for next cycle */
03704 #ifdef rtai
03705 rt_task_wait_period();
03706 while(0 == emcmotStruct)
03707 {
03708 rt_task_wait_period();
03709 }
03710 #endif
03711 #ifdef rtlinux
03712 #ifdef USE_RTL2
03713 pthread_wait_np();
03714 #else
03715 rt_task_wait();
03716 #endif
03717 #endif
03718 #if defined(rtai) || defined(rtlinux)
03719 } /* end of: forever loop for RT task */
03720 #endif
03721
03722 #ifdef USE_RTL2
03723 return NULL;
03724 #endif
03725
03726 } /* end of: emcmotController() function */
|
|
|
Definition at line 5140 of file emcmot.c. 05141 {
05142 emcmot_done = 1;
05143 }
|
|
|
Definition at line 1067 of file emcmot.c. 01068 {
01069 #if defined(rtlinux) || defined(rtai)
01070 outb(byte, MOT_DOUT_PORT);
01071 #endif
01072 }
|
|
||||||||||||
|
Definition at line 5150 of file emcmot.c. 05151 {
05152 int t;
05153 int len;
05154
05155 for (t = 1; t < argc; t++) {
05156 /* try -ini */
05157 /* NOTE: motion controller cannot normally read an INI file.
05158 This is provided for main() simulation, which can read
05159 an INI file and needs it for the plant simulation parameters */
05160 if (!strcmp(argv[t], "-ini")) {
05161 if (t == argc - 1) {
05162 diagnostics("missing -ini parameter\n");
05163 return -1;
05164 }
05165 else {
05166 strcpy(EMCMOT_INIFILE, argv[t+1]);
05167 t++; /* step over following arg */
05168 continue;
05169 }
05170 }
05171
05172 /* try SHMEM_BASE_ADDRESS */
05173 len = strlen("SHMEM_BASE_ADDRESS");
05174 if (! strncmp(argv[t], "SHMEM_BASE_ADDRESS", len)) {
05175 if (argv[t][len] != '=' ||
05176 1 != sscanf(&argv[t][len + 1], "%li", &SHMEM_BASE_ADDRESS)) {
05177 diagnostics("syntax: %s SHMEM_BASE_ADDRESS=integer\n", argv[0]);
05178 return -1;
05179 }
05180 else {
05181 continue;
05182 }
05183 }
05184
05185 /* try SHMEM_KEY */
05186 len = strlen("SHMEM_KEY");
05187 if (! strncmp(argv[t], "SHMEM_KEY", len)) {
05188 if (argv[t][len] != '=' ||
05189 1 != sscanf(&argv[t][len + 1], "%i", &SHMEM_KEY)) {
05190 diagnostics("syntax: %s SHMEM_KEY=integer\n", argv[0]);
05191 return -1;
05192 }
05193 else {
05194 continue;
05195 }
05196 }
05197
05198 /* FIXME */
05199 /* try -noforward */
05200 if (!strcmp(argv[t], "-noforward")) {
05201 EMCMOT_NO_FORWARD_KINEMATICS = 1;
05202 kinType = KINEMATICS_INVERSE_ONLY;
05203 continue;
05204 }
05205
05206 /* no match-- bad arg */
05207 diagnostics("bad argument to %s: %s\n", argv[0], argv[t]);
05208 return -1;
05209 }
05210
05211 return 0;
05212 }
|
|
|
Definition at line 899 of file emcmot.c. 00900 {
00901 double joint[EMCMOT_MAX_AXIS];
00902 int axis;
00903
00904 /* fill in all joints with 0 */
00905 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
00906 joint[axis] = 0.0;
00907 }
00908
00909 /* now fill in with real values, for joints that are used */
00910 kinematicsInverse(&pos, joint, &iflags, &fflags);
00911
00912 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
00913 if (! GET_AXIS_ACTIVE_FLAG(axis)) {
00914 /* if axis is not active, don't even look at its limits */
00915 continue;
00916 }
00917
00918 if (joint[axis] > emcmotConfig->maxLimit[axis] ||
00919 joint[axis] < emcmotConfig->minLimit[axis]) {
00920 return 0; /* can't move further past limit */
00921 }
00922 }
00923
00924 /* okay to move */
00925 return 1;
00926 }
|
|
|
Definition at line 4331 of file emcmot.c. Referenced by main().
04332 {
04333 int axis;
04334 int t;
04335 #ifdef USE_RTL2
04336 hrtime_t now;
04337 pthread_attr_t attr;
04338 struct sched_param sched_param;
04339 struct timespec resolution;
04340 int resperiod;
04341 hrtime_t hr_timer_period;
04342 #endif
04343 PID_STRUCT pid;
04344 #ifdef rtai
04345 int error_code;
04346 #endif
04347
04348 /* lpg - echo module params so we know they were accepted */
04349 #ifdef STEPPER_MOTORS
04350 char *pstype;
04351 switch(STEPPING_TYPE){
04352 case 0: pstype = "Step/Dir"; break;
04353 case 1: pstype = "Phase"; break;
04354 case 2: pstype = "Quadrature/other"; break;
04355 default: pstype = "Invalid";
04356 }
04357 diagnostics("emcmot: STEPPING_TYPE = %s\n",pstype);
04358 diagnostics("emcmot: PARPORT_IO_ADDRESS = 0x%x\n",PARPORT_IO_ADDRESS);
04359 #endif
04360 diagnostics("emcmot: SHMEM_BASE_ADDRESS = %ld\n",SHMEM_BASE_ADDRESS);
04361 diagnostics("emcmot: SHMEM_KEY = %d\n",SHMEM_KEY);
04362 diagnostics("emcmot: PERIOD = %dns\n",PERIOD);
04363 diagnostics("emcmot: EMCMOT_TASK_PRIORITY = %d\n",EMCMOT_TASK_PRIORITY);
04364 diagnostics("emcmot: EMCMOT_TASK_STACK_SIZE = %d\n",EMCMOT_TASK_STACK_SIZE);
04365 #ifdef STEPPER_MOTORS
04366 diagnostics("emcmot: FREQ_TASK_PRIORITY = %d\n",FREQ_TASK_PRIORITY);
04367 diagnostics("emcmot: FREQ_TASK_STACK_SIZE = %d\n",FREQ_TASK_STACK_SIZE);
04368 #endif
04369 #ifdef rtai
04370 diagnostics("emcmot: sizeof(RT_TASK) = %d\n", sizeof(RT_TASK));
04371 #endif
04372
04373 /* lpg - the next 2 params only exist for non stepper systems (servo to go)*/
04374 #if 0
04375 diagnostics("emcmot: STG_BASE_ADDRESS = 0x%hx\n",STG_BASE_ADDRESS);
04376 diagnostics("emcmot: FIND_STG_BASE_ADDRESS = %d\n",FIND_STG_BASE_ADDRESS);
04377 #endif
04378
04379
04380 emcmotTask_created=0;
04381 freqTask_created=0;
04382 emcmotStruct=0;
04383 emcmotDebug=0;
04384 emcmotStatus=0;
04385 emcmotCommand=0;
04386 emcmotConfig=0;
04387
04388 /* record the kinematics type of the machine */
04389 kinType = kinematicsType();
04390 if (EMCMOT_NO_FORWARD_KINEMATICS) {
04391 kinType = KINEMATICS_INVERSE_ONLY;
04392 }
04393
04394 #ifdef rtai
04395 rt_mount_rtai();
04396 rt_linux_use_fpu(1);
04397 emcmotStruct = rtai_kmalloc(SHMEM_KEY, sizeof(EMCMOT_STRUCT));
04398 if(0 == emcmotStruct)
04399 {
04400 diagnostics("emcmot: can't allocate shared memory with rtai_kmalloc(%d,%d)\n.", SHMEM_KEY,sizeof(EMCMOT_STRUCT));
04401 return -1;
04402 }
04403 diagnostics("emcmot: emcmotStruct allocated at 0x%X from rtai_kmalloc(%d,%d)\n", ((unsigned int) emcmotStruct), SHMEM_KEY, sizeof(EMCMOT_STRUCT));
04404
04405 rt_set_periodic_mode();
04406 /* PERIOD is in microseconds, convert to nanoseconds then to rtai counts
04407 and set the timer..*/
04408 rtaiTickPeriod = start_rt_timer(nano2count(PERIOD));
04409 if (rtaiTickPeriod < 1 )
04410 {
04411 diagnostics("emcmot: problem with start_rt_timer(%d)\n",
04412 nano2count(PERIOD));
04413 return(-1);
04414 }
04415 rtaiTickPeriod_long = (long) rtaiTickPeriod;
04416 diagnostics("emcmot: rtaiTickPeriod=%d\n",rtaiTickPeriod_long);
04417 #else
04418 #ifdef rtlinux
04419
04420 /* use pure periodic timing */
04421 #ifdef USE_RTL2
04422 local_clock = rtl_getschedclock();
04423
04424 /* PERIOD units were established for RTL 09J which was approximately
04425 microseconds the same as the timer resolution,
04426 but in RTL 2.0 most of the funtions take nanosecond periods and we
04427 should dynamically discover the timer resolution.
04428 THE PERIOD units were changed to nanoseconds on 7-Mar-2000, so
04429 RTL2 no longer needs to convert but RTL1 does now.
04430 */
04431 clock_getres (local_clock, &resolution);
04432 resperiod = timespec_to_ns(&resolution); /* resperiod probably equals 838 */
04433
04434 /* make period and even timer interval */
04435 PERIOD /= resperiod;
04436 PERIOD *= resperiod;
04437 if (PERIOD < resperiod) {
04438 PERIOD = resperiod;
04439 }
04440 hr_timer_period = (hrtime_t) PERIOD;
04441
04442 if (rtl_setclockmode(local_clock, RTL_CLOCK_MODE_PERIODIC,
04443 hr_timer_period)) {
04444 diagnostics("can't set periodic mode\n");
04445 if (rtl_setclockmode(local_clock, RTL_CLOCK_MODE_ONESHOT,0)) {
04446 diagnostics("can't set oneshot mode\n"); ;
04447 }
04448 }
04449
04450 #else /* RTL1 */
04451
04452 /*
04453 THE PERIOD units were changed from timer ticks to nanoseconds on
04454 7-Mar-2000, so RTL2 no longer needs to convert but RTL1 does now
04455 */
04456 PERIOD = (int) (((double) PERIOD) / 1.0e9 * ((double) RT_TICKS_PER_SEC));
04457 rtstart = rtl_set_periodic_mode(PERIOD);
04458
04459 if (rtstart == RT_TIME_END) {
04460 /* can't do it-- revert to oneshot mode */
04461 rtl_set_oneshot_mode();
04462 diagnostics("reverting to oneshot mode\n");
04463 }
04464 else {
04465 diagnostics("running in periodic mode\n");
04466 }
04467 #endif
04468
04469 #ifdef USE_RTL2
04470 /* set shared memory pointer using mbuff which does not require that
04471 memory be reserved in lilo.conf */
04472 emcmotStruct = (EMCMOT_STRUCT *) mbuff_alloc("emcmotStruct", sizeof(EMCMOT_STRUCT));
04473 #else
04474 #if defined(rtlinux2) /* set shared memory pointer using ioremap for
04475 2.1+ kernels */
04476 emcmotStruct = (EMCMOT_STRUCT *) ioremap(SHMEM_BASE_ADDRESS, sizeof(EMCMOT_STRUCT));
04477 #else
04478 /* set shared memory pointer */
04479 emcmotStruct = (EMCMOT_STRUCT *) vremap(SHMEM_BASE_ADDRESS, sizeof(EMCMOT_STRUCT));
04480 #endif
04481
04482 #endif
04483
04484 #else /* not rtlinux */
04485 /* get command shmem */
04486 shmem = rcs_shm_open(SHMEM_KEY, sizeof(EMCMOT_STRUCT), 1, 0666);
04487 if (NULL == shmem ||
04488 NULL == shmem->addr) {
04489 diagnostics("can't get shared memory\n");
04490 return -1;
04491 }
04492
04493 memset(shmem->addr, 0, sizeof(EMCMOT_STRUCT));
04494 /* map shmem area into local address space */
04495 emcmotStruct = (EMCMOT_STRUCT *) shmem->addr;
04496
04497 #endif /* else not rtlinux */
04498
04499 #endif /* not rtai */
04500
04501 /* we'll reference emcmotStruct directly */
04502 emcmotCommand = (EMCMOT_COMMAND *) &emcmotStruct->command;
04503 emcmotStatus = (EMCMOT_STATUS *) &emcmotStruct->status;
04504 emcmotConfig = (EMCMOT_CONFIG *) &emcmotStruct->config;
04505 emcmotDebug = (EMCMOT_DEBUG *) &emcmotStruct->debug;
04506
04507 emcmotError = (EMCMOT_ERROR *) &emcmotStruct->error;
04508 emcmotLog = (EMCMOT_LOG *) &emcmotStruct->log;
04509 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
04510 emcmotComp[axis] = (EMCMOT_COMP *) &emcmotStruct->comp[axis];
04511
04512 emcmotDebug->bcomp[axis]=0; /* backlash comp value */
04513 emcmotDebug->bcompdir[axis]=0; /* 0=none, 1=pos, -1=neg */
04514 emcmotDebug->bcompincr[axis]=0; /* incremental backlash comp */
04515 emcmotDebug->bac_done[axis]=0;
04516 emcmotDebug->bac_d[axis]=0;
04517 emcmotDebug->bac_di[axis]=0;
04518 emcmotDebug->bac_D[axis]=0;
04519 emcmotDebug->bac_halfD[axis]=0;
04520 emcmotDebug->bac_incrincr[axis]=0;
04521 emcmotDebug->bac_incr[axis]=0;
04522 }
04523
04524 /* zero shared memory */
04525 for (t = 0; t < sizeof(EMCMOT_STRUCT); t++) {
04526 ((char *) emcmotStruct)[t] = 0;
04527 }
04528
04529 /* init locals */
04530 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
04531 emcmotDebug->maxLimitSwitchCount[axis] = 0;
04532 emcmotDebug->minLimitSwitchCount[axis] = 0;
04533 emcmotDebug->ampFaultCount[axis] = 0;
04534 }
04535
04536 /* init compensation struct */
04537 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
04538 emcmotComp[axis]->total = 0;
04539 emcmotComp[axis]->alter = 0.0;
04540 /* leave out the avgint, nominal, forward, and reverse, since
04541 these can't be zero and the total flag prevents their use anyway */
04542 }
04543
04544 /* init error struct */
04545 emcmotErrorInit(emcmotError);
04546
04547 /* init command struct */
04548 emcmotCommand->head = 0;
04549 emcmotCommand->command = 0;
04550 emcmotCommand->commandNum = 0;
04551 emcmotCommand->tail = 0;
04552
04553 /* init status struct */
04554
04555 emcmotStatus->head = 0;
04556 emcmotDebug->head = 0;
04557 emcmotConfig->head = 0;
04558
04559 emcmotStatus->motionFlag = 0;
04560 SET_MOTION_ERROR_FLAG(0);
04561 SET_MOTION_COORD_FLAG(0);
04562 SET_MOTION_TELEOP_FLAG(0);
04563 emcmotDebug->split = 0;
04564 emcmotStatus->commandEcho = 0;
04565 emcmotStatus->commandNumEcho = 0;
04566 emcmotStatus->commandStatus = 0;
04567 emcmotStatus->heartbeat = 0;
04568 emcmotStatus->computeTime = 0.0;
04569 emcmotConfig->numAxes = EMCMOT_MAX_AXIS;
04570 emcmotConfig->trajCycleTime = TRAJ_CYCLE_TIME;
04571 emcmotConfig->servoCycleTime = SERVO_CYCLE_TIME;
04572 emcmotStatus->pos.tran.x = 0.0;
04573 emcmotStatus->pos.tran.y = 0.0;
04574 emcmotStatus->pos.tran.z = 0.0;
04575 emcmotStatus->actualPos.tran.x = 0.0;
04576 emcmotStatus->actualPos.tran.y = 0.0;
04577 emcmotStatus->actualPos.tran.z = 0.0;
04578 emcmotStatus->vel = VELOCITY;
04579 emcmotConfig->limitVel = VELOCITY;
04580 emcmotStatus->acc = ACCELERATION;
04581 emcmotStatus->qVscale = 1.0;
04582 emcmotStatus->id = 0;
04583 emcmotStatus->depth = 0;
04584 emcmotStatus->activeDepth = 0;
04585 emcmotStatus->paused = 0;
04586 emcmotStatus->overrideLimits = 0;
04587 SET_MOTION_INPOS_FLAG(1);
04588 emcmotStatus->logOpen = 0;
04589 emcmotStatus->logStarted = 0;
04590 emcmotStatus->logSize = 0;
04591 emcmotStatus->logSkip = 0;
04592 emcmotStatus->logPoints = 0;
04593 SET_MOTION_ENABLE_FLAG(0);
04594 emcmotConfig->kinematics_type = kinType;
04595
04596 emcmotDebug->oldPos = emcmotStatus->pos;
04597 emcmotDebug->oldVel.tran.x = 0.0;
04598 emcmotDebug->oldVel.tran.y = 0.0;
04599 emcmotDebug->oldVel.tran.z = 0.0;
04600
04601 MARK_EMCMOT_CONFIG_CHANGE();
04602
04603 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
04604 emcmotConfig->homingVel[axis] = VELOCITY;
04605 emcmotConfig->homeOffset[axis] = 0.0;
04606 emcmotStatus->axisFlag[axis] = 0;
04607 emcmotConfig->maxLimit[axis] = MAX_LIMIT;
04608 emcmotConfig->minLimit[axis] = MIN_LIMIT;
04609 emcmotConfig->maxOutput[axis] = MAX_OUTPUT;
04610 emcmotConfig->minOutput[axis] = MIN_OUTPUT;
04611 emcmotConfig->minFerror[axis] = 0.0; /* gives a true linear ferror */
04612 emcmotConfig->maxFerror[axis] = MAX_FERROR;
04613 emcmotDebug->ferrorCurrent[axis] = 0.0;
04614 emcmotDebug->ferrorHighMark[axis] = 0.0;
04615 emcmotStatus->outputScale[axis] = OUTPUT_SCALE;
04616 emcmotStatus->outputOffset[axis] = OUTPUT_OFFSET;
04617 emcmotStatus->inputScale[axis] = INPUT_SCALE;
04618 emcmotDebug->inverseInputScale[axis] = 1.0 / INPUT_SCALE;
04619 emcmotStatus->inputOffset[axis] = INPUT_OFFSET;
04620 emcmotDebug->inverseOutputScale[axis] = 1.0 / OUTPUT_SCALE;
04621 emcmotStatus->axVscale[axis] = 1.0;
04622 emcmotConfig->axisLimitVel[axis] = 1.0;
04623 emcmotDebug->bigVel[axis] = 1.0;
04624 SET_AXIS_ENABLE_FLAG(axis, 0);
04625 SET_AXIS_ACTIVE_FLAG(axis, 0); /* default is not to use it; need an
04626 explicit activate */
04627 SET_AXIS_NSL_FLAG(axis, 0);
04628 SET_AXIS_PSL_FLAG(axis, 0);
04629 SET_AXIS_NHL_FLAG(axis, 0);
04630 SET_AXIS_PHL_FLAG(axis, 0);
04631 SET_AXIS_INPOS_FLAG(axis, 1);
04632 SET_AXIS_HOMING_FLAG(axis, 0);
04633 SET_AXIS_HOMED_FLAG(axis, 0);
04634 SET_AXIS_FERROR_FLAG(axis, 0);
04635 SET_AXIS_FAULT_FLAG(axis, 0);
04636 SET_AXIS_ERROR_FLAG(axis, 0);
04637 emcmotConfig->axisPolarity[axis] = (EMCMOT_AXIS_FLAG) 0xFFFFFFFF;
04638 /* will read encoders directly, so don't set them here */
04639 }
04640
04641 /* FIXME-- add emcmotError */
04642
04643 /* init min-max-avg stats */
04644 mmxavgInit(&emcmotDebug->tMmxavg, emcmotDebug->tMmxavgSpace, MMXAVG_SIZE);
04645 mmxavgInit(&emcmotDebug->sMmxavg, emcmotDebug->sMmxavgSpace, MMXAVG_SIZE);
04646 mmxavgInit(&emcmotDebug->nMmxavg, emcmotDebug->nMmxavgSpace, MMXAVG_SIZE);
04647 mmxavgInit(&emcmotDebug->yMmxavg, emcmotDebug->yMmxavgSpace, MMXAVG_SIZE);
04648 mmxavgInit(&emcmotDebug->fMmxavg, emcmotDebug->fMmxavgSpace, MMXAVG_SIZE);
04649 mmxavgInit(&emcmotDebug->fyMmxavg, emcmotDebug->fyMmxavgSpace, MMXAVG_SIZE);
04650 emcmotDebug->tMin = 0.0;
04651 emcmotDebug->tMax = 0.0;
04652 emcmotDebug->tAvg = 0.0;
04653 emcmotDebug->sMin = 0.0;
04654 emcmotDebug->sMax = 0.0;
04655 emcmotDebug->sAvg = 0.0;
04656 emcmotDebug->nMin = 0.0;
04657 emcmotDebug->nMax = 0.0;
04658 emcmotDebug->nAvg = 0.0;
04659 emcmotDebug->yMin = 0.0;
04660 emcmotDebug->yMax = 0.0;
04661 emcmotDebug->yAvg = 0.0;
04662 emcmotDebug->fyMin = 0.0;
04663 emcmotDebug->fyMax = 0.0;
04664 emcmotDebug->fyAvg = 0.0;
04665 emcmotDebug->fMin = 0.0;
04666 emcmotDebug->fMax = 0.0;
04667 emcmotDebug->fAvg = 0.0;
04668
04669 emcmotDebug->cur_time = emcmotDebug->last_time = 0.0;
04670 emcmotDebug->start_time = etime();
04671 emcmotDebug->running_time = 0.0;
04672
04673 /* init motion emcmotDebug->queue */
04674 if (-1 == tpCreate(&emcmotDebug->queue, DEFAULT_TC_QUEUE_SIZE, emcmotDebug->queueTcSpace)) {
04675 diagnostics("can't create motion emcmotDebug->queue\n");
04676 return -1;
04677 }
04678 tpInit(&emcmotDebug->queue);
04679 tpSetCycleTime(&emcmotDebug->queue, emcmotConfig->trajCycleTime);
04680 tpSetPos(&emcmotDebug->queue, emcmotStatus->pos);
04681 tpSetVmax(&emcmotDebug->queue, emcmotStatus->vel);
04682 tpSetAmax(&emcmotDebug->queue, emcmotStatus->acc);
04683
04684 /* init the axis components */
04685 pid.p = P_GAIN;
04686 pid.i = I_GAIN;
04687 pid.d = D_GAIN;
04688 pid.ff0 = FF0_GAIN;
04689 pid.ff1 = FF1_GAIN;
04690 pid.ff2 = FF2_GAIN;
04691 pid.backlash = BACKLASH;
04692 pid.bias = BIAS;
04693 pid.maxError = MAX_ERROR;
04694
04695 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
04696 if (-1 == tpCreate(&emcmotDebug->freeAxis[axis], FREE_AXIS_QUEUE_SIZE, emcmotDebug->freeAxisTcSpace[axis])) {
04697 diagnostics("can't create axis emcmotDebug->queue %d\n", axis);
04698 return -1;
04699 }
04700 tpInit(&emcmotDebug->freeAxis[axis]);
04701 tpSetCycleTime(&emcmotDebug->freeAxis[axis], emcmotConfig->trajCycleTime);
04702 /* emcmotDebug->freePose is inited to 0's in decl */
04703 tpSetPos(&emcmotDebug->freeAxis[axis], emcmotDebug->freePose);
04704 tpSetVmax(&emcmotDebug->freeAxis[axis], emcmotStatus->vel);
04705 tpSetAmax(&emcmotDebug->freeAxis[axis], emcmotStatus->acc);
04706 pidInit(&emcmotConfig->pid[axis]);
04707 pidSetGains(&emcmotConfig->pid[axis], pid);
04708 cubicInit(&emcmotDebug->cubic[axis]);
04709 }
04710
04711 /* init the time and rate using functions to affect traj, the
04712 pids, and the cubics properly, since they're coupled */
04713 setTrajCycleTime(TRAJ_CYCLE_TIME);
04714 setServoCycleTime(SERVO_CYCLE_TIME);
04715
04716 /* init board */
04717
04718 if (-1 == extMotInit((const char *) EMCMOT_INIFILE)) {
04719 diagnostics("can't initialize motion hardware\n");
04720 return -1;
04721 }
04722
04723 if (-1 == extDioInit((const char *) EMCMOT_INIFILE)) {
04724 diagnostics("can't initialize DIO hardware\n");
04725 return -1;
04726 }
04727
04728 if (-1 == extAioInit((const char *) EMCMOT_INIFILE)) {
04729 diagnostics("can't initialize AIO hardware\n");
04730 return -1;
04731 }
04732
04733 extEncoderSetIndexModel(EXT_ENCODER_INDEX_MODEL_MANUAL);
04734 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
04735 emcmotDebug->rawInput[axis] = 0.0;
04736 emcmotDebug->rawOutput[axis] = 0.0;
04737 emcmotDebug->coarseJointPos[axis] = 0.0;
04738 emcmotDebug->jointPos[axis] = 0.0;
04739 emcmotDebug->jointVel[axis] = 0.0;
04740 emcmotStatus->axisPos[axis] = 0.0;
04741 emcmotDebug->oldJointPos[axis] = 0.0;
04742 emcmotDebug->outJointPos[axis] = 0.0;
04743
04744 emcmotDebug->homingPhase[axis] = 0;
04745 emcmotDebug->latchFlag[axis] = 0;
04746 emcmotDebug->saveLatch[axis] = 0.0;
04747
04748 emcmotStatus->input[axis] = 0.0;
04749 emcmotDebug->oldInput[axis] = 0.0;
04750 emcmotDebug->oldInputValid[axis]=0;
04751 emcmotStatus->output[axis] = 0.0;
04752
04753 emcmotDebug->jointHome[axis] = 0.0;
04754
04755 extAmpEnable(axis,
04756 ! GET_AXIS_ENABLE_POLARITY(axis));
04757 }
04758
04759 emcmotStatus->tail = 0;
04760
04761 #ifdef rtai
04762 diagnostics("emcmot: initializing emcmotTask\n");
04763 if( 0 != ( error_code =
04764 rt_task_init(&emcmotTask, /* RT_TASK */
04765 emcmotController, /* task function */
04766 1, /* arg */
04767 EMCMOT_TASK_STACK_SIZE, /* stack */
04768 EMCMOT_TASK_PRIORITY, /* priority */
04769 1, /* uses fpu */
04770 emcmotsig)) /* signal function */
04771 )
04772 {
04773 diagnostics("rt_task_init failed for emcmotTask error_code=%d\n",
04774 error_code);
04775 return -1;
04776 }
04777 now = rt_get_time();
04778 diagnostics("emcmot: rtaiTickPeriod=%d\n",rtaiTickPeriod);
04779 if(rtaiTickPeriod > 0)
04780 {
04781 rtaiTickPeriod_long = (long) rtaiTickPeriod;
04782 diagnostics("servoCycleTime=%dns\n",
04783 (int) (1e9* emcmotConfig->servoCycleTime));
04784 iperiod = nano2count((int) (1e9* emcmotConfig->servoCycleTime));
04785 diagnostics("servoCycleTime=%d ticks\n",
04786 iperiod);
04787
04788 if ( iperiod < rtaiTickPeriod_long)
04789 {
04790 iperiod = rtaiTickPeriod_long;
04791 }
04792 iperiod = (iperiod + rtaiTickPeriod_long/2)/ rtaiTickPeriod_long;
04793 iperiod *= rtaiTickPeriod_long;
04794 iperiod_rtime = (RTIME) iperiod;
04795 now = rt_get_time();
04796 setServoCycleTime(count2nano(iperiod)*1e-9);
04797 diagnostics("emcmot: making emcmotTask periodic at a rate of %d ticks or %d nanoseconds \n", iperiod , count2nano(iperiod));
04798 if ( 0 != (error_code =
04799 rt_task_make_periodic(&emcmotTask,
04800 now+5*rtaiTickPeriod,
04801 iperiod_rtime)
04802 ))
04803 {
04804 diagnostics("rt_task_make_periodic failed for emcmotTask error_code=%d\n",
04805 error_code);
04806 return -1;
04807 }
04808 emcmotTask_created=1;
04809 }
04810 diagnostics("emcmot: rtaiTickPeriod=%d\n",rtaiTickPeriod);
04811
04812 #ifdef STEPPER_MOTORS
04813 diagnostics("emcmot: initializing freqTask\n");
04814 switch (STEPPING_TYPE) /* lpg */
04815 {
04816 case 1: /* phase stepping */
04817 error_code = rt_task_init(&freqTask, /* RT_TASK */
04818 phasefunc, /* task function */
04819 1, /* task function arg */
04820 FREQ_TASK_STACK_SIZE, /* stack */
04821 FREQ_TASK_PRIORITY, /* priority */
04822 1, /* use fpu */
04823 freqsig); /* signal func */
04824 break;
04825 case 2: /* lpg quadrature/other phase stepping */
04826 error_code = rt_task_init(&freqTask, /* RT_TASK */
04827 lpg_phase_drive, /* task func */
04828 1, /* arg */
04829 FREQ_TASK_STACK_SIZE, /* stack */
04830 FREQ_TASK_PRIORITY,
04831 1, /* use fpu */
04832 freqsig); /* signal func */
04833 default: /* default is step/direction */
04834 error_code = rt_task_init(&freqTask, /* RT_TASK */
04835 freqfunc, /* task func */
04836 1, /* arg */
04837 FREQ_TASK_STACK_SIZE, /* stack */
04838 FREQ_TASK_PRIORITY,
04839 1, /* use fpu */
04840 freqsig); /* signal func */
04841 break;
04842 }
04843 diagnostics("emcmot: rtaiTickPeriod=%d\n",rtaiTickPeriod);
04844 if(error_code != 0)
04845 {
04846 diagnostics("rt_task_init failed for freqTask error_code = %d\n",
04847 error_code);
04848 return -1;
04849 }
04850 if( rtaiTickPeriod > 0 )
04851 {
04852 now = rt_get_time();
04853 diagnostics("emcmot: making freqTask periodic at a rate of %d ticks or %d nanoseconds \n", ((int) rtaiTickPeriod_long) , ((int) count2nano(rtaiTickPeriod)));
04854 error_code = rt_task_make_periodic(&freqTask,
04855 now+5*rtaiTickPeriod,
04856 rtaiTickPeriod);
04857 if(error_code != 0)
04858 {
04859 diagnostics("rt_task_make_periodic failed for freqTask error_code = %d\n",
04860 error_code);
04861 return -1;
04862 }
04863 freqTask_created=1;
04864 }
04865
04866 #endif
04867
04868 #else
04869
04870 #ifdef rtlinux
04871
04872 /* init control task */
04873
04874 #ifdef USE_RTL2
04875 pthread_attr_init (&attr);
04876 sched_param.sched_priority = EMCMOT_TASK_PRIORITY;
04877 pthread_attr_setschedparam (&attr, &sched_param);
04878 attr.use_fp = 1;
04879 attr.stack_size = EMCMOT_TASK_STACK_SIZE;
04880 pthread_create( &emcmotTask, &attr, emcmotController, (void *) 1);
04881
04882 /* get current time as base for starting tasks */
04883 now =gethrtime();
04884
04885 pthread_setfp_np(emcmotTask,1);
04886 #else
04887 rt_task_init(&emcmotTask, /* RT_TASK * */
04888 emcmotController, /* task code */
04889 0, /* startup arg to task code */
04890 EMCMOT_TASK_STACK_SIZE, /* task stack size */
04891 EMCMOT_TASK_PRIORITY); /* priority */
04892
04893 /* make sure we save FP context */
04894 #if defined(rtlinux_09J) || defined(rtlinux_1_0) || defined(rtlinux2)
04895 rt_task_use_fp(&emcmotTask, 1);
04896 #else
04897 rt_use_fp(1);
04898 #endif
04899 #endif /* ! USE_RTL2 */
04900
04901 /* schedule control task to run */
04902 #ifdef USE_RTL2
04903 iperiod = (int) (HRTICKS_PER_SEC * emcmotConfig->servoCycleTime);
04904 #else
04905 iperiod = (int) (RT_TICKS_PER_SEC * emcmotConfig->servoCycleTime);
04906 #endif
04907
04908 iperiod = iperiod / PERIOD;
04909 iperiod = iperiod * PERIOD;
04910
04911 #ifdef USE_RTL2
04912 rtperiod = (hrtime_t) iperiod;
04913 #else
04914 rtperiod = (RTIME) iperiod;
04915 #endif
04916 #ifdef USE_RTL2
04917 pthread_make_periodic_np(emcmotTask,
04918 gethrtime() + rtperiod,
04919 rtperiod);
04920 #else
04921 rt_task_make_periodic(&emcmotTask,
04922 rtstart + rtperiod,
04923 rtperiod);
04924 #endif
04925
04926 #endif
04927
04928 #ifdef STEPPER_MOTORS
04929
04930 /* init stepper motor task */
04931 #ifdef USE_RTL2
04932 pthread_attr_init (&attr);
04933 sched_param.sched_priority = FREQ_TASK_PRIORITY;
04934 pthread_attr_setschedparam (&attr, &sched_param);
04935 attr.use_fp = 1;
04936 attr.stack_size = FREQ_TASK_STACK_SIZE;
04937 switch (STEPPING_TYPE) /* lpg */
04938 {
04939 case 1: /* phase stepping */
04940 pthread_create(&freqTask, &attr, phasefunc, (void *) 1); break;
04941 case 2: /* lpg quadrature/other phase stepping */
04942 pthread_create(&freqTask, &attr, lpg_phase_drive, (void *) 1); break;
04943 default: /* default is step/direction */
04944 pthread_create(&freqTask, &attr, freqfunc, (void *) 1);
04945 }
04946
04947 /* get current time as base for starting tasks */
04948 pthread_setfp_np(freqTask, 1);
04949 pthread_make_periodic_np(freqTask,
04950 gethrtime() + PERIOD,
04951 PERIOD);
04952
04953 #else
04954 switch (STEPPING_TYPE)
04955 {
04956 case 1: /* phase stepping */
04957 rt_task_init(&freqTask, /* RT_TASK * */
04958 phasefunc, /* task code */
04959 0, /* startup arg to task code */
04960 FREQ_TASK_STACK_SIZE, /* task stack size */
04961 FREQ_TASK_PRIORITY); /* priority */
04962 break;
04963
04964 case 2: /* lpg quadrature/other phase stepping */
04965 rt_task_init(&freqTask, /* RT_TASK * */
04966 lpg_phase_drive, /* task code */
04967 0, /* startup arg to task code */
04968 FREQ_TASK_STACK_SIZE, /* task stack size */
04969 FREQ_TASK_PRIORITY); /* priority */
04970 break;
04971
04972 default: /* default is step/direction */
04973 rt_task_init(&freqTask, /* RT_TASK * */
04974 freqfunc, /* task code */
04975 0, /* startup arg to task code */
04976 FREQ_TASK_STACK_SIZE, /* task stack size */
04977 FREQ_TASK_PRIORITY); /* priority */
04978 }
04979
04980 /* make sure we save FP context */
04981 rt_task_use_fp(&freqTask, 1);
04982
04983 rt_task_make_periodic(&freqTask,
04984 rt_get_time() + PERIOD,
04985 PERIOD);
04986
04987 #endif /* ! USE_RTL2 */
04988 #endif /* STEPPER_MOTORS */
04989 #endif /* rtlinux */
04990
04991 diagnostics("emcmot: init_module finished\n");
04992
04993 return 0;
04994 }
|
|
|
Definition at line 854 of file emcmot.c. Referenced by emcmotController().
00855 {
00856 int axis;
00857
00858 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
00859 if (GET_AXIS_HOMING_FLAG(axis)) {
00860 return 1;
00861 }
00862 }
00863
00864 /* got here, so none are homing */
00865 return 0;
00866 }
|
|
||||||||||||
|
Definition at line 5221 of file emcmot.c. 05225 {
05226 double delta; /* elapsed time */
05227 int cycles=0;
05228 double start_time,cur_time;
05229 #ifndef UNDER_CE
05230 /* trap ^C */
05231 signal(SIGINT, emcmot_quit);
05232
05233 /* process command line args */
05234 if (0 != getArgs(argc, argv)) {
05235 diagnostics("can't init module-- bad arguments\n");
05236 exit(1);
05237 }
05238 #endif
05239
05240 /* set up data structs */
05241 if (-1 == init_module()) {
05242 diagnostics("can't init module-- execution permission problems?\n");
05243 #ifndef UNDER_CE
05244 exit(1);
05245 #else
05246 return 1;
05247 #endif
05248 }
05249
05250 start_time = etime();
05251 while (! emcmot_done) {
05252 cycles++;
05253 delta = etime();
05254 emcmotController(0);
05255 cur_time = etime();
05256 delta = cur_time - delta;
05257 delta = emcmotConfig->servoCycleTime - delta;
05258
05259 if (delta > 0.0) {
05260 esleep(delta);
05261 }
05262 }
05263
05264 cleanup_module();
05265 #ifndef UNDER_CE
05266 exit(0);
05267 #else
05268 return 0;
05269 #endif
05270 }
|
|
||||||||||||
|
Definition at line 837 of file emcmot.c. 00838 {
00839 va_list args;
00840 char error[EMCMOT_ERROR_LEN];
00841
00842 va_start(args, fmt);
00843 #ifndef UNDER_CE
00844 vsprintf(error, fmt, args);
00845 #else
00846 RCS_CE_VSPRINTF(error,fmt,args);
00847 #endif
00848 va_end(args);
00849
00850 emcmotErrorPut(emcmotError, error);
00851 }
|
|
|
Definition at line 1038 of file emcmot.c. 01039 {
01040 static int t;
01041
01042 /* make sure it's not zero */
01043 if (secs <= 0.0) {
01044 return;
01045 }
01046
01047 MARK_EMCMOT_CONFIG_CHANGE();
01048
01049 /* compute the interpolation rate as nearest integer to traj/servo*/
01050 emcmotConfig->interpolationRate =
01051 (int) (emcmotConfig->trajCycleTime / secs + 0.5);
01052
01053 /* set the cubic interpolation rate and PID cycle time */
01054 for (t = 0; t < EMCMOT_MAX_AXIS; t++) {
01055 cubicSetInterpolationRate(&emcmotDebug->cubic[t], emcmotConfig->interpolationRate);
01056 cubicSetSegmentTime(&emcmotDebug->cubic[t], secs);
01057 pidSetCycleTime(&emcmotConfig->pid[t], secs);
01058 }
01059
01060 /* copy into status out */
01061 emcmotConfig->servoCycleTime = secs;
01062 }
|
|
|
Definition at line 1009 of file emcmot.c. 01010 {
01011 static int t;
01012
01013 /* make sure it's not zero */
01014 if (secs <= 0.0) {
01015 return;
01016 }
01017
01018 MARK_EMCMOT_CONFIG_CHANGE();
01019
01020 /* compute the interpolation rate as nearest integer to traj/servo*/
01021 emcmotConfig->interpolationRate =
01022 (int) (secs / emcmotConfig->servoCycleTime + 0.5);
01023
01024 /* set traj planner */
01025 tpSetCycleTime(&emcmotDebug->queue, secs);
01026
01027 /* set the free planners, cubic interpolation rate and segment time */
01028 for (t = 0; t < EMCMOT_MAX_AXIS; t++) {
01029 tpSetCycleTime(&emcmotDebug->freeAxis[t], secs);
01030 cubicSetInterpolationRate(&emcmotDebug->cubic[t], emcmotConfig->interpolationRate);
01031 }
01032
01033 /* copy into status out */
01034 emcmotConfig->trajCycleTime = secs;
01035 }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1.2.11.1 written by Dimitri van Heesch,
© 1997-2001