void StepperMotor::on_enable(void *argument)
{
- enable(argument != nullptr);
+ // argument is a uin32_t where bit0 is on or off, and bit 1:X, 2:Y, 3:Z, 4:A, 5:B, 6:C etc
+ // for now if bit0 is 1 we turn all on, if 0 we turn all off otherwise we turn selected axis off
+ uint32_t bm= (uint32_t)argument;
+ if(bm == 0x01) {
+ enable(true);
+
+ }else if(bm == 0 || ((bm&0x01) == 0 && ((bm&(0x02<<motor_id)) != 0)) ) {
+ enable(false);
+ }
}
void StepperMotor::change_steps_per_mm(float new_steps)
StepperMotor(Pin& step, Pin& dir, Pin& en);
~StepperMotor();
+ void set_motor_id(uint8_t id) { motor_id= id; }
+ uint8_t get_motor_id() const { return motor_id; }
+
// called from step ticker ISR
inline bool step() { step_pin.set(1); current_position_steps += (direction?-1:1); return moving; }
// called from unstep ISR
void on_halt(void *argument);
void on_enable(void *argument);
- int index;
-
Pin step_pin;
Pin dir_pin;
Pin en_pin;
float last_milestone_mm;
volatile struct {
+ uint8_t motor_id:8;
volatile bool direction:1;
volatile bool moving:1;
bool selected:1;
__debugbreak();
}
actuators.push_back(motor);
+ motor->set_motor_id(n_motors);
return n_motors++;
}
THEKERNEL->call_event(ON_ENABLE, (void*)1); // turn all enable pins on
break;
- case 18: // this used to support parameters, now it ignores them
+ case 18: // this allows individual motors to be turned off, no parameters falls through to turn all off
+ if(gcode->get_num_args() > 0) {
+ // bitmap of motors to turn off, where bit 1:X, 2:Y, 3:Z, 4:A, 5:B, 6:C
+ uint32_t bm= 0;
+ for (int i = 0; i < n_motors; ++i) {
+ char axis= (i <= Z_AXIS ? 'X'+i : 'A'+(i-3));
+ if(gcode->has_letter(axis)) bm |= (0x02<<i); // set appropriate bit
+ }
+ // handle E parameter as currently selected extruder ABC
+ if(gcode->has_letter('E')) {
+ for (int i = E_AXIS; i < n_motors; ++i) {
+ // find first selected extruder
+ if(actuators[i]->is_selected()) {
+ bm |= (0x02<<i); // set appropriate bit
+ break;
+ }
+ }
+ }
+
+ THEKERNEL->conveyor->wait_for_idle();
+ THEKERNEL->call_event(ON_ENABLE, (void *)bm);
+ break;
+ }
+ // fall through
case 84:
THEKERNEL->conveyor->wait_for_idle();
THEKERNEL->call_event(ON_ENABLE, nullptr); // turn all enable pins off
// This may cause the initial step to be missed if on-idle is delayed too much but we can't do SPI in an interrupt
void MotorDriverControl::on_enable(void *argument)
{
- enable_event= true;
- enable_flg= (argument != nullptr);
+ // argument is a uin32_t where bit0 is on or off, and bit 1:X, 2:Y, 3:Z, 4:A, 5:B, 6:C etc
+ // for now if bit0 is 1 we turn all on, if 0 we turn all off otherwise we turn selected axis off
+ uint32_t i= (designator >= 'X' || designator <= 'Z') ? designator-'X' : designator-'A'+3;
+ uint32_t bm= (uint32_t)argument;
+ if(bm == 0x01) {
+ enable_event= true;
+ enable_flg= true;
+
+ }else if(bm == 0 || ( (bm&0x01) == 0 && (bm&(0x02<<i)) != 0 )) {
+ enable_event= true;
+ enable_flg= false;
+ }
}
void MotorDriverControl::on_idle(void *argument)
microsteps= set_microstep(microsteps); // driver may change the steps it sets to
if(gcode->subcode == 1 && current_microsteps != microsteps) {
// also reset the steps/mm
- int a= designator-'A';
- if(a >= 0 && a <=2) {
+ uint32_t a= (designator >= 'X' || designator <= 'Z') ? designator-'X' : designator-'A'+3;
+ if(a < THEROBOT->get_number_registered_motors()) {
float s= THEROBOT->actuators[a]->get_steps_per_mm()*((float)microsteps/current_microsteps);
THEROBOT->actuators[a]->change_steps_per_mm(s);
gcode->stream->printf("steps/mm for %c changed to: %f\n", designator, s);
} else if(gcode->m == 911) {
// set or get raw registers
// M911 will dump all the registers and status of all the motors
- // M911.1 Pn (or A0) will dump the registers and status of the selected motor. X0 will request format in processing machine readable format
- // M911.2 Pn (or B0) Rxxx Vyyy sets Register xxx to value yyy for motor nnn, xxx == 255 writes the registers, xxx == 0 shows what registers are mapped to what
- // M911.3 Pn (or C0) will set the options based on the parameters passed as below...
+ // M911.1 Pn (or X0) will dump the registers and status of the selected motor. R0 will request format in processing machine readable format
+ // M911.2 Pn (or Y0) Rxxx Vyyy sets Register xxx to value yyy for motor nnn, xxx == 255 writes the registers, xxx == 0 shows what registers are mapped to what
+ // M911.3 Pn (or Z0) will set the options based on the parameters passed as below...
// TMC2660:-
// M911.3 Onnn Qnnn setStallGuardThreshold O=stall_guard_threshold, Q=stall_guard_filter_enabled
// M911.3 Hnnn Innn Jnnn Knnn Lnnn setCoolStepConfiguration H=lower_SG_threshold, I=SG_hysteresis, J=current_decrement_step_size, K=current_increment_step_size, L=lower_current_limit
}else if(gcode->get_value('P') == id || gcode->has_letter(designator)) {
if(gcode->subcode == 1) {
- dump_status(gcode->stream, !gcode->has_letter('X'));
+ dump_status(gcode->stream, !gcode->has_letter('R'));
}else if(gcode->subcode == 2 && gcode->has_letter('R') && gcode->has_letter('V')) {
set_raw_register(gcode->stream, gcode->get_value('R'), gcode->get_value('V'));