Newer
Older
* Copyright (C) 2016, 2017 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 <http://www.gnu.org/licenses/>.
* About Marlin
*
* This firmware is a mashup between Sprinter and grbl.
* - https://github.com/kliment/Sprinter
* - https://github.com/simen/grbl/tree
*/
* -----------------
* G-Codes in Marlin
* -----------------
*
* Helpful G-code references:
* - http://linuxcnc.org/handbook/gcode/g-code.html
* - http://objects.reprap.org/wiki/Mendel_User_Manual:_RepRapGCodes
*
* Help to document Marlin's G-codes online:
* - https://github.com/MarlinFirmware/MarlinDocumentation
*
* -----------------
* G0 -> G1
* G1 - Coordinated Movement X Y Z E
* G2 - CW ARC
* G3 - CCW ARC
* G4 - Dwell S<seconds> or P<milliseconds>
* G5 - Cubic B-spline with XYZE destination and IJPQ offsets
* G10 - Retract filament according to settings of M207
* G11 - Retract recover filament according to settings of M208
* G12 - Clean tool
* G20 - Set input units to inches
* G21 - Set input units to millimeters
* G26 - Mesh Validation Pattern (Requires UBL_G26_MESH_VALIDATION)
* G27 - Park Nozzle (Requires NOZZLE_PARK_FEATURE)
* G28 - Home one or more axes
* G29 - Detailed Z probe, probes the bed at 3 or more points. Will fail if you haven't homed yet.
* G30 - Single Z probe, probes bed at X Y location (defaults to current XY location)
* G31 - Dock sled (Z_PROBE_SLED only)
* G32 - Undock sled (Z_PROBE_SLED only)
* G33 - Delta Auto-Calibration (Requires DELTA_AUTO_CALIBRATION)
* G38 - Probe target - similar to G28 except it uses the Z_MIN_PROBE for all three axes
* G42 - Coordinated move to a mesh point (Requires AUTO_BED_LEVELING_UBL)
* G90 - Use Absolute Coordinates
* G91 - Use Relative Coordinates
* G92 - Set current position to coordinates given
*
* "M" Codes
*
* M0 - Unconditional stop - Wait for user to press a button on the LCD (Only if ULTRA_LCD is enabled)
* M1 - Same as M0
* M3 - Turn laser/spindle on, set spindle/laser speed/power, set rotation to clockwise
* M4 - Turn laser/spindle on, set spindle/laser speed/power, set rotation to counter-clockwise
* M5 - Turn laser/spindle off
* M17 - Enable/Power all stepper motors
* M18 - Disable all stepper motors; same as M84
* M20 - List SD card. (Requires SDSUPPORT)
* M21 - Init SD card. (Requires SDSUPPORT)
* M22 - Release SD card. (Requires SDSUPPORT)
* M23 - Select SD file: "M23 /path/file.gco". (Requires SDSUPPORT)
* M24 - Start/resume SD print. (Requires SDSUPPORT)
* M25 - Pause SD print. (Requires SDSUPPORT)
* M26 - Set SD position in bytes: "M26 S12345". (Requires SDSUPPORT)
* M27 - Report SD print status. (Requires SDSUPPORT)
* M28 - Start SD write: "M28 /path/file.gco". (Requires SDSUPPORT)
* M29 - Stop SD write. (Requires SDSUPPORT)
* M30 - Delete file from SD: "M30 /path/file.gco"
* M31 - Report time since last M109 or SD card start to serial.
* M32 - Select file and start SD print: "M32 [S<bytepos>] !/path/file.gco#". (Requires SDSUPPORT)
* Use P to run other files as sub-programs: "M32 P !filename#"
* The '#' is necessary when calling from within sd files, as it stops buffer prereading
* M33 - Get the longname version of a path. (Requires LONG_FILENAME_HOST_SUPPORT)
* M34 - Set SD Card sorting options. (Requires SDCARD_SORT_ALPHA)
* M42 - Change pin status via gcode: M42 P<pin> S<value>. LED pin assumed if P is omitted.
* M43 - Display pin status, watch pins for changes, watch endstops & toggle LED, Z servo probe test, toggle pins
* M48 - Measure Z Probe repeatability: M48 P<points> X<pos> Y<pos> V<level> E<engage> L<legs>. (Requires Z_MIN_PROBE_REPEATABILITY_TEST)
* M75 - Start the print job timer.
* M76 - Pause the print job timer.
* M77 - Stop the print job timer.
* M78 - Show statistical information about the print jobs. (Requires PRINTCOUNTER)
* M80 - Turn on Power Supply. (Requires POWER_SUPPLY > 0)
* M81 - Turn off Power Supply. (Requires POWER_SUPPLY > 0)
* M82 - Set E codes absolute (default).
* M83 - Set E codes relative while in Absolute (G90) mode.
* M84 - Disable steppers until next move, or use S<seconds> to specify an idle
* duration after which steppers should turn off. S0 disables the timeout.
* M85 - Set inactivity shutdown timer with parameter S<seconds>. To disable set zero (default)
* M92 - Set planner.axis_steps_per_mm for one or more axes.
* M100 - Watch Free Memory (for debugging) (Requires M100_FREE_MEMORY_WATCHER)
* M104 - Set extruder target temp.
* M105 - Report current temperatures.
* M106 - Fan on.
* M107 - Fan off.
* M108 - Break out of heating loops (M109, M190, M303). With no controller, breaks out of M0/M1. (Requires EMERGENCY_PARSER)
* M109 - Sxxx Wait for extruder current temp to reach target temp. Waits only when heating
* Rxxx Wait for extruder current temp to reach target temp. Waits when heating and cooling
* If AUTOTEMP is enabled, S<mintemp> B<maxtemp> F<factor>. Exit autotemp by any M109 without F
* M110 - Set the current line number. (Used by host printing)
* M111 - Set debug flags: "M111 S<flagbits>". See flag bits defined in enum.h.
* M112 - Emergency stop.
* M113 - Get or set the timeout interval for Host Keepalive "busy" messages. (Requires HOST_KEEPALIVE_FEATURE)
* M114 - Report current position.
* M115 - Report capabilities. (Extended capabilities requires EXTENDED_CAPABILITIES_REPORT)
* M117 - Display a message on the controller screen. (Requires an LCD)
* M119 - Report endstops status.
* M120 - Enable endstops detection.
* M121 - Disable endstops detection.
* M125 - Save current position and move to filament change position. (Requires PARK_HEAD_ON_PAUSE)
* M126 - Solenoid Air Valve Open. (Requires BARICUDA)
* M127 - Solenoid Air Valve Closed. (Requires BARICUDA)
* M128 - EtoP Open. (Requires BARICUDA)
* M129 - EtoP Closed. (Requires BARICUDA)
* M140 - Set bed target temp. S<temp>
* 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>. Values 0-255. (Requires BLINKM, RGB_LED, RGBW_LED, 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 - Save the mix as a virtual extruder. (Requires MIXING_EXTRUDER and MIXING_VIRTUAL_TOOLS)
* M165 - Set the proportions for a mixing extruder. Use parameters ABCDHI to set the mixing factors. (Requires MIXING_EXTRUDER)
* M190 - Sxxx Wait for bed current temp to reach target temp. ** Waits only when heating! **
* Rxxx Wait for bed current temp to reach target temp. ** Waits for heating or cooling. **
* M200 - Set filament diameter, D<diameter>, setting E axis units to cubic. (Use S0 to revert to linear units.)
* M201 - Set max acceleration in units/s^2 for print moves: "M201 X<accel> Y<accel> Z<accel> E<accel>"
* M202 - Set max acceleration in units/s^2 for travel moves: "M202 X<accel> Y<accel> Z<accel> E<accel>" ** UNUSED IN MARLIN! **
* M203 - Set maximum feedrate: "M203 X<fr> Y<fr> Z<fr> E<fr>" in units/sec.
* M204 - Set default acceleration in units/sec^2: P<printing> R<extruder_only> T<travel>
* M205 - Set advanced settings. Current units apply:
S<print> T<travel> minimum speeds
B<minimum segment time>
X<max X jerk>, Y<max Y jerk>, Z<max Z jerk>, E<max E jerk>
* M206 - Set additional homing offset. (Disabled by NO_WORKSPACE_OFFSETS or DELTA)
* M207 - Set Retract Length: S<length>, Feedrate: F<units/min>, and Z lift: Z<distance>. (Requires FWRETRACT)
* M208 - Set Recover (unretract) Additional (!) Length: S<length> and Feedrate: F<units/min>. (Requires FWRETRACT)
* M209 - Turn Automatic Retract Detection on/off: S<0|1> (For slicers that don't support G10/11). (Requires FWRETRACT)
Every normal extrude-only move will be classified as retract depending on the direction.
* M211 - Enable, Disable, and/or Report software endstops: S<0|1> (Requires MIN_SOFTWARE_ENDSTOPS or MAX_SOFTWARE_ENDSTOPS)
* M218 - Set a tool offset: "M218 T<index> X<offset> Y<offset>". (Requires 2 or more extruders)
* M220 - Set Feedrate Percentage: "M220 S<percent>" (i.e., "FR" on the LCD)
* M221 - Set Flow Percentage: "M221 S<percent>"
* M226 - Wait until a pin is in a given state: "M226 P<pin> S<state>"
* M240 - Trigger a camera to take a photograph. (Requires CHDK or PHOTOGRAPH_PIN)
* M250 - Set LCD contrast: "M250 C<contrast>" (0-63). (Requires LCD support)
* M260 - i2c Send Data (Requires EXPERIMENTAL_I2CBUS)
* M261 - i2c Request Data (Requires EXPERIMENTAL_I2CBUS)
* M280 - Set servo position absolute: "M280 P<index> S<angle|µs>". (Requires servos)
* M300 - Play beep sound S<frequency Hz> P<duration ms>
* M301 - Set PID parameters P I and D. (Requires PIDTEMP)
* M302 - Allow cold extrudes, or set the minimum extrude S<temperature>. (Requires PREVENT_COLD_EXTRUSION)
* M303 - PID relay autotune S<temperature> sets the target temperature. Default 150C. (Requires PIDTEMP)
* M304 - Set bed PID parameters P I and D. (Requires PIDTEMPBED)
* M350 - Set microstepping mode. (Requires digital microstepping pins.)
* M351 - Toggle MS1 MS2 pins directly. (Requires digital microstepping pins.)
* M355 - Set Case Light on/off and set brightness. (Requires CASE_LIGHT_PIN)
* M380 - Activate solenoid on active extruder. (Requires EXT_SOLENOID)
* M381 - Disable all solenoids. (Requires EXT_SOLENOID)
* M400 - Finish all moves.
* M401 - Lower Z probe. (Requires a probe)
* M402 - Raise Z probe. (Requires a probe)
* M404 - Display or set the Nominal Filament Width: "W<diameter>". (Requires FILAMENT_WIDTH_SENSOR)
* M405 - Enable Filament Sensor flow control. "M405 D<delay_cm>". (Requires FILAMENT_WIDTH_SENSOR)
* M406 - Disable Filament Sensor flow control. (Requires FILAMENT_WIDTH_SENSOR)
* M407 - Display measured filament diameter in millimeters. (Requires FILAMENT_WIDTH_SENSOR)
* M410 - Quickstop. Abort all planned moves.
* M420 - Enable/Disable Leveling (with current values) S1=enable S0=disable (Requires MESH_BED_LEVELING or ABL)
* M421 - Set a single Z coordinate in the Mesh Leveling grid. X<units> Y<units> Z<units> (Requires MESH_BED_LEVELING or AUTO_BED_LEVELING_UBL)
* M428 - Set the home_offset based on the current_position. Nearest edge applies. (Disabled by NO_WORKSPACE_OFFSETS or DELTA)
* M500 - Store parameters in EEPROM. (Requires EEPROM_SETTINGS)
* M501 - Restore parameters from EEPROM. (Requires EEPROM_SETTINGS)
* 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.
* M540 - Enable/disable SD card abort on endstop hit: "M540 S<state>". (Requires ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED)
* M600 - Pause for filament change: "M600 X<pos> Y<pos> Z<raise> E<first_retract> L<later_retract>". (Requires ADVANCED_PAUSE_FEATURE)
* M665 - Set delta configurations: "M665 L<diagonal rod> R<delta radius> S<segments/s> A<rod A trim mm> B<rod B trim mm> C<rod C trim mm> I<tower A trim angle> J<tower B trim angle> K<tower C trim angle>" (Requires DELTA)
* M666 - Set delta endstop adjustment. (Requires DELTA)
* M605 - Set dual x-carriage movement mode: "M605 S<mode> [X<x_offset>] [R<temp_offset>]". (Requires DUAL_X_CARRIAGE)
* M851 - Set Z probe's Z offset in current units. (Negative = below the nozzle.)
* M860 - Report the position of position encoder modules.
* M861 - Report the status of position encoder modules.
* M862 - Perform an axis continuity test for position encoder modules.
* M863 - Perform steps-per-mm calibration for position encoder modules.
* M864 - Change position encoder module I2C address.
* M865 - Check position encoder module firmware version.
* M866 - Report or reset position encoder module error count.
* M867 - Enable/disable or toggle error correction for position encoder modules.
* M868 - Report or set position encoder module error correction threshold.
* M869 - Report position encoder module error.
* M900 - Get and/or Set advance K factor and WH/D ratio. (Requires LIN_ADVANCE)
* M906 - Set or get motor current in milliamps using axis codes X, Y, Z, E. Report values if no axis codes given. (Requires HAVE_TMC2130)
* M907 - Set digital trimpot motor current using axis codes. (Requires a board with digital trimpots)
* M908 - Control digital trimpot directly. (Requires DAC_STEPPER_CURRENT or DIGIPOTSS_PIN)
* M909 - Print digipot/DAC current value. (Requires DAC_STEPPER_CURRENT)
* M910 - Commit digipot/DAC value to external EEPROM via I2C. (Requires DAC_STEPPER_CURRENT)
* M911 - Report stepper driver overtemperature pre-warn condition. (Requires HAVE_TMC2130)
* M912 - Clear stepper driver overtemperature pre-warn condition flag. (Requires HAVE_TMC2130)
* M913 - Set HYBRID_THRESHOLD speed. (Requires HYBRID_THRESHOLD)
* M914 - Set SENSORLESS_HOMING sensitivity. (Requires SENSORLESS_HOMING)
*
* M360 - SCARA calibration: Move to cal-position ThetaA (0 deg calibration)
* M361 - SCARA calibration: Move to cal-position ThetaB (90 deg calibration - steps per degree)
* M362 - SCARA calibration: Move to cal-position PsiA (0 deg calibration)
* M363 - SCARA calibration: Move to cal-position PsiB (90 deg calibration - steps per degree)
* M364 - SCARA calibration: Move to cal-position PSIC (90 deg to Theta calibration position)
*
* ************ Custom codes - This can change to suit future G-code regulations
* M928 - Start SD logging: "M928 filename.gco". Stop with M29. (Requires SDSUPPORT)
*
* "T" Codes
*
* T0-T3 - Select an extruder (tool) by index: "T<n> F<units/min>"
#include "Marlin.h"
#include "ultralcd.h"
#include "planner.h"
#include "stepper.h"
#include "endstops.h"
#include "temperature.h"
#include "cardreader.h"
#include "configuration_store.h"
#include "language.h"
#include "pins_arduino.h"
#include "math.h"
#include "nozzle.h"
#include "duration_t.h"
#include "types.h"
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
#if HAS_ABL
#include "vector_3.h"
#if ENABLED(AUTO_BED_LEVELING_LINEAR)
#include "qr_solve.h"
#endif
#elif ENABLED(MESH_BED_LEVELING)
#include "mesh_bed_leveling.h"
#endif
#if ENABLED(BEZIER_CURVE_SUPPORT)
#include "planner_bezier.h"
#endif
#if HAS_BUZZER && DISABLED(LCD_USE_I2C_BUZZER)
#include "buzzer.h"
#endif
#if ENABLED(USE_WATCHDOG)
#include "watchdog.h"
#endif
#if ENABLED(BLINKM)
#include "blinkm.h"
#include "Wire.h"
#endif
#if ENABLED(PCA9632)
#include "pca9632.h"
#endif
#if HAS_SERVOS
#include "servo.h"
#endif
#if HAS_DIGIPOTSS
#include <SPI.h>
#endif
#if ENABLED(DAC_STEPPER_CURRENT)
#include "stepper_dac.h"
#endif
#if ENABLED(EXPERIMENTAL_I2CBUS)
#include "twibus.h"
#endif
#if ENABLED(I2C_POSITION_ENCODERS)
#include "I2CPositionEncoder.h"
#endif
#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
#include "endstop_interrupts.h"
#endif
#if ENABLED(M100_FREE_MEMORY_WATCHER)
void M100_dump_routine(const char * const title, const char *start, const char *end);
#if ENABLED(SDSUPPORT)
#endif
#if ENABLED(EXPERIMENTAL_I2CBUS)
TWIBus i2c;
#endif
bool G38_move = false,
G38_endstop_hit = false;
extern bool defer_return_to_status;
extern bool ubl_lcd_map_control;
#define UBL_MESH_VALID !( ( ubl.z_values[0][0] == ubl.z_values[0][1] && ubl.z_values[0][1] == ubl.z_values[0][2] \
&& ubl.z_values[1][0] == ubl.z_values[1][1] && ubl.z_values[1][1] == ubl.z_values[1][2] \
&& ubl.z_values[2][0] == ubl.z_values[2][1] && ubl.z_values[2][1] == ubl.z_values[2][2] \
&& ubl.z_values[0][0] == 0 && ubl.z_values[1][0] == 0 && ubl.z_values[2][0] == 0 ) \
|| isnan(ubl.z_values[0][0]))
uint8_t marlin_debug_flags = DEBUG_NONE;
/**
* Cartesian Current Position
* Used to track the logical position as moves are queued.
* Used by 'line_to_current_position' to do a move after changing it.
* Used by 'SYNC_PLAN_POSITION_KINEMATIC' to update 'planner.position'.
*/
float current_position[XYZE] = { 0.0 };
/**
* Cartesian Destination
* A temporary position, usually applied to 'current_position'.
* Set with 'gcode_get_destination' or 'set_destination_to_current'.
* 'line_to_destination' sets 'current_position' to 'destination'.
*/
/**
* axis_homed
* Flags that each linear axis was homed.
* XYZ on cartesian, ABC on delta, ABZ on SCARA.
*
* axis_known_position
* Flags that the position is known in each linear axis. Set when homed.
* Cleared whenever a stepper powers off, potentially losing its position.
*/
bool axis_homed[XYZ] = { false }, axis_known_position[XYZ] = { false };
/**
* GCode line number handling. Hosts may opt to include line numbers when
* sending commands to Marlin, and lines will be checked for sequentiality.
static long gcode_N, gcode_LastN, Stopped_gcode_LastN = 0;
/**
* GCode Command Queue
* A simple ring buffer of BUFSIZE command strings.
*
* Commands are copied into this buffer by the command injectors
* (immediate, serial, sd card) and they are processed sequentially by
* the main loop. The process_next_command function parses the next
* command and hands off execution to individual handler functions.
*/
uint8_t commands_in_queue = 0; // Count of commands in the queue
static uint8_t cmd_queue_index_r = 0, // Ring buffer read position
cmd_queue_index_w = 0; // Ring buffer write position
#if ENABLED(M100_FREE_MEMORY_WATCHER)
char command_queue[BUFSIZE][MAX_CMD_SIZE]; // Necessary so M100 Free Memory Dumper can show us the commands and any corruption
#else // This can be collapsed back to the way it was soon.
static char command_queue[BUFSIZE][MAX_CMD_SIZE];
/**
* Next Injected Command pointer. NULL if no commands are being injected.
* Used by Marlin internally to ensure that commands initiated from within
* are enqueued ahead of any pending serial or sd card commands.
*/
static const char *injected_commands_P = NULL;
#if ENABLED(TEMPERATURE_UNITS_SUPPORT)
TempUnit input_temp_units = TEMPUNIT_C;
#endif
/**
* Feed rates are often configured with mm/m
* but the planner and stepper like mm/s units.
*/
static const float homing_feedrate_mm_s[] PROGMEM = {
MMM_TO_MMS(HOMING_FEEDRATE_Z), MMM_TO_MMS(HOMING_FEEDRATE_Z),
MMM_TO_MMS(HOMING_FEEDRATE_XY), MMM_TO_MMS(HOMING_FEEDRATE_XY),
MMM_TO_MMS(HOMING_FEEDRATE_Z), 0
FORCE_INLINE float homing_feedrate(const AxisEnum a) { return pgm_read_float(&homing_feedrate_mm_s[a]); }
float feedrate_mm_s = MMM_TO_MMS(1500.0);
static float saved_feedrate_mm_s;
int feedrate_percentage = 100, saved_feedrate_percentage,
flow_percentage[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(100);
bool axis_relative_modes[] = AXIS_RELATIVE_MODES,
#if ENABLED(VOLUMETRIC_DEFAULT_ON)
true
#else
false
#endif
float filament_size[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(DEFAULT_NOMINAL_FILAMENT_DIA),
volumetric_multiplier[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(1.0);
#if HAS_WORKSPACE_OFFSET
#if HAS_POSITION_SHIFT
// The distance that XYZ has been offset by G92. Reset by G28.
float position_shift[XYZ] = { 0 };
#endif
#if HAS_HOME_OFFSET
// This offset is added to the configured home position.
// Set by M206, M428, or menu item. Saved to EEPROM.
float home_offset[XYZ] = { 0 };
#endif
#if HAS_HOME_OFFSET && HAS_POSITION_SHIFT
// The above two are combined to save on computes
float workspace_offset[XYZ] = { 0 };
#endif
// Software Endstops are based on the configured limits.
bool soft_endstops_enabled = true;
#endif
float soft_endstop_min[XYZ] = { X_MIN_POS, Y_MIN_POS, Z_MIN_POS },
soft_endstop_max[XYZ] = { X_MAX_POS, Y_MAX_POS, Z_MAX_POS };
int16_t fanSpeeds[FAN_COUNT] = { 0 };
#if ENABLED(PROBING_FANS_OFF)
bool fans_paused = false;
int16_t paused_fanSpeeds[FAN_COUNT] = { 0 };
#endif
// The active extruder (tool). Set with T<extruder> command.
// Relative Mode. Enable with G91, disable with G90.
static bool relative_mode = false;
// For M109 and M190, this flag may be cleared (by M108) to exit the wait loop
// For M0/M1, this flag may be cleared (by M108) to exit the wait-for-user loop
volatile bool wait_for_user = false;
const char axis_codes[XYZE] = { 'X', 'Y', 'Z', 'E' };
// Number of characters read in the current line of serial input
millis_t previous_cmd_ms = 0;
static millis_t max_inactive_time = 0;
static millis_t stepper_inactive_time = (DEFAULT_STEPPER_DEACTIVE_TIME) * 1000UL;
#if ENABLED(PRINTCOUNTER)
PrintCounter print_job_timer = PrintCounter();
#else
Stopwatch print_job_timer = Stopwatch();
#endif
// Buzzer - I2C on the LCD or a BEEPER_PIN
#if ENABLED(LCD_USE_I2C_BUZZER)
#define BUZZ(d,f) lcd_buzz(d, f)
Buzzer buzzer;
#define BUZZ(d,f) buzzer.tone(d, f)
#else
#define BUZZ(d,f) NOOP
#if HAS_BED_PROBE
float zprobe_zoffset = Z_PROBE_OFFSET_FROM_EXTRUDER;
#endif
float xy_probe_feedrate_mm_s = MMM_TO_MMS(XY_PROBE_SPEED);
#define XY_PROBE_FEEDRATE_MM_S xy_probe_feedrate_mm_s
#elif defined(XY_PROBE_SPEED)
#define XY_PROBE_FEEDRATE_MM_S MMM_TO_MMS(XY_PROBE_SPEED)
#define XY_PROBE_FEEDRATE_MM_S PLANNER_XY_FEEDRATE()
#if ENABLED(AUTO_BED_LEVELING_BILINEAR)
#if ENABLED(DELTA)
#define ADJUST_DELTA(V) \
if (planner.abl_enabled) { \
const float zadj = bilinear_z_offset(V); \
delta[A_AXIS] += zadj; \
delta[B_AXIS] += zadj; \
delta[C_AXIS] += zadj; \
}
#else
#define ADJUST_DELTA(V) if (planner.abl_enabled) { delta[Z_AXIS] += bilinear_z_offset(V); }
#endif
#elif IS_KINEMATIC
#define ADJUST_DELTA(V) NOOP
#endif
float z_endstop_adj =
#ifdef Z_DUAL_ENDSTOPS_ADJUSTMENT
Z_DUAL_ENDSTOPS_ADJUSTMENT
#else
0
#endif
;
float hotend_offset[XYZ][HOTENDS];
#endif
const int z_servo_angle[2] = Z_SERVO_ANGLES;
#if ENABLED(BARICUDA)
int baricuda_valve_pressure = 0;
int baricuda_e_to_p_pressure = 0;
#if ENABLED(FWRETRACT)
bool retracted[EXTRUDERS] = { false };
bool retracted_swap[EXTRUDERS] = { false };
float retract_length = RETRACT_LENGTH;
float retract_length_swap = RETRACT_LENGTH_SWAP;
float retract_feedrate_mm_s = RETRACT_FEEDRATE;
float retract_zlift = RETRACT_ZLIFT;
float retract_recover_length = RETRACT_RECOVER_LENGTH;
float retract_recover_length_swap = RETRACT_RECOVER_LENGTH_SWAP;
float retract_recover_feedrate_mm_s = RETRACT_RECOVER_FEEDRATE;
#if HAS_POWER_SWITCH
bool powersupply_on =
#if ENABLED(PS_DEFAULT_OFF)
#if ENABLED(DELTA)
float delta[ABC],
endstop_adj[ABC] = { 0 };
// These values are loaded or reset at boot time when setup() calls
// settings.load(), which calls recalc_delta_settings().
delta_tower[ABC][2],
delta_diagonal_rod,
delta_diagonal_rod_2_tower[ABC],
delta_segments_per_second,
delta_clip_start_height = Z_MAX_POS;
float delta_safe_distance_from_top();
Pablo Clemente
committed
#if ENABLED(AUTO_BED_LEVELING_BILINEAR)
float bilinear_grid_factor[2],
z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y];
#if IS_SCARA
// Float constants for SCARA calculations
const float L1 = SCARA_LINKAGE_1, L2 = SCARA_LINKAGE_2,
L1_2 = sq(float(L1)), L1_2_2 = 2.0 * L1_2,
L2_2 = sq(float(L2));
float delta_segments_per_second = SCARA_SEGMENTS_PER_SECOND,
#if ENABLED(FILAMENT_WIDTH_SENSOR)
bool filament_sensor = false; // M405 turns on filament sensor control. M406 turns it off.
float filament_width_nominal = DEFAULT_NOMINAL_FILAMENT_DIA, // Nominal filament width. Change with M404.
filament_width_meas = DEFAULT_MEASURED_FILAMENT_DIA; // Measured filament diameter
int8_t measurement_delay[MAX_MEASUREMENT_DELAY + 1]; // Ring buffer to delayed measurement. Store extruder factor after subtracting 100
int filwidth_delay_index[2] = { 0, -1 }; // Indexes into ring buffer
int meas_delay_cm = MEASUREMENT_DELAY_CM; // Distance delay setting
#if ENABLED(FILAMENT_RUNOUT_SENSOR)
#if ENABLED(ADVANCED_PAUSE_FEATURE)
AdvancedPauseMenuResponse advanced_pause_menu_response;
#if ENABLED(MIXING_EXTRUDER)
float mixing_factor[MIXING_STEPPERS]; // Reciprocal of mix proportion. 0.0 = off, otherwise >= 1.0.
#if MIXING_VIRTUAL_TOOLS > 1
float mixing_virtual_tool_mix[MIXING_VIRTUAL_TOOLS][MIXING_STEPPERS];
#endif
#endif
#if HAS_Z_SERVO_ENDSTOP
#define DEPLOY_Z_SERVO() MOVE_SERVO(Z_ENDSTOP_SERVO_NR, z_servo_angle[0])
#define STOW_Z_SERVO() MOVE_SERVO(Z_ENDSTOP_SERVO_NR, z_servo_angle[1])
#endif
#ifdef AUTOMATIC_CURRENT_CONTROL
bool auto_current_control = 0;
#endif
#if ENABLED(PID_EXTRUSION_SCALING)
#if ENABLED(HOST_KEEPALIVE_FEATURE)
MarlinBusyState busy_state = NOT_BUSY;
static millis_t next_busy_signal_ms = 0;
uint8_t host_keepalive_interval = DEFAULT_KEEPALIVE_INTERVAL;
#else
#define host_keepalive() NOOP
#endif
#if ENABLED(I2C_POSITION_ENCODERS)
I2CPositionEncodersMgr I2CPEM;
uint8_t blockBufferIndexRef = 0;
millis_t lastUpdateMillis;
#endif
FORCE_INLINE float pgm_read_any(const float *p) { return pgm_read_float_near(p); }
FORCE_INLINE signed char pgm_read_any(const signed char *p) { return pgm_read_byte_near(p); }
#define XYZ_CONSTS_FROM_CONFIG(type, array, CONFIG) \
static const PROGMEM type array##_P[XYZ] = { X_##CONFIG, Y_##CONFIG, Z_##CONFIG }; \
static inline type array(AxisEnum axis) { return pgm_read_any(&array##_P[axis]); } \
typedef void __void_##CONFIG##__
XYZ_CONSTS_FROM_CONFIG(float, base_min_pos, MIN_POS);
XYZ_CONSTS_FROM_CONFIG(float, base_max_pos, MAX_POS);
XYZ_CONSTS_FROM_CONFIG(float, base_home_pos, HOME_POS);
XYZ_CONSTS_FROM_CONFIG(float, max_length, MAX_LENGTH);
XYZ_CONSTS_FROM_CONFIG(float, home_bump_mm, HOME_BUMP_MM);
XYZ_CONSTS_FROM_CONFIG(signed char, home_dir, HOME_DIR);
/**
* ***************************************************************************
* ******************************** FUNCTIONS ********************************
* ***************************************************************************
*/
void get_available_commands();
void process_next_command();
void prepare_move_to_destination();
void set_current_from_steppers_for_axis(const AxisEnum axis);
void plan_arc(float target[XYZE], float* offset, uint8_t clockwise);
#if ENABLED(BEZIER_CURVE_SUPPORT)
void plan_cubic_move(const float offset[4]);
#endif
void tool_change(const uint8_t tmp_extruder, const float fr_mm_s=0.0, bool no_move=false);
void report_current_position();
void report_current_position_detail();
#if ENABLED(DEBUG_LEVELING_FEATURE)
void print_xyz(const char* prefix, const char* suffix, const float x, const float y, const float z) {
serialprintPGM(prefix);
SERIAL_CHAR('(');
SERIAL_ECHO(x);
SERIAL_ECHOPAIR(", ", y);
SERIAL_ECHOPAIR(", ", z);
if (suffix) serialprintPGM(suffix); else SERIAL_EOL();
void print_xyz(const char* prefix, const char* suffix, const float xyz[]) {
print_xyz(prefix, suffix, xyz[X_AXIS], xyz[Y_AXIS], xyz[Z_AXIS]);
void print_xyz(const char* prefix, const char* suffix, const vector_3 &xyz) {
print_xyz(prefix, suffix, xyz.x, xyz.y, xyz.z);
#define DEBUG_POS(SUFFIX,VAR) do { \
print_xyz(PSTR(" " STRINGIFY(VAR) "="), PSTR(" : " SUFFIX "\n"), VAR); }while(0)
*
* Set the planner/stepper positions directly from current_position with
* no kinematic translation. Used for homing axes and cartesian/core syncing.
#if ENABLED(DEBUG_LEVELING_FEATURE)
if (DEBUGGING(LEVELING)) DEBUG_POS("sync_plan_position", current_position);
#endif
planner.set_position_mm(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
}
inline void sync_plan_position_e() { planner.set_e_position_mm(current_position[E_AXIS]); }
inline void sync_plan_position_kinematic() {
#if ENABLED(DEBUG_LEVELING_FEATURE)
if (DEBUGGING(LEVELING)) DEBUG_POS("sync_plan_position_kinematic", current_position);
planner.set_position_mm_kinematic(current_position);
#define SYNC_PLAN_POSITION_KINEMATIC() sync_plan_position_kinematic()
#define SYNC_PLAN_POSITION_KINEMATIC() sync_plan_position()
#if ENABLED(SDSUPPORT)
#include "SdFatUtil.h"
int freeMemory() { return SdFatUtil::FreeRam(); }
#else
extern char __bss_end;
extern char __heap_start;
extern void* __brkval;
int freeMemory() {
int free_memory;
if ((int)__brkval == 0)
free_memory = ((int)&free_memory) - ((int)&__bss_end);
else
free_memory = ((int)&free_memory) - ((int)__brkval);
return free_memory;
}
extern void digipot_i2c_set_current(uint8_t channel, float current);
extern void digipot_i2c_init();
#endif
* Inject the next "immediate" command, when possible, onto the front of the queue.
* Return true if any immediate commands remain to inject.
static bool drain_injected_commands_P() {
if (injected_commands_P != NULL) {
size_t i = 0;
strncpy_P(cmd, injected_commands_P, sizeof(cmd) - 1);
cmd[sizeof(cmd) - 1] = '\0';
while ((c = cmd[i]) && c != '\n') i++; // find the end of this gcode command
cmd[i] = '\0';
if (enqueue_and_echo_command(cmd)) // success?
injected_commands_P = c ? injected_commands_P + i + 1 : NULL; // next command or done
}
return (injected_commands_P != NULL); // return whether any more remain
}
/**
* Record one or many commands to run from program memory.
* Aborts the current queue, if any.
* Note: drain_injected_commands_P() must be called repeatedly to drain the commands afterwards
void enqueue_and_echo_commands_P(const char * const pgcode) {
injected_commands_P = pgcode;
drain_injected_commands_P(); // first command executed asap (when possible)
}
/**
* Clear the Marlin command queue
*/
void clear_command_queue() {
cmd_queue_index_r = cmd_queue_index_w;
commands_in_queue = 0;
}
* Once a new command is in the ring buffer, call this to commit it
inline void _commit_command(bool say_ok) {
send_ok[cmd_queue_index_w] = say_ok;
if (++cmd_queue_index_w >= BUFSIZE) cmd_queue_index_w = 0;
* Copy a command from RAM into the main command buffer.
* Return true if the command was successfully added.
* Return false for a full buffer, or if the 'command' is a comment.
*/
inline bool _enqueuecommand(const char* cmd, bool say_ok=false) {
if (*cmd == ';' || commands_in_queue >= BUFSIZE) return false;
strcpy(command_queue[cmd_queue_index_w], cmd);
_commit_command(say_ok);
Jérémie FRANCOIS
committed
return true;
}
/**
* Enqueue with Serial Echo
*/
bool enqueue_and_echo_command(const char* cmd, bool say_ok/*=false*/) {
if (_enqueuecommand(cmd, say_ok)) {
SERIAL_ECHOPAIR(MSG_ENQUEUEING, cmd);
SERIAL_CHAR('"');
return true;
}
return false;
}
#endif
}
#if ENABLED(FILAMENT_RUNOUT_SENSOR)
void setup_filrunoutpin() {
#if ENABLED(ENDSTOPPULLUP_FIL_RUNOUT)
SET_INPUT_PULLUP(FIL_RUNOUT_PIN);
#else
SET_INPUT(FIL_RUNOUT_PIN);
#if ENABLED(PS_DEFAULT_OFF)
OUT_WRITE(PS_ON_PIN, PS_ON_AWAKE);
#endif
}
servo[0].attach(SERVO0_PIN);
servo[0].detach(); // Just set up the pin. We don't have a position yet. Don't move to a random position.
servo[1].attach(SERVO1_PIN);
servo[2].attach(SERVO2_PIN);
servo[3].attach(SERVO3_PIN);
Gord Christmas
committed
*
* The servo might be deployed and positioned too low to stow
* when starting up the machine or rebooting the board.
* There's no way to know where the nozzle is positioned until
* homing has been done - no homing with z-probe without init!
*
*/
}
/**
* Stepper Reset (RigidBoard, et.al.)
*/
#if HAS_STEPPER_RESET
void disableStepperDrivers() {
OUT_WRITE(STEPPER_RESET_PIN, LOW); // drive it down to hold in reset motor driver chips
void enableStepperDrivers() { SET_INPUT(STEPPER_RESET_PIN); } // set to input, which allows it to be pulled high by pullups
#if ENABLED(EXPERIMENTAL_I2CBUS) && I2C_SLAVE_ADDRESS > 0
void i2c_on_receive(int bytes) { // just echo all bytes received to serial
i2c.receive(bytes);
}
void i2c_on_request() { // just send dummy data for now
void set_led_color(
const uint8_t r, const uint8_t g, const uint8_t b
#if ENABLED(RGBW_LED)
, const uint8_t w=0
#endif
) {
#if ENABLED(BLINKM)
// This variant uses i2c to send the RGB components to the device.
SendColors(r, g, b);
#endif
#if ENABLED(RGB_LED) || ENABLED(RGBW_LED)
// This variant uses 3 separate pins for the RGB components.
// If the pins can do PWM then their intensity will be set.