M190命令
/**
設置熱牀溫度**
**/
inline void gcode_M190()
{
if (DEBUGGING(DRYRUN))
return;
LCD_MESSAGEPGM(MSG_BED_HEATING);//輸出Bed Heating
const bool no_wait_for_cooling = parser.seenval('S');//當指令有S時,此值是設定的溫度值
if (no_wait_for_cooling || parser.seenval('R'))
{
thermalManager.setTargetBed(parser.value_celsius()); //設置熱牀的目標溫度
#if ENABLED(PRINTJOB_TIMER_AUTOSTART)
if (parser.value_celsius() > BED_MINTEMP)
print_job_timer.start();
#endif
}
else
return;
millis_t residency_start_ms = 0;
// Loop until the temperature has stabilized
#define TEMP_BED_CONDITIONS (!residency_start_ms || PENDING(now, residency_start_ms + (TEMP_BED_RESIDENCY_TIME) * 1000UL))
float target_temp = -1.0, old_temp = 9999.0;
bool wants_to_cool = false;
wait_for_heatup = true;
millis_t now, next_temp_ms = 0, next_cool_check_ms = 0;
#if DISABLED(BUSY_WHILE_HEATING)
KEEPALIVE_STATE(NOT_BUSY);
#endif
target_extruder = active_extruder; // for print_heaterstates
do
{
// Target temperature might be changed during the loop
//目標溫度可能在循環時候改變
if (target_temp != thermalManager.degTargetBed())
{
wants_to_cool = thermalManager.isCoolingBed();//判斷是否目標溫度小於當前溫度爲真,此時需要cool
target_temp = thermalManager.degTargetBed();//返回目標溫度
// Exit if S<lower>, continue if S<higher>, R<lower>, or R<higher>
if (no_wait_for_cooling && wants_to_cool)//需要cool就跳出加熱
break;
}
now = millis();
if (ELAPSED(now, next_temp_ms)) //now > next_temp_ms
{ //Print Temp Reading every 1 second while heating up.
//當加熱時,每一秒打印溫度
next_temp_ms = now + 1000UL;
print_heaterstates();
#if TEMP_BED_RESIDENCY_TIME > 0
SERIAL_PROTOCOLPGM(" W:");
if (residency_start_ms)
SERIAL_PROTOCOL(long((((TEMP_BED_RESIDENCY_TIME) * 1000UL) - (now - residency_start_ms)) / 1000UL));
else
SERIAL_PROTOCOLCHAR('?');
#endif
SERIAL_EOL();
}
idle();//可得到當前溫度
refresh_cmd_timeout(); // to prevent stepper_inactive_time from running out
const float temp = thermalManager.degBed(); //返回當前溫度
#if TEMP_BED_RESIDENCY_TIME > 0
const float temp_diff = FABS(target_temp - temp);//溫度差值
if (!residency_start_ms)
{
// Start the TEMP_BED_RESIDENCY_TIME timer when we reach target temp for the first time.
if (temp_diff < TEMP_BED_WINDOW) residency_start_ms = now;//當到達目標溫度附近
}
else if (temp_diff > TEMP_BED_HYSTERESIS) //大於遲滯
{
// Restart the timer whenever the temperature falls outside the hysteresis.
residency_start_ms = now;
}
#endif // TEMP_BED_RESIDENCY_TIME > 0
//防止永遠等待
// Prevent a wait-forever situation if R is misused i.e. M190 R0
if (wants_to_cool)
{
// Break after MIN_COOLING_SLOPE_TIME_BED seconds
// if the temperature did not drop at least MIN_COOLING_SLOPE_DEG_BED
if (!next_cool_check_ms || ELAPSED(now, next_cool_check_ms))
{
if (old_temp - temp < MIN_COOLING_SLOPE_DEG_BED) break;
next_cool_check_ms = now + 1000UL * MIN_COOLING_SLOPE_TIME_BED;
old_temp = temp;
}
}
} while (wait_for_heatup && TEMP_BED_CONDITIONS); //等加熱循環
if (wait_for_heatup)
LCD_MESSAGEPGM(MSG_BED_DONE);
#if DISABLED(BUSY_WHILE_HEATING)
KEEPALIVE_STATE(IN_HANDLER);
#endif
}
設置目標擠出機
bool get_target_extruder_from_command(const uint16_t code) {
if (parser.seenval('T'))
{
const int8_t e = parser.value_byte();
if (e >= EXTRUDERS)
{
SERIAL_ECHO_START();
SERIAL_CHAR('M');
SERIAL_ECHO(code);
SERIAL_ECHOLNPAIR(" " MSG_INVALID_EXTRUDER " ", e);
return true;
}
target_extruder = e;
}
else
target_extruder = active_extruder;
return false;
}
設置nozzle的溫度
inline void gcode_M109()
{
if (get_target_extruder_from_command(109)) //爲1是錯誤
return;
if (DEBUGGING(DRYRUN)) return;
#if ENABLED(SINGLENOZZLE)
if (target_extruder != active_extruder) return;
#endif
const bool no_wait_for_cooling = parser.seenval('S');//有s參數
if (no_wait_for_cooling || parser.seenval('R'))
{
const int16_t temp = parser.value_celsius();
thermalManager.setTargetHotend(temp, target_extruder);//設置目標nozzle
#if ENABLED(DUAL_X_CARRIAGE)
if (dual_x_carriage_mode == DXC_DUPLICATION_MODE && target_extruder == 0)
thermalManager.setTargetHotend(temp ? temp + duplicate_extruder_temp_offset : 0, 1);
#endif
#if ENABLED(PRINTJOB_TIMER_AUTOSTART)
/**
* Use half EXTRUDE_MINTEMP to allow nozzles to be put into hot
* standby mode, (e.g., in a dual extruder setup) without affecting
* the running print timer.
*/
if (parser.value_celsius() <= (EXTRUDE_MINTEMP) / 2)
{
print_job_timer.stop();
LCD_MESSAGEPGM(WELCOME_MSG);
}
else
print_job_timer.start();
#endif
if (thermalManager.isHeatingHotend(target_extruder)) //目標溫度大於當前溫度
lcd_status_printf_P(0, PSTR("E%i %s"), target_extruder + 1, MSG_HEATING);
}
else
return;
#if ENABLED(AUTOTEMP)
planner.autotemp_M104_M109();
#endif
#if TEMP_RESIDENCY_TIME > 0
millis_t residency_start_ms = 0;
// Loop until the temperature has stabilized
#define TEMP_CONDITIONS (!residency_start_ms || PENDING(now, residency_start_ms + (TEMP_RESIDENCY_TIME) * 1000UL))
#else
// Loop until the temperature is very close target
#define TEMP_CONDITIONS (wants_to_cool ? thermalManager.isCoolingHotend(target_extruder) : thermalManager.isHeatingHotend(target_extruder))
#endif
float target_temp = -1.0, old_temp = 9999.0;
bool wants_to_cool = false;
wait_for_heatup = true;
millis_t now, next_temp_ms = 0, next_cool_check_ms = 0;
#if DISABLED(BUSY_WHILE_HEATING)
KEEPALIVE_STATE(NOT_BUSY);
#endif
#if ENABLED(PRINTER_EVENT_LEDS)
const float start_temp = thermalManager.degHotend(target_extruder);
uint8_t old_blue = 0;
#endif
do {
// Target temperature might be changed during the loop
if (target_temp != thermalManager.degTargetHotend(target_extruder)) {
wants_to_cool = thermalManager.isCoolingHotend(target_extruder);
target_temp = thermalManager.degTargetHotend(target_extruder);
// Exit if S<lower>, continue if S<higher>, R<lower>, or R<higher>
if (no_wait_for_cooling && wants_to_cool) break;
}
now = millis();
if (ELAPSED(now, next_temp_ms))
{ //Print temp & remaining time every 1s while waiting
next_temp_ms = now + 1000UL;
print_heaterstates();
#if TEMP_RESIDENCY_TIME > 0
SERIAL_PROTOCOLPGM(" W:");
if (residency_start_ms)
SERIAL_PROTOCOL(long((((TEMP_RESIDENCY_TIME) * 1000UL) - (now - residency_start_ms)) / 1000UL));
else
SERIAL_PROTOCOLCHAR('?');
#endif
SERIAL_EOL();
}
idle();
refresh_cmd_timeout(); // to prevent stepper_inactive_time from running out
const float temp = thermalManager.degHotend(target_extruder);
#if ENABLED(PRINTER_EVENT_LEDS)
// Gradually change LED strip from violet to red as nozzle heats up
if (!wants_to_cool)
{
const uint8_t blue = map(constrain(temp, start_temp, target_temp), start_temp, target_temp, 255, 0);
if (blue != old_blue)
{
old_blue = blue;
set_led_color(255, 0, blue
#if ENABLED(NEOPIXEL_LED)
, 0
, pixels.getBrightness()
#if ENABLED(NEOPIXEL_IS_SEQUENTIAL)
, true
#endif
#endif
);
}
}
#endif
#if TEMP_RESIDENCY_TIME > 0
const float temp_diff = FABS(target_temp - temp);
if (!residency_start_ms) {
// Start the TEMP_RESIDENCY_TIME timer when we reach target temp for the first time.
if (temp_diff < TEMP_WINDOW) residency_start_ms = now;
}
else if (temp_diff > TEMP_HYSTERESIS) {
// Restart the timer whenever the temperature falls outside the hysteresis.
residency_start_ms = now;
}
#endif
// Prevent a wait-forever situation if R is misused i.e. M109 R0
if (wants_to_cool)
{
// break after MIN_COOLING_SLOPE_TIME seconds
// if the temperature did not drop at least MIN_COOLING_SLOPE_DEG
if (!next_cool_check_ms || ELAPSED(now, next_cool_check_ms)) {
if (old_temp - temp < MIN_COOLING_SLOPE_DEG) break;
next_cool_check_ms = now + 1000UL * MIN_COOLING_SLOPE_TIME;
old_temp = temp;
}
}
} while (wait_for_heatup && TEMP_CONDITIONS);//循環加熱
if (wait_for_heatup)
{
LCD_MESSAGEPGM(MSG_HEATING_COMPLETE);
#if ENABLED(PRINTER_EVENT_LEDS)
#if ENABLED(RGB_LED) || ENABLED(BLINKM) || ENABLED(PCA9632) || ENABLED(RGBW_LED)
set_led_color(LED_WHITE);
#endif
#if ENABLED(NEOPIXEL_LED)
set_neopixel_color(pixels.Color(NEO_WHITE));
#endif
#endif
}
#if DISABLED(BUSY_WHILE_HEATING)
KEEPALIVE_STATE(IN_HANDLER);
#endif
}