prusa3d / PrusaSlicer

G-code generator for 3D printers (RepRap, Makerbot, Ultimaker etc.)
https://www.prusa3d.com/prusaslicer/
GNU Affero General Public License v3.0
7.73k stars 1.93k forks source link

[FR] Chamber Temperature Support M141/M191 #4356

Closed Andrei-Pozolotin closed 4 months ago

Andrei-Pozolotin commented 4 years ago

RE:

  1. currently PrusaSlicer v 2.2.0 has no support for chamber temperature settings:

image

  1. which is properly supported by OctoPrint v 1.4.0, i.e.:

image

rtyr commented 4 years ago

As a workaround, it should be possible to use custom g-code section in filament settings for that purpose.

ch

Andrei-Pozolotin commented 4 years ago
  1. sure, yes, thank you

  2. except that insert happens "too late": this is how slicer generates gcode at present:

    M107
    M190 S120 ; set bed temperature and wait for it to be reached
    M104 S310 ; set temperature
    PRINT_START ; <---------------- location of per-printer insert
    M109 S310 ; set temperature and wait for it to be reached
    G21 ; set units to millimeters
    G90 ; use absolute coordinates
    M83 ; use relative distances for extrusion
    FILAMENT_START ; <---------------- location of per-filament insert
  3. instead, M141/M191 insert need to happen twice:

    • before first "bed temperature" M190
    • and before last "tool temperature" M109
      M107
      M141 S70  ; set chamber temperature (no wait) <---------------- ONE
      M190 S120 ; set bed temperature and wait for it to be reached
      ...
      M191 S70  ; set chamber temperature (with wait) <---------------- TWO
      M109 S310 ; set temperature and wait for it to be reached
natthapolvanasrivilai commented 2 years ago

Is there any update on the heated chamber feature?

lukasmatena commented 2 years ago

@natthapolvanasrivilai Not in PrusaSlicer 2.4. It should really be possible to handle it in custom G-Codes, though.

radaiko commented 2 years ago

+1 from my side. I need a chamber temperature as well to be set in the filament tab but I use it then as an variable in the PRINT Start command which will run a script on Klipper to start heating and wait till the camber reaches the temp.

Only then it will start with bed mesh, purge line and so on.

So as an custom g-code for the filament it's really to late.

I use it now with SuperSlicer but I want to switch back to PrusaSlicer. This is the only thing what's holds me back. The minimum chamber temperature is really necessary for material like ABS, ASA, PA-CF to has as minimum warping as possible.

djcutch commented 2 years ago

Here is some crazy code i did to get it to work with out feild.

gcode:

Parameters

{% set bed_temp = params.BED|default(60)|int %}
{% set extruder_temp = params.EXTRUDER_LAYER|default(210)|int %}
{% if bed_temp > 100|int %}
  {% set chambertemp = params.CHAMBER_TEMP|default(60)|int %}
{% else %}
  {% set chambertemp = params.CHAMBER_TEMP|default(30)|int %}
{% endif %}
M117 Heating...
G28
G0 X175 Y175 Z175 F2000
M106 S255
M117 set bed final temp {bed_temp}   
M140 S{bed_temp}                         ; set bed final temp
M117 Waiting for bed final temp {bed_temp}  
M190 S{bed_temp}                         ; wait for bed final temp
{% if bed_temp > 100|int %}
  M104 S200
{% else %}
  M104 S170
{% endif %}  
TEMPERATURE_WAIT SENSOR="temperature_sensor chamber" MINIMUM={(chambertemp|float * 0.9)|round}
M106 S0
M104 S0
M117 QUAD_GANTRY_LEVEL
G32
M117 set extruder final temp to 80% {extruder_temp} 
M104 S{extruder_temp|int * 0.80}                        ; set extruder temp 80% of final temp
M117 wait for extruder final temp to reach 80%  {extruder_temp} 
M109 S{extruder_temp|int * 0.80}           ; get the nozzle up to 80% temp so the cleaning brush can knock off debris
G21 ; set units to millimeters
G90 ; use absolute coordinates
M83 ; use relative distances for extrusion
{% if bed_temp > 100|int %}
M117 Heat Soak
M106 S255
HEAT_SOAK
{% endif %}
M106 S0
IconoclastXYZ commented 1 year ago

+1 - given Arachne and the forthcoming organic supports, this is the only part holding me back from switching from Superslicer.

Using a Voron with chamber temperature control is straightforward on Superslicer, and as noted above, comes too late if using custom filament code.

drelich commented 1 year ago

Any update on this? Such a basic feature, I can't believe it's still not done two and a half years since the OP's post...

szafran81 commented 1 year ago

Have you guys tried this in the start g-code:

M190 S0
M104 S0
PRINT_START EXTRUDER={first_layer_temperature[initial_extruder]} BED=[first_layer_bed_temperature]

That way one sets up everything in PRINT_START in the correct order. One can add something like FILAMENT=[filament_type] to the params passed to PRINT_START script to use it to set the chamber temp. And I know it's still not the correct way of doing this, but maybe it helps someone.

IconoclastXYZ commented 1 year ago

That is a great idea. You could then put something like this in the PRINT_START macro: {% set filament = params.FILAMENT|default("NONE")|string %} to catch the filament type and then this to set the chamber temp:

    {% if filament != 'NONE' %}                                                         
        {% set fct = {'ASA': 30, 'ABS': 50, 'NYLON': 35, 'PLA': 0, 'PC': 50 } %}
        {% set chamber = fct[filament] %}
        { action_respond_info("Filament chamber temp - " + chamber|string) }
    {% endif %}

This means that I can call the same PRINT_START from SuperSlicer or PrusaSlicer.

szafran81 commented 1 year ago

One just needs to remember that those:

M190 S0
M104 S0

must be in the start g-code field in PSlicer otherwise it will put them in with temps set in the filament options.

Edigorin commented 1 year ago

Here's how I did it. Thanks to @szafran81 and @IconoclastXYZ for their ideas. (My Setup is for a RatRig V-Core 500.)

This assumes you have a chamber temperature sensor definied as such in printer.cfg: [temperature_sensor chamber_temp]

Define this in your slicer custom Printer Start G-Code: START_PRINT EXTRUDER_TEMP=[first_layer_temperature] BED_TEMP=[first_layer_bed_temperature] FILAMENT=[filament_type]

I prefer to define the required CHAMBER_TEMP in my printer configuration, as you would otherwise need seperate printer profiles for each chamber temperature you print with. Make sure the filament type is defined in PrusaSlicer under "Filament Settings-Advanced-Filament type"

Create this Macro in your printer.cfg:

[gcode_macro _START_PRINT_HEAT_CHAMBER]
description: Uses the chamber sensor to wait for chamber temp.
gcode:
  {% if params.FILAMENT is defined %} 
    {% set filament = params.FILAMENT|default("NONE")|string %}
    {% if filament != 'NONE' %}
      {% set fct = ({"ASA": 55, "ABS": 55, "NYLON": 35, "PLA": 0, "PC": 50, "PET": 42 }) %} #adjust as needed
      {% set fbt = ({"ASA": 115, "ABS": 115, "NYLON": 115, "PLA": 0, "PC": 115, "PET": 85 }) %} #adjust as needed 
      {% set chamber = fct[filament] %}
      {% set bed = fbt[filament] %}
      { action_respond_info("Filament: " + filament|string + ", Chamber Temp: " + chamber|string + ", Preheat Bed Temp: " + bed|string) }
      {% set chamber_temp = printer["temperature_sensor chamber_temp"].temperature|float %}
      {% if chamber_temp < chamber|int %}
        RESPOND MSG="Heating chamber..."
        M140 S{bed|int} #set bed temp to reach desired chamber temp
        M104 S{150} #preheat extruder while waiting
        M106 S191 #enable fan 75% to spread the heat better
        G28 #replace with MAYBE_HOME if available
        #Z_TILT_ADJUST #if available, adjust Z-Tilt while waiting. This will be done again after preheating, but faster as it was already run.
        G0 X{printer.toolhead.axis_maximum.x/2} Y{printer.toolhead.axis_maximum.y/2} Z{20} F6000 #Go to center of bed
        TEMPERATURE_WAIT SENSOR="temperature_sensor chamber_temp" MINIMUM={chamber|int} #Wait for chamber Temp
        M117 Finished Heating chamber... 
        #RESPOND MSG="Finished Heating chamber..." #can be enabled if RESPOND feature is enabled
      {% else %}
        M117 Chamber already heated.
        #RESPOND MSG="Chamber already heated." #can be enabled if RESPOND feature is enabled
      {% endif %}
    {% else %}
      M117 Issue with Slicer Filament Detection. 
      #RESPOND MSG="Issue with Slicer Filament Detection." #can be enabled if RESPOND feature is enabled
    {% endif %}
  {% endif %}

Adjust chamber and bed preheat temperatures as needed. Add filament types as needed.

Call the macro at the start of your START_PRINT macro: _START_PRINT_HEAT_CHAMBER CHAMBER_TEMP={params.CHAMBER_TEMP} FILAMENT={params.FILAMENT}

AustinTylerDean commented 1 year ago

image

I guess I don't have this right. Should it be print_start instead? I've always scratched my head when I see macros and such written one way or the other.

szafran81 commented 1 year ago

It looks like you do have something wrong in your config. Do remove the macro from your config and copy/paste as @Edigorin posted, and then change things in it. And do call the macro exactly as he said.

EDIT: Also note PRINT_START is not the same as _START_PRINT_HEAT_CHAMBER. You need to call the _START_PRINT_HEAT_CHAMBER submacro from the PRINT_START macro as stated above.

AustinTylerDean commented 1 year ago

It looks like you do have something wrong in your config. Do remove the macro from your config and copy/paste as @Edigorin posted, and then change things in it. And do call the macro exactly as he said.

EDIT: Also note PRINT_START is not the same as _START_PRINT_HEAT_CHAMBER. You need to call the _START_PRINT_HEAT_CHAMBER submacro from the PRINT_START macro as stated above.

I guess PRINT_START and START_PRINT macro names have been done both ways with custom macros, so that was the initial problem.

Through a BUNCH of testing, I have augmented everything to work perfectly, including the initiation and correct heat soak routine for an ACTIVE heater for the chamber (with dedicated heater fan). This thread was invaluable to me!!!

It certainly would be nice to have our interface easily accommodate a chamber temp, though! If anyone has an active heater and would like some help, please don't hesitate to ask. I'm not going to splooge my code all over this thread without a declared invitation though :)

szafran81 commented 1 year ago

@AustinTylerDean splooge away. Sameone may use it in the future (like me ;) - i do plan to put some kind of a heating element inside my 2 Vorons)

IconoclastXYZ commented 1 year ago

I agree with @szafran81, splooge away.

I did my active chamber heating slightly differently than @Edigorin because I wanted to keep the setup compatible with both PrrusaSlicer (which does not let you emit ChamberTemp into the Print_Start routine and SuperSlicer (which does).

It also sets up the exhaust fan to stop the chamber overheating (as the bed warms up) and incorporates a bed heating equilibration sensor instead of waiting a fixed time after the thermistor underneath reaches the set temp.

It needs a duplicate pin override:

## Allows the chamber temperature sensor to be used for the chamber temp, the chamber heater and the exhaust fan
[duplicate_pin_override]
pins: EBBCan: PA3, PA8

Then

[gcode_macro PRINT_START]
# For setting the parameters as persistent variables so they can be referenced in PRINT_START2
variable_bedtemp: 0
variable_hotendtemp: 0
variable_chambertemp: 0
gcode:      
    # Parameters
   {% set bed = params.BED|int %}
   {% set hotend = params.HOTEND|int %}
   {% set chamber = params.CHAMBER|default(0)|int %}

    # An alternative way to work out chamber temperature from PrusaSlicer, which does not pass CHAMBER
    {% set filament = params.FILAMENT|default("NONE")|string %}   
    { action_respond_info("Filament type - " + filament) }
    {% if filament != 'NONE' %}                                                         
        {% set fct = {'ASA': 50, 'ABS': 50, 'NYLON': 0, 'PLA': 0, 'PC': 50, 'PET': 45 } %}
        {% set chamber = fct[filament] %}
        { action_respond_info("Filament chamber temp - " + chamber|string) }
    {% endif %}

   # Set the parameters as persistent variables so they can be referenced outside of the macro (in PRINT_END)
   SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=bedtemp VALUE={bed}    
   SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=hotendtemp VALUE={hotend}  
   SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=chambertemp VALUE={chamber}    

   UPDATE_DELAYED_GCODE ID=EXHAUST_OFF DURATION=0                                     ; cancel exhaust off timer (if there is one)
   UPDATE_DELAYED_GCODE ID=DELAYED_OFF DURATION=0                                     ; cancel off timer (if there is one)
   SET_PIN PIN=caselight VALUE=0.67                                                   ; turn on case light
   _RESETSPEEDS                                                                       ; reset speed, accel etc to configured values
   SET_NOZZLE_LEDS_BY_NAME COLOR="WHITE"                                                ; turn on nozzle LEDs
   SET_LOGO_LEDS_BY_NAME COLOR="WHITE"                                                  ; set logo LEDs back to white
   SET_Z_THERMAL_ADJUST ENABLE=1
   M104 S{150}                                                                            ; set hotend to no-ooze temp allowed for TAP bed probe
   M140 S{bed}                                                                            ; set bed to target temp
   G28                                                                                    ; home
   CLEANNOZZLE
   G28
   G90                                                                                    ; absolute positioning

   {% if chamber > 35 %}                                                                ; if the chamber desired temp is over baseline (35) then setup exhaust fan to keep it under control
        SET_TEMPERATURE_FAN_TARGET temperature_fan=Exhaust target={chamber+1}           ; plus 1 to temp to offset hysteresis
        SET_HEATER_TEMPERATURE HEATER=chamber_heater TARGET={chamber}                   ; set the chamber heater to work above 35C target
    {% else %}
        SET_TEMPERATURE_FAN_TARGET temperature_fan=Exhaust target=35
    {% endif %}

   {% if printer["temperature_sensor chamber"].temperature < chamber and chamber > 35 %}                ; - if chamber is not at temp yet:
      HEATSOAK T={bed} MOVE=1                                                                           ;   heatsoak macro + park in center
      M190 S{bed}                                                                                   ;   set bed chamber heating temp
       { action_respond_info("Waiting for chamber to reach temperature") }
       TEMPERATURE_WAIT SENSOR="temperature_sensor chamber" MINIMUM={chamber}                           ;   wait for chamber final temp
       { action_respond_info("Waiting for bed to reach set temp") }
       M190 S{bed}                                                                                    ; waits for bed to return to desired temp
    {% else %}                                                                                          ; - if chamber is already at temp:
        {% if printer.heater_bed.temperature < (bed-2) %}                                               ; -- but bed is not fully heated (within 2C):
            HEATSOAK T={bed} MOVE=1                                                                     ;       heatsoak and park
            M190 S{bed}                                                                                 ;       wait for bed final temp
        {% else %}                                                                                      ; -- and bed is already heated:
            HEATSOAK T={bed} MOVE=0                                                                     ;       "heatsoak" without parking (only still calling this because it does some other things like turn off exahaust fan)
        {% endif %}
    {% endif %} 

    { action_respond_info('Waiting for bed undersurface to reach %.1fC' % (bed*0.80)) }
    TEMPERATURE_WAIT SENSOR="temperature_sensor Bed_Rear_Bottom" MINIMUM={bed*0.80}                   ; wait for the outside of the bed to be within 15% of the center under the heating pad
    SET_LOGO_LEDS_BY_NAME COLOR="WHITE"                                                  ; set logo LEDs back to white
   M106 S0                                                                                              ; turn off part cooling fan (from heatsoak)
   BED_MESH_CLEAR                                                                                       ; clear bed mesh
    { action_respond_info("Performing QGL and BedMesh") }
   QUAD_GANTRY_LEVEL                                                                                    ; quad gantry level
   G28 Z                                                                                                ; home z
   BED_MESH_CALIBRATE                                                                                   ; mesh
   G28 Z                                                                                                ; home z again

    G0 X55 Y350 F19500  ; go to purge bucket whilst warming up to temp
    M109 S{hotend}                                                                                      ; set & wait for hotend final temp
    ADAPTIVE_PURGE

   G92 E0                                                                                           ; reset Extruder
   G1 Z10 F3000                                                                                     ; move Z Axis up
   SET_FILAMENT_SENSOR SENSOR=filament_sensor ENABLE=1                                              ; enable filament sensor

    M117  # Blank message - hopefully
IconoclastXYZ commented 1 year ago

One way of mounting the heater - with an ASA printed hot air diverter angled so that it doesn't just heat the front door:

20230626_202315 20230626_202218

AustinTylerDean commented 1 year ago

EDIT: Cleaned up some formatting and descriptions of my rig. Adjusted code slightly.

; chamber heater and fan config (DON'T COPY AND PASTE THIS PART, DO YOUR $*&#ING HOMEWORK!) ; Be sure to start conservatively and plan on blowing a couple fuses. This would be a good thing! ; This was with an Amazon Basics 500W personal space heater that I dissected. I wired a mains heater leg to an SSR, and the fan to a fan connector on the Octopus board with 12v jumper (I junked the 120VAC to 12VDC buck that was already installed). I also installed the same thermal fuse that's installed on the bed (120C) to replace the ceramic fuse already in the heater. Lastly, I cut out the momentary pushbutton safety switch that closes when the device is upright. ; By cutting the black acrylic rear wall of the printer to fit the heater shroud, I was able to take the shroud and the enclosure of the Amazon heater and sandwich them to the acrylic wall. By using the stock screws and screw holes, the whole heater assembly firmly mounts to the acrylic wall. Even the grill fits flush, so the gantry can roll right on by! I installed this in the upper left corner looking through the front doors as to help mitigate the airflow flowing directly on the print. Though I saw a pretty clever heater + airflow solution by @IconoclastXYZ in this thread. Be sure to check that out.

I also ran a generic thermistor into the chamber for chamber temp.

[heater_generic chamber_heater] heater_pin: PA2 sensor_type: Generic 3950 sensor_pin: PF4 control: watermark max_delta: 0.1 max_power: 0.45 min_temp: 0 max_temp: 70

[verify_heater chamber_heater] max_error: 360 check_gain_time: 480 hysteresis: 5 heating_gain: 1

[heater_fan chamber_fan] pin:PD12 max_power: 1.0 heater: chamber_heater heater_temp: 70 fan_speed: 0.8

; embedded in PRINT_START macro _START_PRINT_HEAT_CHAMBER CHAMBER_TEMP={params.CHAMBER_TEMP} FILAMENT={params.FILAMENT} EXTRUDER_TEMP={params.EXTRUDER_TEMP}

; standalone macro (this allows you to set your bed and chamber based on the filament type passed by PrusaSlicer)

*[gcode_macro _START_PRINT_HEAT_CHAMBER] description: Uses the chamber sensor to wait for chamber temp. gcode: {% if params.FILAMENT is defined %} {% set filament = params.FILAMENT|default("NONE")|string %} {% set target_extruder = params.EXTRUDER_TEMP|int %} {% if filament != 'NONE' %} {% set fct = ({"ASA": 50, "ABS": 50, "NYLON": 35, "PLA": 0, "PC": 50, "PET": 42 }) %} #adjust as needed {% set fbt = ({"ASA": 95, "ABS": 95, "NYLON": 95, "PLA": 0, "PC": 100, "PET": 70 }) %} #adjust as needed {% set chamber = fct[filament] %} {% set bed = fbt[filament] %} { action_respond_info("Filament: " + filament|string + ", Chamber Temp: " + chamber|string + ", Preheat Bed Temp: " + bed|string) } {% set chamber_temp = printer["heater_generic chamber_heater"].temperature|float %} {% if chamber_temp < chamber|int %} RESPOND MSG="Heating chamber..." M141 S{chamber|int} #set chamber heater to temp based on filament choice of PrusaSlicer M140 S{bed|int} #set bed temp to reach desired chamber temp M104 S{(target_extruder 0.8)} #preheat extruder while waiting M106 S191 #enable fan 75% to spread the heat better G28 #replace with MAYBE_HOME if available G0 X{printer.toolhead.axis_maximum.x/2} Y{printer.toolhead.axis_maximum.y/2} Z{20} F6000 #Go to center of bed TEMPERATURE_WAIT SENSOR="heater_generic chamber_heater" MINIMUM={chamber|int} #Wait for chamber Temp M104 S{target_extruder|int} M117 Finished Heating chamber...

RESPOND MSG="Finished Heating chamber..." #can be enabled if RESPOND feature is enabled

  {% else %}
    M117 Chamber already heated.
    #RESPOND MSG="Chamber already heated." #can be enabled if RESPOND feature is enabled
  {% endif %}
{% else %}
  M117 Issue with Slicer Filament Detection. 
  #RESPOND MSG="Issue with Slicer Filament Detection." #can be enabled if RESPOND feature is enabled
{% endif %}

{% endif %}**

I hope I didn't forget any other critical pieces...

AustinTylerDean commented 1 year ago

One way of mounting the heater - with an ASA printed hot air diverter angled so that it doesn't just heat the front door:

20230626_202315 20230626_202218

Wow, that (you as well) is dope. What kind of panels are those? And is that just a badge yoyo holding up your umb/ptfe?

I think you maxed out the design btdubs.

IconoclastXYZ commented 1 year ago

Hey @AustinTylerDean, thanks!

The panels are 8mm polycarbonate Twinwall from Bunnings (https://github.com/IconoclastXYZ/Voron/blob/main/articles/insulation.md) - makes for really good insulation, is cheap, easy to cut to size (unlike perspex!) and lets the light through. Even with the heater running right against it, the outside is cool, unlike the front door (standard clear perspex) which gets nice and warm! It is also much safer to have up against an active heater given its higher glass transition temp and melting point.

And yes, the badge yoyo works great!

Jan-Soustruznik commented 9 months ago

Issue created, SPE-1901. Thank you

sirjaymz commented 9 months ago

1337 days ...

moth4017 commented 4 months ago

Please can you also add dry box heat too. is there a way to add to the start G code M191 S "wait for chamber to reach temperature?

lukasmatena commented 4 months ago

Support for heated chamber was added in 2.8.0. Closing.