Setting up chamber heating with Klipper and Octoprint

I recently (finally!) enclosed my SK-Tank and am now adding chamber heating. I thought I’d share all the steps I went through to enable this.

Physical Installation

Rather than worry about whether my control board has enough power on one of its heater controls (really meant for a hot end) for a 200W PTC heater, I just bought an AC 200W PTC heater and used a SCR to control it, hooked up in parallel with the bed heater SCR. This also means that if I decide I need more power, I can just add another PTC heater behind that same new SCR. Here’s a simplified schematic:

To the left of this schematic and not shown, connected to ports 1 and 2 of the two SCRs, are connections to two heater MOSFETs on the controller board. In my case, that’s a BTT GTR.

(Not shown in that simplified schematic is that the bed heater has a thermal fuse on the load side, the heat sink on the chamber SCR has a thermal fuse, and the PTC chamber heater I think has an internal thermal fuse, and becomes less powerful as it heats up, so it is self-limiting. I left that out because I believe the chamber SCR doesn’t actually need the thermal fuse; it’s a leftover from the previous use of that SCR.)

From their github repository for the GTR board, here’s one corner of the board:

So the “BED OUT” (which they seem to have forgotten to label is controlled by pin PA2) goes to to the SCR connected to the AC bed heater, and I’m using “HEAT2” (which is labeled with pin PB0) to control the SCR connected to the PTC heater.

Next, I grabbed a bare thermistor that was intended for a hot end, and attached it in the chamber so it isn’t touching the walls.

Then I connected it to an open thermistor port “T1” which this part of the diagram shows is pin PC2.

Klipper Configuration

Now I added some Klipper printer.cfg entries.

[heater_generic chamber]
heater_pin: PB0
max_power: 1.0
sensor_type: NTC 100K beta 3950
sensor_pin: PC2
control: watermark
max_delta: 1.0
min_temp: -100
max_temp: 70
gcode_id: C

[verify_heater chamber]
max_error: 300
check_gain_time: 480
hysteresis: 5
heating_gain: 1

[gcode_macro M141]
gcode:
   SET_HEATER_TEMPERATURE HEATER=chamber TARGET={params.S}

[gcode_macro M191]
gcode:
   SET_HEATER_TEMPERATURE HEATER=chamber TARGET={params.S}
   TEMPERATURE_WAIT SENSOR="heater_generic heater_chamber" MINIMUM={params.S}

The watermark control is “bang-bang” off/on control, instead of the PID controls that get used for most things. The gcode_id: C means that the response to the M105 status command encodes the chamber temperature with the letter C like this:

M105
ok B:30.2 /0.0 C:39.8 /50.0 T0:30.8 /0.0

That reads:

  • B (bed) temperature currently 30.2, set to 0
  • C (chamber) temperature currently 39.8, set to 50
  • T0 (tool 0, my hotend) temperature currently 30.8, set to 0

The gcode_macros map the normal chamber M-commands to Klipper’s extended command syntax for this heater.

Octoprint Configuration

Now Octoprint needs to know that there is a chamber heater. If you try to send the M141 command without configuring a chamber heater, it helpfully tells you that you need to edit the printer profile to turn that on. To do that, use the wrench icon at the top to get into Octoprint settings, Printer Profiles, pencil icon to edit the profile for the printer in question, Print bed & print volume, and select Heated Chamber

After that, you’ll have the chamber temperature as an option on the Temperature tab. However, Octoprint doesn’t seem to have the ability to include chamber heating in its presets, and I see a feature request from 2019 for this so I’m guessing it’s not a priority.

Results

It looks like I was wise to choose a solution that would be easy to extend to a second heater. I find that if I turn the chamber heater on alone, the chamber goes fairly quickly to almost 40°C, but doesn’t get much higher. Adding 400W of bed heater helps it climb, but it still struggles to get close to 50°C as you can see in this graph:

Even after about 15 minutes of both the bed and chamber heaters going, the chamber temperature doesn’t quite reach 50°C. In my printer, there are holes near the bottom and the top of the enclosure for belts to go through; only the extruder stepper is inside the enclosure. (It’s rated for 180°C so hopefully that is OK.)

With the bed heater going, if I set the desired chamber temperature to 45°, you can see the hysteresis in chamber temperature:

While I have a bit more sealing I can do at the bottom of the front door of the chamber, I think I’ll buy a 400 W PTC heater and either replace the 200W with the 400W or use them in parallel. In retrospect, if I’d noticed that there was a 400W version in the first place, I would have just ordered it.

I have another heater control and thermistor input empty still on the board. I suppose I could buy yet another SCR and change the macro to use them both to get to temperature, but make the setpoint for the 400W heater be a little lower than the 200W heater, or even just mount its thermistor in a different location with a different temperature. I might do that; if I do I’ll share that configuration as well.

2 Likes

My Qidi X-Max 3 has about an eighth of a cubic meter of internal volume to heat with a 200W heater. My SK-Tank enclosure has almost a quarter of a cubic meter. It also probably isn’t quite as tight, given that I have some gaps at the front near the bottom of the door, and five places where belts pass through the enclosure (keeping all the steppers except the high-temperature extruder motor outside the heated chamber).

That means that it makes sense that it should easily require twice the power to heat, and probably a bit more.

Starting a couple degrees colder than my previous experiment (a cold front went through…) using only the new 400W heater, my enclosure reached 45°C in just over 10 minutes, and in about 15 minutes reached the 47.5° that took about 25 minutes previously. In 25 minutes, it reached 51° with just the 400W heater

The 400W heater is substantially physically larger than the 200W heater. I had vaguely expected the same frame with a more powerful (lower resistance) element inside it, but also I’m not particularly surprised that it’s just more element.

The 200W heater appears to have higher velociy; at least, when I first turned it on, the temperature reading dropped quickly from 51.7° to 49.2° ­— not because the air suddenly really got colder; clearly it did a better job of mixing the air at that higher velocity. With both heaters on, I did get to a chamber temperature of over 60°:

I have the fans sitting loose on the floor of the enclosure for testing, while I try to decide how to affix them permanently. The dip in the graph was me opening the door to move one of the fans to not point so directly at the side. (The outside of the polycarbonate twinwall was getting a little bit hot in one place.) I can feel that the top of the door is where a substantial amount of heat is escaping.

The 400W heater alone can’t quite maintain 60°; by having the 400W heater run constantly, I see the 200W heater cycle about once per minute to maintain 60°. Then it drops down to around 55° when running only the 400W heater constantly.

I don’t think I’m likely to want a chamber temperature higher than 60°

Turning the bed up to 80°, I see that it doesn’t need nearly so much of a boost from the 200W heater above the 400W baseline to hold a chamber temperature of 60° — In fact, with the bed at 80° and the 400W heater running constantly, the 200W heater barely runs.

I’ve been feeling where heat is escaping and sealing some places better, but the front door is the worst. I’ll probably want to at least add a magnetic catch at the top. I already am using a magnetic catch for the main handle, but the top of the door leaks heat.

I’ve decided that I am going to set up a second SCR. I have one more heater output from the board, and I can set up the M141 and M191 to switch both heaters on, using different setpoints and hysteresis for the two heaters so that both are used to get to temperature, but at most settings, one heater will run full-time and the other part time. I think that I’ll end up with three conditions:

  • below about 45°, once it reaches temperature, I should arrange it so that only the 200W heater cycles and the 400W heater is always off
  • between 45° and 55°, the 200W heater is always on and the 400W heater cycles
  • above 55°, the 400W heater is always on and the 200W heater cycles
  • and, I guess, a fourth: at temperatures that I don’t expect to set, they’ll both be on all the time because they just can’t manage to hold it at temperature. :smiley:

I note that running the 400W chamber heater, the 200W chamber heater, and the 400W heated bed simultaneously (along with a few other smaller loads) makes my 1500VA UPS unhappy. This makes sense, since a 1500VA UPS can actually typically supply about a 900W resistive load. I’m thinking that maybe the chamber heaters should be on their own, non-battery-protected circuit, instead of sharing the circuit with all the other heaters.

2 Likes

I don’t, actually. But I’m not using the wifi header, so I can borrow PC7 from it. I’ve just hooked up PC7 and the adjacent GND to the third SSR…

Sharing thermistors between two heaters requires that you explicitly enable sharing a pin, since usually that’s accidental and potentially a bad thing to do.

[duplicate_pin_override]
# Allow using PC2 to sense temperature for both chamberlow and chamberhigh
pins: PC2

[heater_generic chamberlow]
heater_pin: PB0
sensor_type: Generic 3950
sensor_pin: PC2
min_temp: -100
max_temp: 70
gcode_id: C
max_power: 1.0
control: watermark
max_delta: 1.0

[verify_heater chamberlow]
max_error: 300
check_gain_time: 480
hysteresis: 5
heating_gain: 1

[heater_generic chamberhigh]
heater_pin: PC7
sensor_type: Generic 3950
sensor_pin: PC2
min_temp: -100
max_temp: 70
max_power: 1.0
control: watermark
max_delta: 1.0

[verify_heater chamberhigh]
max_error: 300
check_gain_time: 480
hysteresis: 5
heating_gain: 1

[gcode_macro SET_CHAMBER_TEMPERATURE]
gcode:
   {% set target = params.S|default(0)|float %}
   {% set lowtarget = target - 0.2 %}
   {% set preheattarget = target - 0.5 %}
   {% if target <= 45.0 %}
     # Both to heat, low-power heater to maintain temp
     SET_HEATER_TEMPERATURE HEATER=chamberlow TARGET={target}
     SET_HEATER_TEMPERATURE HEATER=chamberhigh TARGET={preheattarget}
   {% elif target <= 55.0 %}
     # Both to heat, low-power mostly on, high-power cycles
     SET_HEATER_TEMPERATURE HEATER=chamberlow TARGET={target}
     SET_HEATER_TEMPERATURE HEATER=chamberhigh TARGET={lowtarget}
   {% else %}
     # Both to heat, high-power mostly on, low-power cycles
     SET_HEATER_TEMPERATURE HEATER=chamberlow TARGET={lowtarget}
     SET_HEATER_TEMPERATURE HEATER=chamberhigh TARGET={target}
   {% endif %}

[gcode_macro M141]
gcode:
   SET_CHAMBER_TEMPERATURE S={params.S}

[gcode_macro M191]
gcode:
   SET_CHAMBER_TEMPERATURE S={params.S}
   TEMPERATURE_WAIT SENSOR="heater_generic heater_chamberlow" MINIMUM={params.S}

I have improved the seal since I did my earlier testing, so I suspect that I’ll end up tweaking the temperatures and setpoints for the different heating stages with more testing; this is an in-progress example of what I’m testing, not a recipe for any other printer.

I did in fact move both chamber heaters to non-battery-backed power. I heard my UPS complain when I turned on both chamber heaters without the bed or extruder heating, so I clearly needed to make that change.

I used an 8A fuse for the two chamber heaters, since 600W / 120V = 5A and 8A is the next size higher that I have; it’s also low enough for the wiring that it supports.

3 Likes

Hello MJ,
How is your heated chamber working after a year?
I had my Ender3 in a heated chamber, It was a cluster of wiring. So I set out to design a Rpi hat style MOSfett driver board, epic fail.
So now I’m going back to an 8 channel driver board to drive my fans lights and heaters from my pi4 or Pi zero. I had connected a pi2040 as a sacrificial board but I was getting to many glitches. I’m using a BTT mini E3v3 board, and found that it has five I/O pins un designated. I believe I will use them to control the drivers, into the SCR for the 1000W PTC heater. I will use your config setup when I’m at that point.

(I don’t go by MJ btw)

It works fine.

Right now that printer is being modified again because a bed adhesion failure caused the hot end to be destroyed, and I’m in the middle of converting it to a BL-touch, so it’s not operational, but from a heating standpoint it worked fine.

1 Like