Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of Smoothie by
Endstops.cpp
00001 /* 00002 This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl). 00003 Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 00004 Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 00005 You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 00006 */ 00007 00008 #include "libs/Module.h" 00009 #include "libs/Kernel.h" 00010 #include "modules/communication/utils/Gcode.h" 00011 #include "modules/robot/Conveyor.h" 00012 #include "Endstops.h" 00013 #include "libs/nuts_bolts.h" 00014 #include "libs/Pin.h" 00015 #include "libs/StepperMotor.h" 00016 #include "wait_api.h" // mbed.h lib 00017 00018 #define ALPHA_AXIS 0 00019 #define BETA_AXIS 1 00020 #define GAMMA_AXIS 2 00021 #define X_AXIS 0 00022 #define Y_AXIS 1 00023 #define Z_AXIS 2 00024 00025 #define NOT_HOMING 0 00026 #define MOVING_TO_ORIGIN_FAST 1 00027 #define MOVING_BACK 2 00028 #define MOVING_TO_ORIGIN_SLOW 3 00029 00030 #define endstops_module_enable_checksum CHECKSUM("endstops_enable") 00031 #define corexy_homing_checksum CHECKSUM("corexy_homing") 00032 #define delta_homing_checksum CHECKSUM("delta_homing") 00033 00034 #define alpha_min_endstop_checksum CHECKSUM("alpha_min_endstop") 00035 #define beta_min_endstop_checksum CHECKSUM("beta_min_endstop") 00036 #define gamma_min_endstop_checksum CHECKSUM("gamma_min_endstop") 00037 00038 #define alpha_max_endstop_checksum CHECKSUM("alpha_max_endstop") 00039 #define beta_max_endstop_checksum CHECKSUM("beta_max_endstop") 00040 #define gamma_max_endstop_checksum CHECKSUM("gamma_max_endstop") 00041 00042 #define alpha_trim_checksum CHECKSUM("alpha_trim") 00043 #define beta_trim_checksum CHECKSUM("beta_trim") 00044 #define gamma_trim_checksum CHECKSUM("gamma_trim") 00045 00046 // these values are in steps and should be deprecated 00047 #define alpha_fast_homing_rate_checksum CHECKSUM("alpha_fast_homing_rate") 00048 #define beta_fast_homing_rate_checksum CHECKSUM("beta_fast_homing_rate") 00049 #define gamma_fast_homing_rate_checksum CHECKSUM("gamma_fast_homing_rate") 00050 00051 #define alpha_slow_homing_rate_checksum CHECKSUM("alpha_slow_homing_rate") 00052 #define beta_slow_homing_rate_checksum CHECKSUM("beta_slow_homing_rate") 00053 #define gamma_slow_homing_rate_checksum CHECKSUM("gamma_slow_homing_rate") 00054 00055 #define alpha_homing_retract_checksum CHECKSUM("alpha_homing_retract") 00056 #define beta_homing_retract_checksum CHECKSUM("beta_homing_retract") 00057 #define gamma_homing_retract_checksum CHECKSUM("gamma_homing_retract") 00058 #define endstop_debounce_count_checksum CHECKSUM("endstop_debounce_count") 00059 00060 // same as above but in user friendly mm/s and mm 00061 #define alpha_fast_homing_rate_mm_checksum CHECKSUM("alpha_fast_homing_rate_mm_s") 00062 #define beta_fast_homing_rate_mm_checksum CHECKSUM("beta_fast_homing_rate_mm_s") 00063 #define gamma_fast_homing_rate_mm_checksum CHECKSUM("gamma_fast_homing_rate_mm_s") 00064 00065 #define alpha_slow_homing_rate_mm_checksum CHECKSUM("alpha_slow_homing_rate_mm_s") 00066 #define beta_slow_homing_rate_mm_checksum CHECKSUM("beta_slow_homing_rate_mm_s") 00067 #define gamma_slow_homing_rate_mm_checksum CHECKSUM("gamma_slow_homing_rate_mm_s") 00068 00069 #define alpha_homing_retract_mm_checksum CHECKSUM("alpha_homing_retract_mm") 00070 #define beta_homing_retract_mm_checksum CHECKSUM("beta_homing_retract_mm") 00071 #define gamma_homing_retract_mm_checksum CHECKSUM("gamma_homing_retract_mm") 00072 00073 #define endstop_debounce_count_checksum CHECKSUM("endstop_debounce_count") 00074 00075 #define alpha_homing_direction_checksum CHECKSUM("alpha_homing_direction") 00076 #define beta_homing_direction_checksum CHECKSUM("beta_homing_direction") 00077 #define gamma_homing_direction_checksum CHECKSUM("gamma_homing_direction") 00078 #define home_to_max_checksum CHECKSUM("home_to_max") 00079 #define home_to_min_checksum CHECKSUM("home_to_min") 00080 #define alpha_min_checksum CHECKSUM("alpha_min") 00081 #define beta_min_checksum CHECKSUM("beta_min") 00082 #define gamma_min_checksum CHECKSUM("gamma_min") 00083 00084 #define alpha_max_checksum CHECKSUM("alpha_max") 00085 #define beta_max_checksum CHECKSUM("beta_max") 00086 #define gamma_max_checksum CHECKSUM("gamma_max") 00087 00088 #define alpha_steps_per_mm_checksum CHECKSUM("alpha_steps_per_mm") 00089 #define beta_steps_per_mm_checksum CHECKSUM("beta_steps_per_mm") 00090 #define gamma_steps_per_mm_checksum CHECKSUM("gamma_steps_per_mm") 00091 00092 Endstops::Endstops() 00093 { 00094 this->status = NOT_HOMING; 00095 home_offset[0] = home_offset[1] = home_offset[2] = 0.0F; 00096 } 00097 00098 void Endstops::on_module_loaded() 00099 { 00100 // Do not do anything if not enabled 00101 if ( THEKERNEL->config->value( endstops_module_enable_checksum )->by_default(true)->as_bool() == false ) { 00102 return; 00103 } 00104 00105 register_for_event(ON_CONFIG_RELOAD); 00106 this->register_for_event(ON_GCODE_RECEIVED); 00107 00108 // Take StepperMotor objects from Robot and keep them here 00109 this->steppers[0] = THEKERNEL->robot->alpha_stepper_motor; 00110 this->steppers[1] = THEKERNEL->robot->beta_stepper_motor; 00111 this->steppers[2] = THEKERNEL->robot->gamma_stepper_motor; 00112 00113 // Settings 00114 this->on_config_reload(this); 00115 00116 } 00117 00118 // Get config 00119 void Endstops::on_config_reload(void *argument) 00120 { 00121 this->pins[0].from_string( THEKERNEL->config->value(alpha_min_endstop_checksum )->by_default("nc" )->as_string())->as_input(); 00122 this->pins[1].from_string( THEKERNEL->config->value(beta_min_endstop_checksum )->by_default("nc" )->as_string())->as_input(); 00123 this->pins[2].from_string( THEKERNEL->config->value(gamma_min_endstop_checksum )->by_default("nc" )->as_string())->as_input(); 00124 this->pins[3].from_string( THEKERNEL->config->value(alpha_max_endstop_checksum )->by_default("nc" )->as_string())->as_input(); 00125 this->pins[4].from_string( THEKERNEL->config->value(beta_max_endstop_checksum )->by_default("nc" )->as_string())->as_input(); 00126 this->pins[5].from_string( THEKERNEL->config->value(gamma_max_endstop_checksum )->by_default("nc" )->as_string())->as_input(); 00127 00128 // we need to know steps per mm for M206, also use them for all settings 00129 this->steps_per_mm[0] = THEKERNEL->config->value(alpha_steps_per_mm_checksum )->as_number(); 00130 this->steps_per_mm[1] = THEKERNEL->config->value(beta_steps_per_mm_checksum )->as_number(); 00131 this->steps_per_mm[2] = THEKERNEL->config->value(gamma_steps_per_mm_checksum )->as_number(); 00132 00133 this->fast_rates[0] = THEKERNEL->config->value(alpha_fast_homing_rate_checksum )->by_default(4000 )->as_number(); 00134 this->fast_rates[1] = THEKERNEL->config->value(beta_fast_homing_rate_checksum )->by_default(4000 )->as_number(); 00135 this->fast_rates[2] = THEKERNEL->config->value(gamma_fast_homing_rate_checksum )->by_default(6400 )->as_number(); 00136 this->slow_rates[0] = THEKERNEL->config->value(alpha_slow_homing_rate_checksum )->by_default(2000 )->as_number(); 00137 this->slow_rates[1] = THEKERNEL->config->value(beta_slow_homing_rate_checksum )->by_default(2000 )->as_number(); 00138 this->slow_rates[2] = THEKERNEL->config->value(gamma_slow_homing_rate_checksum )->by_default(3200 )->as_number(); 00139 this->retract_steps[0] = THEKERNEL->config->value(alpha_homing_retract_checksum )->by_default(400 )->as_number(); 00140 this->retract_steps[1] = THEKERNEL->config->value(beta_homing_retract_checksum )->by_default(400 )->as_number(); 00141 this->retract_steps[2] = THEKERNEL->config->value(gamma_homing_retract_checksum )->by_default(1600 )->as_number(); 00142 00143 // newer mm based config values override the old ones, convert to steps/mm and steps, defaults to what was set in the older config settings above 00144 this->fast_rates[0] = THEKERNEL->config->value(alpha_fast_homing_rate_mm_checksum )->by_default(this->fast_rates[0] / steps_per_mm[0])->as_number() * steps_per_mm[0]; 00145 this->fast_rates[1] = THEKERNEL->config->value(beta_fast_homing_rate_mm_checksum )->by_default(this->fast_rates[1] / steps_per_mm[1])->as_number() * steps_per_mm[1]; 00146 this->fast_rates[2] = THEKERNEL->config->value(gamma_fast_homing_rate_mm_checksum )->by_default(this->fast_rates[2] / steps_per_mm[2])->as_number() * steps_per_mm[2]; 00147 this->slow_rates[0] = THEKERNEL->config->value(alpha_slow_homing_rate_mm_checksum )->by_default(this->slow_rates[0] / steps_per_mm[0])->as_number() * steps_per_mm[0]; 00148 this->slow_rates[1] = THEKERNEL->config->value(beta_slow_homing_rate_mm_checksum )->by_default(this->slow_rates[1] / steps_per_mm[1])->as_number() * steps_per_mm[1]; 00149 this->slow_rates[2] = THEKERNEL->config->value(gamma_slow_homing_rate_mm_checksum )->by_default(this->slow_rates[2] / steps_per_mm[2])->as_number() * steps_per_mm[2]; 00150 this->retract_steps[0] = THEKERNEL->config->value(alpha_homing_retract_mm_checksum )->by_default(this->retract_steps[0] / steps_per_mm[0])->as_number() * steps_per_mm[0]; 00151 this->retract_steps[1] = THEKERNEL->config->value(beta_homing_retract_mm_checksum )->by_default(this->retract_steps[1] / steps_per_mm[1])->as_number() * steps_per_mm[1]; 00152 this->retract_steps[2] = THEKERNEL->config->value(gamma_homing_retract_mm_checksum )->by_default(this->retract_steps[2] / steps_per_mm[2])->as_number() * steps_per_mm[2]; 00153 00154 this->debounce_count = THEKERNEL->config->value(endstop_debounce_count_checksum )->by_default(0)->as_number(); 00155 00156 00157 // get homing direction and convert to boolean where true is home to min, and false is home to max 00158 int home_dir = get_checksum(THEKERNEL->config->value(alpha_homing_direction_checksum)->by_default("home_to_min")->as_string()); 00159 this->home_direction[0] = home_dir != home_to_max_checksum; 00160 00161 home_dir = get_checksum(THEKERNEL->config->value(beta_homing_direction_checksum)->by_default("home_to_min")->as_string()); 00162 this->home_direction[1] = home_dir != home_to_max_checksum; 00163 00164 home_dir = get_checksum(THEKERNEL->config->value(gamma_homing_direction_checksum)->by_default("home_to_min")->as_string()); 00165 this->home_direction[2] = home_dir != home_to_max_checksum; 00166 00167 this->homing_position[0] = this->home_direction[0] ? THEKERNEL->config->value(alpha_min_checksum)->by_default(0)->as_number() : THEKERNEL->config->value(alpha_max_checksum)->by_default(200)->as_number(); 00168 this->homing_position[1] = this->home_direction[1] ? THEKERNEL->config->value(beta_min_checksum )->by_default(0)->as_number() : THEKERNEL->config->value(beta_max_checksum )->by_default(200)->as_number();; 00169 this->homing_position[2] = this->home_direction[2] ? THEKERNEL->config->value(gamma_min_checksum)->by_default(0)->as_number() : THEKERNEL->config->value(gamma_max_checksum)->by_default(200)->as_number();; 00170 00171 this->is_corexy = THEKERNEL->config->value(corexy_homing_checksum)->by_default(false)->as_bool(); 00172 this->is_delta = THEKERNEL->config->value(delta_homing_checksum)->by_default(false)->as_bool(); 00173 00174 // endstop trim used by deltas to do soft adjusting, in mm, convert to steps, and negate depending on homing direction 00175 // eg on a delta homing to max, a negative trim value will move the carriage down, and a positive will move it up 00176 int dirx = (this->home_direction[0] ? 1 : -1); 00177 int diry = (this->home_direction[1] ? 1 : -1); 00178 int dirz = (this->home_direction[2] ? 1 : -1); 00179 this->trim[0] = THEKERNEL->config->value(alpha_trim_checksum )->by_default(0 )->as_number() * steps_per_mm[0] * dirx; 00180 this->trim[1] = THEKERNEL->config->value(beta_trim_checksum )->by_default(0 )->as_number() * steps_per_mm[1] * diry; 00181 this->trim[2] = THEKERNEL->config->value(gamma_trim_checksum )->by_default(0 )->as_number() * steps_per_mm[2] * dirz; 00182 } 00183 00184 void Endstops::wait_for_homed(char axes_to_move) 00185 { 00186 bool running = true; 00187 unsigned int debounce[3] = {0, 0, 0}; 00188 while (running) { 00189 running = false; 00190 THEKERNEL->call_event(ON_IDLE); 00191 for ( char c = 'X'; c <= 'Z'; c++ ) { 00192 if ( ( axes_to_move >> ( c - 'X' ) ) & 1 ) { 00193 if ( this->pins[c - 'X' + (this->home_direction[c - 'X'] ? 0 : 3)].get() ) { 00194 if ( debounce[c - 'X'] < debounce_count ) { 00195 debounce[c - 'X'] ++; 00196 running = true; 00197 } else if ( this->steppers[c - 'X']->moving ) { 00198 this->steppers[c - 'X']->move(0, 0); 00199 } 00200 } else { 00201 // The endstop was not hit yet 00202 running = true; 00203 debounce[c - 'X'] = 0; 00204 } 00205 } 00206 } 00207 } 00208 } 00209 00210 // this homing works for cartesian and delta printers, not for HBots/CoreXY 00211 void Endstops::do_homing(char axes_to_move) 00212 { 00213 // Start moving the axes to the origin 00214 this->status = MOVING_TO_ORIGIN_FAST; 00215 for ( char c = 'X'; c <= 'Z'; c++ ) { 00216 if ( ( axes_to_move >> ( c - 'X' ) ) & 1 ) { 00217 this->steppers[c - 'X']->set_speed(this->fast_rates[c - 'X']); 00218 this->steppers[c - 'X']->move(this->home_direction[c - 'X'], 10000000); 00219 } 00220 } 00221 00222 // Wait for all axes to have homed 00223 this->wait_for_homed(axes_to_move); 00224 00225 // Move back a small distance 00226 this->status = MOVING_BACK; 00227 bool inverted_dir; 00228 for ( char c = 'X'; c <= 'Z'; c++ ) { 00229 if ( ( axes_to_move >> ( c - 'X' ) ) & 1 ) { 00230 inverted_dir = !this->home_direction[c - 'X']; 00231 this->steppers[c - 'X']->set_speed(this->slow_rates[c - 'X']); 00232 this->steppers[c - 'X']->move(inverted_dir, this->retract_steps[c - 'X']); 00233 } 00234 } 00235 00236 // Wait for moves to be done 00237 for ( char c = 'X'; c <= 'Z'; c++ ) { 00238 if ( ( axes_to_move >> ( c - 'X' ) ) & 1 ) { 00239 while ( this->steppers[c - 'X']->moving ) { 00240 THEKERNEL->call_event(ON_IDLE); 00241 } 00242 } 00243 } 00244 00245 // Start moving the axes to the origin slowly 00246 this->status = MOVING_TO_ORIGIN_SLOW; 00247 for ( char c = 'X'; c <= 'Z'; c++ ) { 00248 if ( ( axes_to_move >> ( c - 'X' ) ) & 1 ) { 00249 this->steppers[c - 'X']->set_speed(this->slow_rates[c - 'X']); 00250 this->steppers[c - 'X']->move(this->home_direction[c - 'X'], 10000000); 00251 } 00252 } 00253 00254 // Wait for all axes to have homed 00255 this->wait_for_homed(axes_to_move); 00256 00257 if (this->is_delta) { 00258 // move for soft trim 00259 this->status = MOVING_BACK; 00260 for ( char c = 'X'; c <= 'Z'; c++ ) { 00261 if ( this->trim[c - 'X'] != 0 && ( axes_to_move >> ( c - 'X' ) ) & 1 ) { 00262 inverted_dir = !this->home_direction[c - 'X']; 00263 // move up or down depending on sign of trim 00264 if (this->trim[c - 'X'] < 0) inverted_dir = !inverted_dir; 00265 this->steppers[c - 'X']->set_speed(this->slow_rates[c - 'X']); 00266 this->steppers[c - 'X']->move(inverted_dir, this->trim[c - 'X']); 00267 } 00268 } 00269 00270 // Wait for moves to be done 00271 for ( char c = 'X'; c <= 'Z'; c++ ) { 00272 if ( ( axes_to_move >> ( c - 'X' ) ) & 1 ) { 00273 //THEKERNEL->streams->printf("axis %c \r\n", c ); 00274 while ( this->steppers[c - 'X']->moving ) { 00275 THEKERNEL->call_event(ON_IDLE); 00276 } 00277 } 00278 } 00279 } 00280 00281 // Homing is done 00282 this->status = NOT_HOMING; 00283 } 00284 00285 void Endstops::wait_for_homed_corexy(int axis) 00286 { 00287 bool running = true; 00288 unsigned int debounce[3] = {0, 0, 0}; 00289 while (running) { 00290 running = false; 00291 THEKERNEL->call_event(ON_IDLE); 00292 if ( this->pins[axis + (this->home_direction[axis] ? 0 : 3)].get() ) { 00293 if ( debounce[axis] < debounce_count ) { 00294 debounce[axis] ++; 00295 running = true; 00296 } else { 00297 // turn both off if running 00298 if (this->steppers[X_AXIS]->moving) this->steppers[X_AXIS]->move(0, 0); 00299 if (this->steppers[Y_AXIS]->moving) this->steppers[Y_AXIS]->move(0, 0); 00300 } 00301 } else { 00302 // The endstop was not hit yet 00303 running = true; 00304 debounce[axis] = 0; 00305 } 00306 } 00307 } 00308 00309 void Endstops::corexy_home(int home_axis, bool dirx, bool diry, float fast_rate, float slow_rate, unsigned int retract_steps) 00310 { 00311 this->status = MOVING_TO_ORIGIN_FAST; 00312 this->steppers[X_AXIS]->set_speed(fast_rate); 00313 this->steppers[X_AXIS]->move(dirx, 10000000); 00314 this->steppers[Y_AXIS]->set_speed(fast_rate); 00315 this->steppers[Y_AXIS]->move(diry, 10000000); 00316 00317 // wait for primary axis 00318 this->wait_for_homed_corexy(home_axis); 00319 00320 // Move back a small distance 00321 this->status = MOVING_BACK; 00322 this->steppers[X_AXIS]->set_speed(slow_rate); 00323 this->steppers[X_AXIS]->move(!dirx, retract_steps); 00324 this->steppers[Y_AXIS]->set_speed(slow_rate); 00325 this->steppers[Y_AXIS]->move(!diry, retract_steps); 00326 00327 // wait until done 00328 while ( this->steppers[X_AXIS]->moving || this->steppers[Y_AXIS]->moving) { 00329 THEKERNEL->call_event(ON_IDLE); 00330 } 00331 00332 // Start moving the axes to the origin slowly 00333 this->status = MOVING_TO_ORIGIN_SLOW; 00334 this->steppers[X_AXIS]->set_speed(slow_rate); 00335 this->steppers[X_AXIS]->move(dirx, 10000000); 00336 this->steppers[Y_AXIS]->set_speed(slow_rate); 00337 this->steppers[Y_AXIS]->move(diry, 10000000); 00338 00339 // wait for primary axis 00340 this->wait_for_homed_corexy(home_axis); 00341 } 00342 00343 // this homing works for HBots/CoreXY 00344 void Endstops::do_homing_corexy(char axes_to_move) 00345 { 00346 // TODO should really make order configurable, and select whether to allow XY to home at the same time, diagonally 00347 // To move XY at the same time only one motor needs to turn, determine which motor and which direction based on min or max directions 00348 // allow to move until an endstop triggers, then stop that motor. Speed up when moving diagonally to match X or Y speed 00349 // continue moving in the direction not yet triggered (which means two motors turning) until endstop hit 00350 00351 if((axes_to_move & 0x03) == 0x03) { // both X and Y need Homing 00352 // determine which motor to turn and which way 00353 bool dirx= this->home_direction[X_AXIS]; 00354 bool diry= this->home_direction[Y_AXIS]; 00355 int motor; 00356 bool dir; 00357 if(dirx && diry) { // min/min 00358 motor= X_AXIS; 00359 dir= true; 00360 }else if(dirx && !diry) { // min/max 00361 motor= Y_AXIS; 00362 dir= true; 00363 }else if(!dirx && diry) { // max/min 00364 motor= Y_AXIS; 00365 dir= false; 00366 }else if(!dirx && !diry) { // max/max 00367 motor= X_AXIS; 00368 dir= false; 00369 } 00370 00371 // then move both X and Y until one hits the endstop 00372 this->status = MOVING_TO_ORIGIN_FAST; 00373 this->steppers[motor]->set_speed(this->fast_rates[motor]*1.4142); // need to allow for more ground covered when moving diagonally 00374 this->steppers[motor]->move(dir, 10000000); 00375 // wait until either X or Y hits the endstop 00376 bool running= true; 00377 while (running) { 00378 THEKERNEL->call_event(ON_IDLE); 00379 for(int m=X_AXIS;m<=Y_AXIS;m++) { 00380 if(this->pins[m + (this->home_direction[m] ? 0 : 3)].get()) { 00381 // turn off motor 00382 if(this->steppers[motor]->moving) this->steppers[motor]->move(0, 0); 00383 running= false; 00384 break; 00385 } 00386 } 00387 } 00388 } 00389 00390 // move individual axis 00391 if (axes_to_move & 0x01) { // Home X, which means both X and Y in same direction 00392 bool dir= this->home_direction[X_AXIS]; 00393 corexy_home(X_AXIS, dir, dir, this->fast_rates[X_AXIS], this->slow_rates[X_AXIS], this->retract_steps[X_AXIS]); 00394 } 00395 00396 if (axes_to_move & 0x02) { // Home Y, which means both X and Y in different directions 00397 bool dir= this->home_direction[Y_AXIS]; 00398 corexy_home(Y_AXIS, dir, !dir, this->fast_rates[Y_AXIS], this->slow_rates[Y_AXIS], this->retract_steps[Y_AXIS]); 00399 } 00400 00401 if (axes_to_move & 0x04) { // move Z 00402 do_homing(0x04); // just home normally for Z 00403 } 00404 00405 // Homing is done 00406 this->status = NOT_HOMING; 00407 } 00408 00409 // Start homing sequences by response to GCode commands 00410 void Endstops::on_gcode_received(void *argument) 00411 { 00412 Gcode *gcode = static_cast<Gcode *>(argument); 00413 if ( gcode->has_g) { 00414 if ( gcode->g == 28 ) { 00415 gcode->mark_as_taken(); 00416 // G28 is received, we have homing to do 00417 00418 // First wait for the queue to be empty 00419 THEKERNEL->conveyor->wait_for_empty_queue(); 00420 00421 // Do we move select axes or all of them 00422 char axes_to_move = 0; 00423 // only enable homing if the endstop is defined, deltas always home all axis 00424 bool home_all = this->is_delta || !( gcode->has_letter('X') || gcode->has_letter('Y') || gcode->has_letter('Z') ); 00425 00426 for ( char c = 'X'; c <= 'Z'; c++ ) { 00427 if ( (home_all || gcode->has_letter(c)) && this->pins[c - 'X' + (this->home_direction[c - 'X'] ? 0 : 3)].connected() ) { 00428 axes_to_move += ( 1 << (c - 'X' ) ); 00429 } 00430 } 00431 00432 // Enable the motors 00433 THEKERNEL->stepper->turn_enable_pins_on(); 00434 00435 // do the actual homing 00436 if (is_corexy) 00437 do_homing_corexy(axes_to_move); 00438 else 00439 do_homing(axes_to_move); 00440 00441 // Zero the ax(i/e)s position, add in the home offset 00442 for ( int c = 0; c <= 2; c++ ) { 00443 if ( (axes_to_move >> c) & 1 ) { 00444 THEKERNEL->robot->reset_axis_position(this->homing_position[c] + this->home_offset[c], c); 00445 } 00446 } 00447 } 00448 } else if (gcode->has_m) { 00449 switch (gcode->m) { 00450 case 119: { 00451 00452 int px = this->home_direction[0] ? 0 : 3; 00453 int py = this->home_direction[1] ? 1 : 4; 00454 int pz = this->home_direction[2] ? 2 : 5; 00455 const char *mx = this->home_direction[0] ? "min" : "max"; 00456 const char *my = this->home_direction[1] ? "min" : "max"; 00457 const char *mz = this->home_direction[2] ? "min" : "max"; 00458 00459 gcode->stream->printf("X %s:%d Y %s:%d Z %s:%d\n", mx, this->pins[px].get(), my, this->pins[py].get(), mz, this->pins[pz].get()); 00460 gcode->mark_as_taken(); 00461 } 00462 break; 00463 00464 case 206: // M206 - set homing offset 00465 if (gcode->has_letter('X')) home_offset[0] = gcode->get_value('X'); 00466 if (gcode->has_letter('Y')) home_offset[1] = gcode->get_value('Y'); 00467 if (gcode->has_letter('Z')) home_offset[2] = gcode->get_value('Z'); 00468 gcode->stream->printf("X %5.3f Y %5.3f Z %5.3f\n", home_offset[0], home_offset[1], home_offset[2]); 00469 gcode->mark_as_taken(); 00470 break; 00471 00472 case 500: // save settings 00473 case 503: // print settings 00474 gcode->stream->printf(";Home offset (mm):\nM206 X%1.2f Y%1.2f Z%1.2f\n", home_offset[0], home_offset[1], home_offset[2]); 00475 if (is_delta) { 00476 float mm[3]; 00477 trim2mm(mm); 00478 gcode->stream->printf(";Trim (mm):\nM666 X%1.2f Y%1.2f Z%1.2f\n", mm[0], mm[1], mm[2]); 00479 gcode->stream->printf(";Max Z\nM665 Z%1.2f\n", this->homing_position[2]); 00480 } 00481 gcode->mark_as_taken(); 00482 break; 00483 00484 case 665: { // M665 - set max gamma/z height 00485 gcode->mark_as_taken(); 00486 float gamma_max = this->homing_position[2]; 00487 if (gcode->has_letter('Z')) { 00488 this->homing_position[2] = gamma_max = gcode->get_value('Z'); 00489 } 00490 gcode->stream->printf("Max Z %8.3f ", gamma_max); 00491 gcode->add_nl = true; 00492 } 00493 break; 00494 00495 00496 case 666: { // M666 - set trim for each axis in mm 00497 float mm[3]; 00498 trim2mm(mm); 00499 00500 if (gcode->has_letter('X')) mm[0] = gcode->get_value('X'); 00501 if (gcode->has_letter('Y')) mm[1] = gcode->get_value('Y'); 00502 if (gcode->has_letter('Z')) mm[2] = gcode->get_value('Z'); 00503 00504 int dirx = (this->home_direction[0] ? 1 : -1); 00505 int diry = (this->home_direction[1] ? 1 : -1); 00506 int dirz = (this->home_direction[2] ? 1 : -1); 00507 trim[0] = lround(mm[0] * steps_per_mm[0]) * dirx; // convert back to steps 00508 trim[1] = lround(mm[1] * steps_per_mm[1]) * diry; 00509 trim[2] = lround(mm[2] * steps_per_mm[2]) * dirz; 00510 00511 // print the current trim values in mm and steps 00512 gcode->stream->printf("X %5.3f (%d) Y %5.3f (%d) Z %5.3f (%d)\n", mm[0], trim[0], mm[1], trim[1], mm[2], trim[2]); 00513 gcode->mark_as_taken(); 00514 } 00515 break; 00516 00517 // NOTE this is to test accuracy of lead screws etc. 00518 case 910: { // M910 - move specific number of raw steps 00519 int x= 0, y=0 , z= 0, f= 200*16; 00520 if (gcode->has_letter('F')) f = gcode->get_value('F'); 00521 if (gcode->has_letter('X')) { 00522 x = gcode->get_value('X'); 00523 this->steppers[X_AXIS]->set_speed(f); 00524 this->steppers[X_AXIS]->move(x<0, abs(x)); 00525 } 00526 if (gcode->has_letter('Y')) { 00527 y = gcode->get_value('Y'); 00528 this->steppers[Y_AXIS]->set_speed(f); 00529 this->steppers[Y_AXIS]->move(y<0, abs(y)); 00530 } 00531 if (gcode->has_letter('Z')) { 00532 z = gcode->get_value('Z'); 00533 this->steppers[Z_AXIS]->set_speed(f); 00534 this->steppers[Z_AXIS]->move(z<0, abs(z)); 00535 } 00536 gcode->stream->printf("Moved X %d Y %d Z %d F %d steps\n", x, y, z, f); 00537 gcode->mark_as_taken(); 00538 break; 00539 } 00540 } 00541 } 00542 } 00543 00544 void Endstops::trim2mm(float *mm) 00545 { 00546 int dirx = (this->home_direction[0] ? 1 : -1); 00547 int diry = (this->home_direction[1] ? 1 : -1); 00548 int dirz = (this->home_direction[2] ? 1 : -1); 00549 00550 mm[0] = this->trim[0] / this->steps_per_mm[0] * dirx; // convert to mm 00551 mm[1] = this->trim[1] / this->steps_per_mm[1] * diry; 00552 mm[2] = this->trim[2] / this->steps_per_mm[2] * dirz; 00553 } 00554
Generated on Tue Jul 12 2022 20:09:00 by
1.7.2
