2 This page is in the table of contents.
3 Some filaments contract too much and warp the extruded object. To prevent this you have to print the object in a temperature regulated chamber and/or on a temperature regulated bed. The chamber tool allows you to control the bed and chamber temperature and the holding pressure.
5 The chamber gcodes are also described at:
7 http://reprap.org/wiki/Mendel_User_Manual:_RepRapGCodes
9 The chamber manual page is at:
11 http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Chamber
14 The default 'Activate Chamber' checkbox is on. When it is on, the functions described below will work, when it is off, nothing will be done.
18 The initial bed temperature is defined by 'Bed Temperature'. If the 'Bed Temperature End Change Height' is greater or equal to the 'Bed Temperature Begin Change Height' and the 'Bed Temperature Begin Change Height' is greater or equal to zero, then the temperature will be ramped toward the 'Bed Temperature End'. The ramp will start once the extruder reaches the 'Bed Temperature Begin Change Height', then the bed temperature will approach the 'Bed Temperature End' as the extruder reaches the 'Bed Temperature End Change Height', finally the bed temperature will stay at the 'Bed Temperature End' for the remainder of the build.
20 The idea is described at:
21 http://www.makerbot.com/blog/2011/03/17/if-you-cant-stand-the-heat/
23 ====Bed Temperature====
26 Defines the initial print bed temperature in Celcius by adding an M140 command.
28 ====Bed Temperature Begin Change Height====
31 Defines the height of the beginning of the temperature ramp. If the 'Bed Temperature End Change Height' is less than zero, the bed temperature will remain at the initial 'Bed Temperature'.
33 ====Bed Temperature End Change Height====
36 Defines the height of the end of the temperature ramp. If the 'Bed Temperature End Change Height' is less than zero or less than the 'Bed Temperature Begin Change Height', the bed temperature will remain at the initial 'Bed Temperature'.
38 ====Bed Temperature End====
41 Defines the end bed temperature if there is a temperature ramp.
43 ===Chamber Temperature===
46 Defines the chamber temperature in Celcius by adding an M141 command.
51 Defines the holding pressure of a mechanism, like a vacuum table or electromagnet, to hold the bed surface or object, by adding an M142 command. The holding pressure is in bars. For hardware which only has on/off holding, when the holding pressure is zero, turn off holding, when the holding pressure is greater than zero, turn on holding.
55 A resistor heated aluminum plate by Bothacker:
61 http://bothacker.com/2009/12/18/heated-build-platform/
64 A heated copper build plate by Domingo:
66 http://casainho-emcrepstrap.blogspot.com/
70 http://casainho-emcrepstrap.blogspot.com/2010/01/first-time-with-pla-testing-it-also-on.html
72 http://casainho-emcrepstrap.blogspot.com/2010/01/call-for-helpideas-to-develop-heated.html
74 http://casainho-emcrepstrap.blogspot.com/2010/01/new-heated-build-platform.html
76 http://casainho-emcrepstrap.blogspot.com/2010/01/no-acrylic-and-instead-kapton-tape-on.html
78 http://casainho-emcrepstrap.blogspot.com/2010/01/problems-with-heated-build-platform-and.html
80 http://casainho-emcrepstrap.blogspot.com/2010/01/perfect-build-platform.html
82 http://casainho-emcrepstrap.blogspot.com/2009/12/almost-no-warp.html
84 http://casainho-emcrepstrap.blogspot.com/2009/12/heated-base-plate.html
87 A heated build stage by jmil, over at:
93 http://www.hive76.org/handling-hot-build-surfaces
95 http://www.hive76.org/heated-build-stage-success
98 A heated base by the Metalab folks:
100 http://reprap.soup.io
104 http://reprap.soup.io/?search=heated%20base
107 A resistor heated aluminum bed by Nophead:
109 http://hydraraptor.blogspot.com
113 http://hydraraptor.blogspot.com/2010/01/will-it-stick.html
115 http://hydraraptor.blogspot.com/2010/01/hot-metal-and-serendipity.html
117 http://hydraraptor.blogspot.com/2010/01/new-year-new-plastic.html
119 http://hydraraptor.blogspot.com/2010/01/hot-bed.html
122 A resistive wire heated plexiglass plate by prusajr:
128 http://prusadjs.cz/2010/01/heated-reprap-print-bed-mk2/
130 http://prusadjs.cz/2009/11/look-ma-no-warping-heated-reprap-print-bed/
133 A resistor heated aluminum plate by Zaggo at Pleasant Software:
135 http://pleasantsoftware.com/developer/3d/
139 http://pleasantsoftware.com/developer/3d/2009/12/05/raftless/
141 http://pleasantsoftware.com/developer/3d/2009/11/15/living-in-times-of-warp-free-printing/
143 http://pleasantsoftware.com/developer/3d/2009/11/12/canned-heat/
146 The following examples chamber the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and chamber.py.
149 This brings up the chamber dialog.
151 > python chamber.py Screw Holder Bottom.stl
152 The chamber tool is parsing the file:
153 Screw Holder Bottom.stl
155 The chamber tool has created the file:
156 Screw Holder Bottom_chamber.gcode
161 from __future__ import absolute_import
163 from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret
164 from fabmetheus_utilities import archive
165 from fabmetheus_utilities import euclidean
166 from fabmetheus_utilities import gcodec
167 from fabmetheus_utilities import settings
168 from skeinforge_application.skeinforge_utilities import skeinforge_craft
169 from skeinforge_application.skeinforge_utilities import skeinforge_polyfile
170 from skeinforge_application.skeinforge_utilities import skeinforge_profile
173 __author__ = 'Enrique Perez (perez_enrique@yahoo.com)'
174 __date__ = '$Date: 2008/21/04 $'
175 __license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
178 def getCraftedText(fileName, text='', repository=None):
179 "Chamber the file or text."
180 return getCraftedTextFromText(archive.getTextIfEmpty(fileName, text), repository)
182 def getCraftedTextFromText(gcodeText, repository=None):
183 "Chamber a gcode linear move text."
184 if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'chamber'):
186 if repository == None:
187 repository = settings.getReadRepository(ChamberRepository())
188 if not repository.activateChamber.value:
190 return ChamberSkein().getCraftedGcode(gcodeText, repository)
192 def getNewRepository():
193 'Get new repository.'
194 return ChamberRepository()
196 def writeOutput(fileName, shouldAnalyze=True):
197 "Chamber a gcode linear move file."
198 skeinforge_craft.writeChainTextWithNounMessage(fileName, 'chamber', shouldAnalyze)
201 class ChamberRepository(object):
202 "A class to handle the chamber settings."
204 "Set the default settings, execute title & settings fileName."
205 skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.chamber.html', self )
206 self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Chamber', self, '')
207 self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Chamber')
208 self.activateChamber = settings.BooleanSetting().getFromValue('Activate Chamber', self, False )
209 settings.LabelSeparator().getFromRepository(self)
210 settings.LabelDisplay().getFromName('- Bed -', self )
211 self.bedTemperature = settings.FloatSpin().getFromValue(20.0, 'Bed Temperature (Celcius):', self, 90.0, 60.0)
212 self.bedTemperatureBeginChangeHeight = settings.FloatSpin().getFromValue(-1.0, 'Bed Temperature Begin Change Height (mm):', self, 20.0, -1.0)
213 self.bedTemperatureEndChangeHeight = settings.FloatSpin().getFromValue(-1.0, 'Bed Temperature End Change Height (mm):', self, 40.0, -1.0)
214 self.bedTemperatureEnd = settings.FloatSpin().getFromValue(20.0, 'Bed Temperature End (Celcius):', self, 90.0, 20.0)
215 settings.LabelSeparator().getFromRepository(self)
216 self.chamberTemperature = settings.FloatSpin().getFromValue( 20.0, 'Chamber Temperature (Celcius):', self, 90.0, 30.0 )
217 self.holdingForce = settings.FloatSpin().getFromValue( 0.0, 'Holding Force (bar):', self, 100.0, 0.0 )
218 self.executeTitle = 'Chamber'
221 "Chamber button has been clicked."
222 fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled)
223 for fileName in fileNames:
224 writeOutput(fileName)
228 class ChamberSkein(object):
229 "A class to chamber a skein of extrusions."
232 self.changeWidth = None
233 self.distanceFeedRate = gcodec.DistanceFeedRate()
236 self.oldBedTemperature = None
238 def addBedTemperature(self, bedTemperature):
239 'Add bed temperature if it is different from the old.'
240 if bedTemperature != self.oldBedTemperature:
241 self.distanceFeedRate.addParameter('M140', bedTemperature)
242 self.oldBedTemperature = bedTemperature
244 def getCraftedGcode(self, gcodeText, repository):
245 "Parse gcode text and store the chamber gcode."
246 endAtLeastBegin = repository.bedTemperatureEndChangeHeight.value >= repository.bedTemperatureBeginChangeHeight.value
247 if endAtLeastBegin and repository.bedTemperatureBeginChangeHeight.value >= 0.0:
248 self.changeWidth = repository.bedTemperatureEndChangeHeight.value - repository.bedTemperatureBeginChangeHeight.value
249 self.repository = repository
250 self.lines = archive.getTextLines(gcodeText)
251 self.parseInitialization()
252 for line in self.lines[self.lineIndex :]:
254 return self.distanceFeedRate.output.getvalue()
256 def parseInitialization(self):
257 'Parse gcode initialization and store the parameters.'
258 for self.lineIndex in xrange(len(self.lines)):
259 line = self.lines[self.lineIndex]
260 splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line)
261 firstWord = gcodec.getFirstWord(splitLine)
262 self.distanceFeedRate.parseSplitLine(firstWord, splitLine)
263 if firstWord == '(</extruderInitialization>)':
264 self.distanceFeedRate.addTagBracketedProcedure('chamber')
266 self.distanceFeedRate.addLine(line)
268 def parseLine(self, line):
269 "Parse a gcode line and add it to the chamber skein."
270 splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line)
271 if len(splitLine) < 1:
273 firstWord = splitLine[0]
274 if firstWord == '(<crafting>)':
275 self.distanceFeedRate.addLine(line)
276 self.addBedTemperature(self.repository.bedTemperature.value)
277 self.distanceFeedRate.addParameter('M141', self.repository.chamberTemperature.value) # Set chamber temperature.
278 self.distanceFeedRate.addParameter('M142', self.repository.holdingForce.value) # Set holding pressure.
280 self.distanceFeedRate.addLine(line)
281 if firstWord == '(<layer>' and self.changeWidth != None:
282 z = float(splitLine[1])
283 if z >= self.repository.bedTemperatureEndChangeHeight.value:
284 self.addBedTemperature(self.repository.bedTemperatureEnd.value)
286 if z <= self.repository.bedTemperatureBeginChangeHeight.value:
288 along = (z - self.repository.bedTemperatureBeginChangeHeight.value) / self.changeWidth
289 self.addBedTemperature(self.repository.bedTemperature.value * (1 - along) + self.repository.bedTemperatureEnd.value * along)
293 "Display the chamber dialog."
294 if len(sys.argv) > 1:
295 writeOutput(' '.join(sys.argv[1 :]))
297 settings.startMainLoopFromConstructor(getNewRepository())
299 if __name__ == "__main__":