所以我尝试为我的步进电机的运动实现一个 S 曲线;但是,我觉得这对于我希望步进电机做的简单事情来说太复杂了:平滑运动。不必一眨眼就从a到b,顺手就行。此外,该函数会超调大量步数(pos_err 几乎总是步数的 40%)。
void stepper_t::step(int32_t steps, direction dir)
{
float32_t pulse_delay; /* Stepper pulse delay [microsec] */
int8_t count = 0; /* Count the number of pulses */
int32_t pos_err = 0; /* Error in position */
int16_t speed = 3200; /* Steady state velocity [pulse/s] */
int8_t var = 0;
int32_t move_time = (steps / (speed / 1000000)); /* Total time moving */
int32_t accel_time = move_time < 30000 ? (move_time / 2) : 30000; /* Acceleration time [microsec] */
int32_t decel_time = move_time < 30000 ? (move_time / 2) : 30000; /* Deceleration time [microsec] */
int32_t constant_speed = move_time - (accel_time + decel_time); /* Time during constant velocity [microsec] */
int32_t curr_time = decel_time / 30; /* Current time [microsec]
You need to seed the initial time
with something > 0 so you don't
calculate too long of a delay */
this->set_direction(dir);
while (var < 1) {
if (curr_time < accel_time) {
/* Acceleration */
pulse_delay = ((float32_t) accel_time / (2.f * ((float32_t) speed / 1000000.f) * (float32_t) curr_time));
} else if ((curr_time >= accel_time) && (curr_time < (accel_time + constant_speed))) {
/* Constant velocity */
pulse_delay = (1.f / (2.f * ((float32_t) speed / 1000000.f)));
} else if ((curr_time >= (accel_time + constant_speed)) && (curr_time < (accel_time + constant_speed + decel_time))) {
/* Deceleration */
pulse_delay = (1.f / (2.f * (((float32_t) speed / 1000000.f) - ((float32_t) speed / (1000000.f * (float32_t) decel_time)) * ((float32_t) curr_time - (float32_t) accel_time - (float32_t) constant_speed))));
}
/* Time is incremented by pulse delay twice due to the pin going
high, then low, delaying twice */
curr_time = curr_time + (int32_t) (float32_t) (2.f * pulse_delay);
/* Send pulse with calculated delay */
Chip_GPIO_SetPinState(LPC_GPIO_PORT, this->GPIO_step_port, this->GPIO_step_pin, true);
OS_Delayus((OS_U16) pulse_delay);
Chip_GPIO_SetPinState(LPC_GPIO_PORT, this->GPIO_step_port, this->GPIO_step_pin, false);
OS_Delayus((OS_U16) pulse_delay);
count++;
/* Correct for any position error due to rounding */
if (curr_time > (accel_time + constant_speed + decel_time)) {
pos_err = steps - count;
if (pos_err < 0) {
pos_err = -1 * pos_err;
if (dir == OUTWARD) {
this->set_direction(INWARD);
} else {
this->set_direction(OUTWARD);
}
}
for (; pos_err > 0; pos_err--) {
Chip_GPIO_SetPinState(LPC_GPIO_PORT, this->GPIO_step_port, this->GPIO_step_pin, true);
OS_Delayus((OS_U16) pulse_delay);
Chip_GPIO_SetPinState(LPC_GPIO_PORT, this->GPIO_step_port, this->GPIO_step_pin, false);
OS_Delayus((OS_U16) pulse_delay);
}
count = 0;
curr_time = decel_time / 9;
var++;
}
}
}
为什么我不能像这样使用余弦来计算两者之间的延迟?
void step2(int32_t steps) {
int8_t count = 0;
float32_t delay;
while (count < steps) {
delay = (cos ( (PI * 2 * count)/steps ) + 1) * 5000 + 10000;
Chip_GPIO_SetPinState(LPC_GPIO_PORT, this->GPIO_step_port, this->GPIO_step_pin, true);
OS_Delayus((OS_U16) delay);
Chip_GPIO_SetPinState(LPC_GPIO_PORT, this->GPIO_step_port, this->GPIO_step_pin, false);
OS_Delayus((OS_U16) delay);
count++;
}
}