📄 control.c
字号:
position here, because it will still be queried */ emcmotStatus->probedPos = emcmotStatus->carte_pos_fb; emcmotStatus->probing=0; reportError("G38.2 probe move finished without tripping probe\n"); SET_MOTION_ERROR_FLAG(1); } } /* read spindle angle (for threading, etc) */ emcmotStatus->spindleRevs = *emcmot_hal_data->spindle_revs; emcmotStatus->spindleSpeedIn = *emcmot_hal_data->spindle_speed_in; /* compute net feed and spindle scale factors */ if ( emcmotStatus->motion_state == EMCMOT_MOTION_COORD ) { /* use the enables that were queued with the current move */ enables = emcmotStatus->enables_queued; } else { /* use the enables that are in effect right now */ enables = emcmotStatus->enables_new; } /* feed scaling first: feed_scale, adaptive_feed, and feed_hold */ scale = 1.0; if ( enables & FS_ENABLED ) { scale *= emcmotStatus->feed_scale; } if ( enables & AF_ENABLED ) { /* read and clamp (0.0 to 1.0) adaptive feed HAL pin */ tmp = *emcmot_hal_data->adaptive_feed; if ( tmp > 1.0 ) { tmp = 1.0; } else if ( tmp < 0.0 ) { tmp = 0.0; } scale *= tmp; } if ( enables & FH_ENABLED ) { /* read feed hold HAL pin */ if ( *emcmot_hal_data->feed_hold ) { scale = 0; } } /* save the resulting combined scale factor */ emcmotStatus->net_feed_scale = scale; /* now do spindle scaling: only one item to consider */ scale = 1.0; if ( enables & SS_ENABLED ) { scale *= emcmotStatus->spindle_scale; } /* save the resulting combined scale factor */ emcmotStatus->net_spindle_scale = scale; /* read and process per-joint inputs */ for (joint_num = 0; joint_num < num_joints; joint_num++) { /* point to axis HAL data */ axis_data = &(emcmot_hal_data->axis[joint_num]); /* point to joint data */ joint = &joints[joint_num]; if (!GET_JOINT_ACTIVE_FLAG(joint)) { /* if joint is not active, skip it */ continue; } /* copy data from HAL to joint structure */ joint->index_enable = *(axis_data->index_enable); joint->motor_pos_fb = *(axis_data->motor_pos_fb); /* calculate pos_fb */ if (( joint->home_state == HOME_INDEX_SEARCH_WAIT ) && ( joint->index_enable == 0 )) { /* special case - we're homing the joint, and it just hit the index. The encoder count might have made a step change. The homing code will correct for it later, so we ignore motor_pos_fb and set pos_fb to match the commanded value instead. */ joint->pos_fb = joint->pos_cmd; } else { /* normal case: subtract backlash comp and motor offset */ joint->pos_fb = joint->motor_pos_fb - (joint->backlash_filt + joint->motor_offset); } /* calculate following error */ joint->ferror = joint->pos_cmd - joint->pos_fb; abs_ferror = fabs(joint->ferror); /* update maximum ferror if needed */ if (abs_ferror > joint->ferror_high_mark) { joint->ferror_high_mark = abs_ferror; } /* calculate following error limit */ if (joint->vel_limit > 0.0) { joint->ferror_limit = joint->max_ferror * fabs(joint->vel_cmd) / joint->vel_limit; } else { joint->ferror_limit = 0; } if (joint->ferror_limit < joint->min_ferror) { joint->ferror_limit = joint->min_ferror; } /* update following error flag */ if (abs_ferror > joint->ferror_limit) { SET_JOINT_FERROR_FLAG(joint, 1); } else { SET_JOINT_FERROR_FLAG(joint, 0); } /* read limit switches */ if (*(axis_data->pos_lim_sw)) { SET_JOINT_PHL_FLAG(joint, 1); } else { SET_JOINT_PHL_FLAG(joint, 0); } if (*(axis_data->neg_lim_sw)) { SET_JOINT_NHL_FLAG(joint, 1); } else { SET_JOINT_NHL_FLAG(joint, 0); } joint->on_pos_limit = GET_JOINT_PHL_FLAG(joint); joint->on_neg_limit = GET_JOINT_NHL_FLAG(joint); /* read amp fault input */ if (*(axis_data->amp_fault)) { SET_JOINT_FAULT_FLAG(joint, 1); } else { SET_JOINT_FAULT_FLAG(joint, 0); } /* read home switch input */ if (*(axis_data->home_sw)) { SET_JOINT_HOME_SWITCH_FLAG(joint, 1); } else { SET_JOINT_HOME_SWITCH_FLAG(joint, 0); } /* end of read and process axis inputs loop */ }}static void do_forward_kins(void){/* there are four possibilities for kinType: IDENTITY: Both forward and inverse kins are available, and they can used without an initial guess, even if one or more joints are not homed. In this case, we apply the forward kins to the joint->pos_fb to produce carte_pos_fb, and if all axes are homed we set carte_pos_fb_ok to 1 to indicate that the feedback data is good. BOTH: Both forward and inverse kins are available, but the forward kins need an initial guess, and/or the kins require all joints to be homed before they work properly. Here we must tread carefully. IF all the joints have been homed, we apply the forward kins to the joint->pos_fb to produce carte_pos_fb, and set carte_pos_fb_ok to indicate that the feedback is good. We use the previous value of carte_pos_fb as the initial guess. If all joints have not been homed, we don't call the kinematics, instead we set carte_pos_fb to the cartesean coordinates of home, as stored in the global worldHome, and we set carte_fb_ok to 0 to indicate that the feedback is invalid.\todo FIXME - maybe setting to home isn't the right thing to do. We need it to be set to home eventually, (right before the first attemt to run the kins), but that doesn't mean we should say we're at home when we're not. INVERSE_ONLY: Only inverse kinematics are available, forward kinematics cannot be used. So we have to fake it, the question is simply "what way of faking it is best". In free mode, or if all axes have not been homed, the feedback position is unknown. If we are in teleop or coord mode, or if we are in free mode and all axes are homed, and haven't been moved since they were homed, then we set carte_pos_fb to carte_pos_cmd, and set carte_pos_fb_ok to 1. If we are in free mode, and any axis is not homed, or any axis has moved since it was homed, we leave cart_pos_fb alone, and set carte_pos_fb_ok to 0. FORWARD_ONLY: Only forward kinematics are available, inverse kins cannot be used. This exists for completeness only, since EMC won't work without inverse kinematics.*//*! \todo FIXME FIXME FIXME - need to put a rate divider in here, run it at the traj rate */ double joint_pos[EMCMOT_MAX_JOINTS] = {0,}; int joint_num, all_homed, all_at_home, result; emcmot_joint_t *joint; all_homed = 1; all_at_home = 1; /* copy joint position feedback to local array */ for (joint_num = 0; joint_num < num_joints; joint_num++) { /* point to joint struct */ joint = &joints[joint_num]; /* copy feedback */ joint_pos[joint_num] = joint->pos_fb; /* check for homed, only if the current joint is active */ if (!GET_JOINT_ACTIVE_FLAG(joint)) { /* if joint is not active, don't even look at its limits */ continue; } if (!GET_JOINT_HOMED_FLAG(joint)) { all_homed = 0; all_at_home = 0; } else if (!GET_JOINT_AT_HOME_FLAG(joint)) { all_at_home = 0; } } switch (kinType) { case KINEMATICS_IDENTITY: kinematicsForward(joint_pos, &emcmotStatus->carte_pos_fb, &fflags, &iflags); if (checkAllHomed()) { emcmotStatus->carte_pos_fb_ok = 1; } else { emcmotStatus->carte_pos_fb_ok = 0; } break; case KINEMATICS_BOTH: if (checkAllHomed()) { /* is previous value suitable for use as initial guess? */ if (!emcmotStatus->carte_pos_fb_ok) { /* no, use home position as initial guess */ emcmotStatus->carte_pos_fb = emcmotStatus->world_home; } /* calculate Cartesean position feedback from joint pos fb */ result = kinematicsForward(joint_pos, &emcmotStatus->carte_pos_fb, &fflags, &iflags); /* check to make sure kinematics converged */ if (result < 0) { /* error during kinematics calculations */ emcmotStatus->carte_pos_fb_ok = 0; } else { /* it worked! */ emcmotStatus->carte_pos_fb_ok = 1; } } else { emcmotStatus->carte_pos_fb_ok = 0; } break; case KINEMATICS_INVERSE_ONLY: if ((GET_MOTION_COORD_FLAG()) || (GET_MOTION_TELEOP_FLAG())) { /* use Cartesean position command as feedback value */ emcmotStatus->carte_pos_fb = emcmotStatus->carte_pos_cmd; emcmotStatus->carte_pos_fb_ok = 1; } else { emcmotStatus->carte_pos_fb_ok = 0; } break; default: emcmotStatus->carte_pos_fb_ok = 0; break; }}static void check_for_faults(void){ int joint_num; emcmot_joint_t *joint; int neg_limit_override, pos_limit_override; /* check for various global fault conditions */ /* only check enable input if running */ if ( GET_MOTION_ENABLE_FLAG() != 0 ) { if ( *(emcmot_hal_data->enable) == 0 ) { reportError("motion stopped by enable input"); emcmotDebug->enabling = 0; } } /* check for various joint fault conditions */ for (joint_num = 0; joint_num < num_joints; joint_num++) { /* point to joint data */ joint = &joints[joint_num]; /* only check active, enabled axes */ if ( GET_JOINT_ACTIVE_FLAG(joint) && GET_JOINT_ENABLE_FLAG(joint) ) { /* are any limits for this joint overridden? */ neg_limit_override = emcmotStatus->overrideLimitMask & ( 1 << (joint_num*2)); pos_limit_override = emcmotStatus->overrideLimitMask & ( 2 << (joint_num*2)); /* check for hard limits */ if ((GET_JOINT_PHL_FLAG(joint) && ! pos_limit_override ) || (GET_JOINT_NHL_FLAG(joint) && ! neg_limit_override )) { /* joint is on limit switch, should we trip? */ if (GET_JOINT_HOMING_FLAG(joint)) { /* no, ignore limits */ } else { /* trip on limits */ if (!GET_JOINT_ERROR_FLAG(joint)) { /* report the error just this once */ reportError("joint %d on limit switch error", joint_num); } SET_JOINT_ERROR_FLAG(joint, 1); emcmotDebug->enabling = 0; } } /* check for amp fault */ if (GET_JOINT_FAULT_FLAG(joint)) { /* axis is faulted, trip */ if (!GET_JOINT_ERROR_FLAG(joint)) { /* report the error just this once */ reportError("joint %d amplifier fault", joint_num); } SET_JOINT_ERROR_FLAG(joint, 1); emcmotDebug->enabling = 0; } /* check for excessive following error */ if (GET_JOINT_FERROR_FLAG(joint)) { if (!GET_JOINT_ERROR_FLAG(joint)) { /* report the error just this once */ reportError("joint %d following error", joint_num); } SET_JOINT_ERROR_FLAG(joint, 1); emcmotDebug->enabling = 0; } /* end of if AXIS_ACTIVE_FLAG(joint) */ } /* end of check for joint faults loop */ }}static void set_operating_mode(void){ int joint_num; emcmot_joint_t *joint; axis_hal_t *axis_data; /* check for disabling */ if (!emcmotDebug->enabling && GET_MOTION_ENABLE_FLAG()) { /* clear out the motion emcmotDebug->queue and interpolators */ tpClear(&emcmotDebug->queue); for (joint_num = 0; joint_num < num_joints; joint_num++) { /* point to joint data */ axis_data = &(emcmot_hal_data->axis[joint_num]); joint = &joints[joint_num]; /* disable free mode planner */ joint->free_tp_enable = 0; /* drain coord mode interpolators */ cubicDrain(&(joint->cubic)); if (GET_JOINT_ACTIVE_FLAG(joint)) { SET_JOINT_ENABLE_FLAG(joint, 0); SET_JOINT_HOMING_FLAG(joint, 0); joint->home_state = HOME_IDLE; } /* don't clear the joint error flag, since that may signify why we just went into disabled state */ } /* reset the trajectory interpolation counter, so that the kinematics functions called during the disabled state run at the nominal trajectory rate rather than the servo rate. It's loaded with emcmotConfig->interpolationRate when it goes to zero. *//*! \todo FIXME - interpolation is still under construction *//*! \todo Another #if 0 */#if 0 interpolationCounter = 0;#endif SET_MOTION_ENABLE_FLAG(0); /* don't clear the motion error flag, since that may signify why we just went into disabled state */ } /* check for emcmotDebug->enabling */ if (emcmotDebug->enabling && !GET_MOTION_ENABLE_FLAG()) { tpSetPos(&emcmotDebug->queue, emcmotStatus->carte_pos_cmd); for (joint_num = 0; joint_num < num_joints; joint_num++) { /* point to joint data */ axis_data = &(emcmot_hal_data->axis[joint_num]); joint = &joints[joint_num]; joint->free_pos_cmd = joint->pos_cmd; if (GET_JOINT_ACTIVE_FLAG(joint)) { SET_JOINT_ENABLE_FLAG(joint, 1); SET_JOINT_HOMING_FLAG(joint, 0); joint->home_state = HOME_IDLE; } /* clear any outstanding axis errors when going into enabled state */ SET_JOINT_ERROR_FLAG(joint, 0); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -