Merge pull request #1042 from wolfmanjm/feature/M18-allow-axis-parameter
authorJim Morris <morris@wolfman.com>
Sun, 16 Oct 2016 05:23:03 +0000 (22:23 -0700)
committerGitHub <noreply@github.com>
Sun, 16 Oct 2016 05:23:03 +0000 (22:23 -0700)
Feature/m18 allow axis parameter

src/libs/StepperMotor.cpp
src/libs/StepperMotor.h
src/modules/robot/Robot.cpp
src/modules/utils/motordrivercontrol/MotorDriverControl.cpp

index cee458d..65b0248 100644 (file)
@@ -51,7 +51,15 @@ void StepperMotor::on_halt(void *argument)
 
 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)
index 17ec0eb..1673a36 100644 (file)
@@ -15,6 +15,9 @@ class StepperMotor  : public Module {
         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
@@ -56,8 +59,6 @@ class StepperMotor  : public Module {
         void on_halt(void *argument);
         void on_enable(void *argument);
 
-        int index;
-
         Pin step_pin;
         Pin dir_pin;
         Pin en_pin;
@@ -72,6 +73,7 @@ class StepperMotor  : public Module {
         float   last_milestone_mm;
 
         volatile struct {
+            uint8_t motor_id:8;
             volatile bool direction:1;
             volatile bool moving:1;
             bool selected:1;
index f4e9fc8..b91c2c8 100644 (file)
@@ -254,6 +254,7 @@ uint8_t Robot::register_motor(StepperMotor *motor)
         __debugbreak();
     }
     actuators.push_back(motor);
+    motor->set_motor_id(n_motors);
     return n_motors++;
 }
 
@@ -519,7 +520,30 @@ void Robot::on_gcode_received(void *argument)
                 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
index 3e270fc..f5611e8 100644 (file)
@@ -189,8 +189,18 @@ bool MotorDriverControl::config_module(uint16_t cs)
 // 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)
@@ -252,8 +262,8 @@ void MotorDriverControl::on_gcode_received(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);
@@ -272,9 +282,9 @@ void MotorDriverControl::on_gcode_received(void *argument)
         } 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
@@ -292,7 +302,7 @@ void MotorDriverControl::on_gcode_received(void *argument)
 
             }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'));