Обновление 2.0.6.1

This commit is contained in:
Sergey
2020-08-31 17:02:51 +03:00
parent 241305cd8b
commit adee4a7475
439 changed files with 19973 additions and 6430 deletions

View File

@@ -405,7 +405,7 @@ inline bool turn_on_heaters() {
inline bool prime_nozzle() {
const feedRate_t fr_slow_e = planner.settings.max_feedrate_mm_s[E_AXIS] / 15.0f;
#if HAS_LCD_MENU && DISABLED(TOUCH_BUTTONS) // ui.button_pressed issue with touchscreen
#if HAS_LCD_MENU && !HAS_TOUCH_XPT2046 // ui.button_pressed issue with touchscreen
#if ENABLED(PREVENT_LENGTHY_EXTRUDE)
float Total_Prime = 0.0;
#endif
@@ -490,7 +490,7 @@ void GcodeSuite::G26() {
// Don't allow Mesh Validation without homing first,
// or if the parameter parsing did not go OK, abort
if (axis_unhomed_error()) return;
if (homing_needed_error()) return;
// Change the tool first, if specified
if (parser.seenval('T')) tool_change(parser.value_int());

View File

@@ -176,7 +176,7 @@ void GcodeSuite::G35() {
probe.stow();
// After this operation the Z position needs correction
set_axis_not_trusted(Z_AXIS);
set_axis_never_homed(Z_AXIS);
// Home Z after the alignment procedure
process_subcommands_now_P(PSTR("G28Z"));

View File

@@ -30,7 +30,7 @@
#include "../../module/probe.h"
#if ENABLED(EEPROM_SETTINGS)
#include "../../module/configuration_store.h"
#include "../../module/settings.h"
#endif
#if ENABLED(EXTENSIBLE_UI)

View File

@@ -183,7 +183,7 @@ G29_TYPE GcodeSuite::G29() {
faux = ENABLED(DEBUG_LEVELING_FEATURE) && DISABLED(PROBE_MANUALLY) ? parser.boolval('C') : no_action;
// Don't allow auto-leveling without homing first
if (axis_unhomed_error()) G29_RETURN(false);
if (homing_needed_error()) G29_RETURN(false);
if (!no_action && planner.leveling_active && parser.boolval('O')) { // Auto-level only if needed
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("> Auto-level not needed, skip");

View File

@@ -118,7 +118,7 @@
DEBUG_SECTION(log_G28, "home_z_safely", DEBUGGING(LEVELING));
// Disallow Z homing if X or Y homing is needed
if (axis_unhomed_error(_BV(X_AXIS) | _BV(Y_AXIS))) return;
if (homing_needed_error(_BV(X_AXIS) | _BV(Y_AXIS))) return;
sync_plan_position();
@@ -299,8 +299,8 @@ void GcodeSuite::G28() {
#else // NOT DELTA
const bool homeZ = parser.seen('Z'),
needX = homeZ && TERN0(Z_SAFE_HOMING, axes_need_homing(_BV(X_AXIS))),
needY = homeZ && TERN0(Z_SAFE_HOMING, axes_need_homing(_BV(Y_AXIS))),
needX = homeZ && TERN0(Z_SAFE_HOMING, axes_should_home(_BV(X_AXIS))),
needY = homeZ && TERN0(Z_SAFE_HOMING, axes_should_home(_BV(Y_AXIS))),
homeX = needX || parser.seen('X'), homeY = needY || parser.seen('Y'),
home_all = homeX == homeY && homeX == homeZ, // All or None
doX = home_all || homeX, doY = home_all || homeY, doZ = home_all || homeZ;

View File

@@ -346,7 +346,7 @@ void GcodeSuite::G34() {
#if ENABLED(HOME_AFTER_G34)
// After this operation the z position needs correction
set_axis_not_trusted(Z_AXIS);
set_axis_never_homed(Z_AXIS);
// Home Z after the alignment procedure
process_subcommands_now_P(PSTR("G28Z"));
#else

View File

@@ -584,7 +584,7 @@ void GcodeSuite::G425() {
TEMPORARY_SOFT_ENDSTOP_STATE(false);
TEMPORARY_BED_LEVELING_STATE(false);
if (axis_unhomed_error()) return;
if (homing_needed_error()) return;
measurements_t m;

View File

@@ -45,7 +45,7 @@
* - When calibrating bed, probe temperature is held constant.
* Compensation values are deltas to first probe measurement at bed temp. = 60°C.
* - The hotend will not be heated at any time.
* - On my Prusa MK3S clone I put a piece of paper between the probe and the hotend
* - On my Průša MK3S clone I put a piece of paper between the probe and the hotend
* so the hotend fan would not cool my probe constantly. Alternativly you could just
* make sure the fan is not running while running the calibration process.
*

View File

@@ -26,7 +26,7 @@
#include "../gcode.h"
#include "../queue.h"
#include "../../libs/hex_print_routines.h"
#include "../../libs/hex_print.h"
#include "../../MarlinCore.h" // for idle()
@@ -156,8 +156,8 @@ inline int32_t count_test_bytes(const char * const start_free_memory) {
// Start and end the dump on a nice 16 byte boundary
// (even though the values are not 16-byte aligned).
//
start_free_memory = (char*)(ptr_int_t(uint32_t(start_free_memory) & ~0xFUL)); // Align to 16-byte boundary
end_free_memory = (char*)(ptr_int_t(uint32_t(end_free_memory) | 0xFUL)); // Align end_free_memory to the 15th byte (at or above end_free_memory)
start_free_memory = (char*)(uintptr_t(uint32_t(start_free_memory) & ~0xFUL)); // Align to 16-byte boundary
end_free_memory = (char*)(uintptr_t(uint32_t(end_free_memory) | 0xFUL)); // Align end_free_memory to the 15th byte (at or above end_free_memory)
// Dump command main loop
while (start_free_memory < end_free_memory) {
@@ -189,8 +189,8 @@ inline int32_t count_test_bytes(const char * const start_free_memory) {
// Round the start and end locations to produce full lines of output
//
dump_free_memory(
(char*)(ptr_int_t(uint32_t(start) & ~0xFUL)), // Align to 16-byte boundary
(char*)(ptr_int_t(uint32_t(end) | 0xFUL)) // Align end_free_memory to the 15th byte (at or above end_free_memory)
(char*)(uintptr_t(uint32_t(start) & ~0xFUL)), // Align to 16-byte boundary
(char*)(uintptr_t(uint32_t(end) | 0xFUL)) // Align end_free_memory to the 15th byte (at or above end_free_memory)
);
}

View File

@@ -27,13 +27,10 @@
#include "../gcode.h"
#include "../../module/motion.h"
#include "../../module/probe.h"
#include "../../lcd/ultralcd.h"
#include "../../feature/bedlevel/bedlevel.h"
#if HAS_SPI_LCD
#include "../../lcd/ultralcd.h"
#endif
#if HAS_LEVELING
#include "../../module/planner.h"
#endif
@@ -58,7 +55,7 @@ extern const char SP_Y_STR[];
void GcodeSuite::M48() {
if (axis_unhomed_error()) return;
if (homing_needed_error()) return;
const int8_t verbose_level = parser.byteval('V', 1);
if (!WITHIN(verbose_level, 0, 4)) {
@@ -77,61 +74,85 @@ void GcodeSuite::M48() {
const ProbePtRaise raise_after = parser.boolval('E') ? PROBE_PT_STOW : PROBE_PT_RAISE;
xy_float_t next_pos = current_position;
const xy_pos_t probe_pos = {
parser.linearval('X', next_pos.x + probe.offset_xy.x), // If no X use the probe's current X position
parser.linearval('Y', next_pos.y + probe.offset_xy.y) // If no Y, ditto
// Test at the current position by default, overridden by X and Y
const xy_pos_t test_position = {
parser.linearval('X', current_position.x + probe.offset_xy.x), // If no X use the probe's current X position
parser.linearval('Y', current_position.y + probe.offset_xy.y) // If no Y, ditto
};
if (!probe.can_reach(probe_pos)) {
if (!probe.can_reach(test_position)) {
ui.set_status_P(GET_TEXT(MSG_M48_OUT_OF_BOUNDS), 99);
SERIAL_ECHOLNPGM("? (X,Y) out of bounds.");
return;
}
// Get the number of leg moves per test-point
bool seen_L = parser.seen('L');
uint8_t n_legs = seen_L ? parser.value_byte() : 0;
if (n_legs > 15) {
SERIAL_ECHOLNPGM("?Number of legs in movement not plausible (0-15).");
SERIAL_ECHOLNPGM("?Legs of movement implausible (0-15).");
return;
}
if (n_legs == 1) n_legs = 2;
// Schizoid motion as an optional stress-test
const bool schizoid_flag = parser.boolval('S');
if (schizoid_flag && !seen_L) n_legs = 7;
/**
* Now get everything to the specified probe point So we can safely do a
* probe to get us close to the bed. If the Z-Axis is far from the bed,
* we don't want to use that as a starting point for each probe.
*/
if (verbose_level > 2)
SERIAL_ECHOLNPGM("Positioning the probe...");
// Disable bed level correction in M48 because we want the raw data when we probe
// Always disable Bed Level correction before probing...
#if HAS_LEVELING
const bool was_enabled = planner.leveling_active;
set_bed_leveling_enabled(false);
#endif
// Work with reasonable feedrates
remember_feedrate_scaling_off();
float mean = 0.0, sigma = 0.0, min = 99999.9, max = -99999.9, sample_set[n_samples];
// Working variables
float mean = 0.0, // The average of all points so far, used to calculate deviation
sigma = 0.0, // Standard deviation of all points so far
min = 99999.9, // Smallest value sampled so far
max = -99999.9, // Largest value sampled so far
sample_set[n_samples]; // Storage for sampled values
auto dev_report = [](const bool verbose, const float &mean, const float &sigma, const float &min, const float &max, const bool final=false) {
if (verbose) {
SERIAL_ECHOPAIR_F("Mean: ", mean, 6);
if (!final) SERIAL_ECHOPAIR_F(" Sigma: ", sigma, 6);
SERIAL_ECHOPAIR_F(" Min: ", min, 3);
SERIAL_ECHOPAIR_F(" Max: ", max, 3);
SERIAL_ECHOPAIR_F(" Range: ", max-min, 3);
if (final) SERIAL_EOL();
}
if (final) {
SERIAL_ECHOLNPAIR_F("Standard Deviation: ", sigma, 6);
SERIAL_EOL();
}
};
// Move to the first point, deploy, and probe
const float t = probe.probe_at_point(probe_pos, raise_after, verbose_level);
const float t = probe.probe_at_point(test_position, raise_after, verbose_level);
bool probing_good = !isnan(t);
if (probing_good) {
randomSeed(millis());
float sample_sum = 0.0;
LOOP_L_N(n, n_samples) {
#if HAS_SPI_LCD
// Display M48 progress in the status bar
ui.status_printf_P(0, PSTR(S_FMT ": %d/%d"), GET_TEXT(MSG_M48_POINT), int(n + 1), int(n_samples));
#endif
// When there are "legs" of movement move around the point before probing
if (n_legs) {
// Pick a random direction, starting angle, and radius
const int dir = (random(0, 10) > 5.0) ? -1 : 1; // clockwise or counter clockwise
float angle = random(0, 360);
const float radius = random(
@@ -142,48 +163,51 @@ void GcodeSuite::M48() {
int(5), int(0.125 * _MIN(X_BED_SIZE, Y_BED_SIZE))
#endif
);
if (verbose_level > 3) {
SERIAL_ECHOPAIR("Start radius:", radius, " angle:", angle, " dir:");
if (dir > 0) SERIAL_CHAR('C');
SERIAL_ECHOLNPGM("CW");
}
// Move from leg to leg in rapid succession
LOOP_L_N(l, n_legs - 1) {
float delta_angle;
// Move some distance around the perimeter
float delta_angle;
if (schizoid_flag) {
// The points of a 5 point star are 72 degrees apart. We need to
// skip a point and go to the next one on the star.
// The points of a 5 point star are 72 degrees apart.
// Skip a point and go to the next one on the star.
delta_angle = dir * 2.0 * 72.0;
}
else {
// If we do this line, we are just trying to move further
// around the circle.
delta_angle = dir * (float) random(25, 45);
// Just move further along the perimeter.
delta_angle = dir * (float)random(25, 45);
}
angle += delta_angle;
while (angle > 360.0) angle -= 360.0; // We probably do not need to keep the angle between 0 and 2*PI, but the
// Arduino documentation says the trig functions should not be given values
while (angle < 0.0) angle += 360.0; // outside of this range. It looks like they behave correctly with
// numbers outside of the range, but just to be safe we clamp them.
const xy_pos_t noz_pos = probe_pos - probe.offset_xy;
next_pos.set(noz_pos.x + cos(RADIANS(angle)) * radius,
noz_pos.y + sin(RADIANS(angle)) * radius);
// Trig functions work without clamping, but just to be safe...
while (angle > 360.0) angle -= 360.0;
while (angle < 0.0) angle += 360.0;
#if DISABLED(DELTA)
LIMIT(next_pos.x, X_MIN_POS, X_MAX_POS);
LIMIT(next_pos.y, Y_MIN_POS, Y_MAX_POS);
#else
// If we have gone out too far, we can do a simple fix and scale the numbers
// back in closer to the origin.
// Choose the next position as an offset to chosen test position
const xy_pos_t noz_pos = test_position - probe.offset_xy;
xy_pos_t next_pos = {
noz_pos.x + cos(RADIANS(angle)) * radius,
noz_pos.y + sin(RADIANS(angle)) * radius
};
#if ENABLED(DELTA)
// If the probe can't reach the point on a round bed...
// Simply scale the numbers to bring them closer to origin.
while (!probe.can_reach(next_pos)) {
next_pos *= 0.8f;
if (verbose_level > 3)
SERIAL_ECHOLNPAIR_P(PSTR("Moving inward: X"), next_pos.x, SP_Y_STR, next_pos.y);
}
#else
// For a rectangular bed just keep the probe in bounds
LIMIT(next_pos.x, X_MIN_POS, X_MAX_POS);
LIMIT(next_pos.y, Y_MIN_POS, Y_MAX_POS);
#endif
if (verbose_level > 3)
@@ -194,45 +218,35 @@ void GcodeSuite::M48() {
} // n_legs
// Probe a single point
sample_set[n] = probe.probe_at_point(probe_pos, raise_after, 0);
const float pz = probe.probe_at_point(test_position, raise_after, 0);
// Break the loop if the probe fails
probing_good = !isnan(sample_set[n]);
probing_good = !isnan(pz);
if (!probing_good) break;
/**
* Get the current mean for the data points we have so far
*/
float sum = 0.0;
LOOP_LE_N(j, n) sum += sample_set[j];
mean = sum / (n + 1);
// Store the new sample
sample_set[n] = pz;
NOMORE(min, sample_set[n]);
NOLESS(max, sample_set[n]);
// Keep track of the largest and smallest samples
NOMORE(min, pz);
NOLESS(max, pz);
/**
* Now, use that mean to calculate the standard deviation for the
* data points we have so far
*/
sum = 0.0;
LOOP_LE_N(j, n)
sum += sq(sample_set[j] - mean);
// Get the mean value of all samples thus far
sample_sum += pz;
mean = sample_sum / (n + 1);
sigma = SQRT(sum / (n + 1));
if (verbose_level > 0) {
if (verbose_level > 1) {
SERIAL_ECHO(n + 1);
SERIAL_ECHOPAIR(" of ", int(n_samples));
SERIAL_ECHOPAIR_F(": z: ", sample_set[n], 3);
if (verbose_level > 2) {
SERIAL_ECHOPAIR_F(" mean: ", mean, 4);
SERIAL_ECHOPAIR_F(" sigma: ", sigma, 6);
SERIAL_ECHOPAIR_F(" min: ", min, 3);
SERIAL_ECHOPAIR_F(" max: ", max, 3);
SERIAL_ECHOPAIR_F(" range: ", max-min, 3);
}
SERIAL_EOL();
}
// Calculate the standard deviation so far.
// The value after the last sample will be the final output.
float dev_sum = 0.0;
LOOP_LE_N(j, n) dev_sum += sq(sample_set[j] - mean);
sigma = SQRT(dev_sum / (n + 1));
if (verbose_level > 1) {
SERIAL_ECHO(n + 1);
SERIAL_ECHOPAIR(" of ", int(n_samples));
SERIAL_ECHOPAIR_F(": z: ", pz, 3);
dev_report(verbose_level > 2, mean, sigma, min, max);
SERIAL_EOL();
}
} // n_samples loop
@@ -242,16 +256,7 @@ void GcodeSuite::M48() {
if (probing_good) {
SERIAL_ECHOLNPGM("Finished!");
if (verbose_level > 0) {
SERIAL_ECHOPAIR_F("Mean: ", mean, 6);
SERIAL_ECHOPAIR_F(" Min: ", min, 3);
SERIAL_ECHOPAIR_F(" Max: ", max, 3);
SERIAL_ECHOLNPAIR_F(" Range: ", max-min, 3);
}
SERIAL_ECHOLNPAIR_F("Standard Deviation: ", sigma, 6);
SERIAL_EOL();
dev_report(verbose_level > 0, mean, sigma, min, max, true);
#if HAS_SPI_LCD
// Display M48 results in the status bar

View File

@@ -33,7 +33,21 @@
* B<baudrate> - Baud rate (bits per second)
*/
void GcodeSuite::M575() {
const int32_t baud = parser.ulongval('B');
int32_t baud = parser.ulongval('B');
switch (baud) {
case 24:
case 96:
case 192:
case 384:
case 576:
case 1152: baud *= 100; break;
case 250:
case 500: baud *= 1000; break;
case 19: baud = 19200; break;
case 38: baud = 38400; break;
case 57: baud = 57600; break;
case 115: baud = 115200; break;
}
switch (baud) {
case 2400: case 9600: case 19200: case 38400: case 57600:
case 115200: case 250000: case 500000: case 1000000: {

View File

@@ -22,20 +22,12 @@
#include "../../inc/MarlinConfig.h"
#if ENABLED(SMART_EFFECTOR) && PIN_EXISTS(SMART_EFFECTOR_MOD)
#if ENABLED(DUET_SMART_EFFECTOR) && PIN_EXISTS(SMART_EFFECTOR_MOD)
#include "../gcode.h"
#include "../../HAL/shared/Delay.h"
#include "../parser.h"
/**
* M672 - Set/reset Duet Smart Effector sensitivity
*
* One of these is required:
* S<sensitivity> - 0-255
* R - Flag to reset sensitivity to default
*/
/**
* The Marlin format for the M672 command is different than shown in the Duet Smart Effector
* documentation https://duet3d.dozuki.com/Wiki/Smart_effector_and_carriage_adapters_for_delta_printer
@@ -77,6 +69,13 @@ void M672_send(uint8_t b) { // bit rate requirement: 1KHz +/- 30%
}
}
/**
* M672 - Set/reset Duet Smart Effector sensitivity
*
* One of these is required:
* S<sensitivity> - 0-255
* R - Flag to reset sensitivity to default
*/
void GcodeSuite::M672() {
if (parser.seen('R')) {
M672_send(M672_ERASEBYTE);
@@ -96,4 +95,4 @@ void GcodeSuite::M672() {
OUT_WRITE(SMART_EFFECTOR_MOD_PIN, LOW); // Keep Smart Effector in NORMAL mode
}
#endif // SMART_EFFECTOR && SMART_EFFECTOR_MOD_PIN
#endif // DUET_SMART_EFFECTOR && SMART_EFFECTOR_MOD_PIN

View File

@@ -21,16 +21,14 @@
*/
#include "../gcode.h"
#include "../../module/temperature.h"
#include "../../module/stepper.h"
#include "../../module/printcounter.h" // for print_job_timer
#include "../../module/planner.h" // for planner.finish_and_disable
#include "../../module/printcounter.h" // for print_job_timer.stop
#include "../../lcd/ultralcd.h" // for LCD_MESSAGEPGM_P
#include "../../inc/MarlinConfig.h"
#if HAS_LCD_MENU
#include "../../lcd/ultralcd.h"
#endif
#if HAS_SUICIDE
#include "../../MarlinCore.h"
#endif
@@ -39,6 +37,8 @@
#if ENABLED(AUTO_POWER_CONTROL)
#include "../../feature/power.h"
#else
void restore_stepper_drivers();
#endif
// Could be moved to a feature, but this is all the data
@@ -108,7 +108,5 @@ void GcodeSuite::M81() {
PSU_OFF();
#endif
#if HAS_LCD_MENU
LCD_MESSAGEPGM_P(PSTR(MACHINE_NAME " " STR_OFF "."));
#endif
LCD_MESSAGEPGM_P(PSTR(MACHINE_NAME " " STR_OFF "."));
}

View File

@@ -0,0 +1,92 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program 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.
*
* This program 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "../../inc/MarlinConfig.h"
#if ALL(HAS_SPI_FLASH, SDSUPPORT, MARLIN_DEV_MODE)
#include "../gcode.h"
#include "../../sd/cardreader.h"
#include "../../libs/W25Qxx.h"
/**
* M993: Backup SPI Flash to SD
*/
void GcodeSuite::M993() {
if (!card.isMounted()) card.mount();
char fname[] = "spiflash.bin";
card.openFileWrite(fname);
if (!card.isFileOpen()) {
SERIAL_ECHOLNPAIR("Failed to open ", fname, " to write.");
return;
}
W25QXXFlash W25QXX;
uint8_t buf[1024];
uint32_t addr = 0;
W25QXX.init(SPI_QUARTER_SPEED);
SERIAL_ECHOPGM("Save SPI Flash");
while (addr < SPI_FLASH_SIZE) {
W25QXX.SPI_FLASH_BufferRead(buf, addr, COUNT(buf));
addr += COUNT(buf);
card.write(buf, COUNT(buf));
if (addr % (COUNT(buf) * 10) == 0) SERIAL_CHAR('.');
}
SERIAL_ECHOLNPGM(" done");
card.closefile();
}
/**
* M994: Load a backup from SD to SPI Flash
*/
void GcodeSuite::M994() {
if (!card.isMounted()) card.mount();
char fname[] = "spiflash.bin";
card.openFileRead(fname);
if (!card.isFileOpen()) {
SERIAL_ECHOLNPAIR("Failed to open ", fname, " to read.");
return;
}
W25QXXFlash W25QXX;
uint8_t buf[1024];
uint32_t addr = 0;
W25QXX.init(SPI_QUARTER_SPEED);
W25QXX.SPI_FLASH_BulkErase();
SERIAL_ECHOPGM("Load SPI Flash");
while(addr < SPI_FLASH_SIZE) {
card.read(buf, COUNT(buf));
W25QXX.SPI_FLASH_BufferWrite(buf, addr, COUNT(buf));
addr += COUNT(buf);
if (addr % (COUNT(buf) * 10) == 0) SERIAL_CHAR('.');
}
SERIAL_ECHOLNPGM(" done");
card.closefile();
}
#endif // HAS_SPI_FLASH && SDSUPPORT && MARLIN_DEV_MODE

View File

@@ -28,7 +28,9 @@
* M997: Perform in-application firmware update
*/
void GcodeSuite::M997() {
flashFirmware(parser.intval('S'));
}
#endif

View File

@@ -21,7 +21,7 @@
*/
#include "../gcode.h"
#include "../../module/configuration_store.h"
#include "../../module/settings.h"
#include "../../core/serial.h"
#include "../../inc/MarlinConfig.h"
@@ -60,7 +60,7 @@ void GcodeSuite::M502() {
#if ENABLED(EEPROM_SETTINGS)
#if ENABLED(MARLIN_DEV_MODE)
#include "../../libs/hex_print_routines.h"
#include "../../libs/hex_print.h"
#endif
/**

View File

@@ -126,7 +126,7 @@ void GcodeSuite::M240() {
#ifdef PHOTO_POSITION
if (axis_unhomed_error()) return;
if (homing_needed_error()) return;
const xyz_pos_t old_pos = {
current_position.x + parser.linearval('A'),

View File

@@ -20,45 +20,47 @@
*
*/
#include "../../gcode.h"
#include "../../../inc/MarlinConfig.h"
#if HAS_CASE_LIGHT
#include "../../../feature/caselight.h"
#if ENABLED(CASE_LIGHT_ENABLE)
/**
* M355: Turn case light on/off and set brightness
*
* P<byte> Set case light brightness (PWM pin required - ignored otherwise)
*
* S<bool> Set case light on/off
*
* When S turns on the light on a PWM pin then the current brightness level is used/restored
*
* M355 P200 S0 turns off the light & sets the brightness level
* M355 S1 turns on the light with a brightness of 200 (assuming a PWM pin)
*/
void GcodeSuite::M355() {
uint8_t args = 0;
if (parser.seenval('P')) {
++args, case_light_brightness = parser.value_byte();
case_light_arg_flag = false;
}
if (parser.seenval('S')) {
++args, case_light_on = parser.value_bool();
case_light_arg_flag = true;
}
if (args) update_case_light();
#include "../../../feature/caselight.h"
#include "../../gcode.h"
// always report case light status
SERIAL_ECHO_START();
if (!case_light_on) {
SERIAL_ECHOLNPGM("Case light: off");
}
else {
if (!PWM_PIN(CASE_LIGHT_PIN)) SERIAL_ECHOLNPGM("Case light: on");
else SERIAL_ECHOLNPAIR("Case light: ", case_light_brightness);
}
/**
* M355: Turn case light on/off and set brightness
*
* P<byte> Set case light brightness (PWM pin required - ignored otherwise)
*
* S<bool> Set case light on/off
*
* When S turns on the light on a PWM pin then the current brightness level is used/restored
*
* M355 P200 S0 turns off the light & sets the brightness level
* M355 S1 turns on the light with a brightness of 200 (assuming a PWM pin)
*/
void GcodeSuite::M355() {
bool didset = false;
if (parser.seenval('P')) {
didset = true;
caselight.brightness = parser.value_byte();
}
#endif // HAS_CASE_LIGHT
const bool sflag = parser.seenval('S');
if (sflag) {
didset = true;
caselight.on = parser.value_bool();
}
if (didset) caselight.update(sflag);
// Always report case light status
SERIAL_ECHO_START();
SERIAL_ECHOPGM("Case light: ");
if (!caselight.on)
SERIAL_ECHOLNPGM(STR_OFF);
else {
if (!PWM_PIN(CASE_LIGHT_PIN)) SERIAL_ECHOLNPGM(STR_ON);
else SERIAL_ECHOLN(int(caselight.brightness));
}
}
#endif // CASE_LIGHT_ENABLE

View File

@@ -45,7 +45,7 @@
*/
void GcodeSuite::G12() {
// Don't allow nozzle cleaning without homing first
if (axis_unhomed_error()) return;
if (homing_needed_error()) return;
#ifdef WIPE_SEQUENCE_COMMANDS
if (!parser.seen_any()) {

View File

@@ -35,7 +35,10 @@
* If brightness is left out, no value changed
*
* With NEOPIXEL_LED:
* I<index> Set the Neopixel index to affect. Default: All
* I<index> Set the NeoPixel index to affect. Default: All
*
* With NEOPIXEL2_SEPARATE:
* S<index> The NeoPixel strip to set. Default is index 0.
*
* Examples:
*
@@ -47,18 +50,35 @@
* M150 P127 ; Set LED 50% brightness
* M150 P ; Set LED full brightness
* M150 I1 R ; Set NEOPIXEL index 1 to red
* M150 S1 I1 R ; Set SEPARATE index 1 to red
*/
void GcodeSuite::M150() {
#if ENABLED(NEOPIXEL_LED)
neo.set_neo_index(parser.intval('I', -1));
const uint8_t index = parser.intval('I', -1);
#if ENABLED(NEOPIXEL2_SEPARATE)
const uint8_t unit = parser.intval('S'),
brightness = unit ? neo2.brightness() : neo.brightness();
*(unit ? &neo2.neoindex : &neo.neoindex) = index;
#else
const uint8_t brightness = neo.brightness();
neo.neoindex = index;
#endif
#endif
leds.set_color(MakeLEDColor(
const LEDColor color = MakeLEDColor(
parser.seen('R') ? (parser.has_value() ? parser.value_byte() : 255) : 0,
parser.seen('U') ? (parser.has_value() ? parser.value_byte() : 255) : 0,
parser.seen('B') ? (parser.has_value() ? parser.value_byte() : 255) : 0,
parser.seen('W') ? (parser.has_value() ? parser.value_byte() : 255) : 0,
parser.seen('P') ? (parser.has_value() ? parser.value_byte() : 255) : neo.brightness()
));
parser.seen('P') ? (parser.has_value() ? parser.value_byte() : 255) : brightness
);
#if ENABLED(NEOPIXEL2_SEPARATE)
if (unit == 1) { leds2.set_color(color); return; }
#endif
leds.set_color(color);
}
#endif // HAS_COLOR_LEDS

View File

@@ -0,0 +1,83 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program 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.
*
* This program 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "../../../inc/MarlinConfigPre.h"
#if ENABLED(PASSWORD_FEATURE)
#include "../../../feature/password/password.h"
#include "../../../core/serial.h"
#include "../../gcode.h"
//
// M510: Lock Printer
//
void GcodeSuite::M510() {
password.lock_machine();
}
//
// M511: Unlock Printer
//
#if ENABLED(PASSWORD_UNLOCK_GCODE)
void GcodeSuite::M511() {
if (password.is_locked) {
password.value_entry = parser.ulongval('P');
password.authentication_check();
}
}
#endif // PASSWORD_UNLOCK_GCODE
//
// M512: Set/Change/Remove Password
//
#if ENABLED(PASSWORD_CHANGE_GCODE)
void GcodeSuite::M512() {
if (password.is_set && parser.ulongval('P') != password.value) {
SERIAL_ECHOLNPGM(STR_WRONG_PASSWORD);
return;
}
if (parser.seenval('S')) {
password.value_entry = parser.ulongval('S');
if (password.value_entry < CAT(1e, PASSWORD_LENGTH)) {
password.is_set = true;
password.value = password.value_entry;
SERIAL_ECHOLNPAIR(STR_PASSWORD_SET, password.value); // TODO: Update password.string
}
else
SERIAL_ECHOLNPGM(STR_PASSWORD_TOO_LONG);
}
else {
password.is_set = false;
SERIAL_ECHOLNPGM(STR_PASSWORD_REMOVED);
}
SERIAL_ECHOLNPGM(STR_REMINDER_SAVE_SETTINGS);
}
#endif // PASSWORD_CHANGE_GCODE
#endif // PASSWORD_FEATURE

View File

@@ -34,7 +34,7 @@
*/
void GcodeSuite::G27() {
// Don't allow nozzle parking without homing first
if (axis_unhomed_error()) return;
if (homing_needed_error()) return;
nozzle.park(parser.ushortval('P'));
}

View File

@@ -61,7 +61,7 @@ void GcodeSuite::M701() {
#if ENABLED(NO_MOTION_BEFORE_HOMING)
// Don't raise Z if the machine isn't homed
if (axes_need_homing()) park_point.z = 0;
if (axes_should_home()) park_point.z = 0;
#endif
#if ENABLED(MIXING_EXTRUDER)
@@ -149,7 +149,7 @@ void GcodeSuite::M702() {
#if ENABLED(NO_MOTION_BEFORE_HOMING)
// Don't raise Z if the machine isn't homed
if (axes_need_homing()) park_point.z = 0;
if (axes_should_home()) park_point.z = 0;
#endif
#if ENABLED(MIXING_EXTRUDER)

View File

@@ -61,6 +61,10 @@ GcodeSuite gcode;
#include "../feature/spindle_laser.h"
#endif
#if ENABLED(PASSWORD_FEATURE)
#include "../feature/password/password.h"
#endif
#include "../MarlinCore.h" // for idle()
// Inactivity shutdown
@@ -245,7 +249,20 @@ void GcodeSuite::dwell(millis_t time) {
void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
KEEPALIVE_STATE(IN_HANDLER);
DEBUG("Cmd %c %d",parser.command_letter,parser.codenum);
#if ENABLED(MKS_WIFI)
DEBUG("Gcode: %c %d",parser.command_letter,parser.codenum);
#endif
/**
* Block all Gcodes except M511 Unlock Printer, if printer is locked
* Will still block Gcodes if M511 is disabled, in which case the printer should be unlocked via LCD Menu
*/
#if ENABLED(PASSWORD_FEATURE)
if (password.is_locked && !(parser.command_letter == 'M' && parser.codenum == 511)) {
SERIAL_ECHO_MSG(STR_PRINTER_LOCKED);
return;
}
#endif
// Handle a known G, M, or T
switch (parser.command_letter) {
@@ -791,6 +808,16 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 504: M504(); break; // M504: Validate EEPROM contents
#endif
#if ENABLED(PASSWORD_FEATURE)
case 510: M510(); break; // M510: Lock Printer
#if ENABLED(PASSWORD_UNLOCK_GCODE)
case 511: M511(); break; // M511: Unlock Printer
#endif
#if ENABLED(PASSWORD_CHANGE_GCODE)
case 512: M512(); break;
#endif // M512: Set/Change/Remove Password
#endif
#if ENABLED(SDSUPPORT)
case 524: M524(); break; // M524: Abort the current SD print job
#endif
@@ -820,7 +847,7 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 666: M666(); break; // M666: Set delta or multiple endstop adjustment
#endif
#if ENABLED(SMART_EFFECTOR) && PIN_EXISTS(SMART_EFFECTOR_MOD)
#if ENABLED(DUET_SMART_EFFECTOR) && PIN_EXISTS(SMART_EFFECTOR_MOD)
case 672: M672(); break; // M672: Set/clear Duet Smart Effector sensitivity
#endif
@@ -897,7 +924,7 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 351: M351(); break; // M351: Toggle MS1 MS2 pins directly, S# determines MS1 or MS2, X# sets the pin high/low.
#endif
#if HAS_CASE_LIGHT
#if ENABLED(CASE_LIGHT_ENABLE)
case 355: M355(); break; // M355: Set case light brightness
#endif
@@ -926,14 +953,34 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 422: M422(); break; // M422: Set Z Stepper automatic alignment position using probe
#endif
#if ALL(HAS_SPI_FLASH, SDSUPPORT, MARLIN_DEV_MODE)
case 993: M993(); break; // M993: Backup SPI Flash to SD
case 994: M994(); break; // M994: Load a Backup from SD to SPI Flash
#endif
#if ENABLED(TOUCH_SCREEN_CALIBRATION)
case 995: M995(); break; // M995: Touch screen calibration for TFT display
#endif
#if ENABLED(MKS_WIFI)
case 991: if ( serial_port_index) {mks_m991();}; return;
case 997: if ( serial_port_index) {mks_m997();}; return;
#endif
#if ENABLED(MKS_WIFI)
case 997: if ( serial_port_index) {
mks_m997();
}else{
#if ENABLED(PLATFORM_M997_SUPPORT)
M997();
#endif
};
return;
#else
#if ENABLED(PLATFORM_M997_SUPPORT)
case 997: M997(); break; // M997: Perform in-application firmware update
#endif
#endif
case 999: M999(); break; // M999: Restart after being Stopped

View File

@@ -155,7 +155,7 @@
* M141 - Set heated chamber target temp. S<temp> (Requires a chamber heater)
* M145 - Set heatup values for materials on the LCD. H<hotend> B<bed> F<fan speed> for S<material> (0=PLA, 1=ABS)
* M149 - Set temperature units. (Requires TEMPERATURE_UNITS_SUPPORT)
* M150 - Set Status LED Color as R<red> U<green> B<blue> P<bright>. Values 0-255. (Requires BLINKM, RGB_LED, RGBW_LED, NEOPIXEL_LED, PCA9533, or PCA9632).
* M150 - Set Status LED Color as R<red> U<green> B<blue> W<white> P<bright>. Values 0-255. (Requires BLINKM, RGB_LED, RGBW_LED, NEOPIXEL_LED, PCA9533, or PCA9632).
* M155 - Auto-report temperatures with interval of S<seconds>. (Requires AUTO_REPORT_TEMPERATURES)
* M163 - Set a single proportion for a mixing extruder. (Requires MIXING_EXTRUDER)
* M164 - Commit the mix and save to a virtual tool (current, or as specified by 'S'). (Requires MIXING_EXTRUDER)
@@ -225,6 +225,9 @@
* M502 - Revert to the default "factory settings". ** Does not write them to EEPROM! **
* M503 - Print the current settings (in memory): "M503 S<verbose>". S0 specifies compact output.
* M504 - Validate EEPROM contents. (Requires EEPROM_SETTINGS)
* M510 - Lock Printer
* M511 - Unlock Printer
* M512 - Set/Change/Remove Password
* M524 - Abort the current SD print job started with M24. (Requires SDSUPPORT)
* M540 - Enable/disable SD card abort on endstop hit: "M540 S<state>". (Requires SD_ABORT_ON_ENDSTOP_HIT)
* M569 - Enable stealthChop on an axis. (Requires at least one _DRIVER_TYPE to be TMC2130/2160/2208/2209/5130/5160)
@@ -233,7 +236,7 @@
* M605 - Set Dual X-Carriage movement mode: "M605 S<mode> [X<x_offset>] [R<temp_offset>]". (Requires DUAL_X_CARRIAGE)
* M665 - Set delta configurations: "M665 H<delta height> L<diagonal rod> R<delta radius> S<segments/s> B<calibration radius> X<Alpha angle trim> Y<Beta angle trim> Z<Gamma angle trim> (Requires DELTA)
* M666 - Set/get offsets for delta (Requires DELTA) or dual endstops. (Requires [XYZ]_DUAL_ENDSTOPS)
* M672 - Set/Reset Duet Smart Effector's sensitivity. (Requires SMART_EFFECTOR and SMART_EFFECTOR_MOD_PIN)
* M672 - Set/Reset Duet Smart Effector's sensitivity. (Requires DUET_SMART_EFFECTOR and SMART_EFFECTOR_MOD_PIN)
* M701 - Load filament (Requires FILAMENT_LOAD_UNLOAD_GCODES)
* M702 - Unload filament (Requires FILAMENT_LOAD_UNLOAD_GCODES)
* M810-M819 - Define/execute a G-code macro (Requires GCODE_MACROS)
@@ -276,6 +279,9 @@
* ************ Custom codes - This can change to suit future G-code regulations
* G425 - Calibrate using a conductive object. (Requires CALIBRATION_GCODE)
* M928 - Start SD logging: "M928 filename.gco". Stop with M29. (Requires SDSUPPORT)
* M993 - Backup SPI Flash to SD
* M994 - Load a Backup from SD to SPI Flash
* M995 - Touch screen calibration for TFT display
* M997 - Perform in-application firmware update
* M999 - Restart after being stopped by error
*
@@ -701,7 +707,7 @@ private:
static void M351();
#endif
TERN_(HAS_CASE_LIGHT, static void M355());
TERN_(CASE_LIGHT_ENABLE, static void M355());
TERN_(REPETIER_GCODE_M360, static void M360());
@@ -757,6 +763,16 @@ private:
#endif
TERN_(EEPROM_SETTINGS, static void M504());
#if ENABLED(PASSWORD_FEATURE)
static void M510();
#if ENABLED(PASSWORD_UNLOCK_GCODE)
static void M511();
#endif
#if ENABLED(PASSWORD_CHANGE_GCODE)
static void M512();
#endif
#endif
TERN_(SDSUPPORT, static void M524());
TERN_(SD_ABORT_ON_ENDSTOP_HIT, static void M540());
@@ -776,7 +792,7 @@ private:
static void M666();
#endif
#if ENABLED(SMART_EFFECTOR) && PIN_EXISTS(SMART_EFFECTOR_MOD)
#if ENABLED(DUET_SMART_EFFECTOR) && PIN_EXISTS(SMART_EFFECTOR_MOD)
static void M672();
#endif
@@ -843,6 +859,13 @@ private:
TERN_(MAGNETIC_PARKING_EXTRUDER, static void M951());
TERN_(TOUCH_SCREEN_CALIBRATION, static void M995());
#if BOTH(HAS_SPI_FLASH, SDSUPPORT)
static void M993();
static void M994();
#endif
TERN_(PLATFORM_M997_SUPPORT, static void M997());
static void M999();

View File

@@ -61,7 +61,7 @@ void GcodeSuite::M206() {
* Use M206 to set these values directly.
*/
void GcodeSuite::M428() {
if (axis_unhomed_error()) return;
if (homing_needed_error()) return;
xyz_float_t diff;
LOOP_XYZ(i) {

View File

@@ -93,8 +93,8 @@ void GcodeSuite::M115() {
cap_line(PSTR("SOFTWARE_POWER"), ENABLED(PSU_CONTROL));
// TOGGLE_LIGHTS (M355)
cap_line(PSTR("TOGGLE_LIGHTS"), ENABLED(HAS_CASE_LIGHT));
cap_line(PSTR("CASE_LIGHT_BRIGHTNESS"), TERN0(HAS_CASE_LIGHT, PWM_PIN(CASE_LIGHT_PIN)));
cap_line(PSTR("TOGGLE_LIGHTS"), ENABLED(CASE_LIGHT_ENABLE));
cap_line(PSTR("CASE_LIGHT_BRIGHTNESS"), TERN0(CASE_LIGHT_ENABLE, PWM_PIN(CASE_LIGHT_PIN)));
// EMERGENCY_PARSER (M108, M112, M410, M876)
cap_line(PSTR("EMERGENCY_PARSER"), ENABLED(EMERGENCY_PARSER));

View File

@@ -0,0 +1,39 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program 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.
*
* This program 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "../../inc/MarlinConfig.h"
#if ENABLED(TOUCH_SCREEN_CALIBRATION)
#include "../gcode.h"
#include "../../lcd/menu/menu.h"
/**
* M995: Touch screen calibration for TFT display
*/
void GcodeSuite::M995() {
ui.goto_screen(touch_screen_calibration);
}
#endif // TOUCH_SCREEN_CALIBRATION

View File

@@ -52,7 +52,7 @@ void GcodeSuite::G0_G1(
if (IsRunning()
#if ENABLED(NO_MOTION_BEFORE_HOMING)
&& !axis_unhomed_error(
&& !homing_needed_error(
(parser.seen('X') ? _BV(X_AXIS) : 0)
| (parser.seen('Y') ? _BV(Y_AXIS) : 0)
| (parser.seen('Z') ? _BV(Z_AXIS) : 0) )

View File

@@ -29,7 +29,7 @@
/**
* Parameters interpreted according to:
* https://linuxcnc.org/docs/2.6/html/gcode/gcode.html#sec:G5-Cubic-Spline
* https://linuxcnc.org/docs/2.7/html/gcode/g-code.html#gcode:g5
* However I, J omission is not supported at this point; all
* parameters can be omitted and default to zero.
*/

View File

@@ -31,7 +31,7 @@
//#define DEBUG_GCODE_PARSER
#if ENABLED(DEBUG_GCODE_PARSER)
#include "../libs/hex_print_routines.h"
#include "../libs/hex_print.h"
#endif
#if ENABLED(TEMPERATURE_UNITS_SUPPORT)

View File

@@ -40,7 +40,7 @@ GCodeQueue queue;
#endif
#if ENABLED(BINARY_FILE_TRANSFER)
#include "../feature/binary_protocol.h"
#include "../feature/binary_stream.h"
#endif
#if ENABLED(POWER_LOSS_RECOVERY)
@@ -639,11 +639,10 @@ void GCodeQueue::advance() {
#if ENABLED(SERIAL_STATS_DROPPED_RX)
SERIAL_ECHOLNPAIR("Dropped bytes: ", MYSERIAL0.dropped());
#endif
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
SERIAL_ECHOLNPAIR("Max RX Queue Size: ", MYSERIAL0.rxMaxEnqueued());
#endif
#endif // !defined(__AVR__) || !defined(USBCON)
#endif
ok_to_send();
}

View File

@@ -75,7 +75,10 @@ void GcodeSuite::M1001() {
TERN_(POWER_LOSS_RECOVERY, recovery.purge());
// Announce SD file completion
SERIAL_ECHOLNPGM(STR_FILE_PRINTED);
{
PORT_REDIRECT(SERIAL_BOTH);
SERIAL_ECHOLNPGM(STR_FILE_PRINTED);
}
// Update the status LED color
#if HAS_LEDS_OFF_FLAG