Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SINGLENOZZLE: EXTRUDERS versus HOTENDS #3895

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 29 additions & 9 deletions Marlin/Conditionals.h
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,21 @@
#define HAS_PID_HEATING (ENABLED(PIDTEMP) || ENABLED(PIDTEMPBED))
#define HAS_PID_FOR_BOTH (ENABLED(PIDTEMP) && ENABLED(PIDTEMPBED))

/**
* SINGLENOZZLE needs to differentiate EXTRUDERS and HOTENDS
* And all "extruders" are in the same place.
*/
#if ENABLED(SINGLENOZZLE)
#define HOTENDS 1
#undef TEMP_SENSOR_1_AS_REDUNDANT
#undef HOTEND_OFFSET_X
#undef HOTEND_OFFSET_Y
#define HOTEND_OFFSET_X { 0 }
#define HOTEND_OFFSET_Y { 0 }
#else
#define HOTENDS EXTRUDERS
#endif

/**
* ARRAY_BY_EXTRUDERS based on EXTRUDERS
*/
Expand All @@ -551,15 +566,20 @@
#define ARRAY_BY_EXTRUDERS1(v1) ARRAY_BY_EXTRUDERS(v1, v1, v1, v1)

/**
* With SINGLENOZZLE all "extruders" are in the same place
* ARRAY_BY_HOTENDS based on HOTENDS
*/
#if ENABLED(SINGLENOZZLE)
#undef EXTRUDER_OFFSET_X
#undef EXTRUDER_OFFSET_Y
#define EXTRUDER_OFFSET_X { 0 }
#define EXTRUDER_OFFSET_Y { 0 }
#if HOTENDS > 3
#define ARRAY_BY_HOTENDS(v1, v2, v3, v4) { v1, v2, v3, v4 }
#elif HOTENDS > 2
#define ARRAY_BY_HOTENDS(v1, v2, v3, v4) { v1, v2, v3 }
#elif HOTENDS > 1
#define ARRAY_BY_HOTENDS(v1, v2, v3, v4) { v1, v2 }
#else
#define ARRAY_BY_HOTENDS(v1, v2, v3, v4) { v1 }
#endif

#define ARRAY_BY_HOTENDS1(v1) ARRAY_BY_HOTENDS(v1, v1, v1, v1)

/**
* Z_DUAL_ENDSTOPS endstop reassignment
*/
Expand Down Expand Up @@ -695,11 +715,11 @@
* Helper Macros for heaters and extruder fan
*/
#define WRITE_HEATER_0P(v) WRITE(HEATER_0_PIN, v)
#if EXTRUDERS > 1 || ENABLED(HEATERS_PARALLEL)
#if HOTENDS > 1 || ENABLED(HEATERS_PARALLEL)
#define WRITE_HEATER_1(v) WRITE(HEATER_1_PIN, v)
#if EXTRUDERS > 2
#if HOTENDS > 2
#define WRITE_HEATER_2(v) WRITE(HEATER_2_PIN, v)
#if EXTRUDERS > 3
#if HOTENDS > 3
#define WRITE_HEATER_3(v) WRITE(HEATER_3_PIN, v)
#endif
#endif
Expand Down
12 changes: 6 additions & 6 deletions Marlin/Configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@
// Offset of the extruders (uncomment if using more than one and relying on firmware to position when changing).
// The offset has to be X=0, Y=0 for the extruder 0 hotend (default extruder).
// For the other hotends it is their distance from the extruder 0 hotend.
//#define EXTRUDER_OFFSET_X {0.0, 20.00} // (in mm) for each extruder, offset of the hotend on the X axis
//#define EXTRUDER_OFFSET_Y {0.0, 5.00} // (in mm) for each extruder, offset of the hotend on the Y axis
//#define HOTEND_OFFSET_X {0.0, 20.00} // (in mm) for each extruder, offset of the hotend on the X axis
//#define HOTEND_OFFSET_Y {0.0, 5.00} // (in mm) for each extruder, offset of the hotend on the Y axis

//// The following define selects which power supply you have. Please choose the one that matches your setup
// 1 = ATX
Expand Down Expand Up @@ -224,8 +224,8 @@
#define BED_MAXTEMP 150

// If you want the M105 heater power reported in watts, define the BED_WATTS, and (shared for all extruders) EXTRUDER_WATTS
//#define EXTRUDER_WATTS (12.0*12.0/6.7) // P=U^2/R
//#define BED_WATTS (12.0*12.0/1.1) // P=U^2/R
//#define HOTEND_WATTS (12.0*12.0/6.7) // P=U^2/R
//#define BED_WATTS (12.0*12.0/1.1) // P=U^2/R

//===========================================================================
//============================= PID Settings ================================
Expand All @@ -241,8 +241,8 @@
//#define PID_DEBUG // Sends debug data to the serial port.
//#define PID_OPENLOOP 1 // Puts PID in open loop. M104/M140 sets the output power from 0 to PID_MAX
//#define SLOW_PWM_HEATERS // PWM with very low frequency (roughly 0.125Hz=8s) and minimum state time of approximately 1s useful for heaters driven by a relay
//#define PID_PARAMS_PER_EXTRUDER // Uses separate PID parameters for each extruder (useful for mismatched extruders)
// Set/get with gcode: M301 E[extruder number, 0-2]
//#define PID_PARAMS_PER_HOTEND // Uses separate PID parameters for each extruder (useful for mismatched extruders)
// Set/get with gcode: M301 E[extruder number, 0-2]
#define PID_FUNCTIONAL_RANGE 10 // If the temperature difference between the target temperature and the actual temperature
// is more than PID_FUNCTIONAL_RANGE then the PID will be shut off and the heater will be set to min/max.
#define PID_INTEGRAL_DRIVE_MAX PID_MAX //limit for the integral term
Expand Down
2 changes: 1 addition & 1 deletion Marlin/Configuration_adv.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@
#define X2_MAX_POS 353 // set maximum to the distance between toolheads when both heads are homed
#define X2_HOME_DIR 1 // the second X-carriage always homes to the maximum endstop position
#define X2_HOME_POS X2_MAX_POS // default home position is the maximum carriage position
// However: In this mode the EXTRUDER_OFFSET_X value for the second extruder provides a software
// However: In this mode the HOTEND_OFFSET_X value for the second extruder provides a software
// override for X2_HOME_POS. This also allow recalibration of the distance between the two endstops
// without modifying the firmware (through the "M218 T1 X???" command).
// Remember: you should set the second extruder x-offset to 0 in your slicer.
Expand Down
100 changes: 54 additions & 46 deletions Marlin/Marlin_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -356,16 +356,16 @@ static uint8_t target_extruder;
#endif

// Extruder offsets
#if EXTRUDERS > 1
#ifndef EXTRUDER_OFFSET_X
#define EXTRUDER_OFFSET_X { 0 } // X offsets for each extruder
#if HOTENDS > 1
#ifndef HOTEND_OFFSET_X
#define HOTEND_OFFSET_X { 0 } // X offsets for each extruder
#endif
#ifndef EXTRUDER_OFFSET_Y
#define EXTRUDER_OFFSET_Y { 0 } // Y offsets for each extruder
#ifndef HOTEND_OFFSET_Y
#define HOTEND_OFFSET_Y { 0 } // Y offsets for each extruder
#endif
float extruder_offset[][EXTRUDERS] = {
EXTRUDER_OFFSET_X,
EXTRUDER_OFFSET_Y
float hotend_offset[][HOTENDS] = {
HOTEND_OFFSET_X,
HOTEND_OFFSET_Y
#if ENABLED(DUAL_X_CARRIAGE)
, { 0 } // Z offsets for each extruder
#endif
Expand Down Expand Up @@ -1249,7 +1249,7 @@ XYZ_CONSTS_FROM_CONFIG(signed char, home_dir, HOME_DIR);
* This allow soft recalibration of the second extruder offset position
* without firmware reflash (through the M218 command).
*/
return (extruder_offset[X_AXIS][1] > 0) ? extruder_offset[X_AXIS][1] : X2_HOME_POS;
return (hotend_offset[X_AXIS][1] > 0) ? hotend_offset[X_AXIS][1] : X2_HOME_POS;
}

static int x_home_dir(int extruder) {
Expand Down Expand Up @@ -1280,7 +1280,7 @@ static void update_software_endstops(AxisEnum axis) {

#if ENABLED(DUAL_X_CARRIAGE)
if (axis == X_AXIS) {
float dual_max_x = max(extruder_offset[X_AXIS][1], X2_MAX_POS);
float dual_max_x = max(hotend_offset[X_AXIS][1], X2_MAX_POS);
if (active_extruder != 0) {
sw_endstop_min[X_AXIS] = X2_MIN_POS + offs;
sw_endstop_max[X_AXIS] = dual_max_x + offs;
Expand Down Expand Up @@ -4362,6 +4362,10 @@ inline void gcode_M104() {
if (get_target_extruder_from_command(104)) return;
if (DEBUGGING(DRYRUN)) return;

#if ENABLED(SINGLENOZZLE)
if (target_extruder != active_extruder) return;
#endif

if (code_seen('S')) {
float temp = code_value();
thermalManager.setTargetHotend(temp, target_extruder);
Expand Down Expand Up @@ -4407,8 +4411,8 @@ inline void gcode_M104() {
SERIAL_PROTOCOLPGM(" /");
SERIAL_PROTOCOL_F(thermalManager.degTargetBed(), 1);
#endif
#if EXTRUDERS > 1
for (int8_t e = 0; e < EXTRUDERS; ++e) {
#if HOTENDS > 1
for (int8_t e = 0; e < HOTENDS; ++e) {
SERIAL_PROTOCOLPGM(" T");
SERIAL_PROTOCOL(e);
SERIAL_PROTOCOLCHAR(':');
Expand All @@ -4433,8 +4437,8 @@ inline void gcode_M104() {
#else
SERIAL_PROTOCOL(thermalManager.getHeaterPower(target_extruder));
#endif
#if EXTRUDERS > 1
for (int8_t e = 0; e < EXTRUDERS; ++e) {
#if HOTENDS > 1
for (int8_t e = 0; e < HOTENDS; ++e) {
SERIAL_PROTOCOLPGM(" @");
SERIAL_PROTOCOL(e);
SERIAL_PROTOCOLCHAR(':');
Expand All @@ -4453,13 +4457,13 @@ inline void gcode_M104() {
SERIAL_PROTOCOLPGM("C->");
SERIAL_PROTOCOL_F(thermalManager.rawBedTemp() / OVERSAMPLENR, 0);
#endif
for (int8_t cur_extruder = 0; cur_extruder < EXTRUDERS; ++cur_extruder) {
for (int8_t cur_hotend = 0; cur_hotend < HOTENDS; ++cur_hotend) {
SERIAL_PROTOCOLPGM(" T");
SERIAL_PROTOCOL(cur_extruder);
SERIAL_PROTOCOL(cur_hotend);
SERIAL_PROTOCOLCHAR(':');
SERIAL_PROTOCOL_F(thermalManager.degHotend(cur_extruder), 1);
SERIAL_PROTOCOL_F(thermalManager.degHotend(cur_hotend), 1);
SERIAL_PROTOCOLPGM("C->");
SERIAL_PROTOCOL_F(thermalManager.rawHotendTemp(cur_extruder) / OVERSAMPLENR, 0);
SERIAL_PROTOCOL_F(thermalManager.rawHotendTemp(cur_hotend) / OVERSAMPLENR, 0);
}
#endif
}
Expand Down Expand Up @@ -4516,6 +4520,10 @@ inline void gcode_M109() {
if (get_target_extruder_from_command(109)) return;
if (DEBUGGING(DRYRUN)) return;

#if ENABLED(SINGLENOZZLE)
if (target_extruder != active_extruder) return;
#endif

bool no_wait_for_cooling = code_seen('S');
if (no_wait_for_cooling || code_seen('R')) {
float temp = code_value();
Expand Down Expand Up @@ -5391,7 +5399,7 @@ inline void gcode_M206() {

#endif // FWRETRACT

#if EXTRUDERS > 1
#if HOTENDS > 1

/**
* M218 - set hotend offset (in mm)
Expand All @@ -5404,29 +5412,29 @@ inline void gcode_M206() {
inline void gcode_M218() {
if (get_target_extruder_from_command(218)) return;

if (code_seen('X')) extruder_offset[X_AXIS][target_extruder] = code_value();
if (code_seen('Y')) extruder_offset[Y_AXIS][target_extruder] = code_value();
if (code_seen('X')) hotend_offset[X_AXIS][target_extruder] = code_value();
if (code_seen('Y')) hotend_offset[Y_AXIS][target_extruder] = code_value();

#if ENABLED(DUAL_X_CARRIAGE)
if (code_seen('Z')) extruder_offset[Z_AXIS][target_extruder] = code_value();
if (code_seen('Z')) hotend_offset[Z_AXIS][target_extruder] = code_value();
#endif

SERIAL_ECHO_START;
SERIAL_ECHOPGM(MSG_HOTEND_OFFSET);
for (int e = 0; e < EXTRUDERS; e++) {
for (int e = 0; e < HOTENDS; e++) {
SERIAL_CHAR(' ');
SERIAL_ECHO(extruder_offset[X_AXIS][e]);
SERIAL_ECHO(hotend_offset[X_AXIS][e]);
SERIAL_CHAR(',');
SERIAL_ECHO(extruder_offset[Y_AXIS][e]);
SERIAL_ECHO(hotend_offset[Y_AXIS][e]);
#if ENABLED(DUAL_X_CARRIAGE)
SERIAL_CHAR(',');
SERIAL_ECHO(extruder_offset[Z_AXIS][e]);
SERIAL_ECHO(hotend_offset[Z_AXIS][e]);
#endif
}
SERIAL_EOL;
}

#endif // EXTRUDERS > 1
#endif // HOTENDS > 1

/**
* M220: Set speed percentage factor, aka "Feed Rate" (M220 S95)
Expand Down Expand Up @@ -5556,7 +5564,7 @@ inline void gcode_M226() {
// default behaviour (omitting E parameter) is to update for extruder 0 only
int e = code_seen('E') ? code_value() : 0; // extruder being updated

if (e < EXTRUDERS) { // catch bad input value
if (e < HOTENDS) { // catch bad input value
if (code_seen('P')) PID_PARAM(Kp, e) = code_value();
if (code_seen('I')) PID_PARAM(Ki, e) = scalePID_i(code_value());
if (code_seen('D')) PID_PARAM(Kd, e) = scalePID_d(code_value());
Expand All @@ -5568,10 +5576,10 @@ inline void gcode_M226() {

thermalManager.updatePID();
SERIAL_ECHO_START;
#if ENABLED(PID_PARAMS_PER_EXTRUDER)
#if ENABLED(PID_PARAMS_PER_HOTEND)
SERIAL_ECHO(" e:"); // specify extruder in serial output
SERIAL_ECHO(e);
#endif // PID_PARAMS_PER_EXTRUDER
#endif // PID_PARAMS_PER_HOTEND
SERIAL_ECHO(" p:");
SERIAL_ECHO(PID_PARAM(Kp, e));
SERIAL_ECHO(" i:");
Expand Down Expand Up @@ -5690,7 +5698,7 @@ inline void gcode_M303() {

float temp = code_seen('S') ? code_value() : (e < 0 ? 70.0 : 150.0);

if (e >= 0 && e < EXTRUDERS)
if (e >= 0 && e < HOTENDS)
target_extruder = e;

KEEPALIVE_STATE(NOT_BUSY); // don't send "busy: processing" messages during autotune output
Expand Down Expand Up @@ -6272,13 +6280,13 @@ inline void gcode_M503() {
SERIAL_ECHO_START;
SERIAL_ECHOPGM(MSG_HOTEND_OFFSET);
SERIAL_CHAR(' ');
SERIAL_ECHO(extruder_offset[X_AXIS][0]);
SERIAL_ECHO(hotend_offset[X_AXIS][0]);
SERIAL_CHAR(',');
SERIAL_ECHO(extruder_offset[Y_AXIS][0]);
SERIAL_ECHO(hotend_offset[Y_AXIS][0]);
SERIAL_CHAR(' ');
SERIAL_ECHO(duplicate_extruder_x_offset);
SERIAL_CHAR(',');
SERIAL_ECHOLN(extruder_offset[Y_AXIS][1]);
SERIAL_ECHOLN(hotend_offset[Y_AXIS][1]);
break;
case DXC_FULL_CONTROL_MODE:
case DXC_AUTO_PARK_MODE:
Expand Down Expand Up @@ -6436,7 +6444,7 @@ inline void gcode_T(uint8_t tmp_extruder) {
#endif
}

#if EXTRUDERS > 1
#if HOTENDS > 1
if (tmp_extruder != active_extruder) {
// Save current position to return to after applying extruder offset
set_destination_to_current();
Expand All @@ -6454,8 +6462,8 @@ inline void gcode_T(uint8_t tmp_extruder) {
}

// apply Y & Z extruder offset (x offset is already used in determining home pos)
current_position[Y_AXIS] -= extruder_offset[Y_AXIS][active_extruder] - extruder_offset[Y_AXIS][tmp_extruder];
current_position[Z_AXIS] -= extruder_offset[Z_AXIS][active_extruder] - extruder_offset[Z_AXIS][tmp_extruder];
current_position[Y_AXIS] -= hotend_offset[Y_AXIS][active_extruder] - hotend_offset[Y_AXIS][tmp_extruder];
current_position[Z_AXIS] -= hotend_offset[Z_AXIS][active_extruder] - hotend_offset[Z_AXIS][tmp_extruder];
active_extruder = tmp_extruder;

// This function resets the max/min values - the current position may be overwritten below.
Expand Down Expand Up @@ -6485,11 +6493,11 @@ inline void gcode_T(uint8_t tmp_extruder) {
#else // !DUAL_X_CARRIAGE
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
// Offset extruder, make sure to apply the bed level rotation matrix
vector_3 tmp_offset_vec = vector_3(extruder_offset[X_AXIS][tmp_extruder],
extruder_offset[Y_AXIS][tmp_extruder],
vector_3 tmp_offset_vec = vector_3(hotend_offset[X_AXIS][tmp_extruder],
hotend_offset[Y_AXIS][tmp_extruder],
0),
act_offset_vec = vector_3(extruder_offset[X_AXIS][active_extruder],
extruder_offset[Y_AXIS][active_extruder],
act_offset_vec = vector_3(hotend_offset[X_AXIS][active_extruder],
hotend_offset[Y_AXIS][active_extruder],
0),
offset_vec = tmp_offset_vec - act_offset_vec;

Expand Down Expand Up @@ -6521,7 +6529,7 @@ inline void gcode_T(uint8_t tmp_extruder) {

// The newly-selected extruder is actually at...
for (int i=X_AXIS; i<=Y_AXIS; i++) {
float diff = extruder_offset[i][tmp_extruder] - extruder_offset[i][active_extruder];
float diff = hotend_offset[i][tmp_extruder] - hotend_offset[i][active_extruder];
current_position[i] += diff;
position_shift[i] += diff; // Offset the coordinate space
update_software_endstops((AxisEnum)i);
Expand Down Expand Up @@ -6552,7 +6560,7 @@ inline void gcode_T(uint8_t tmp_extruder) {
enable_solenoid_on_active_extruder();
#endif // EXT_SOLENOID

#endif // EXTRUDERS > 1
#endif // HOTENDS > 1

feedrate = stored_feedrate;

Expand Down Expand Up @@ -6983,7 +6991,7 @@ void process_next_command() {
break;
#endif // FWRETRACT

#if EXTRUDERS > 1
#if HOTENDS > 1
case 218: // M218 - set hotend offset (in mm), T<extruder_number> X<offset_on_X> Y<offset_on_Y>
gcode_M218();
break;
Expand Down Expand Up @@ -7853,8 +7861,8 @@ void prepare_move() {
float max_temp = 0.0;
if (ELAPSED(millis(), next_status_led_update_ms)) {
next_status_led_update_ms += 500; // Update every 0.5s
for (int8_t cur_extruder = 0; cur_extruder < EXTRUDERS; ++cur_extruder)
max_temp = max(max(max_temp, thermalManager.degHotend(cur_extruder)), thermalManager.degTargetHotend(cur_extruder));
for (int8_t cur_hotend = 0; cur_hotend < HOTENDS; ++cur_hotend)
max_temp = max(max(max_temp, thermalManager.degHotend(cur_hotend)), thermalManager.degTargetHotend(cur_hotend));
#if HAS_TEMP_BED
max_temp = max(max(max_temp, thermalManager.degTargetBed()), thermalManager.degBed());
#endif
Expand Down
Loading