Allow non contigous definition of ABC homing endstops
[clinton/Smoothieware.git] / src / modules / tools / endstops / Endstops.cpp
index 56eb473..efc7d15 100644 (file)
@@ -228,6 +228,7 @@ bool Endstops::load_old_config()
 bool Endstops::load_config()
 {
     bool limit_enabled= false;
+    size_t max_index= 0;
 
     std::array<homing_info_t, k_max_actuators> temp_axis_array; // needs to be at least XYZ, but allow for ABC
     {
@@ -273,6 +274,9 @@ bool Endstops::load_config()
                 continue;
         }
 
+        // keep track of the maximum index that has been defined
+        if(i > max_index) max_index= i;
+
         // init pin struct
         pin_info->debounce= 0;
         pin_info->axis= toupper(axis[0]);
@@ -330,7 +334,8 @@ bool Endstops::load_config()
     // if no pins defined then disable the module
     if(endstops.empty()) return false;
 
-    // copy to the homing_axis array
+    // copy to the homing_axis array, make sure that undefined entries are filled in as well
+    // as the order is important and all slots must be filled upto the max_index
     for (size_t i = 0; i < temp_axis_array.size(); ++i) {
         if(temp_axis_array[i].axis == 0) {
             // was not configured above, if it is XYZ then we need to force a dummy entry
@@ -340,6 +345,14 @@ bool Endstops::load_config()
                 t.axis_index= i;
                 t.pin_info= nullptr; // this tells it that it cannot be used for homing
                 homing_axis.push_back(t);
+
+            }else if(i <= max_index) {
+                // for instance case where we defined C without A or B
+                homing_info_t t;
+                t.axis= 'A' + i;
+                t.axis_index= i;
+                t.pin_info= nullptr; // this tells it that it cannot be used for homing
+                homing_axis.push_back(t);
             }
 
         }else{
@@ -471,7 +484,7 @@ void Endstops::back_off_home(axis_bitmap_t axis)
         slow_rate= homing_axis[Z_AXIS].slow_rate;
 
     } else {
-        // cartesians, concatenate all the moves we need to do into one gcode
+        // cartesians concatenate all the moves we need to do into one gcode
         for( auto& e : homing_axis) {
             if(!axis[e.axis_index]) continue; // only for axes we asked to move
 
@@ -648,12 +661,14 @@ void Endstops::home(axis_bitmap_t a)
 
     // check that the endstops were hit and it did not stop short for some reason
     // if the endstop is not triggered then enter ALARM state
-    // with deltas we check all three axis were triggered
-    for (size_t i = X_AXIS; i <= Z_AXIS; ++i) {
-        if((axis_to_home[i] || this->is_delta || this->is_rdelta) && !homing_axis[i].pin_info->triggered) {
-            this->status = NOT_HOMING;
-            THEKERNEL->call_event(ON_HALT, nullptr);
-            return;
+    // with deltas we check all three axis were triggered, but at least one of XYZ must be set to home
+    if(axis_to_home[X_AXIS] || axis_to_home[Y_AXIS] || axis_to_home[Z_AXIS]) {
+        for (size_t i = X_AXIS; i <= Z_AXIS; ++i) {
+            if((axis_to_home[i] || this->is_delta || this->is_rdelta) && !homing_axis[i].pin_info->triggered) {
+                this->status = NOT_HOMING;
+                THEKERNEL->call_event(ON_HALT, nullptr);
+                return;
+            }
         }
     }
 
@@ -732,16 +747,16 @@ void Endstops::process_home_command(Gcode* gcode)
     THEROBOT->compensationTransform= nullptr;
 
     // deltas always home Z axis only, which moves all three actuators
-    bool home_in_z = this->is_delta || this->is_rdelta;
+    bool home_in_z_only = this->is_delta || this->is_rdelta;
 
     // figure out which axis to home
     axis_bitmap_t haxis;
     haxis.reset();
 
-    if(!home_in_z) { // ie not a delta
-        bool axis_speced = (gcode->has_letter('X') || gcode->has_letter('Y') || gcode->has_letter('Z') ||
-                            gcode->has_letter('A') || gcode->has_letter('B') || gcode->has_letter('C'));
+    bool axis_speced = (gcode->has_letter('X') || gcode->has_letter('Y') || gcode->has_letter('Z') ||
+                        gcode->has_letter('A') || gcode->has_letter('B') || gcode->has_letter('C'));
 
+    if(!home_in_z_only) { // ie not a delta
         for (auto &p : homing_axis) {
             // only enable homing if the endstop is defined,
             if(p.pin_info == nullptr) continue;
@@ -758,10 +773,26 @@ void Endstops::process_home_command(Gcode* gcode)
         }
 
     } else {
-        // Only Z axis homes (even though all actuators move this is handled by arm solution)
-        haxis.set(Z_AXIS);
-        // we also set the kinematics to a known good position, this is necessary for a rotary delta, but doesn't hurt for linear delta
-        THEROBOT->reset_axis_position(0, 0, 0);
+        bool home_z= !axis_speced || gcode->has_letter('X') || gcode->has_letter('Y') || gcode->has_letter('Z');
+
+        // if we specified an axis we check ABC
+        for (size_t i = A_AXIS; i < homing_axis.size(); ++i) {
+            auto &p= homing_axis[i];
+            if(p.pin_info == nullptr) continue;
+            if(!axis_speced || gcode->has_letter(p.axis)) haxis.set(p.axis_index);
+        }
+
+        if(home_z){
+            // Only Z axis homes (even though all actuators move this is handled by arm solution)
+            haxis.set(Z_AXIS);
+            // we also set the kinematics to a known good position, this is necessary for a rotary delta, but doesn't hurt for linear delta
+            THEROBOT->reset_axis_position(0, 0, 0);
+        }
+    }
+
+    if(haxis.none()) {
+        THEKERNEL->streams->printf("WARNING: Nothing to home\n");
+        return;
     }
 
     // do the actual homing
@@ -803,7 +834,7 @@ void Endstops::process_home_command(Gcode* gcode)
     // check if on_halt (eg kill or fail)
     if(THEKERNEL->is_halted()) {
         if(!THEKERNEL->is_grbl_mode()) {
-            THEKERNEL->streams->printf("ERROR: Homing cycle failed\n");
+            THEKERNEL->streams->printf("ERROR: Homing cycle failed - check the max_travel settings\n");
         }else{
             THEKERNEL->streams->printf("ALARM: Homing fail\n");
         }
@@ -812,7 +843,7 @@ void Endstops::process_home_command(Gcode* gcode)
         return;
     }
 
-    if(home_in_z || is_scara) { // deltas and scaras only
+    if(home_in_z_only || is_scara) { // deltas and scaras only
         // Here's where we would have been if the endstops were perfectly trimmed
         // NOTE on a rotary delta home_offset is actuator position in degrees when homed and
         // home_offset is the theta offset for each actuator, so M206 is used to set theta offset for each actuator in degrees
@@ -853,8 +884,20 @@ void Endstops::process_home_command(Gcode* gcode)
             }
         }
 
-        // for deltas we say all axis are homed even though it was only Z
-        for (auto &p : homing_axis) p.homed= true;
+        // for deltas we say all 3 axis are homed even though it was only Z
+        homing_axis[X_AXIS].homed= true;
+        homing_axis[Y_AXIS].homed= true;
+        homing_axis[Z_AXIS].homed= true;
+
+        // if we also homed ABC then we need to reset them
+        for (size_t i = A_AXIS; i < homing_axis.size(); ++i) {
+            auto &p= homing_axis[i];
+            if (haxis[p.axis_index]) { // if we requested this axis to home
+                THEROBOT->reset_axis_position(p.homing_position + p.home_offset, p.axis_index);
+                // set flag indicating axis was homed, it stays set once set until H/W reset or unhomed
+                p.homed= true;
+            }
+        }
 
     } else {
         // Zero the ax(i/e)s position, add in the home offset
@@ -877,7 +920,7 @@ void Endstops::process_home_command(Gcode* gcode)
         // if limit switches are enabled we must back off endstop after setting home
         back_off_home(haxis);
 
-    } else if(this->move_to_origin_after_home || homing_axis[X_AXIS].pin_info->limit_enable) {
+    } else if(haxis[Z_AXIS] && (this->move_to_origin_after_home || homing_axis[X_AXIS].pin_info->limit_enable)) {
         // deltas are not left at 0,0 because of the trim settings, so move to 0,0 if requested, but we need to back off endstops first
         // also need to back off endstops if limits are enabled
         back_off_home(haxis);
@@ -1137,6 +1180,13 @@ void Endstops::on_get_public_data(void* argument)
         bool *homing = static_cast<bool *>(pdr->get_data_ptr());
         *homing = this->status != NOT_HOMING;
         pdr->set_taken();
+
+    } else if(pdr->second_element_is(get_homed_status_checksum)) {
+        bool *homed = static_cast<bool *>(pdr->get_data_ptr());
+        for (int i = 0; i < 3; ++i) {
+            homed[i]= homing_axis[i].homed;
+        }
+        pdr->set_taken();
     }
 }