From e9742a1a05425a22c3ceffa0a51ef37d35dbc15b Mon Sep 17 00:00:00 2001 From: Alden Hart Date: Tue, 17 Jan 2017 07:06:32 -0500 Subject: [PATCH] Coolant work. Checkpoint --- g2core/alarm.cpp | 2 +- g2core/canonical_machine.cpp | 2 +- g2core/config_app.cpp | 13 +- g2core/coolant.cpp | 231 ++++++++++++++++----------- g2core/coolant.h | 94 +++++++---- g2core/cycle_feedhold.cpp | 4 +- g2core/gcode_parser.cpp | 10 +- g2core/settings/settings_makeblock.h | 3 +- 8 files changed, 214 insertions(+), 145 deletions(-) mode change 100755 => 100644 g2core/coolant.cpp mode change 100755 => 100644 g2core/coolant.h diff --git a/g2core/alarm.cpp b/g2core/alarm.cpp index 9b580c3b..dbbdfeab 100644 --- a/g2core/alarm.cpp +++ b/g2core/alarm.cpp @@ -124,7 +124,7 @@ void cm_halt_all(void) { cm_halt_motion(); spindle_control_immediate(SPINDLE_OFF); - cm_coolant_off_immediate(); + coolant_control_immediate(COOLANT_OFF, COOLANT_BOTH); } void cm_halt_motion(void) diff --git a/g2core/canonical_machine.cpp b/g2core/canonical_machine.cpp index 0d11172c..53c6a6d6 100644 --- a/g2core/canonical_machine.cpp +++ b/g2core/canonical_machine.cpp @@ -1556,7 +1556,7 @@ static void _exec_program_finalize(float *value, bool *flag) cm_set_distance_mode(cm->default_distance_mode); cm_set_arc_distance_mode(INCREMENTAL_DISTANCE_MODE);// always the default spindle_control_immediate(SPINDLE_OFF); // M5 - cm_coolant_off_immediate(); // M9 + coolant_control_immediate(COOLANT_OFF, COOLANT_BOTH);// M9 cm_set_feed_rate_mode(UNITS_PER_MINUTE_MODE); // G94 cm_set_motion_mode(MODEL, MOTION_MODE_CANCEL_MOTION_MODE);// NIST specifies G1 (MOTION_MODE_STRAIGHT_FEED), but we cancel motion mode. Safer. cm_reset_overrides(); // reset feedrate the spindle overrides diff --git a/g2core/config_app.cpp b/g2core/config_app.cpp index 489cfe2b..f09d7654 100644 --- a/g2core/config_app.cpp +++ b/g2core/config_app.cpp @@ -850,11 +850,11 @@ const cfgItem_t cfgArray[] = { { "sp","sps", _f0, 0, sp_print_sps, sp_get_sps, sp_set_sps, (float *)&cs.null, 0 }, // spindle speed // Coolant functions - { "sys","cofp",_fipn,0, cm_print_cofp,get_ui8, set_01, (float *)&coolant.flood_polarity, COOLANT_FLOOD_POLARITY }, - { "sys","comp",_fipn,0, cm_print_comp,get_ui8, set_01, (float *)&coolant.mist_polarity, COOLANT_MIST_POLARITY }, - { "sys","coph",_fipn,0, cm_print_coph,get_ui8, set_01, (float *)&coolant.pause_on_hold, COOLANT_PAUSE_ON_HOLD }, - { "", "com", _fiz, 0, cm_print_com, get_ui8, set_nul, (float *)&coolant.mist_enable, 0 }, // get mist coolant enable - { "", "cof", _fiz, 0, cm_print_cof, get_ui8, set_nul, (float *)&coolant.flood_enable, 0 }, // get flood coolant enable + { "co","coph", _fip, 0, co_print_coph, co_get_coph, co_set_coph, (float *)&cs.null, COOLANT_PAUSE_ON_HOLD }, + { "co","comp", _fip, 0, co_print_comp, co_get_comp, co_set_comp, (float *)&cs.null, COOLANT_MIST_POLARITY }, + { "co","cofp", _fip, 0, co_print_cofp, co_get_cofp, co_set_cofp, (float *)&cs.null, COOLANT_FLOOD_POLARITY }, + { "co","com", _f0, 0, co_print_com, co_get_com, co_set_com, (float *)&cs.null, 0 }, // mist coolant enable + { "co","cof", _f0, 0, co_print_cof, co_get_com, co_set_com, (float *)&cs.null, 0 }, // flood coolant enable // General system parameters { "sys","jt", _fipn, 2, cm_print_jt, cm_get_jt, cm_set_jt, (float *)&cs.null, JUNCTION_INTEGRATION_TIME }, @@ -1062,10 +1062,11 @@ const cfgItem_t cfgArray[] = { // - Optional DIAGNOSTIC_PARAMETERS // - Uber groups (count these separately) -#define FIXED_GROUPS 3 +#define FIXED_GROUPS 4 { "","sys",_f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // system group { "","p1", _f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // PWM 1 group { "","sp", _f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // Spindle group + { "","co", _f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // Coolant group #define AXIS_GROUPS AXES { "","x", _f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // axis groups diff --git a/g2core/coolant.cpp b/g2core/coolant.cpp old mode 100755 new mode 100644 index f19cea95..31dee229 --- a/g2core/coolant.cpp +++ b/g2core/coolant.cpp @@ -2,7 +2,7 @@ * coolant.cpp - canonical machine coolant driver * This file is part of the g2core project * - * Copyright (c) 2015 - 2016 Alden S. Hart, Jr. + * Copyright (c) 2015 - 2017 Alden S. Hart, Jr. * * This file ("the software") is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2 as published by the @@ -37,121 +37,160 @@ /**** Allocate structures ****/ -cmCoolantSingleton_t coolant; +coCoolant_t coolant; /**** Static functions ****/ -static void _exec_coolant_control(float* value, bool* flags); +static void _exec_coolant_control(float* value, bool* flag); /* * coolant_init() * coolant_reset() */ void coolant_init() { - coolant.mist_enable = COOLANT_OFF; - coolant.flood_enable = COOLANT_OFF; + coolant.mist_state = COOLANT_OFF; + coolant.flood_state = COOLANT_OFF; } void coolant_reset() { coolant_init(); - cm_coolant_off_immediate(); + coolant_control_immediate(COOLANT_OFF, COOLANT_BOTH); } /* - * cm_coolant_off_immediate() - turn off all coolant - * cm_coolant_optional_pause() - pause coolants if option is true - * cm_coolant_resume() - restart paused coolants + * coolant_control_immediate() - execute coolant control immediately + * coolant_control_sync() - queue a coolant control to the planner buffer + * _exec_coolant_control() - actually execute the coolant command */ -void cm_coolant_off_immediate() { - float value[] = {0, 0, 0, 0, 0, 0}; - bool flags[] = {1, 1, 0, 0, 0, 0}; +stat_t coolant_control_immediate(coControl control, coSelect select) +{ + float value[] = { (float)control }; + bool flags[] = { (select & COOLANT_MIST), (select & COOLANT_FLOOD) }; _exec_coolant_control(value, flags); -} + return(STAT_OK); +} -void cm_coolant_optional_pause(bool option) { - if (option) { - float value[] = {0, 0, 0, 0, 0, 0}; - bool flags[] = {0, 0, 0, 0, 0, 0}; - - if (coolant.flood_enable == COOLANT_ON) { - coolant.flood_enable = COOLANT_PAUSE; // mark as paused - flags[COOLANT_FLOOD] = 1; // set flag so it will turn off - } - if (coolant.mist_enable == COOLANT_ON) { - coolant.mist_enable = COOLANT_PAUSE; // mark as paused - flags[COOLANT_MIST] = 1; - } - _exec_coolant_control(value, flags); // execute (w/o changing local state) +stat_t coolant_control_sync(coControl control, coSelect select) +{ + // skip the PAUSE operation if pause-enable is not enabled (pause-on-hold) + if ((control == COOLANT_PAUSE) && (!coolant.pause_enable)) { + return (STAT_OK); } -} - -void cm_coolant_resume() { -// float value[] = { 1,1,0,0,0,0 }; // ++++ Will this work? No need to set 'value' below - float value[] = {0, 0, 0, 0, 0, 0}; - bool flags[] = {0, 0, 0, 0, 0, 0}; - - if (coolant.flood_enable == COOLANT_PAUSE) { - coolant.flood_enable = COOLANT_ON; - value[COOLANT_FLOOD] = 1; - flags[COOLANT_FLOOD] = true; - } - if (coolant.mist_enable == COOLANT_PAUSE) { - coolant.mist_enable = COOLANT_ON; - value[COOLANT_MIST] = 1; - flags[COOLANT_MIST] = true; - } - _exec_coolant_control(value, flags); -} - -/* - * cm_mist_coolant_control() - access points from Gcode parser - * cm_flood_coolant_control() - access points from Gcode parser - * _exec_coolant_control() - combined flood and mist coolant control - * - * - value[0] is flood state - * - value[1] is mist state - * - uses flags to determine which to run - */ - -stat_t cm_flood_coolant_control(uint8_t flood_enable) { - float value[] = {(float)flood_enable, 0, 0, 0, 0, 0}; - bool flags[] = {1, 0, 0, 0, 0, 0}; + + // queue the coolant control + float value[] = { (float)control }; + bool flags[] = { (select & COOLANT_MIST), (select & COOLANT_FLOOD) }; mp_queue_command(_exec_coolant_control, value, flags); - return (STAT_OK); + return(STAT_OK); } -stat_t cm_mist_coolant_control(uint8_t mist_enable) { - float value[] = {0, (float)mist_enable, 0, 0, 0, 0}; - bool flags[] = {0, 1, 0, 0, 0, 0}; - mp_queue_command(_exec_coolant_control, value, flags); - return (STAT_OK); -} - -// NOTE: flood and mist coolants are mapped to the same pin - see hardware.h -#define _set_flood_enable_bit_hi() flood_enable_pin.set() -#define _set_flood_enable_bit_lo() flood_enable_pin.clear() -#define _set_mist_enable_bit_hi() mist_enable_pin.set() -#define _set_mist_enable_bit_lo() mist_enable_pin.clear() - -static void _exec_coolant_control(float* value, bool* flags) { - if (flags[COOLANT_FLOOD]) { - coolant.flood_enable = (cmCoolantEnable)value[COOLANT_FLOOD]; - if (!((coolant.flood_enable & 0x01) ^ coolant.flood_polarity)) { // inverted XOR - _set_flood_enable_bit_hi(); - } else { - _set_flood_enable_bit_lo(); +static void _exec_coolant_control(float* value, bool* flag) { + + coControl control = (coControl)value[0]; + if (control > COOLANT_ACTION_MAX) { + return; + } + + bool action; // set true to perform the action + int8_t enable_bit; +// coControl previous_state = control.mist_state; + + if (flag[0]) { // Mist, M7 + action = true; + enable_bit = 0; + switch (control) { + case COOLANT_OFF: { + coolant.mist_state = COOLANT_OFF; + break; + } + case COOLANT_ON: { + coolant.mist_state = COOLANT_ON; + enable_bit = 1; + break; + } + case COOLANT_PAUSE: { + if (coolant.mist_state == COOLANT_ON) { + coolant.mist_state = COOLANT_PAUSE; + } else { + action = false; + } + break; + } + case COOLANT_RESUME: { + if (coolant.mist_state == COOLANT_PAUSE) { + coolant.mist_state = COOLANT_ON; + enable_bit = 1; + } else { + action = false; + } + break; + } + } + if (action) { + if (!(enable_bit ^ coolant.mist_polarity)) { // inverted XOR + mist_enable_pin.set(); + } else { + mist_enable_pin.clear(); + } } } - if (flags[COOLANT_MIST]) { - coolant.mist_enable = (cmCoolantEnable)value[COOLANT_MIST]; - if (!((coolant.mist_enable & 0x01) ^ coolant.mist_polarity)) { - _set_mist_enable_bit_hi(); - } else { - _set_mist_enable_bit_lo(); + if (flag[1]) { // Flood, M8 + action = true; + enable_bit = 0; + switch (control) { + case COOLANT_OFF: { + coolant.flood_state = COOLANT_OFF; + break; + } + case COOLANT_ON: { + coolant.flood_state = COOLANT_ON; + enable_bit = 1; + break; + } + case COOLANT_PAUSE: { + if (coolant.flood_state == COOLANT_ON) { + coolant.flood_state = COOLANT_PAUSE; + } else { + action = false; + } + break; + } + case COOLANT_RESUME: { + if (coolant.flood_state == COOLANT_PAUSE) { + coolant.flood_state = COOLANT_ON; + enable_bit = 1; + } else { + action = false; + } + break; + } } - } -} + if (action) { + if (!(enable_bit ^ coolant.flood_polarity)) { // inverted XOR + flood_enable_pin.set(); + } else { + flood_enable_pin.clear(); + } + } + } +} + +/*********************************************************************************** + **** Coolant Settings ************************************************************* + ***********************************************************************************/ + +stat_t co_get_coph(nvObj_t *nv) { return(get_int(nv, coolant.pause_enable)); } +stat_t co_set_coph(nvObj_t *nv) { return(set_int(nv, (uint8_t &)coolant.pause_enable, 0, 1)); } +stat_t co_get_comp(nvObj_t *nv) { return(get_int(nv, coolant.mist_polarity)); } +stat_t co_set_comp(nvObj_t *nv) { return(set_int(nv, (uint8_t &)coolant.mist_polarity, 0, 1)); } +stat_t co_get_cofp(nvObj_t *nv) { return(get_int(nv, coolant.flood_polarity)); } +stat_t co_set_cofp(nvObj_t *nv) { return(set_int(nv, (uint8_t &)coolant.flood_polarity, 0, 1)); } + +stat_t co_get_com(nvObj_t *nv) { return(get_int(nv, coolant.flood_state)); } +stat_t co_set_com(nvObj_t *nv) { return(coolant_control_immediate((coControl)nv->value, COOLANT_MIST)); } +stat_t co_get_cof(nvObj_t *nv) { return(get_float(nv, coolant.mist_state)); } +stat_t co_set_cof(nvObj_t *nv) { return(coolant_control_immediate((coControl)nv->value, COOLANT_FLOOD)); } /*********************************************************************************** * TEXT MODE SUPPORT @@ -163,13 +202,13 @@ static void _exec_coolant_control(float* value, bool* flags) { const char fmt_coph[] = "[coph] coolant pause on hold%7d [0=no,1=pause_on_hold]\n"; const char fmt_comp[] = "[comp] coolant mist polarity%7d [0=low is ON,1=high is ON]\n"; const char fmt_cofp[] = "[cofp] coolant flood polarity%6d [0=low is ON,1=high is ON]\n"; -const char fmt_com[] = "Mist coolant:%6d [0=OFF,1=ON]\n"; -const char fmt_cof[] = "Flood coolant:%5d [0=OFF,1=ON]\n"; +const char fmt_com[] = "[com] coolant mist%16d [0=OFF,1=ON]\n"; +const char fmt_cof[] = "[cof] coolant flood%15d [0=OFF,1=ON]\n"; -void cm_print_coph(nvObj_t* nv) { text_print(nv, fmt_coph); } // TYPE_INT -void cm_print_comp(nvObj_t* nv) { text_print(nv, fmt_comp); } // TYPE_INT -void cm_print_cofp(nvObj_t* nv) { text_print(nv, fmt_cofp); } // TYPE_INT -void cm_print_com(nvObj_t* nv) { text_print(nv, fmt_com); } // TYPE_INT -void cm_print_cof(nvObj_t* nv) { text_print(nv, fmt_cof); } // TYPE_INT +void co_print_coph(nvObj_t* nv) { text_print(nv, fmt_coph); } // TYPE_INT +void co_print_comp(nvObj_t* nv) { text_print(nv, fmt_comp); } // TYPE_INT +void co_print_cofp(nvObj_t* nv) { text_print(nv, fmt_cofp); } // TYPE_INT +void co_print_com(nvObj_t* nv) { text_print(nv, fmt_com); } // TYPE_INT +void co_print_cof(nvObj_t* nv) { text_print(nv, fmt_cof); } // TYPE_INT #endif // __TEXT_MODE diff --git a/g2core/coolant.h b/g2core/coolant.h old mode 100755 new mode 100644 index b30df2a4..d961fea8 --- a/g2core/coolant.h +++ b/g2core/coolant.h @@ -2,7 +2,7 @@ * coolant.h - coolant driver * This file is part of the g2core project * - * Copyright (c) 2015 - 2016 Alden S. Hart, Jr. + * Copyright (c) 2015 - 2017 Alden S. Hart, Jr. * * This file ("the software") is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2 as published by the @@ -31,31 +31,49 @@ typedef enum { COOLANT_OFF = 0, // don't change the order. It gets masked. COOLANT_ON, - COOLANT_PAUSE -} cmCoolantEnable; + COOLANT_PAUSE, + COOLANT_RESUME +} coControl; +#define COOLANT_ACTION_MAX COOLANT_RESUME -typedef enum { COOLANT_ACTIVE_LOW = 0, COOLANT_ACTIVE_HIGH } cmCoolantPolarity; +// *** NOTE: The coolant polarity active hi/low values currently agree with ioMode in gpio.h +// These will all need to be changed to ACTIVE_HIGH = 0, ACTIVE_LOW = 1 +// See: https://github.com/synthetos/g2_private/wiki/GPIO-Design-Discussion#settings-common-to-all-io-types -typedef enum { // used to index the value and flag vectors for coolant execs - COOLANT_FLOOD = 0, - COOLANT_MIST -} cmCoolantIndex; +typedef enum { + COOLANT_ACTIVE_LOW = 0, + COOLANT_ACTIVE_HIGH +} coPolarity; + +typedef enum { // used as a bitmask + COOLANT_NONE = 0, // none selected + COOLANT_MIST = 1, // mist coolant + COOLANT_FLOOD = 2, // flood coolant + COOLANT_BOTH = 3 // both types ('or' of both coolants) +} coSelect; /* - * Coolant control structure + * Coolant control structures */ -typedef struct cmCoolantSingleton { - bool pause_on_hold; // true to pause coolant on feedhold +typedef struct coCoolantChannel { + bool pause_enable; // {coph:} pause on feedhold + coControl state; // coolant state: coControl + coPolarity polarity; // 0=active low, 1=active high +} coCoolantChannel_t; - cmCoolantEnable flood_enable; // COOLANT_ON = flood on (M8), COOLANT_OFF = off (M9) - cmCoolantPolarity flood_polarity; // 0=active low, 1=active high +typedef struct coCoolant { - cmCoolantEnable mist_enable; // COOLANT_ON = mist on (M7), COOLANT_OFF = off (M9) - cmCoolantPolarity mist_polarity; // 0=active low, 1=active high - -} cmCoolantSingleton_t; -extern cmCoolantSingleton_t coolant; +// coCoolantChannel_t mist; +// coCoolantChannel_t flood; + + bool pause_enable; // {coph:} pause on feedhold + coControl mist_state; // M7 coolant + coPolarity mist_polarity; // 0=active low, 1=active high + coControl flood_state; // M8 coolant + coPolarity flood_polarity; // 0=active low, 1=active high +} coCoolant_t; +extern coCoolant_t coolant; /* * Global Scope Functions @@ -64,29 +82,39 @@ extern cmCoolantSingleton_t coolant; void coolant_init(); void coolant_reset(); -stat_t cm_mist_coolant_control(uint8_t mist_enable); // M7 -stat_t cm_flood_coolant_control(uint8_t flood_enable); // M8, M9 -void cm_coolant_off_immediate(void); -void cm_coolant_optional_pause(bool option); -void cm_coolant_resume(void); +stat_t coolant_control_immediate(coControl control, coSelect select); +stat_t coolant_control_sync(coControl control, coSelect select); + +stat_t co_get_coph(nvObj_t *nv); +stat_t co_set_coph(nvObj_t *nv); + +stat_t co_get_comp(nvObj_t *nv); +stat_t co_set_comp(nvObj_t *nv); +stat_t co_get_cofp(nvObj_t *nv); +stat_t co_set_cofp(nvObj_t *nv); + +stat_t co_get_com(nvObj_t *nv); +stat_t co_set_com(nvObj_t *nv); +stat_t co_get_cof(nvObj_t *nv); +stat_t co_set_cof(nvObj_t *nv); /*--- text_mode support functions ---*/ #ifdef __TEXT_MODE -void cm_print_coph(nvObj_t* nv); // coolant pause on hold -void cm_print_comp(nvObj_t* nv); // coolant polarity mist -void cm_print_cofp(nvObj_t* nv); // coolant polarity flood -void cm_print_com(nvObj_t* nv); // report mist coolant state -void cm_print_cof(nvObj_t* nv); // report flood coolant state +void co_print_coph(nvObj_t* nv); // coolant pause on hold +void co_print_comp(nvObj_t* nv); // coolant polarity mist +void co_print_cofp(nvObj_t* nv); // coolant polarity flood +void co_print_com(nvObj_t* nv); // report mist coolant state +void co_print_cof(nvObj_t* nv); // report flood coolant state #else -#define cm_print_coph tx_print_stub -#define cm_print_comp tx_print_stub -#define cm_print_cofp tx_print_stub -#define cm_print_com tx_print_stub -#define cm_print_cof tx_print_stub +#define co_print_coph tx_print_stub +#define co_print_comp tx_print_stub +#define co_print_cofp tx_print_stub +#define co_print_com tx_print_stub +#define co_print_cof tx_print_stub #endif // __TEXT_MODE diff --git a/g2core/cycle_feedhold.cpp b/g2core/cycle_feedhold.cpp index 9709249c..54a44887 100644 --- a/g2core/cycle_feedhold.cpp +++ b/g2core/cycle_feedhold.cpp @@ -251,7 +251,7 @@ stat_t cm_switch_to_hold_context() } spindle_control_sync(SPINDLE_PAUSE); // optional spindle pause - // coolant_control_sync(COOLANT_PAUSE); // optional coolant pause + coolant_control_sync(COOLANT_PAUSE, COOLANT_BOTH); // optional coolant pause return (STAT_OK); } @@ -281,7 +281,7 @@ stat_t cm_return_from_hold_context() // LATER: if value == true return with // *** While still in secondary machine: spindle_control_sync(SPINDLE_RESUME); // resume spindle if paused -// coolant_control_sync(COOLANT_RESUME); // resume coolant if paused + coolant_control_sync(COOLANT_RESUME, COOLANT_BOTH); // resume coolant if paused // perform the G30 move and queue a wait float target[] = { 0,0,0,0,0,0 }; // LATER: Make this move return through XY, then Z diff --git a/g2core/gcode_parser.cpp b/g2core/gcode_parser.cpp index e28a17cb..f75288b1 100644 --- a/g2core/gcode_parser.cpp +++ b/g2core/gcode_parser.cpp @@ -754,10 +754,12 @@ static stat_t _execute_gcode_block(char *active_comment) if (gf.spindle_control) { // spindle OFF, CW, CCW ritorno(spindle_control_sync((spControl)gv.spindle_control)); } - - EXEC_FUNC(cm_mist_coolant_control, mist_coolant); // M7, M9 - EXEC_FUNC(cm_flood_coolant_control, flood_coolant); // M8, M9 also disables mist coolant if OFF - + if (gf.mist_coolant) { + ritorno(coolant_control_sync((coControl)gv.mist_coolant, COOLANT_MIST)); // M7, M9 + } + if (gf.flood_coolant) { + ritorno(coolant_control_sync((coControl)gv.flood_coolant, COOLANT_FLOOD)); // M8, M9 also disables mist coolant if OFF + } if (gv.next_action == NEXT_ACTION_DWELL) { // G4 - dwell ritorno(cm_dwell(gv.P_word)); // return if error, otherwise complete the block } diff --git a/g2core/settings/settings_makeblock.h b/g2core/settings/settings_makeblock.h index db63fd58..68a44ae0 100644 --- a/g2core/settings/settings_makeblock.h +++ b/g2core/settings/settings_makeblock.h @@ -45,13 +45,12 @@ #define SPINDLE_DIR_POLARITY 0 // 0=clockwise is low, 1=clockwise is high #define SPINDLE_PAUSE_ON_HOLD true #define SPINDLE_SPINUP_DELAY 2.0 -#define SPINDLE_SPINDOWN_DELAY 0.0 #define SPINDLE_SPEED_MIN 0.0 #define SPINDLE_SPEED_MAX 20000.0 #define COOLANT_MIST_POLARITY 1 // 0=active low, 1=active high #define COOLANT_FLOOD_POLARITY 1 // 0=active low, 1=active high -#define COOLANT_PAUSE_ON_HOLD false +#define COOLANT_PAUSE_ON_HOLD true #define FEEDHOLD_Z_LIFT 10 // mm to lift Z on feedhold