bool reversed;
float min_rpm;
float max_rpm;
+ float inv_max_rpm;
bool dynamic_power;
float inv_feed;
- bool dirty;
spindle_type_t next_type;
} spindle = {
};
-static float _speed_to_power(float speed) {
- speed *= spindle.override;
+static float _get_power() {
+ switch (spindle.type) {
+ case SPINDLE_TYPE_DISABLED: return 0;
+ case SPINDLE_TYPE_PWM: return pwm_get();
+ case SPINDLE_TYPE_HUANYANG: return huanyang_get();
+ default: return vfd_spindle_get();
+ }
+}
- bool negative = speed < 0;
- if (fabs(speed) < spindle.min_rpm) speed = 0;
- else if (spindle.max_rpm <= fabs(speed)) speed = negative ? -1 : 1;
- else speed /= spindle.max_rpm;
- return spindle.reversed ? -speed : speed;
-}
+static float _speed_to_power(float speed) {
+ bool negative = speed < 0;
+ float power = fabs(speed * spindle.override);
+ if (power < spindle.min_rpm) power = 0;
+ else if (spindle.max_rpm <= power) power = 1;
+ else power *= spindle.inv_max_rpm;
-static power_update_t _get_update() {
- float power = _speed_to_power(spindle.speed);
- if (spindle.dynamic_power)
- power *= spindle.inv_feed ? spindle.inv_feed * exec_get_velocity() : 1;
- return pwm_get_update(power);
+ return (spindle.reversed ^ negative) ? -power : power;
}
static void _set_speed(float speed) {
spindle.speed = speed;
- spindle.dirty = false;
-
- if (spindle.type == SPINDLE_TYPE_PWM) {
- // PWM speed updates must be synchronized with stepper movement
- power_update_t update = _get_update();
- spindle_update(update);
- return;
- }
float power = _speed_to_power(speed);
switch (spindle.type) {
case SPINDLE_TYPE_DISABLED: break;
+
+ case SPINDLE_TYPE_PWM: {
+ // PWM speed updates must be synchronized with stepper movement
+ spindle.sync_speed.dist = 0;
+ spindle.sync_speed.speed = speed;
+ break;
+ }
+
case SPINDLE_TYPE_HUANYANG: huanyang_set(power); break;
default: vfd_spindle_set(power); break;
}
}
+static void _update_speed() {_set_speed(spindle.speed);}
+
+
static void _deinit_cb() {
spindle.type = spindle.next_type;
spindle.next_type = SPINDLE_TYPE_DISABLED;
switch (spindle.type) {
- case SPINDLE_TYPE_DISABLED: break;
- case SPINDLE_TYPE_PWM: pwm_init(); break;
- case SPINDLE_TYPE_HUANYANG: huanyang_init(); break;
- default: vfd_spindle_init(); break;
+ case SPINDLE_TYPE_DISABLED: break;
+ case SPINDLE_TYPE_PWM: pwm_init(); break;
+ case SPINDLE_TYPE_HUANYANG: huanyang_init(); break;
+ default: vfd_spindle_init(); break;
}
- spindle.dirty = true;
+ _update_speed();
}
spindle.type = SPINDLE_TYPE_DISABLED;
switch (old_type) {
- case SPINDLE_TYPE_DISABLED: _deinit_cb(); break;
- case SPINDLE_TYPE_PWM: pwm_deinit(_deinit_cb); break;
- case SPINDLE_TYPE_HUANYANG: huanyang_deinit(_deinit_cb); break;
- default: vfd_spindle_deinit(_deinit_cb); break;
+ case SPINDLE_TYPE_DISABLED: _deinit_cb(); break;
+ case SPINDLE_TYPE_PWM: pwm_deinit(_deinit_cb); break;
+ case SPINDLE_TYPE_HUANYANG: huanyang_deinit(_deinit_cb); break;
+ default: vfd_spindle_deinit(_deinit_cb); break;
}
}
spindle_type_t spindle_get_type() {return spindle.type;}
+static power_update_t _get_power_update() {
+ float power = _speed_to_power(spindle.speed);
+
+ // Handle dynamic power
+ if (spindle.dynamic_power && spindle.inv_feed) {
+ float scale = spindle.inv_feed * exec_get_velocity();
+ if (scale < 1) power *= scale;
+ }
+
+ return pwm_get_update(power);
+}
+
+
void spindle_load_power_updates(power_update_t updates[], float minD,
float maxD) {
float stepD = (maxD - minD) * (1.0 / POWER_MAX_UPDATES);
float d = minD + 1e-3; // Starting distance
for (unsigned i = 0; i < POWER_MAX_UPDATES; i++) {
- bool set = false;
-
+ bool changed = false;
d += stepD; // Ending distance for this power step
- updates[i].state = POWER_IGNORE;
while (true) {
// Load new sync speed if needed and available
spindle.sync_speed = *(sync_speed_t *)(command_next() + 1);
// Exit if we don't have a speed or it's not ready to be set
- if (spindle.sync_speed.dist < 0 || d < spindle.sync_speed.dist) break;
+ if (spindle.sync_speed.dist == -1 || d < spindle.sync_speed.dist) break;
- set = true;
- spindle.speed = spindle.sync_speed.speed;
+ // Load sync speed
spindle.sync_speed.dist = -1; // Mark done
+ spindle.speed = spindle.sync_speed.speed;
+ changed = true;
}
- // Prep power update
- if (spindle.type == SPINDLE_TYPE_PWM) updates[i] = _get_update();
- else if (set) _set_speed(spindle.speed); // Set speed now for non-PWM
+ if (spindle.type == SPINDLE_TYPE_PWM) updates[i] = _get_power_update();
+ else {
+ updates[i].state = POWER_IGNORE;
+ if (changed) _update_speed();
+ }
}
}
-void spindle_update(power_update_t update) {return pwm_update(update);}
-
-
-static void _flush_sync_speeds() {
- spindle.sync_speed.dist = -1;
- while (command_peek() == COMMAND_sync_speed) command_next();
-}
+// Called from hi-level stepper interrupt
+void spindle_update(power_update_t update) {pwm_update(update);}
// Called from lo-level stepper interrupt
void spindle_idle() {
- if (spindle.dirty) _set_speed(spindle.speed);
- _flush_sync_speeds(); // Flush speeds in case we are holding there are more
-}
-
-
-float spindle_get_speed() {
- float speed = 0;
+ if (spindle.sync_speed.dist != -1) {
+ spindle.sync_speed.dist = -1; // Mark done
+ spindle.speed = spindle.sync_speed.speed;
- switch (spindle.type) {
- case SPINDLE_TYPE_DISABLED: break;
- case SPINDLE_TYPE_PWM: speed = pwm_get(); break;
- case SPINDLE_TYPE_HUANYANG: speed = huanyang_get(); break;
- default: speed = vfd_spindle_get(); break;
+ if (spindle.type == SPINDLE_TYPE_PWM) spindle_update(_get_power_update());
+ else _update_speed();
}
-
- return speed * spindle.max_rpm;
-}
-
-
-void spindle_stop() {
- _flush_sync_speeds();
- _set_speed(0);
}
+void spindle_stop() {_set_speed(0);} // Only called when steppers have halted
void spindle_estop() {_set_type(SPINDLE_TYPE_DISABLED);}
-bool spindle_is_reversed() {return spindle.reversed;}
// Var callbacks
uint8_t get_tool_type() {return spindle.type;}
void set_tool_type(uint8_t value) {_set_type((spindle_type_t)value);}
-float get_speed() {return spindle_get_speed();}
+float get_speed() {return _get_power() * spindle.max_rpm;}
bool get_tool_reversed() {return spindle.reversed;}
void set_tool_reversed(bool reversed) {
if (spindle.reversed != reversed) {
spindle.reversed = reversed;
- spindle.dirty = true;
+ _update_speed();
}
}
float get_max_spin() {return spindle.max_rpm;}
-void set_max_spin(float value) {spindle.max_rpm = value; spindle.dirty = true;}
+
+
+void set_max_spin(float value) {
+ if (spindle.max_rpm != value) {
+ spindle.max_rpm = value;
+ spindle.inv_max_rpm = 1 / value;
+ _update_speed();
+ }
+}
+
+
float get_min_spin() {return spindle.min_rpm;}
-void set_min_spin(float value) {spindle.min_rpm = value; spindle.dirty = true;}
+
+
+void set_min_spin(float value) {
+ if (spindle.min_rpm != value) {
+ spindle.min_rpm = value;
+ _update_speed();
+ }
+}
+
+
uint16_t get_speed_override() {return spindle.override * 1000;}
void set_speed_override(uint16_t value) {
- spindle.override = value / 1000.0;
- spindle.dirty = true;
+ value *= 0.001;
+
+ if (spindle.override != value) {
+ spindle.override = value;
+ _update_speed();
+ }
}
void set_dynamic_power(bool enable) {
- if (spindle.dynamic_power == enable) return;
- spindle.dynamic_power = enable;
- spindle.dirty = true;
+ if (spindle.dynamic_power != enable) {
+ spindle.dynamic_power = enable;
+ _update_speed();
+ }
}
void set_inverse_feed(float iF) {
- if (spindle.inv_feed == iF) return;
- spindle.inv_feed = iF;
- spindle.dirty = true;
+ if (spindle.inv_feed != iF) {
+ spindle.inv_feed = iF;
+ _update_speed();
+ }
}
cmd++; // Skip command code
// Get distance and speed
- if (!decode_float(&cmd, &s.dist)) return STAT_BAD_FLOAT;
- if (!decode_float(&cmd, &s.speed)) return STAT_BAD_FLOAT;
+ if (!decode_float(&cmd, &s.dist) || s.dist < 0) return STAT_BAD_FLOAT;
+ if (!decode_float(&cmd, &s.speed)) return STAT_BAD_FLOAT;
// Queue
command_push(COMMAND_sync_speed, &s);
void command_sync_speed_exec(void *data) {
- spindle.sync_speed.dist = -1; // Flush any left over
_set_speed(((sync_speed_t *)data)->speed);
}