#include "stepper.h"
#include "motor.h"
#include "switch.h"
+#include "spindle.h"
#include "usart.h"
#include "drv8711.h"
#include "vars.h"
stepper_init(); // steppers
motor_init(); // motors
switch_init(); // switches
+ spindle_init(); // spindles
exec_init(); // motion exec
vars_init(); // configuration variables
estop_init(); // emergency stop handler
typedef struct {
- uint16_t freq; // base frequency for PWM driver, in Hz
+ uint16_t freq; // base frequency for PWM driver, in Hz
float min_rpm;
float max_rpm;
float min_duty;
float max_duty;
- bool pwm_invert;
+ float duty;
+ float speed;
} pwm_spindle_t;
}
-static void _set_pwm(float speed) {
- if (speed < spindle.min_rpm || estop_triggered()) {
+static void _update_pwm() {
+ float speed = spindle.speed;
+
+ // Disable
+ if (speed <= spindle.min_rpm || estop_triggered()) {
TIMER_PWM.CTRLA = 0;
OUTCLR_PIN(SPIN_PWM_PIN);
_set_enable(false);
}
_set_enable(true);
- // Invert PWM
- if (spindle.pwm_invert) PINCTRL_PIN(SPIN_PWM_PIN) |= PORT_INVEN_bm;
- else PINCTRL_PIN(SPIN_PWM_PIN) &= ~PORT_INVEN_bm;
-
// 100% duty
if (spindle.max_rpm <= speed && spindle.max_duty == 1) {
TIMER_PWM.CTRLB = 0;
// Clamp speed
if (spindle.max_rpm < speed) speed = spindle.max_rpm;
- if (speed < spindle.min_rpm) speed = 0;
// Set clock period and optimal prescaler value
float prescale = (float)(F_CPU >> 16) / spindle.freq;
} else TIMER_PWM.CTRLA = 0;
// Map RPM to duty cycle
- float duty = (speed - spindle.min_rpm) / (spindle.max_rpm - spindle.min_rpm) *
+ spindle.duty =
+ (speed - spindle.min_rpm) / (spindle.max_rpm - spindle.min_rpm) *
(spindle.max_duty - spindle.min_duty) + spindle.min_duty;
// Configure clock
TIMER_PWM.CTRLB = TC1_CCAEN_bm | TC_WGMODE_SINGLESLOPE_gc;
- TIMER_PWM.CCA = TIMER_PWM.PER * duty;
+ TIMER_PWM.CCA = TIMER_PWM.PER * spindle.duty;
}
_set_dir(true);
_set_enable(false);
- DIRSET_PIN(SPIN_PWM_PIN); // Output
+ // PWM output
+ OUTCLR_PIN(SPIN_PWM_PIN);
+ DIRSET_PIN(SPIN_PWM_PIN);
}
void pwm_spindle_set(float speed) {
if (speed) _set_dir(0 < speed);
- _set_pwm(fabs(speed));
+ spindle.speed = fabs(speed);
+ _update_pwm();
}
// TODO these need more effort and should work with the huanyang spindle too
float get_max_spin() {return spindle.max_rpm;}
-void set_max_spin(float value) {spindle.max_rpm = value;}
+void set_max_spin(float value) {spindle.max_rpm = value; _update_pwm();}
float get_min_spin() {return spindle.min_rpm;}
-void set_min_spin(float value) {spindle.min_rpm = value;}
-float get_spin_min_duty() {return spindle.min_duty * 100;}
-void set_spin_min_duty(float value) {spindle.min_duty = value / 100;}
-float get_spin_max_duty() {return spindle.max_duty * 100;}
-void set_spin_max_duty(float value) {spindle.max_duty = value / 100;}
-uint16_t get_spin_freq() {return spindle.freq;}
-void set_spin_freq(uint16_t value) {spindle.freq = value;}
-bool get_pwm_invert() {return spindle.pwm_invert;}
-void set_pwm_invert(bool value) {spindle.pwm_invert = value;}
+void set_min_spin(float value) {spindle.min_rpm = value; _update_pwm();}
+float get_pwm_min_duty() {return spindle.min_duty * 100;}
+
+
+void set_pwm_min_duty(float value) {
+ spindle.min_duty = value / 100;
+ _update_pwm();
+}
+
+
+float get_pwm_max_duty() {return spindle.max_duty * 100;}
+
+
+void set_pwm_max_duty(float value) {
+ spindle.max_duty = value / 100;
+ _update_pwm();
+}
+
+
+float get_pwm_duty() {return spindle.duty;}
+uint16_t get_pwm_freq() {return spindle.freq;}
+void set_pwm_freq(uint16_t value) {spindle.freq = value; _update_pwm();}
+bool get_pwm_invert() {return PINCTRL_PIN(SPIN_PWM_PIN) & PORT_INVEN_bm;}
+
+
+void set_pwm_invert(bool invert) {
+ if (invert) PINCTRL_PIN(SPIN_PWM_PIN) |= PORT_INVEN_bm;
+ else PINCTRL_PIN(SPIN_PWM_PIN) &= ~PORT_INVEN_bm;
+}
void spindle_set_speed(float speed) {
spindle.speed = speed;
+ if (spindle.reversed) speed = -speed;
+
switch (spindle.type) {
- case SPINDLE_TYPE_PWM: pwm_spindle_set(spindle_get_speed()); break;
- case SPINDLE_TYPE_HUANYANG: hy_set(spindle_get_speed()); break;
+ case SPINDLE_TYPE_PWM: pwm_spindle_set(speed); break;
+ case SPINDLE_TYPE_HUANYANG: hy_set(speed); break;
}
}
-float spindle_get_speed() {
- return spindle.reversed ? -spindle.speed : spindle.speed;
-}
+float spindle_get_speed() {return spindle.speed;}
void spindle_stop() {
void set_spin_reversed(bool reversed) {
if (spindle.reversed != reversed) {
spindle.reversed = reversed;
- spindle_set_speed(-spindle.speed);
+ spindle_set_speed(spindle.speed);
}
}
VAR(spin_reversed, sr, bool, 0, 1, 1, "Reverse spin")
VAR(max_spin, sx, f32, 0, 1, 1, "Maximum spindle speed")
VAR(min_spin, sm, f32, 0, 1, 1, "Minimum spindle speed")
-VAR(spin_min_duty, nd, f32, 0, 1, 1, "Minimum PWM duty cycle")
-VAR(spin_max_duty, md, f32, 0, 1, 1, "Maximum PWM duty cycle")
-VAR(spin_freq, sf, u16, 0, 1, 1, "Spindle PWM frequency")
+VAR(pwm_min_duty, nd, f32, 0, 1, 1, "Minimum PWM duty cycle")
+VAR(pwm_max_duty, md, f32, 0, 1, 1, "Maximum PWM duty cycle")
+VAR(pwm_duty, pd, f32, 0, 0, 1, "Current PWM duty cycle")
+VAR(pwm_freq, sf, u16, 0, 1, 1, "Spindle PWM frequency in Hz")
// PWM spindle
VAR(pwm_invert, pi, bool, 0, 1, 1, "Inverted spindle PWM")
script#indicators-template(type="text/x-template")
.indicators
- table
+ table.inputs
tr
- th(colspan=4) Switch Inputs
+ th(colspan=6) Switch Inputs
+ tr
+ th
+ th Pin
+ th Name
+ th
+ th Pin
+ th Name
each motor in '01234'
tr(v-if="is_motor_enabled(#{motor})")
td
.fa(:class="get_class('#{motor}lw')")
+ th {{get_min_pin(#{motor})}}
th #{motor} Min
td
.fa(:class="get_class('#{motor}xw')")
+ th {{get_max_pin(#{motor})}}
th #{motor} Max
tr
td
.fa(:class="get_class('ew')")
- th Estop
+ th 23
+ th EStop
td
.fa(:class="get_class('pw')")
+ th 22
th Probe
- table
+ table.outputs
+ tr
+ th(colspan=6) Outputs
+
tr
- th(colspan=4) Outputs
+ th
+ th Pin
+ th Name
+ th
+ th Pin
+ th Name
tr
td
.fa(:class="get_class('eos')")
+ th 15
th Tool Enable
td
- .fa(:class="get_class('dos')")
- th Tool Direction
+ .fa(:class="get_class('1os')")
+ th 2
+ th Load 1
tr
td
- .fa(:class="get_class('1os')")
- th Load 1
+ .fa(:class="get_class('dos')")
+ th 16
+ th Tool Direction
td
.fa(:class="get_class('2os')")
+ th 1
th Load 2
tr
+ td {{state['pd'] | percent 0}}
+ th 17
+ th Tool PWM
+
td
.fa(:class="get_class('fos')")
- th(colspan=3) Fault
+ th 21
+ th Fault
- table
+ table.measurements
tr
th(colspan=4) Measurements
td {{state['load2'] | fixed 2}} A
th Load 2
- table
+ table.rs485
tr
th(colspan=4) RS485 Spindle
td {{state['ht']}} ℃
th Temp
- table
+ table.legend
tr
th(colspan=10) Legend
.fa.fa-circle.logic-hi
th Logic Hi
+ tr
td
.fa.fa-circle.logic-lo
th Logic Lo
+ tr
td
.fa.fa-circle-o.logic-tri
th Tristated / Disabled
+
+ h2 DB25-M2 breakout
+ center: img(width=400, src="/images/DB25-M2_breakout.png")
},
+ get_min_pin: function (motor) {
+ switch (motor) {
+ case 0: return 3;
+ case 1: return 5;
+ case 2: return 9;
+ case 3: return 11;
+ }
+ },
+
+
+ get_max_pin: function (motor) {
+ switch (motor) {
+ case 0: return 4;
+ case 1: return 8;
+ case 2: return 10;
+ case 3: return 12;
+ }
+ },
+
+
get_class: function (code) {
if (typeof this.state[code] != 'undefined') {
var state = this.state[code];
td, th
padding 4px
+ tr:nth-child(odd)
+ background #f7f7f7
+
+ td:nth-child(1), td:nth-child(3)
+ text-align center
+
+ th:nth-child(2), th:nth-child(4)
+ text-align left
+
+ &.inputs, &.outputs
+ td:nth-child(1), td:nth-child(4)
+ text-align center
+
+ th:nth-child(2), th:nth-child(5)
+ text-align right
+
+ th:nth-child(3), th:nth-child(6)
+ text-align left
+
.logic-lo
color black