From 48433a6254cc437711406d48525e6c97bb754836 Mon Sep 17 00:00:00 2001 From: jbernardis Date: Wed, 25 Feb 2015 19:07:36 -0500 Subject: [PATCH] Configtool: added logic to generate thermistor temp tables. Also enable editing of temperature sensors. --- config/board.3drag.h | 4 + config/board.gen6.h | 3 + config/board.gen7-v1.1-v1.3.h | 4 + config/board.gen7-v1.4.h | 4 + config/board.ramps-v1.2.h | 4 + config/board.ramps-v1.3.h | 4 + config/board.rumba.h | 4 + config/board.sanguinololu-v1.1.h | 4 + config/board.sanguinololu-v1.2.h | 4 + config/board.sanguish.h | 4 + config/board.teensy++-v2.0.h | 4 + config/board.teensy-v2.0.h | 4 + configtool.default.ini | 7 + configtool/addsensordlg.py | 238 +++++++++++++++++++++++++++--- configtool/boardpanel.py | 60 +++++++- configtool/data.py | 2 + configtool/printerpanel.py | 6 +- configtool/sensorpage.py | 38 +++++ configtool/settings.py | 21 +++ configtool/thermistortablefile.py | 119 +++++++++++++++ 20 files changed, 505 insertions(+), 33 deletions(-) create mode 100644 configtool/thermistortablefile.py diff --git a/config/board.3drag.h b/config/board.3drag.h index ccc03a2..efacc19 100644 --- a/config/board.3drag.h +++ b/config/board.3drag.h @@ -145,6 +145,10 @@ // name type pin additional DEFINE_TEMP_SENSOR(extruder, TT_THERMISTOR, AIO13, THERMISTOR_EXTRUDER) DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO14, THERMISTOR_BED) + +// r0 beta r2 vadc +//TEMP_TABLE EXTRUDER (100000, 4092, 4700, 5.0) +//TEMP_TABLE BED (100000, 4092, 4700, 5.0) //DEFINE_TEMP_SENSORS_END diff --git a/config/board.gen6.h b/config/board.gen6.h index 3532edc..7810619 100644 --- a/config/board.gen6.h +++ b/config/board.gen6.h @@ -143,6 +143,9 @@ //DEFINE_TEMP_SENSORS_START // name type pin additional DEFINE_TEMP_SENSOR(extruder, TT_THERMISTOR, AIO5, THERMISTOR_EXTRUDER) + +// r0 beta r2 vadc +//TEMP_TABLE EXTRUDER (100000, 4092, 4700, 5.0) //DEFINE_TEMP_SENSORS_END diff --git a/config/board.gen7-v1.1-v1.3.h b/config/board.gen7-v1.1-v1.3.h index 85f781c..79f129b 100644 --- a/config/board.gen7-v1.1-v1.3.h +++ b/config/board.gen7-v1.1-v1.3.h @@ -149,6 +149,10 @@ // name type pin additional DEFINE_TEMP_SENSOR(extruder, TT_THERMISTOR, AIO1, THERMISTOR_EXTRUDER) DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO2, THERMISTOR_BED) + +// r0 beta r2 vadc +//TEMP_TABLE EXTRUDER (100000, 4092, 4700, 5.0) +//TEMP_TABLE BED (100000, 4092, 4700, 5.0) //DEFINE_TEMP_SENSORS_END diff --git a/config/board.gen7-v1.4.h b/config/board.gen7-v1.4.h index 472c1c3..73e29dd 100644 --- a/config/board.gen7-v1.4.h +++ b/config/board.gen7-v1.4.h @@ -150,6 +150,10 @@ // name type pin additional DEFINE_TEMP_SENSOR(extruder, TT_THERMISTOR, AIO1, THERMISTOR_EXTRUDER) DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO0, THERMISTOR_BED) + +// r0 beta r2 vadc +//TEMP_TABLE EXTRUDER (100000, 4092, 4700, 5.0) +//TEMP_TABLE BED (100000, 4092, 4700, 5.0) //DEFINE_TEMP_SENSORS_END diff --git a/config/board.ramps-v1.2.h b/config/board.ramps-v1.2.h index 3f7f643..7beca7b 100644 --- a/config/board.ramps-v1.2.h +++ b/config/board.ramps-v1.2.h @@ -146,6 +146,10 @@ // name type pin additional DEFINE_TEMP_SENSOR(extruder, TT_THERMISTOR, AIO2, THERMISTOR_EXTRUDER) DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO1, THERMISTOR_BED) + +// r0 beta r2 vadc +//TEMP_TABLE EXTRUDER (100000, 4092, 4700, 5.0) +//TEMP_TABLE BED (100000, 4092, 4700, 5.0) //DEFINE_TEMP_SENSORS_END diff --git a/config/board.ramps-v1.3.h b/config/board.ramps-v1.3.h index a00d73d..6e23e03 100644 --- a/config/board.ramps-v1.3.h +++ b/config/board.ramps-v1.3.h @@ -147,6 +147,10 @@ // name type pin additional DEFINE_TEMP_SENSOR(extruder, TT_THERMISTOR, AIO13, THERMISTOR_EXTRUDER) DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO14, THERMISTOR_BED) + +// r0 beta r2 vadc +//TEMP_TABLE EXTRUDER (100000, 4092, 4700, 5.0) +//TEMP_TABLE BED (100000, 4092, 4700, 5.0) //DEFINE_TEMP_SENSORS_END diff --git a/config/board.rumba.h b/config/board.rumba.h index 8f9df82..044b7cb 100644 --- a/config/board.rumba.h +++ b/config/board.rumba.h @@ -148,6 +148,10 @@ // name type pin additional DEFINE_TEMP_SENSOR(extruder, TT_THERMISTOR, AIO15, THERMISTOR_EXTRUDER) DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO11, THERMISTOR_BED) + +// r0 beta r2 vadc +//TEMP_TABLE EXTRUDER (100000, 4092, 4700, 5.0) +//TEMP_TABLE BED (100000, 4092, 4700, 5.0) //DEFINE_TEMP_SENSORS_END diff --git a/config/board.sanguinololu-v1.1.h b/config/board.sanguinololu-v1.1.h index 4685e51..3f1a651 100644 --- a/config/board.sanguinololu-v1.1.h +++ b/config/board.sanguinololu-v1.1.h @@ -148,6 +148,10 @@ // name type pin additional DEFINE_TEMP_SENSOR(extruder, TT_THERMISTOR, AIO7, THERMISTOR_EXTRUDER) DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO6, THERMISTOR_BED) + +// r0 beta r2 vadc +//TEMP_TABLE EXTRUDER (100000, 4092, 4700, 5.0) +//TEMP_TABLE BED (100000, 4092, 4700, 5.0) //DEFINE_TEMP_SENSORS_END diff --git a/config/board.sanguinololu-v1.2.h b/config/board.sanguinololu-v1.2.h index 2009f85..8badf8f 100644 --- a/config/board.sanguinololu-v1.2.h +++ b/config/board.sanguinololu-v1.2.h @@ -148,6 +148,10 @@ // name type pin additional DEFINE_TEMP_SENSOR(extruder, TT_THERMISTOR, AIO7, THERMISTOR_EXTRUDER) DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO6, THERMISTOR_BED) + +// r0 beta r2 vadc +//TEMP_TABLE EXTRUDER (100000, 4092, 4700, 5.0) +//TEMP_TABLE BED (100000, 4092, 4700, 5.0) //DEFINE_TEMP_SENSORS_END diff --git a/config/board.sanguish.h b/config/board.sanguish.h index b3fe21e..8432db0 100644 --- a/config/board.sanguish.h +++ b/config/board.sanguish.h @@ -148,6 +148,10 @@ // name type pin additional DEFINE_TEMP_SENSOR(extruder, TT_THERMISTOR, AIO1, THERMISTOR_EXTRUDER) DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO0, THERMISTOR_BED) + +// r0 beta r2 vadc +//TEMP_TABLE EXTRUDER (100000, 4092, 4700, 5.0) +//TEMP_TABLE BED (100000, 4092, 4700, 5.0) //DEFINE_TEMP_SENSORS_END diff --git a/config/board.teensy++-v2.0.h b/config/board.teensy++-v2.0.h index 63ead8f..978865e 100644 --- a/config/board.teensy++-v2.0.h +++ b/config/board.teensy++-v2.0.h @@ -145,6 +145,10 @@ // name type pin additional DEFINE_TEMP_SENSOR(extruder, TT_THERMISTOR, AIO7, THERMISTOR_EXTRUDER) DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO6, THERMISTOR_BED) + +// r0 beta r2 vadc +//TEMP_TABLE EXTRUDER (100000, 4092, 4700, 5.0) +//TEMP_TABLE BED (100000, 4092, 4700, 5.0) //DEFINE_TEMP_SENSORS_END diff --git a/config/board.teensy-v2.0.h b/config/board.teensy-v2.0.h index 3a9eea2..33f492f 100644 --- a/config/board.teensy-v2.0.h +++ b/config/board.teensy-v2.0.h @@ -145,6 +145,10 @@ // name type pin additional DEFINE_TEMP_SENSOR(extruder, TT_THERMISTOR, AIO1, THERMISTOR_EXTRUDER) DEFINE_TEMP_SENSOR(bed, TT_THERMISTOR, AIO0, THERMISTOR_BED) + +// r0 beta r2 vadc +//TEMP_TABLE EXTRUDER (100000, 4092, 4700, 5.0) +//TEMP_TABLE BED (100000, 4092, 4700, 5.0) //DEFINE_TEMP_SENSORS_END diff --git a/configtool.default.ini b/configtool.default.ini index dbeef63..de1c31b 100644 --- a/configtool.default.ini +++ b/configtool.default.ini @@ -36,3 +36,10 @@ programmer = stk500v2 # The port through which the firmware will be uploaded - passed to avrdude. port = /dev/ttyACM0 + +# Parameters into the thermistor table generation process. +t0 = 25 +r1 = 0 +numtemps = 25 +maxadc = 1023 +minadc = 0 diff --git a/configtool/addsensordlg.py b/configtool/addsensordlg.py index 3eca544..f086336 100644 --- a/configtool/addsensordlg.py +++ b/configtool/addsensordlg.py @@ -1,22 +1,32 @@ import wx from configtool.data import (pinNames, BSIZESMALL, sensorTypes, offsetTcLabel, - offsetChLabel) + offsetChLabel, reInteger, reFloat) class AddSensorDlg(wx.Dialog): - def __init__(self, parent, names, pins, font): - wx.Dialog.__init__(self, parent, wx.ID_ANY, "Add temperature sensor", - size = (400, 204)) + def __init__(self, parent, names, pins, font, name = "", stype = "", + pin = "", r0 = "", beta = "", r2 = "", vadc = "", + modify = False): + if modify: + title = "Modify temperature sensor" + else: + title = "Add temperature sensor" + wx.Dialog.__init__(self, parent, wx.ID_ANY, title, size = (400, 204)) self.SetFont(font) self.Bind(wx.EVT_CLOSE, self.onCancel) self.names = names self.choices = pins + self.modify = modify labelWidth = 160 self.nameValid = False + self.R0Valid = False + self.betaValid = False + self.R2Valid = False + self.vadcValid = False hsz = wx.BoxSizer(wx.HORIZONTAL) hsz.AddSpacer((10, 10)) @@ -30,9 +40,10 @@ class AddSensorDlg(wx.Dialog): st.SetFont(font) lsz.Add(st, 1, wx.TOP, offsetTcLabel) - self.tcName = wx.TextCtrl(self, wx.ID_ANY, "") + self.tcName = wx.TextCtrl(self, wx.ID_ANY, name) self.tcName.SetFont(font) - self.tcName.SetBackgroundColour("pink") + if not modify: + self.tcName.SetBackgroundColour("pink") self.tcName.Bind(wx.EVT_TEXT, self.onNameEntry) lsz.Add(self.tcName) self.tcName.SetToolTipString("Enter a unique name for this sensor.") @@ -51,7 +62,19 @@ class AddSensorDlg(wx.Dialog): ch = wx.Choice(self, wx.ID_ANY, choices = sl) ch.SetFont(font) ch.Bind(wx.EVT_CHOICE, self.onSensorType) - ch.SetSelection(0) + found = False + for st in sensorTypes.keys(): + if sensorTypes[st] == stype: + i = ch.FindString(st) + if i != wx.NOT_FOUND: + stStart = st + ch.SetSelection(i) + found = True + break + + if not found: + ch.SetSelection(0) + stStart = sl[0] self.chType = ch lsz.Add(ch) @@ -68,7 +91,11 @@ class AddSensorDlg(wx.Dialog): self.chPin = wx.Choice(self, wx.ID_ANY, choices = pins) self.chPin.SetFont(font) self.chPin.Bind(wx.EVT_CHOICE, self.onChoice) - self.chPin.SetSelection(0) + i = self.chPin.FindString(pin) + if i == wx.NOT_FOUND: + self.chPin.SetSelection(0) + else: + self.chPin.SetSelection(i) lsz.Add(self.chPin) self.chPin.SetToolTipString("Choose a pin name for this sensor.") @@ -76,20 +103,71 @@ class AddSensorDlg(wx.Dialog): csz.AddSpacer((10, 10)) lsz = wx.BoxSizer(wx.HORIZONTAL) - st = wx.StaticText(self, wx.ID_ANY, "Additional:", size = (labelWidth, -1), + st = wx.StaticText(self, wx.ID_ANY, "R0:", size = (labelWidth, -1), style = wx.ALIGN_RIGHT) st.SetFont(font) lsz.Add(st, 1, wx.TOP, offsetTcLabel) - self.tcAddtl = wx.TextCtrl(self, wx.ID_ANY, "") - self.tcAddtl.SetFont(font) - self.tcAddtl.Bind(wx.EVT_TEXT, self.onAddtlEntry) - lsz.Add(self.tcAddtl) - self.tcAddtl.SetToolTipString("Enter additional information required " - "by the sensor type.") + self.tcR0 = wx.TextCtrl(self, wx.ID_ANY, r0) + self.tcR0.SetFont(font) + self.tcR0.Bind(wx.EVT_TEXT, self.onR0Entry) + lsz.Add(self.tcR0) + self.tcR0.SetToolTipString("Nominal resistance of the thermistor. " + "Typically 10000 ( = 10k) or 100000 ( = 100k).") + + csz.Add(lsz) + csz.AddSpacer((10, 10)) + + lsz = wx.BoxSizer(wx.HORIZONTAL) + st = wx.StaticText(self, wx.ID_ANY, "Beta:", size = (labelWidth, -1), + style = wx.ALIGN_RIGHT) + st.SetFont(font) + lsz.Add(st, 1, wx.TOP, offsetTcLabel) + + self.tcBeta = wx.TextCtrl(self, wx.ID_ANY, beta) + self.tcBeta.SetFont(font) + self.tcBeta.Bind(wx.EVT_TEXT, self.onBetaEntry) + lsz.Add(self.tcBeta) + self.tcBeta.SetToolTipString("Thermistor beta value. Can be found in the " + "datasheet or measured like described in http" + "://reprap.org/wiki/MeasuringThermistorBeta") csz.Add(lsz) + csz.AddSpacer((10, 10)) + lsz = wx.BoxSizer(wx.HORIZONTAL) + st = wx.StaticText(self, wx.ID_ANY, "R2:", size = (labelWidth, -1), + style = wx.ALIGN_RIGHT) + st.SetFont(font) + lsz.Add(st, 1, wx.TOP, offsetTcLabel) + + self.tcR2 = wx.TextCtrl(self, wx.ID_ANY, r2) + self.tcR2.SetFont(font) + self.tcR2.Bind(wx.EVT_TEXT, self.onR2Entry) + lsz.Add(self.tcR2) + self.tcR2.SetToolTipString("Resistance value of the secondary resistor. " + "This is not a property of the thermistor, but " + "one of the board. Typical values are 4700 " + "( = 4k7 ohms) or 1000 ( = 1k ohms).") + + csz.Add(lsz) + csz.AddSpacer((10, 10)) + + lsz = wx.BoxSizer(wx.HORIZONTAL) + st = wx.StaticText(self, wx.ID_ANY, "Vadc:", size = (labelWidth, -1), + style = wx.ALIGN_RIGHT) + st.SetFont(font) + lsz.Add(st, 1, wx.TOP, offsetTcLabel) + + self.tcVadc = wx.TextCtrl(self, wx.ID_ANY, vadc) + self.tcVadc.SetFont(font) + self.tcVadc.Bind(wx.EVT_TEXT, self.onVadcEntry) + lsz.Add(self.tcVadc) + self.tcVadc.SetToolTipString("Comparison voltage used by the controller. " + "Usually the same as the controller's supply " + "voltage, 3.3 or 5.0 (volts).") + + csz.Add(lsz) csz.AddSpacer((10, 10)) bsz = wx.BoxSizer(wx.HORIZONTAL) @@ -116,13 +194,21 @@ class AddSensorDlg(wx.Dialog): self.SetSizer(hsz) self.Fit() + self.selectSensorType(stStart) + self.validateFields() + def onNameEntry(self, evt): tc = evt.GetEventObject() + self.validateName(tc) + self.checkDlgValidity() + evt.Skip() + + def validateName(self, tc): w = tc.GetValue().strip() if w == "": self.nameValid = False else: - if w in self.names: + if w in self.names and not self.modify: self.nameValid = False else: self.nameValid = True @@ -133,17 +219,110 @@ class AddSensorDlg(wx.Dialog): tc.SetBackgroundColour("pink") tc.Refresh() - self.checkDlgValidity() - evt.Skip() - def checkDlgValidity(self): - if self.nameValid: + if (self.nameValid and self.R0Valid and self.betaValid and + self.R2Valid and self.vadcValid): self.bSave.Enable(True) else: self.bSave.Enable(False) - def onAddtlEntry(self, evt): - evt.Skip() + def onTextCtrlInteger(self, tc, rqd): + w = tc.GetValue().strip() + if w == "": + if rqd: + valid = False + else: + valid = True + else: + m = reInteger.match(w) + if m: + valid = True + else: + valid = False + + if valid: + tc.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW)) + else: + tc.SetBackgroundColour("pink") + + tc.Refresh() + return valid + + def onTextCtrlFloat(self, tc, rqd): + w = tc.GetValue().strip() + if w == "": + if rqd: + valid = False + else: + valid = True + else: + m = reFloat.match(w) + if m: + valid = True + else: + valid = False + + if valid: + tc.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW)) + else: + tc.SetBackgroundColour("pink") + tc.Refresh() + return valid + + def onR0Entry(self, evt): + stype = self.chType.GetString(self.chType.GetSelection()) + if stype in ['Thermistor']: + rqd = True + else: + rqd = False + self.R0Valid = self.onTextCtrlInteger(self.tcR0, rqd) + self.checkDlgValidity() + if evt is not None: + evt.Skip() + + def onBetaEntry(self, evt): + stype = self.chType.GetString(self.chType.GetSelection()) + if stype in ['Thermistor']: + rqd = True + else: + rqd = False + self.betaValid = self.onTextCtrlInteger(self.tcBeta, rqd) + self.checkDlgValidity() + if evt is not None: + evt.Skip() + + def onR2Entry(self, evt): + stype = self.chType.GetString(self.chType.GetSelection()) + if stype in ['Thermistor']: + rqd = True + else: + rqd = False + self.R2Valid = self.onTextCtrlInteger(self.tcR2, rqd) + self.checkDlgValidity() + if evt is not None: + evt.Skip() + + def onVadcEntry(self, evt): + stype = self.chType.GetString(self.chType.GetSelection()) + if stype in ['Thermistor']: + rqd = True + else: + rqd = False + self.vadcValid = self.onTextCtrlFloat(self.tcVadc, rqd) + self.checkDlgValidity() + if evt is not None: + evt.Skip() + + def selectSensorType(self, lbl): + if lbl == 'Thermistor': + flag = True + else: + flag = False + + self.tcR0.Enable(flag); + self.tcBeta.Enable(flag); + self.tcR2.Enable(flag); + self.tcVadc.Enable(flag); def onChoice(self, evt): pass @@ -153,15 +332,26 @@ class AddSensorDlg(wx.Dialog): s = ch.GetSelection() label = ch.GetString(s) + self.selectSensorType(label) + self.validateFields() evt.Skip() + def validateFields(self): + self.validateName(self.tcName) + self.onR0Entry(None) + self.onBetaEntry(None) + self.onR2Entry(None) + self.onVadcEntry(None) + def getValues(self): nm = self.tcName.GetValue() pin = self.choices[self.chPin.GetSelection()] - addtl = self.tcAddtl.GetValue() stype = self.chType.GetString(self.chType.GetSelection()) - if stype not in ['Thermistor']: + if stype in ['Thermistor']: + addtl = [self.tcR0.GetValue().strip(), self.tcBeta.GetValue().strip(), + self.tcR2.GetValue().strip(), self.tcVadc.GetValue().strip()] + else: addtl = "NONE" return (nm, sensorTypes[stype], pin, addtl) diff --git a/configtool/boardpanel.py b/configtool/boardpanel.py index f073d21..01dfbe5 100644 --- a/configtool/boardpanel.py +++ b/configtool/boardpanel.py @@ -11,13 +11,14 @@ from configtool.data import (defineValueFormat, reCandProcessors, reCandCPUClocks, reFloatAttr, reDefine, reDefineBL, reDefQS, reDefQSm, reDefQSm2, reDefBool, reDefBoolBL, reDefHT, - reDefTS, reSensor, reHeater) + reDefTS, reDefTT, reSensor, reHeater, reTempTable) from configtool.pinoutspage import PinoutsPage from configtool.sensorpage import SensorsPage from configtool.heaterspage import HeatersPage from configtool.communicationspage import CommunicationsPage from configtool.cpupage import CpuPage from configtool.protectedfiles import protectedFiles +from configtool.thermistortablefile import generateTempTables class BoardPanel(wx.Panel): @@ -229,6 +230,7 @@ class BoardPanel(wx.Panel): self.candThermPins = [] self.candProcessors = [] self.candClocks = [] + tempTables = {} gatheringHelpText = False helpTextString = "" helpKey = None @@ -295,6 +297,15 @@ class BoardPanel(wx.Panel): self.candClocks.append(t[0]) continue + m = reDefTT.match(ln) + if m: + t = m.groups() + if len(t) == 2: + s = self.parseTempTable(t[1]) + if s: + tempTables[t[0]] = s + continue + continue if ln.lstrip().startswith("#define"): @@ -347,6 +358,11 @@ class BoardPanel(wx.Panel): self.heaters.append(s) continue + for k in range(len(self.sensors)): + tn = self.sensors[k][0].upper() + if tn in tempTables.keys(): + self.sensors[k][3] = tempTables[tn] + if os.path.basename(fn) in protectedFiles: self.parent.enableSaveBoard(False, True) self.protFileLoaded = True @@ -373,7 +389,7 @@ class BoardPanel(wx.Panel): if m: t = m.groups() if len(t) == 4: - return t + return list(t) return None def parseHeater(self, s): @@ -381,12 +397,20 @@ class BoardPanel(wx.Panel): if m: t = m.groups() if len(t) == 3: - return t + return list(t) + return None + + def parseTempTable(self, s): + m = reTempTable.search(s) + if m: + t = m.groups() + if len(t) == 4: + return list(t) return None def onSaveConfig(self, evt): path = self.configFile - self.saveConfigFile(path) + return self.saveConfigFile(path) def onSaveConfigAs(self, evt): wildcard = "Board configuration (board.*.h)|board.*.h" @@ -404,10 +428,12 @@ class BoardPanel(wx.Panel): path = dlg.GetPath() dlg.Destroy() - if self.saveConfigFile(path): + rc = self.saveConfigFile(path) + if rc: self.parent.setBoardTabFile(os.path.basename(path)) self.protFileLoaded = False self.parent.enableSaveBoard(True, True) + return rc def saveConfigFile(self, path): if os.path.basename(path) in protectedFiles: @@ -452,16 +478,26 @@ class BoardPanel(wx.Panel): skipToSensorEnd = False skipToHeaterEnd = False + tempTables = {} for ln in self.cfgBuffer: m = reStartSensors.match(ln) if m: fp.write(ln) fp.write("// name type pin " "additional\n"); + ttString = "\n// r0 beta r2 vadc\n" for s in self.sensors: - sstr = "%-10s%-15s%-7s%s" % ((s[0] + ","), (s[1] + ","), - (s[2] + ","), s[3]) + sstr = "%-10s%-15s%-7s" % ((s[0] + ","), (s[1] + ","), (s[2] + ",")) + if s[3] != "NONE": + tt = s[3] + sstr += "THERMISTOR_%s" % s[0].upper() + ttString += "//TEMP_TABLE %-8s (%-8s%-6s%-6s%s)\n" % \ + (s[0].upper(), (tt[0] + ","), (tt[1] + ","), + (tt[2] + ","), tt[3]) + else: + sstr += s[3] fp.write("DEFINE_TEMP_SENSOR(%s)\n" % sstr) + fp.write(ttString) skipToSensorEnd = True continue @@ -575,6 +611,16 @@ class BoardPanel(wx.Panel): dlg.ShowModal() dlg.Destroy() + if generateTempTables(self.sensors, self.settings): + dlg = wx.MessageDialog(self, + "File ThermistorTable.h successfully written.", + "Save successful", wx.OK + wx.ICON_INFORMATION) + else: + dlg = wx.MessageDialog(self, "Error writing to file ThermistorTable.h.", + "File error", wx.OK + wx.ICON_ERROR) + dlg.ShowModal() + dlg.Destroy() + return True def addNewDefine(self, fp, key, val): diff --git a/configtool/data.py b/configtool/data.py index 29a8f5a..c0b7bec 100644 --- a/configtool/data.py +++ b/configtool/data.py @@ -39,6 +39,7 @@ reCommDefBL = re.compile("^\s*//\s*#define\s+(\w+)\s+(\S+)") reDefQS = re.compile("\s*#define\s+(\w+)\s+(\"[^\"]*\")") reDefTS = re.compile("\s*(DEFINE_TEMP_SENSOR\\([^)]*\\))") reDefHT = re.compile("\s*(DEFINE_HEATER\\([^)]*\\))") +reDefTT = re.compile("^\s*//\s*TEMP_TABLE\s+(\S+)\s+(\\(.*\\))") reDefBool = re.compile("\s*#define\s+(\w+)\s+") reDefBoolBL = re.compile("^\s*#define\s+(\w+)\s+") reCommDefBoolBL = re.compile("^\s*//\s*#define\s+(\S+)\s+") @@ -56,6 +57,7 @@ reHelpTextEnd = re.compile("^\s*\*/") reSensor = re.compile(".*\\(\s*(\w+)\s*,\s*(\w+)\s*,\s*(\w+)\s*,\s*(\w+)\s*\\)") reHeater = re.compile(".*\\(\s*(\w+)\s*,\s*(\w+)\s*,\s*(\w+)\s*\\)") +reTempTable = re.compile(".*\\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d*.?\d*)\s*\\)") reInteger = re.compile("^\d+U?L?$") reFloat = re.compile("^\d+(\.\d*)?$") diff --git a/configtool/printerpanel.py b/configtool/printerpanel.py index 0c6e4db..b5b5d57 100644 --- a/configtool/printerpanel.py +++ b/configtool/printerpanel.py @@ -270,7 +270,7 @@ class PrinterPanel(wx.Panel): def onSaveConfig(self, evt): path = self.configFile - self.saveConfigFile(path) + return self.saveConfigFile(path) def onSaveConfigAs(self, evt): wildcard = "Printer configuration (printer.*.h)|printer.*.h" @@ -288,10 +288,12 @@ class PrinterPanel(wx.Panel): path = dlg.GetPath() dlg.Destroy() - if self.saveConfigFile(path): + rc = self.saveConfigFile(path) + if rc: self.parent.setPrinterTabFile(os.path.basename(path)) self.protFileLoaded = False self.parent.enableSavePrinter(True, True) + return rc def saveConfigFile(self, path): if os.path.basename(path) in protectedFiles: diff --git a/configtool/sensorpage.py b/configtool/sensorpage.py index f9cb67b..dfe6da8 100644 --- a/configtool/sensorpage.py +++ b/configtool/sensorpage.py @@ -42,6 +42,14 @@ class SensorsPage(wx.Panel, Page): bsz.Add(self.bAdd) + bsz.AddSpacer((10, 10)) + self.bModify = wx.Button(self, wx.ID_ANY, "Modify", size = BSIZESMALL) + self.bModify.SetFont(font) + self.bModify.Enable(False) + self.Bind(wx.EVT_BUTTON, self.doModify, self.bModify) + bsz.Add(self.bModify) + self.bModify.SetToolTipString("Modify the selected temperature sensor.") + bsz.AddSpacer((10, 10)) self.bDelete = wx.Button(self, wx.ID_ANY, "Delete", size = BSIZESMALL) self.bDelete.SetFont(font) @@ -60,8 +68,10 @@ class SensorsPage(wx.Panel, Page): self.selection = n if n is None: self.bDelete.Enable(False) + self.bModify.Enable(False) else: self.bDelete.Enable(True) + self.bModify.Enable(True) def doAdd(self, evt): nm = [] @@ -83,6 +93,34 @@ class SensorsPage(wx.Panel, Page): self.validateTable() self.assertModified(True) + def doModify(self, evt): + if self.selection is None: + return + nm = [] + for s in self.sensors: + nm.append(s[0]) + + s = self.sensors[self.selection] + dlg = AddSensorDlg(self, nm, self.validPins, self.font, + name = s[0], stype = s[1], pin = s[2], + r0 = s[3][0], beta = s[3][1], r2 = s[3][2], + vadc = s[3][3], modify = True) + rc = dlg.ShowModal() + if rc == wx.ID_OK: + tt = dlg.getValues() + + dlg.Destroy() + + if rc != wx.ID_OK: + return + + self.assertModified(True) + + self.sensors[self.selection] = tt + self.lb.updateList(self.sensors) + self.validateTable() + self.assertModified(True) + def doDelete(self, evt): if self.selection is None: return diff --git a/configtool/settings.py b/configtool/settings.py index b6c963d..1b9190f 100644 --- a/configtool/settings.py +++ b/configtool/settings.py @@ -22,6 +22,12 @@ class Settings: self.programmer = "wiring" self.port = "/dev/ttyACM0" + self.t0 = 25; + self.r1 = 0; + self.numTemps = 25 + self.maxAdc = 1023 + self.minAdc = 1 + self.cfg = ConfigParser.ConfigParser() self.cfg.optionxform = str if not self.cfg.read(self.inifile): @@ -45,6 +51,16 @@ class Settings: self.port = value elif opt == "objcopyflags": self.objcopyflags = value + elif opt == "t0": + self.t0 = value + elif opt == "r1": + self.r1 = value + elif opt == "numtemps": + self.numTemps = value + elif opt == "maxadc": + self.maxAdc = value + elif opt == "minadc": + self.minAdc = value else: print "Unknown %s option: %s - ignoring." % (self.section, opt) else: @@ -63,6 +79,11 @@ class Settings: self.cfg.set(self.section, "objcopyflags", str(self.objcopyflags)) self.cfg.set(self.section, "programmer", str(self.programmer)) self.cfg.set(self.section, "port", str(self.port)) + self.cfg.set(self.section, "t0", str(self.t0)) + self.cfg.set(self.section, "r1", str(self.r1)) + self.cfg.set(self.section, "numtemps", str(self.numTemps)) + self.cfg.set(self.section, "maxadc", str(self.maxAdc)) + self.cfg.set(self.section, "minadc", str(self.minAdc)) try: cfp = open(self.inifile, 'wb') diff --git a/configtool/thermistortablefile.py b/configtool/thermistortablefile.py new file mode 100644 index 0000000..a6d7851 --- /dev/null +++ b/configtool/thermistortablefile.py @@ -0,0 +1,119 @@ + +import os +from createTemperatureLookup import Thermistor + + +class ThermistorTableFile: + def __init__(self, folder): + self.error = False + fn = os.path.join(folder, "ThermistorTable.h") + try: + self.fp = open(fn, 'wb') + except: + self.error = True + + def close(self): + self.fp.close() + + def output(self, text): + self.fp.write(text + "\n") + + +def generateTempTables(sensors, settings): + ofp = ThermistorTableFile(settings.folder) + if ofp.error: + return False + + mult = 4 + minadc = int(settings.minAdc) + N = int(settings.numTemps) + + # Make a list of single-item dicts to keep the order. + tl = [] + for sensor in sensors: + if sensor[3] != "NONE": + tl.append({sensor[0].upper(): sensor[3]}) + + ofp.output(""); + ofp.output("/**"); + ofp.output(" This file was autogenerated when saving a board with"); + ofp.output(" Teacup's Configtool. You can edit it, but the next board"); + ofp.output(" save operation in Configtool will overwrite it without"); + ofp.output(" asking."); + ofp.output("*/"); + ofp.output(""); + + ofp.output("#define NUMTABLES %d" % len(tl)) + ofp.output("#define NUMTEMPS %d" % N) + ofp.output(""); + + for i in range(len(tl)): + ofp.output("#define THERMISTOR_%s %d" % (tl[i].keys()[0], i)) + ofp.output(""); + + if len(tl) == 0 or N == 0: + ofp.close(); + return True + + ofp.output("const uint16_t PROGMEM temptable[NUMTABLES][NUMTEMPS][2] = {") + + tcount = 0 + for tn in tl: + tcount += 1 + t = tn.values()[0] + r0 = t[0] + beta = t[1] + r2 = t[2] + vadc = t[3] + ofp.output(" // %s temp table parameters:" % tn.keys()[0]) + ofp.output((" // R0 = %s, T0 = %s, R1 = %s, R2 = %s, beta = %s, " + "maxadc = %s") % (r0, settings.t0, settings.r1, r2, + beta, settings.maxAdc)) + ofp.output(" {") + thm = Thermistor(int(r0), + int(settings.t0), + int(beta), + int(settings.r1), + int(r2), + float(vadc), + float(vadc)) + maxadc = int(settings.maxAdc) + zadc = int(thm.setting(0)) + if zadc < maxadc: + maxadc = zadc + + increment = float(maxadc - minadc) / float(N - 1); + ct = 1.0 + adcs = [] + for i in range(N): + adcs.append(int(ct)) + ct += increment + + counter = 0 + for adc in adcs: + counter = counter + 1 + degC = thm.temp(adc) + resistance = thm.resistance(thm.temp(adc)) + vTherm = adc * thm.vadc / 1024 + ptherm = vTherm * vTherm / resistance + if adc > 1: + resolution = thm.temp(adc - 1) - thm.temp(adc) + else: + resolution = thm.temp(adc) - thm.temp(adc + 1) + if counter == len(adcs): + sep = " " + else: + sep = "," + ostr = (" {%4s, %5s}%s // %6.2f C, %6.0f ohms, %0.3f V," + " %0.2f C/count, %0.2f mW") % (adc, int(thm.temp(adc) * mult), + sep, degC, resistance, vTherm, resolution, ptherm * 1000) + ofp.output(ostr) + if tcount == len(tl): + ofp.output(" }") + else: + ofp.output(" },") + + ofp.output("};") + ofp.close() + + return True