⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stepgen.c

📁 Source code for an Numeric Cmputer
💻 C
📖 第 1 页 / 共 3 页
字号:
	freqscale = ((1L << 30) * 2.0) / maxf;	accelscale = freqscale * periodfp;    }    /* now recalc constants related to the period of this funct */    /* only recalc constants if period changes */    if (period != old_dtns) {	/* get ready to detect future period changes */	old_dtns = period;	/* dT is the period of this thread, used for the position loop */	dt = period * 0.000000001;	/* calc the reciprocal once here, to avoid multiple divides later */	recip_dt = 1.0 / dt;    }        /* point at stepgen data */    stepgen = arg;    /* loop thru generators */    for (n = 0; n < num_chan; n++) {	/* check for scale change */	if (stepgen->pos_scale != stepgen->old_scale) {	    /* get ready to detect future scale changes */	    stepgen->old_scale = stepgen->pos_scale;	    /* validate the new scale value */	    if ((stepgen->pos_scale < 1e-20)		&& (stepgen->pos_scale > -1e-20)) {		/* value too small, divide by zero is a bad thing */		stepgen->pos_scale = 1.0;	    }	    /* we will need the reciprocal */	    stepgen->scale_recip = 1.0 / stepgen->pos_scale;	}	/* test for disabled stepgen */	if (*stepgen->enable == 0) {	    /* disabled: keep updating old_pos_cmd */	    stepgen->old_pos_cmd = *stepgen->pos_cmd * stepgen->pos_scale;	    /* set velocity to zero */	    stepgen->freq = 0;	    stepgen->addval = 0;	    stepgen->newaddval = 0;	    /* and skip to next one */	    stepgen++;	    break;	}	/* calculate frequency limit */	if (stepgen->wd.st0.step_type == 0) {	    /* stepping type 0 limit depends on timing params */	    max_freq =		maxf / (stepgen->wd.st0.step_len +			stepgen->wd.st0.step_space);	} else if (stepgen->wd.st0.step_type == 1) {	    /* stepping type 1 limit is thread freq / 2 */	    max_freq = maxf * 0.5;	} else {	    /* all other step types can step at the thread frequency */	    max_freq = maxf;	}	/* check for user specified frequency limit parameter */	if (stepgen->maxvel <= 0.0) {	    /* set to zero if negative */	    stepgen->maxvel = 0.0;	} else {	    /* parameter is non-zero, compare to max_freq */	    if ((stepgen->maxvel * fabs(stepgen->pos_scale)) > max_freq) {		/* parameter is too high, lower it */		stepgen->maxvel = max_freq * fabs(stepgen->scale_recip);	    } else {		/* lower max_freq to match parameter */		max_freq = stepgen->maxvel * fabs(stepgen->pos_scale);	    }	}	/* set internal accel limit to its absolute max, which is	   zero to full speed in one thread period */	max_ac = max_freq * recip_dt;	/* check for user specified accel limit parameter */	if (stepgen->maxaccel <= 0.0) {	    /* set to zero if negative */	    stepgen->maxaccel = 0.0;	} else {	    /* parameter is non-zero, compare to max_ac */	    if ((stepgen->maxaccel * fabs(stepgen->pos_scale)) > max_ac) {		/* parameter is too high, lower it */		stepgen->maxaccel = max_ac * fabs(stepgen->scale_recip);	    } else {		/* lower limit to match parameter */		max_ac = stepgen->maxaccel * fabs(stepgen->pos_scale);	    }	}	/* calculate position command in counts */	pos_cmd = *stepgen->pos_cmd * stepgen->pos_scale;	/* calculate velocity command in counts/sec */	vel_cmd = (pos_cmd - stepgen->old_pos_cmd) * recip_dt;	stepgen->old_pos_cmd = pos_cmd;	/* get current position and velocity in counts and counts/sec */	curr_pos = stepgen->rawcount;	curr_vel = stepgen->freq;	/* At this point we have good values for pos_cmd, curr_pos, 	   vel_cmd, curr_vel, max_freq and max_ac, all in counts, 	   counts/sec, or counts/sec^2.  Now we just have to do 	   something useful with them. */	/* determine which way we need to ramp to match velocity */	if (vel_cmd > curr_vel) {	    match_ac = max_ac;	} else {	    match_ac = -max_ac;	}	/* determine how long the match would take */	match_time = (vel_cmd - curr_vel) / match_ac;	/* calc output position at the end of the match */	avg_v = (vel_cmd + curr_vel) * 0.5;	est_out = curr_pos + avg_v * match_time;	/* calculate the expected command position at that time */	est_cmd = pos_cmd + vel_cmd * (match_time - 1.5 * dt);	/* calculate error at that time */	est_err = est_out - est_cmd;	if (match_time < dt) {	    /* we can match velocity in one period */	    if (fabs(est_err) < 1.0) {		/* after match the position error will be acceptable */		/* so we just do the velocity match */		new_vel = vel_cmd;	    } else {		/* try to correct position error */		new_vel = vel_cmd - 0.5 * est_err * recip_dt;		/* apply accel limits */		if (new_vel > (curr_vel + max_ac * dt)) {		    new_vel = curr_vel + max_ac * dt;		} else if (new_vel < (curr_vel - max_ac * dt)) {		    new_vel = curr_vel - max_ac * dt;		}	    }	} else {	    /* calculate change in final position if we ramp in the	       opposite direction for one period */	    dv = -2.0 * match_ac * dt;	    dp = dv * match_time;	    /* decide which way to ramp */	    if (fabs(est_err + dp * 2.0) < fabs(est_err)) {		match_ac = -match_ac;	    }	    /* and do it */	    new_vel = curr_vel + match_ac * dt;	}	/* apply frequency limit */	if (new_vel > max_freq) {	    new_vel = max_freq;	} else if (new_vel < -max_freq) {	    new_vel = -max_freq;	}	stepgen->freq = new_vel;	/* calculate new addval */	stepgen->newaddval = stepgen->freq * freqscale;	/* calculate new deltalim */	stepgen->deltalim = max_ac * accelscale;	/* move on to next channel */	stepgen++;    }    /* done */}static void update_pos(void *arg, long period){    stepgen_t *stepgen;    int n;    stepgen = arg;    for (n = 0; n < num_chan; n++) {	/* capture raw counts to latches */	*(stepgen->count) = stepgen->rawcount;	/* check for change in scale value */	if (stepgen->pos_scale != stepgen->old_scale) {	    /* get ready to detect future scale changes */	    stepgen->old_scale = stepgen->pos_scale;	    /* validate the new scale value */	    if ((stepgen->pos_scale < 1e-20)		&& (stepgen->pos_scale > -1e-20)) {		/* value too small, divide by zero is a bad thing */		stepgen->pos_scale = 1.0;	    }	    /* we will need the reciprocal */	    stepgen->scale_recip = 1.0 / stepgen->pos_scale;	}	/* scale count to make floating point position */	*(stepgen->pos_fb) = *(stepgen->count) * stepgen->scale_recip;	/* move on to next channel */	stepgen++;    }    /* done */}/************************************************************************                   LOCAL FUNCTION DEFINITIONS                         *************************************************************************/static int export_stepgen(int num, stepgen_t * addr, int step_type){    int n, retval, msg;    char buf[HAL_NAME_LEN + 2];    /* This function exports a lot of stuff, which results in a lot of       logging if msg_level is at INFO or ALL. So we save the current value       of msg_level and restore it later.  If you actually need to log this       function's actions, change the second line below */    msg = rtapi_get_msg_level();    rtapi_set_msg_level(RTAPI_MSG_WARN);    /* export param variable for raw counts */    rtapi_snprintf(buf, HAL_NAME_LEN, "stepgen.%d.rawcounts", num);    retval = hal_param_s32_new(buf, HAL_RD, &(addr->rawcount), comp_id);    if (retval != 0) {	return retval;    }    /* export pin for counts captured by update() */    rtapi_snprintf(buf, HAL_NAME_LEN, "stepgen.%d.counts", num);    retval = hal_pin_s32_new(buf, HAL_WR, &(addr->count), comp_id);    if (retval != 0) {	return retval;    }    /* export parameter for position scaling */    rtapi_snprintf(buf, HAL_NAME_LEN, "stepgen.%d.position-scale", num);    retval = hal_param_float_new(buf, HAL_WR, &(addr->pos_scale), comp_id);    if (retval != 0) {	return retval;    }    /* export pin for position command command */    rtapi_snprintf(buf, HAL_NAME_LEN, "stepgen.%d.position-cmd", num);    retval = hal_pin_float_new(buf, HAL_RD, &(addr->pos_cmd), comp_id);    if (retval != 0) {	return retval;    }    /* export pin for enable command */    rtapi_snprintf(buf, HAL_NAME_LEN, "stepgen.%d.enable", num);    retval = hal_pin_bit_new(buf, HAL_RD, &(addr->enable), comp_id);    if (retval != 0) {	return retval;    }    /* export pin for scaled position captured by update() */    rtapi_snprintf(buf, HAL_NAME_LEN, "stepgen.%d.position-fb", num);    retval = hal_pin_float_new(buf, HAL_WR, &(addr->pos_fb), comp_id);    if (retval != 0) {	return retval;    }    /* export param for scaled velocity (frequency in Hz) */    rtapi_snprintf(buf, HAL_NAME_LEN, "stepgen.%d.frequency", num);    retval = hal_param_float_new(buf, HAL_RD, &(addr->freq), comp_id);    if (retval != 0) {	return retval;    }    /* export parameter for max frequency */    rtapi_snprintf(buf, HAL_NAME_LEN, "stepgen.%d.maxvel", num);    retval = hal_param_float_new(buf, HAL_WR, &(addr->maxvel), comp_id);    if (retval != 0) {	return retval;    }    /* export parameter for max accel/decel */    rtapi_snprintf(buf, HAL_NAME_LEN, "stepgen.%d.maxaccel", num);    retval = hal_param_float_new(buf, HAL_WR, &(addr->maxaccel), comp_id);    if (retval != 0) {	return retval;    }    /* set default parameter values */    addr->pos_scale = 1.0;    addr->old_scale = 1.0;    addr->scale_recip = 1.0;    addr->freq = 0.0;    addr->old_pos_cmd = 0.0;    addr->maxvel = 0.0;    addr->maxaccel = 0.0;    addr->wd.st0.step_type = step_type;    /* init the step generator core to zero output */    addr->accum = 0;    addr->addval = 0;    addr->newaddval = 0;    addr->deltalim = 0;    addr->rawcount = 0;    /* init the position controller */    if (step_type == 0) {	/* setup for stepping type 0 - step/dir */	addr->wd.st0.need_step = 0;	addr->wd.st0.setup_timer = 0;	addr->wd.st0.hold_timer = 0;	addr->wd.st0.space_timer = 0;	addr->wd.st0.len_timer = 0;	/* export parameters for step/dir pulse timing */	rtapi_snprintf(buf, HAL_NAME_LEN, "stepgen.%d.dirsetup", num);	retval =	    hal_param_u8_new(buf, HAL_WR, &(addr->wd.st0.dir_setup),			     comp_id);	if (retval != 0) {	    return retval;	}	rtapi_snprintf(buf, HAL_NAME_LEN, "stepgen.%d.dirhold", num);	retval =	    hal_param_u8_new(buf, HAL_WR, &(addr->wd.st0.dir_hold),			     comp_id);	if (retval != 0) {	    return retval;	}	rtapi_snprintf(buf, HAL_NAME_LEN, "stepgen.%d.steplen", num);	retval =	    hal_param_u8_new(buf, HAL_WR, &(addr->wd.st0.step_len),			     comp_id);	if (retval != 0) {	    return retval;	}	rtapi_snprintf(buf, HAL_NAME_LEN, "stepgen.%d.stepspace", num);	retval =	    hal_param_u8_new(buf, HAL_WR, &(addr->wd.st0.step_space),			     comp_id);	if (retval != 0) {	    return retval;	}	/* init the parameters */	addr->wd.st0.dir_setup = 1;	addr->wd.st0.dir_hold = 1;	addr->wd.st0.step_len = 1;	addr->wd.st0.step_space = 1;	/* export pins for step and direction */	rtapi_snprintf(buf, HAL_NAME_LEN, "stepgen.%d.step", num);	retval =	    hal_pin_bit_new(buf, HAL_WR, &(addr->phase[STEP_PIN]),			    comp_id);	if (retval != 0) {	    return retval;	}	*(addr->phase[STEP_PIN]) = 0;	rtapi_snprintf(buf, HAL_NAME_LEN, "stepgen.%d.dir", num);	retval =	    hal_pin_bit_new(buf, HAL_WR, &(addr->phase[DIR_PIN]), comp_id);	if (retval != 0) {	    return retval;	}	*(addr->phase[DIR_PIN]) = 0;    } else if (step_type == 1) {	/* setup for stepping type 1 - pseudo-PWM */	/* export pins for up and down */	rtapi_snprintf(buf, HAL_NAME_LEN, "stepgen.%d.up", num);	retval =	    hal_pin_bit_new(buf, HAL_WR, &(addr->phase[UP_PIN]), comp_id);	if (retval != 0) {	    return retval;	}	*(addr->phase[UP_PIN]) = 0;	rtapi_snprintf(buf, HAL_NAME_LEN, "stepgen.%d.down", num);	retval =	    hal_pin_bit_new(buf, HAL_WR, &(addr->phase[DOWN_PIN]),			    comp_id);	if (retval != 0) {	    return retval;	}	*(addr->phase[DOWN_PIN]) = 0;    } else {	/* setup for stepping types 2 and higher */	addr->wd.st2.state = 0;	addr->wd.st2.cycle_max = cycle_len_lut[step_type - 2] - 1;	addr->wd.st2.num_phases = num_phases_lut[step_type - 2];	addr->wd.st2.lut = (char *) (&(master_lut[step_type - 2][0]));	/* export pins for output phases */	for (n = 0; n < addr->wd.st2.num_phases; n++) {	    rtapi_snprintf(buf, HAL_NAME_LEN, "stepgen.%d.phase-%c",			   num, n + 'A');	    retval =		hal_pin_bit_new(buf, HAL_WR, &(addr->phase[n]), comp_id);	    if (retval != 0) {		return retval;	    }	    *(addr->phase[n]) = 0;	}    }    /* set initial pin values */    *(addr->count) = 0;    *(addr->pos_fb) = 0.0;    *(addr->pos_cmd) = 0.0;    /* restore saved message level */    rtapi_set_msg_level(msg);    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -