|
@@ -29,6 +29,10 @@
|
29
|
29
|
|
30
|
30
|
#include "Marlin.h"
|
31
|
31
|
|
|
32
|
+#ifdef ENABLE_AUTO_BED_LEVELING
|
|
33
|
+#include "vector_3.h"
|
|
34
|
+#endif // ENABLE_AUTO_BED_LEVELING
|
|
35
|
+
|
32
|
36
|
#include "ultralcd.h"
|
33
|
37
|
#include "planner.h"
|
34
|
38
|
#include "stepper.h"
|
|
@@ -63,6 +67,8 @@
|
63
|
67
|
// G10 - retract filament according to settings of M207
|
64
|
68
|
// G11 - retract recover filament according to settings of M208
|
65
|
69
|
// G28 - Home all Axis
|
|
70
|
+// G29 - Detailed Z-Probe, probes the bed at 3 points. You must de at the home position for this to work correctly.
|
|
71
|
+// G30 - Single Z Probe, probes bed at current XY location.
|
66
|
72
|
// G90 - Use Absolute Coordinates
|
67
|
73
|
// G91 - Use Relative Coordinates
|
68
|
74
|
// G92 - Set current position to cordinates given
|
|
@@ -133,6 +139,8 @@
|
133
|
139
|
// M303 - PID relay autotune S<temperature> sets the target temperature. (default target temperature = 150C)
|
134
|
140
|
// M304 - Set bed PID parameters P I and D
|
135
|
141
|
// M400 - Finish all moves
|
|
142
|
+// M401 - Lower z-probe if present
|
|
143
|
+// M402 - Raise z-probe if present
|
136
|
144
|
// M500 - stores paramters in EEPROM
|
137
|
145
|
// M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily).
|
138
|
146
|
// M502 - reverts to the default "factory settings". You still need to store them in EEPROM afterwards if you want to.
|
|
@@ -388,6 +396,11 @@ void servo_init()
|
388
|
396
|
}
|
389
|
397
|
}
|
390
|
398
|
#endif
|
|
399
|
+
|
|
400
|
+ #if defined (ENABLE_AUTO_BED_LEVELING) && (PROBE_SERVO_DEACTIVATION_DELAY > 0)
|
|
401
|
+ delay(PROBE_SERVO_DEACTIVATION_DELAY);
|
|
402
|
+ servos[servo_endstops[Z_AXIS]].detach();
|
|
403
|
+ #endif
|
391
|
404
|
}
|
392
|
405
|
|
393
|
406
|
void setup()
|
|
@@ -756,6 +769,143 @@ static void axis_is_at_home(int axis) {
|
756
|
769
|
max_pos[axis] = base_max_pos(axis) + add_homeing[axis];
|
757
|
770
|
}
|
758
|
771
|
|
|
772
|
+#ifdef ENABLE_AUTO_BED_LEVELING
|
|
773
|
+static void set_bed_level_equation(float z_at_xLeft_yFront, float z_at_xRight_yFront, float z_at_xLeft_yBack) {
|
|
774
|
+ plan_bed_level_matrix.set_to_identity();
|
|
775
|
+
|
|
776
|
+ vector_3 xLeftyFront = vector_3(LEFT_PROBE_BED_POSITION, FRONT_PROBE_BED_POSITION, z_at_xLeft_yFront);
|
|
777
|
+ vector_3 xLeftyBack = vector_3(LEFT_PROBE_BED_POSITION, BACK_PROBE_BED_POSITION, z_at_xLeft_yBack);
|
|
778
|
+ vector_3 xRightyFront = vector_3(RIGHT_PROBE_BED_POSITION, FRONT_PROBE_BED_POSITION, z_at_xRight_yFront);
|
|
779
|
+
|
|
780
|
+ vector_3 xPositive = (xRightyFront - xLeftyFront).get_normal();
|
|
781
|
+ vector_3 yPositive = (xLeftyBack - xLeftyFront).get_normal();
|
|
782
|
+ vector_3 planeNormal = vector_3::cross(yPositive, xPositive).get_normal();
|
|
783
|
+
|
|
784
|
+ //planeNormal.debug("planeNormal");
|
|
785
|
+ //yPositive.debug("yPositive");
|
|
786
|
+ matrix_3x3 bedLevel = matrix_3x3::create_look_at(planeNormal, yPositive);
|
|
787
|
+ //bedLevel.debug("bedLevel");
|
|
788
|
+
|
|
789
|
+ //plan_bed_level_matrix.debug("bed level before");
|
|
790
|
+ //vector_3 uncorrected_position = plan_get_position_mm();
|
|
791
|
+ //uncorrected_position.debug("position before");
|
|
792
|
+
|
|
793
|
+ // and set our bed level equation to do the right thing
|
|
794
|
+ plan_bed_level_matrix = matrix_3x3::create_inverse(bedLevel);
|
|
795
|
+ //plan_bed_level_matrix.debug("bed level after");
|
|
796
|
+
|
|
797
|
+ vector_3 corrected_position = plan_get_position();
|
|
798
|
+ //corrected_position.debug("position after");
|
|
799
|
+ current_position[X_AXIS] = corrected_position.x;
|
|
800
|
+ current_position[Y_AXIS] = corrected_position.y;
|
|
801
|
+ current_position[Z_AXIS] = corrected_position.z;
|
|
802
|
+
|
|
803
|
+ // but the bed at 0 so we don't go below it.
|
|
804
|
+ current_position[Z_AXIS] = -Z_PROBE_OFFSET_FROM_EXTRUDER;
|
|
805
|
+
|
|
806
|
+ plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
|
|
807
|
+}
|
|
808
|
+
|
|
809
|
+static void run_z_probe() {
|
|
810
|
+ plan_bed_level_matrix.set_to_identity();
|
|
811
|
+ feedrate = homing_feedrate[Z_AXIS];
|
|
812
|
+
|
|
813
|
+ // move down until you find the bed
|
|
814
|
+ float zPosition = -10;
|
|
815
|
+ plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], zPosition, current_position[E_AXIS], feedrate/60, active_extruder);
|
|
816
|
+ st_synchronize();
|
|
817
|
+
|
|
818
|
+ // we have to let the planner know where we are right now as it is not where we said to go.
|
|
819
|
+ zPosition = st_get_position_mm(Z_AXIS);
|
|
820
|
+ plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], zPosition, current_position[E_AXIS]);
|
|
821
|
+
|
|
822
|
+ // move up the retract distance
|
|
823
|
+ zPosition += home_retract_mm(Z_AXIS);
|
|
824
|
+ plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], zPosition, current_position[E_AXIS], feedrate/60, active_extruder);
|
|
825
|
+ st_synchronize();
|
|
826
|
+
|
|
827
|
+ // move back down slowly to find bed
|
|
828
|
+ feedrate = homing_feedrate[Z_AXIS]/4;
|
|
829
|
+ zPosition -= home_retract_mm(Z_AXIS) * 2;
|
|
830
|
+ plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], zPosition, current_position[E_AXIS], feedrate/60, active_extruder);
|
|
831
|
+ st_synchronize();
|
|
832
|
+
|
|
833
|
+ current_position[Z_AXIS] = st_get_position_mm(Z_AXIS);
|
|
834
|
+ // make sure the planner knows where we are as it may be a bit different than we last said to move to
|
|
835
|
+ plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
|
|
836
|
+}
|
|
837
|
+
|
|
838
|
+static void do_blocking_move_to(float x, float y, float z) {
|
|
839
|
+ float oldFeedRate = feedrate;
|
|
840
|
+
|
|
841
|
+ feedrate = XY_TRAVEL_SPEED;
|
|
842
|
+
|
|
843
|
+ current_position[X_AXIS] = x;
|
|
844
|
+ current_position[Y_AXIS] = y;
|
|
845
|
+ current_position[Z_AXIS] = z;
|
|
846
|
+ plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], feedrate/60, active_extruder);
|
|
847
|
+ st_synchronize();
|
|
848
|
+
|
|
849
|
+ feedrate = oldFeedRate;
|
|
850
|
+}
|
|
851
|
+
|
|
852
|
+static void do_blocking_move_relative(float offset_x, float offset_y, float offset_z) {
|
|
853
|
+ do_blocking_move_to(current_position[X_AXIS] + offset_x, current_position[Y_AXIS] + offset_y, current_position[Z_AXIS] + offset_z);
|
|
854
|
+}
|
|
855
|
+
|
|
856
|
+static void setup_for_endstop_move() {
|
|
857
|
+ saved_feedrate = feedrate;
|
|
858
|
+ saved_feedmultiply = feedmultiply;
|
|
859
|
+ feedmultiply = 100;
|
|
860
|
+ previous_millis_cmd = millis();
|
|
861
|
+
|
|
862
|
+ enable_endstops(true);
|
|
863
|
+}
|
|
864
|
+
|
|
865
|
+static void clean_up_after_endstop_move() {
|
|
866
|
+#ifdef ENDSTOPS_ONLY_FOR_HOMING
|
|
867
|
+ enable_endstops(false);
|
|
868
|
+#endif
|
|
869
|
+
|
|
870
|
+ feedrate = saved_feedrate;
|
|
871
|
+ feedmultiply = saved_feedmultiply;
|
|
872
|
+ previous_millis_cmd = millis();
|
|
873
|
+}
|
|
874
|
+
|
|
875
|
+static void engage_z_probe() {
|
|
876
|
+ // Engage Z Servo endstop if enabled
|
|
877
|
+ #ifdef SERVO_ENDSTOPS
|
|
878
|
+ if (servo_endstops[Z_AXIS] > -1) {
|
|
879
|
+#if defined (ENABLE_AUTO_BED_LEVELING) && (PROBE_SERVO_DEACTIVATION_DELAY > 0)
|
|
880
|
+ servos[servo_endstops[Z_AXIS]].attach(0);
|
|
881
|
+#endif
|
|
882
|
+ servos[servo_endstops[Z_AXIS]].write(servo_endstop_angles[Z_AXIS * 2]);
|
|
883
|
+#if defined (ENABLE_AUTO_BED_LEVELING) && (PROBE_SERVO_DEACTIVATION_DELAY > 0)
|
|
884
|
+ delay(PROBE_SERVO_DEACTIVATION_DELAY);
|
|
885
|
+ servos[servo_endstops[Z_AXIS]].detach();
|
|
886
|
+#endif
|
|
887
|
+ }
|
|
888
|
+ #endif
|
|
889
|
+}
|
|
890
|
+
|
|
891
|
+static void retract_z_probe() {
|
|
892
|
+ // Retract Z Servo endstop if enabled
|
|
893
|
+ #ifdef SERVO_ENDSTOPS
|
|
894
|
+ if (servo_endstops[Z_AXIS] > -1) {
|
|
895
|
+#if defined (ENABLE_AUTO_BED_LEVELING) && (PROBE_SERVO_DEACTIVATION_DELAY > 0)
|
|
896
|
+ servos[servo_endstops[Z_AXIS]].attach(0);
|
|
897
|
+#endif
|
|
898
|
+ servos[servo_endstops[Z_AXIS]].write(servo_endstop_angles[Z_AXIS * 2 + 1]);
|
|
899
|
+#if defined (ENABLE_AUTO_BED_LEVELING) && (PROBE_SERVO_DEACTIVATION_DELAY > 0)
|
|
900
|
+ delay(PROBE_SERVO_DEACTIVATION_DELAY);
|
|
901
|
+ servos[servo_endstops[Z_AXIS]].detach();
|
|
902
|
+#endif
|
|
903
|
+ }
|
|
904
|
+ #endif
|
|
905
|
+}
|
|
906
|
+
|
|
907
|
+#endif // #ifdef ENABLE_AUTO_BED_LEVELING
|
|
908
|
+
|
759
|
909
|
static void homeaxis(int axis) {
|
760
|
910
|
#define HOMEAXIS_DO(LETTER) \
|
761
|
911
|
((LETTER##_MIN_PIN > -1 && LETTER##_HOME_DIR==-1) || (LETTER##_MAX_PIN > -1 && LETTER##_HOME_DIR==1))
|
|
@@ -772,6 +922,10 @@ static void homeaxis(int axis) {
|
772
|
922
|
|
773
|
923
|
// Engage Servo endstop if enabled
|
774
|
924
|
#ifdef SERVO_ENDSTOPS
|
|
925
|
+#if defined (ENABLE_AUTO_BED_LEVELING) && (PROBE_SERVO_DEACTIVATION_DELAY > 0)
|
|
926
|
+ if (axis==Z_AXIS) engage_z_probe();
|
|
927
|
+ else
|
|
928
|
+#endif
|
775
|
929
|
if (servo_endstops[axis] > -1) {
|
776
|
930
|
servos[servo_endstops[axis]].write(servo_endstop_angles[axis * 2]);
|
777
|
931
|
}
|
|
@@ -818,6 +972,10 @@ static void homeaxis(int axis) {
|
818
|
972
|
servos[servo_endstops[axis]].write(servo_endstop_angles[axis * 2 + 1]);
|
819
|
973
|
}
|
820
|
974
|
#endif
|
|
975
|
+#if defined (ENABLE_AUTO_BED_LEVELING) && (PROBE_SERVO_DEACTIVATION_DELAY > 0)
|
|
976
|
+ if (axis==Z_AXIS) retract_z_probe();
|
|
977
|
+#endif
|
|
978
|
+
|
821
|
979
|
}
|
822
|
980
|
}
|
823
|
981
|
#define HOMEAXIS(LETTER) homeaxis(LETTER##_AXIS)
|
|
@@ -826,7 +984,9 @@ void process_commands()
|
826
|
984
|
{
|
827
|
985
|
unsigned long codenum; //throw away variable
|
828
|
986
|
char *starpos = NULL;
|
829
|
|
-
|
|
987
|
+#ifdef ENABLE_AUTO_BED_LEVELING
|
|
988
|
+ float x_tmp, y_tmp, z_tmp, real_z;
|
|
989
|
+#endif
|
830
|
990
|
if(code_seen('G'))
|
831
|
991
|
{
|
832
|
992
|
switch((int)code_value())
|
|
@@ -898,6 +1058,11 @@ void process_commands()
|
898
|
1058
|
break;
|
899
|
1059
|
#endif //FWRETRACT
|
900
|
1060
|
case 28: //G28 Home all Axis one at a time
|
|
1061
|
+#ifdef ENABLE_AUTO_BED_LEVELING
|
|
1062
|
+ plan_bed_level_matrix.set_to_identity(); //Reset the plane ("erase" all leveling data)
|
|
1063
|
+#endif //ENABLE_AUTO_BED_LEVELING
|
|
1064
|
+
|
|
1065
|
+
|
901
|
1066
|
saved_feedrate = feedrate;
|
902
|
1067
|
saved_feedmultiply = feedmultiply;
|
903
|
1068
|
feedmultiply = 100;
|
|
@@ -1045,6 +1210,122 @@ void process_commands()
|
1045
|
1210
|
previous_millis_cmd = millis();
|
1046
|
1211
|
endstops_hit_on_purpose();
|
1047
|
1212
|
break;
|
|
1213
|
+
|
|
1214
|
+#ifdef ENABLE_AUTO_BED_LEVELING
|
|
1215
|
+ case 29: // G29 Detailed Z-Probe, probes the bed at 3 points.
|
|
1216
|
+ {
|
|
1217
|
+ #if Z_MIN_PIN == -1
|
|
1218
|
+ #error "You must have a Z_MIN endstop in order to enable Auto Bed Leveling feature!!! Z_MIN_PIN must point to a valid hardware pin."
|
|
1219
|
+ #endif
|
|
1220
|
+
|
|
1221
|
+ st_synchronize();
|
|
1222
|
+ // make sure the bed_level_rotation_matrix is identity or the planner will get it incorectly
|
|
1223
|
+ //vector_3 corrected_position = plan_get_position_mm();
|
|
1224
|
+ //corrected_position.debug("position before G29");
|
|
1225
|
+ plan_bed_level_matrix.set_to_identity();
|
|
1226
|
+ vector_3 uncorrected_position = plan_get_position();
|
|
1227
|
+ //uncorrected_position.debug("position durring G29");
|
|
1228
|
+ current_position[X_AXIS] = uncorrected_position.x;
|
|
1229
|
+ current_position[Y_AXIS] = uncorrected_position.y;
|
|
1230
|
+ current_position[Z_AXIS] = uncorrected_position.z;
|
|
1231
|
+ plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
|
|
1232
|
+ setup_for_endstop_move();
|
|
1233
|
+
|
|
1234
|
+ feedrate = homing_feedrate[Z_AXIS];
|
|
1235
|
+
|
|
1236
|
+ // prob 1
|
|
1237
|
+ do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], Z_RAISE_BEFORE_PROBING);
|
|
1238
|
+ do_blocking_move_to(LEFT_PROBE_BED_POSITION - X_PROBE_OFFSET_FROM_EXTRUDER, BACK_PROBE_BED_POSITION - Y_PROBE_OFFSET_FROM_EXTRUDER, current_position[Z_AXIS]);
|
|
1239
|
+
|
|
1240
|
+ engage_z_probe(); // Engage Z Servo endstop if available
|
|
1241
|
+
|
|
1242
|
+ run_z_probe();
|
|
1243
|
+ float z_at_xLeft_yBack = current_position[Z_AXIS];
|
|
1244
|
+
|
|
1245
|
+ SERIAL_PROTOCOLPGM("Bed x: ");
|
|
1246
|
+ SERIAL_PROTOCOL(LEFT_PROBE_BED_POSITION);
|
|
1247
|
+ SERIAL_PROTOCOLPGM(" y: ");
|
|
1248
|
+ SERIAL_PROTOCOL(BACK_PROBE_BED_POSITION);
|
|
1249
|
+ SERIAL_PROTOCOLPGM(" z: ");
|
|
1250
|
+ SERIAL_PROTOCOL(current_position[Z_AXIS]);
|
|
1251
|
+ SERIAL_PROTOCOLPGM("\n");
|
|
1252
|
+
|
|
1253
|
+ // prob 2
|
|
1254
|
+ do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS] + Z_RAISE_BETWEEN_PROBINGS);
|
|
1255
|
+ do_blocking_move_to(LEFT_PROBE_BED_POSITION - X_PROBE_OFFSET_FROM_EXTRUDER, FRONT_PROBE_BED_POSITION - Y_PROBE_OFFSET_FROM_EXTRUDER, current_position[Z_AXIS]);
|
|
1256
|
+ run_z_probe();
|
|
1257
|
+ float z_at_xLeft_yFront = current_position[Z_AXIS];
|
|
1258
|
+
|
|
1259
|
+ SERIAL_PROTOCOLPGM("Bed x: ");
|
|
1260
|
+ SERIAL_PROTOCOL(LEFT_PROBE_BED_POSITION);
|
|
1261
|
+ SERIAL_PROTOCOLPGM(" y: ");
|
|
1262
|
+ SERIAL_PROTOCOL(FRONT_PROBE_BED_POSITION);
|
|
1263
|
+ SERIAL_PROTOCOLPGM(" z: ");
|
|
1264
|
+ SERIAL_PROTOCOL(current_position[Z_AXIS]);
|
|
1265
|
+ SERIAL_PROTOCOLPGM("\n");
|
|
1266
|
+
|
|
1267
|
+ // prob 3
|
|
1268
|
+ do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS] + Z_RAISE_BETWEEN_PROBINGS);
|
|
1269
|
+ // the current position will be updated by the blocking move so the head will not lower on this next call.
|
|
1270
|
+ do_blocking_move_to(RIGHT_PROBE_BED_POSITION - X_PROBE_OFFSET_FROM_EXTRUDER, FRONT_PROBE_BED_POSITION - Y_PROBE_OFFSET_FROM_EXTRUDER, current_position[Z_AXIS]);
|
|
1271
|
+ run_z_probe();
|
|
1272
|
+ float z_at_xRight_yFront = current_position[Z_AXIS];
|
|
1273
|
+
|
|
1274
|
+ SERIAL_PROTOCOLPGM("Bed x: ");
|
|
1275
|
+ SERIAL_PROTOCOL(RIGHT_PROBE_BED_POSITION);
|
|
1276
|
+ SERIAL_PROTOCOLPGM(" y: ");
|
|
1277
|
+ SERIAL_PROTOCOL(FRONT_PROBE_BED_POSITION);
|
|
1278
|
+ SERIAL_PROTOCOLPGM(" z: ");
|
|
1279
|
+ SERIAL_PROTOCOL(current_position[Z_AXIS]);
|
|
1280
|
+ SERIAL_PROTOCOLPGM("\n");
|
|
1281
|
+
|
|
1282
|
+ clean_up_after_endstop_move();
|
|
1283
|
+
|
|
1284
|
+ set_bed_level_equation(z_at_xLeft_yFront, z_at_xRight_yFront, z_at_xLeft_yBack);
|
|
1285
|
+
|
|
1286
|
+ retract_z_probe(); // Retract Z Servo endstop if available
|
|
1287
|
+
|
|
1288
|
+ st_synchronize();
|
|
1289
|
+
|
|
1290
|
+ // The following code correct the Z height difference from z-probe position and hotend tip position.
|
|
1291
|
+ // The Z height on homing is measured by Z-Probe, but the probe is quite far from the hotend.
|
|
1292
|
+ // When the bed is uneven, this height must be corrected.
|
|
1293
|
+ real_z = float(st_get_position(Z_AXIS))/axis_steps_per_unit[Z_AXIS]; //get the real Z (since the auto bed leveling is already correcting the plane)
|
|
1294
|
+ x_tmp = current_position[X_AXIS] + X_PROBE_OFFSET_FROM_EXTRUDER;
|
|
1295
|
+ y_tmp = current_position[Y_AXIS] + Y_PROBE_OFFSET_FROM_EXTRUDER;
|
|
1296
|
+ z_tmp = current_position[Z_AXIS];
|
|
1297
|
+
|
|
1298
|
+ apply_rotation_xyz(plan_bed_level_matrix, x_tmp, y_tmp, z_tmp); //Apply the correction sending the probe offset
|
|
1299
|
+ current_position[Z_AXIS] = z_tmp - real_z + current_position[Z_AXIS]; //The difference is added to current position and sent to planner.
|
|
1300
|
+ plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
|
|
1301
|
+ }
|
|
1302
|
+ break;
|
|
1303
|
+
|
|
1304
|
+ case 30: // G30 Single Z Probe
|
|
1305
|
+ {
|
|
1306
|
+ engage_z_probe(); // Engage Z Servo endstop if available
|
|
1307
|
+
|
|
1308
|
+ st_synchronize();
|
|
1309
|
+ // TODO: make sure the bed_level_rotation_matrix is identity or the planner will get set incorectly
|
|
1310
|
+ setup_for_endstop_move();
|
|
1311
|
+
|
|
1312
|
+ feedrate = homing_feedrate[Z_AXIS];
|
|
1313
|
+
|
|
1314
|
+ run_z_probe();
|
|
1315
|
+ SERIAL_PROTOCOLPGM("Bed Position X: ");
|
|
1316
|
+ SERIAL_PROTOCOL(current_position[X_AXIS]);
|
|
1317
|
+ SERIAL_PROTOCOLPGM(" Y: ");
|
|
1318
|
+ SERIAL_PROTOCOL(current_position[Y_AXIS]);
|
|
1319
|
+ SERIAL_PROTOCOLPGM(" Z: ");
|
|
1320
|
+ SERIAL_PROTOCOL(current_position[Z_AXIS]);
|
|
1321
|
+ SERIAL_PROTOCOLPGM("\n");
|
|
1322
|
+
|
|
1323
|
+ clean_up_after_endstop_move();
|
|
1324
|
+
|
|
1325
|
+ retract_z_probe(); // Retract Z Servo endstop if available
|
|
1326
|
+ }
|
|
1327
|
+ break;
|
|
1328
|
+#endif // ENABLE_AUTO_BED_LEVELING
|
1048
|
1329
|
case 90: // G90
|
1049
|
1330
|
relative_mode = false;
|
1050
|
1331
|
break;
|
|
@@ -1787,7 +2068,14 @@ void process_commands()
|
1787
|
2068
|
if (code_seen('S')) {
|
1788
|
2069
|
servo_position = code_value();
|
1789
|
2070
|
if ((servo_index >= 0) && (servo_index < NUM_SERVOS)) {
|
|
2071
|
+#if defined (ENABLE_AUTO_BED_LEVELING) && (PROBE_SERVO_DEACTIVATION_DELAY > 0)
|
|
2072
|
+ servos[servo_index].attach(0);
|
|
2073
|
+#endif
|
1790
|
2074
|
servos[servo_index].write(servo_position);
|
|
2075
|
+#if defined (ENABLE_AUTO_BED_LEVELING) && (PROBE_SERVO_DEACTIVATION_DELAY > 0)
|
|
2076
|
+ delay(PROBE_SERVO_DEACTIVATION_DELAY);
|
|
2077
|
+ servos[servo_index].detach();
|
|
2078
|
+#endif
|
1791
|
2079
|
}
|
1792
|
2080
|
else {
|
1793
|
2081
|
SERIAL_ECHO_START;
|
|
@@ -1938,6 +2226,19 @@ void process_commands()
|
1938
|
2226
|
st_synchronize();
|
1939
|
2227
|
}
|
1940
|
2228
|
break;
|
|
2229
|
+#if defined(ENABLE_AUTO_BED_LEVELING) && defined(SERVO_ENDSTOPS)
|
|
2230
|
+ case 401:
|
|
2231
|
+ {
|
|
2232
|
+ engage_z_probe(); // Engage Z Servo endstop if available
|
|
2233
|
+ }
|
|
2234
|
+ break;
|
|
2235
|
+
|
|
2236
|
+ case 402:
|
|
2237
|
+ {
|
|
2238
|
+ retract_z_probe(); // Retract Z Servo endstop if enabled
|
|
2239
|
+ }
|
|
2240
|
+ break;
|
|
2241
|
+#endif
|
1941
|
2242
|
case 500: // M500 Store settings in EEPROM
|
1942
|
2243
|
{
|
1943
|
2244
|
Config_StoreSettings();
|