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
162 #Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module.
165 from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret
166 from fabmetheus_utilities import archive
167 from fabmetheus_utilities import euclidean
168 from fabmetheus_utilities import gcodec
169 from fabmetheus_utilities import settings
170 from skeinforge_application.skeinforge_utilities import skeinforge_craft
171 from skeinforge_application.skeinforge_utilities import skeinforge_polyfile
172 from skeinforge_application.skeinforge_utilities import skeinforge_profile
176 __author__ = 'Enrique Perez (perez_enrique@yahoo.com)'
177 __date__ = '$Date: 2008/21/04 $'
178 __license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
181 def getCraftedText(fileName, text='', repository=None):
182 "Chamber the file or text."
183 return getCraftedTextFromText(archive.getTextIfEmpty(fileName, text), repository)
185 def getCraftedTextFromText(gcodeText, repository=None):
186 "Chamber a gcode linear move text."
187 if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'chamber'):
189 if repository == None:
190 repository = settings.getReadRepository(ChamberRepository())
191 if not repository.activateChamber.value:
193 return ChamberSkein().getCraftedGcode(gcodeText, repository)
195 def getNewRepository():
196 'Get new repository.'
197 return ChamberRepository()
199 def writeOutput(fileName, shouldAnalyze=True):
200 "Chamber a gcode linear move file."
201 skeinforge_craft.writeChainTextWithNounMessage(fileName, 'chamber', shouldAnalyze)
204 class ChamberRepository:
205 "A class to handle the chamber settings."
207 "Set the default settings, execute title & settings fileName."
208 skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.chamber.html', self )
209 self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Chamber', self, '')
210 self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Chamber')
211 self.activateChamber = settings.BooleanSetting().getFromValue('Activate Chamber', self, False )
212 settings.LabelSeparator().getFromRepository(self)
213 settings.LabelDisplay().getFromName('- Bed -', self )
214 self.bedTemperature = settings.FloatSpin().getFromValue(20.0, 'Bed Temperature (Celcius):', self, 90.0, 60.0)
215 self.bedTemperatureBeginChangeHeight = settings.FloatSpin().getFromValue(-1.0, 'Bed Temperature Begin Change Height (mm):', self, 20.0, -1.0)
216 self.bedTemperatureEndChangeHeight = settings.FloatSpin().getFromValue(-1.0, 'Bed Temperature End Change Height (mm):', self, 40.0, -1.0)
217 self.bedTemperatureEnd = settings.FloatSpin().getFromValue(20.0, 'Bed Temperature End (Celcius):', self, 90.0, 20.0)
218 settings.LabelSeparator().getFromRepository(self)
219 self.chamberTemperature = settings.FloatSpin().getFromValue( 20.0, 'Chamber Temperature (Celcius):', self, 90.0, 30.0 )
220 self.holdingForce = settings.FloatSpin().getFromValue( 0.0, 'Holding Force (bar):', self, 100.0, 0.0 )
221 self.executeTitle = 'Chamber'
224 "Chamber button has been clicked."
225 fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled)
226 for fileName in fileNames:
227 writeOutput(fileName)
232 "A class to chamber a skein of extrusions."
235 self.changeWidth = None
236 self.distanceFeedRate = gcodec.DistanceFeedRate()
239 self.oldBedTemperature = None
241 def addBedTemperature(self, bedTemperature):
242 'Add bed temperature if it is different from the old.'
243 if bedTemperature != self.oldBedTemperature:
244 self.distanceFeedRate.addParameter('M140', bedTemperature)
245 self.oldBedTemperature = bedTemperature
247 def getCraftedGcode(self, gcodeText, repository):
248 "Parse gcode text and store the chamber gcode."
249 endAtLeastBegin = repository.bedTemperatureEndChangeHeight.value >= repository.bedTemperatureBeginChangeHeight.value
250 if endAtLeastBegin and repository.bedTemperatureBeginChangeHeight.value >= 0.0:
251 self.changeWidth = repository.bedTemperatureEndChangeHeight.value - repository.bedTemperatureBeginChangeHeight.value
252 self.repository = repository
253 self.lines = archive.getTextLines(gcodeText)
254 self.parseInitialization()
255 for line in self.lines[self.lineIndex :]:
257 return self.distanceFeedRate.output.getvalue()
259 def parseInitialization(self):
260 'Parse gcode initialization and store the parameters.'
261 for self.lineIndex in xrange(len(self.lines)):
262 line = self.lines[self.lineIndex]
263 splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line)
264 firstWord = gcodec.getFirstWord(splitLine)
265 self.distanceFeedRate.parseSplitLine(firstWord, splitLine)
266 if firstWord == '(</extruderInitialization>)':
267 self.distanceFeedRate.addTagBracketedProcedure('chamber')
269 self.distanceFeedRate.addLine(line)
271 def parseLine(self, line):
272 "Parse a gcode line and add it to the chamber skein."
273 splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line)
274 if len(splitLine) < 1:
276 firstWord = splitLine[0]
277 if firstWord == '(<crafting>)':
278 self.distanceFeedRate.addLine(line)
279 self.addBedTemperature(self.repository.bedTemperature.value)
280 self.distanceFeedRate.addParameter('M141', self.repository.chamberTemperature.value) # Set chamber temperature.
281 self.distanceFeedRate.addParameter('M142', self.repository.holdingForce.value) # Set holding pressure.
283 self.distanceFeedRate.addLine(line)
284 if firstWord == '(<layer>' and self.changeWidth != None:
285 z = float(splitLine[1])
286 if z >= self.repository.bedTemperatureEndChangeHeight.value:
287 self.addBedTemperature(self.repository.bedTemperatureEnd.value)
289 if z <= self.repository.bedTemperatureBeginChangeHeight.value:
291 along = (z - self.repository.bedTemperatureBeginChangeHeight.value) / self.changeWidth
292 self.addBedTemperature(self.repository.bedTemperature.value * (1 - along) + self.repository.bedTemperatureEnd.value * along)
296 "Display the chamber dialog."
297 if len(sys.argv) > 1:
298 writeOutput(' '.join(sys.argv[1 :]))
300 settings.startMainLoopFromConstructor(getNewRepository())
302 if __name__ == "__main__":