2020-07-21 03:06:50 +02:00
|
|
|
#!/usr/bin/env python2
|
|
|
|
# Tool to graph temperature sensor ADC resolution
|
|
|
|
#
|
|
|
|
# Copyright (C) 2020 Kevin O'Connor <kevin@koconnor.net>
|
|
|
|
#
|
|
|
|
# This file may be distributed under the terms of the GNU GPLv3 license.
|
|
|
|
import sys, os, optparse
|
|
|
|
import matplotlib
|
|
|
|
|
|
|
|
|
|
|
|
######################################################################
|
|
|
|
# Dummy config / printer / etc. class emulation
|
|
|
|
######################################################################
|
|
|
|
|
|
|
|
class DummyConfig:
|
|
|
|
def __init__(self, config_settings):
|
|
|
|
self.config_settings = config_settings
|
|
|
|
self.sensor_factories = {}
|
|
|
|
# Emulate config class
|
|
|
|
def getfloat(self, option, default, **kw):
|
|
|
|
return self.config_settings.get(option, default)
|
|
|
|
def get(self, option, default=None):
|
|
|
|
return default
|
|
|
|
def get_printer(self):
|
|
|
|
return self
|
|
|
|
def get_name(self):
|
|
|
|
return "dummy"
|
|
|
|
# Emulate printer class
|
|
|
|
def load_object(self, config, name):
|
|
|
|
return self
|
|
|
|
def lookup_object(self, name):
|
|
|
|
return self
|
|
|
|
# Emulate heaters class
|
|
|
|
def add_sensor_factory(self, name, factory):
|
|
|
|
self.sensor_factories[name] = factory
|
|
|
|
def do_create_sensor(self, sensor_type):
|
|
|
|
return self.sensor_factories[sensor_type](self).adc_convert
|
|
|
|
# Emulate query_adc class
|
|
|
|
def register_adc(self, name, klass):
|
|
|
|
pass
|
|
|
|
# Emulate pins class
|
|
|
|
def setup_pin(self, pin_type, pin_name):
|
|
|
|
return self
|
|
|
|
# Emulate mcu_adc class
|
|
|
|
def setup_adc_callback(self, time, callback):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
######################################################################
|
|
|
|
# Plotting
|
|
|
|
######################################################################
|
|
|
|
|
|
|
|
def plot_adc_resolution(config, sensors):
|
|
|
|
# Temperature list
|
|
|
|
all_temps = [float(i) for i in range(1, 351)]
|
|
|
|
temps = all_temps[:-1]
|
|
|
|
# Build plot
|
|
|
|
fig, (ax1, ax2) = matplotlib.pyplot.subplots(nrows=2, sharex=True)
|
|
|
|
pullup = config.getfloat('pullup_resistor', 0.)
|
|
|
|
adc_voltage = config.getfloat('adc_voltage', 0.)
|
|
|
|
ax1.set_title("Temperature Sensor (pullup=%.0f, adc_voltage=%.3f)"
|
|
|
|
% (pullup, adc_voltage))
|
|
|
|
ax1.set_ylabel('ADC')
|
|
|
|
ax2.set_ylabel('ADC change per 1C')
|
|
|
|
for sensor in sensors:
|
|
|
|
sc = config.do_create_sensor(sensor)
|
|
|
|
adcs = [sc.calc_adc(t) for t in all_temps]
|
|
|
|
ax1.plot(temps, adcs[:-1], label=sensor, alpha=0.6)
|
|
|
|
adc_deltas = [abs(adcs[i+1] - adcs[i]) for i in range(len(temps))]
|
|
|
|
ax2.plot(temps, adc_deltas, alpha=0.6)
|
|
|
|
fontP = matplotlib.font_manager.FontProperties()
|
|
|
|
fontP.set_size('x-small')
|
|
|
|
ax1.legend(loc='best', prop=fontP)
|
|
|
|
ax2.set_xlabel('Temperature (C)')
|
|
|
|
ax1.grid(True)
|
|
|
|
ax2.grid(True)
|
|
|
|
fig.tight_layout()
|
|
|
|
return fig
|
|
|
|
|
2020-09-09 23:14:09 +02:00
|
|
|
def plot_resistance(config, sensors):
|
|
|
|
# Temperature list
|
|
|
|
all_temps = [float(i) for i in range(1, 351)]
|
|
|
|
# Build plot
|
|
|
|
fig, ax = matplotlib.pyplot.subplots()
|
|
|
|
pullup = config.getfloat('pullup_resistor', 0.)
|
|
|
|
ax.set_title("Temperature Sensor (pullup=%.0f)" % (pullup,))
|
|
|
|
ax.set_ylabel('Resistance (Ohms)')
|
|
|
|
for sensor in sensors:
|
|
|
|
sc = config.do_create_sensor(sensor)
|
|
|
|
adcs = [sc.calc_adc(t) for t in all_temps]
|
|
|
|
rs = [pullup * adc / (1.0 - adc) for adc in adcs]
|
|
|
|
ax.plot(all_temps, rs, label=sensor, alpha=0.6)
|
|
|
|
fontP = matplotlib.font_manager.FontProperties()
|
|
|
|
fontP.set_size('x-small')
|
|
|
|
ax.legend(loc='best', prop=fontP)
|
|
|
|
ax.set_xlabel('Temperature (C)')
|
|
|
|
ax.grid(True)
|
|
|
|
fig.tight_layout()
|
|
|
|
return fig
|
|
|
|
|
2020-07-21 03:06:50 +02:00
|
|
|
|
|
|
|
######################################################################
|
|
|
|
# Startup
|
|
|
|
######################################################################
|
|
|
|
|
|
|
|
def setup_matplotlib(output_to_file):
|
|
|
|
global matplotlib
|
|
|
|
if output_to_file:
|
|
|
|
matplotlib.rcParams.update({'figure.autolayout': True})
|
|
|
|
matplotlib.use('Agg')
|
|
|
|
import matplotlib.pyplot, matplotlib.dates, matplotlib.font_manager
|
|
|
|
import matplotlib.ticker
|
|
|
|
|
|
|
|
def import_sensors(config):
|
|
|
|
global extras
|
|
|
|
# Load adc_temperature.py and thermistor.py modules
|
|
|
|
kdir = os.path.join(os.path.dirname(__file__), '..', 'klippy')
|
|
|
|
sys.path.append(kdir)
|
|
|
|
import extras.adc_temperature, extras.thermistor
|
|
|
|
extras.thermistor.load_config(config)
|
|
|
|
extras.adc_temperature.load_config(config)
|
|
|
|
|
|
|
|
def main():
|
|
|
|
# Parse command-line arguments
|
|
|
|
usage = "%prog [options]"
|
|
|
|
opts = optparse.OptionParser(usage)
|
|
|
|
opts.add_option("-o", "--output", type="string", dest="output",
|
|
|
|
default=None, help="filename of output graph")
|
|
|
|
opts.add_option("-p", "--pullup", type="float", dest="pullup",
|
|
|
|
default=4700., help="pullup resistor")
|
|
|
|
opts.add_option("-v", "--voltage", type="float", dest="voltage",
|
|
|
|
default=5., help="pullup resistor")
|
|
|
|
opts.add_option("-s", "--sensors", type="string", dest="sensors",
|
|
|
|
default="", help="list of sensors (comma separated)")
|
2020-09-09 23:14:09 +02:00
|
|
|
opts.add_option("-r", "--resistance", action="store_true",
|
|
|
|
help="graph sensor resistance")
|
2020-07-21 03:06:50 +02:00
|
|
|
options, args = opts.parse_args()
|
|
|
|
if len(args) != 0:
|
|
|
|
opts.error("Incorrect number of arguments")
|
|
|
|
|
|
|
|
# Import sensors
|
|
|
|
config_settings = {'pullup_resistor': options.pullup,
|
|
|
|
'adc_voltage': options.voltage}
|
|
|
|
config = DummyConfig(config_settings)
|
|
|
|
import_sensors(config)
|
|
|
|
|
|
|
|
# Determine sensors to graph
|
|
|
|
if options.sensors:
|
|
|
|
sensors = [s.strip() for s in options.sensors.split(',')]
|
|
|
|
else:
|
|
|
|
sensors = sorted(config.sensor_factories.keys())
|
|
|
|
|
|
|
|
# Draw graph
|
|
|
|
setup_matplotlib(options.output is not None)
|
2020-09-09 23:14:09 +02:00
|
|
|
if options.resistance:
|
|
|
|
fig = plot_resistance(config, sensors)
|
|
|
|
else:
|
|
|
|
fig = plot_adc_resolution(config, sensors)
|
2020-07-21 03:06:50 +02:00
|
|
|
|
|
|
|
# Show graph
|
|
|
|
if options.output is None:
|
|
|
|
matplotlib.pyplot.show()
|
|
|
|
else:
|
|
|
|
fig.set_size_inches(8, 6)
|
|
|
|
fig.savefig(options.output)
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
main()
|