我主要使用可编程逻辑控制器(PLC),但是我的任务是修复程序,以帮助我们进行校准。运行此代码时出现以下错误:
AttributeError:表实例没有属性'error_8'
我不得不删除一些代码,因为它不允许我发布所有内容。我对Python相当陌生,因此我可能不知道与属性有关的一些与范围相关的问题。
class Info(tk.Frame):
def __init__(self, master=None, inst_type='Standard'):
tk.Frame.__init__(self, master, bg='white', highlightbackground="black",
highlightcolor="black", highlightthickness=1)
self.order = [['inst_type_label', 'inst_type'],
['barcode_label', 'barcode'],
['model_label', 'model'],
['serial_number_label', 'serial_number'],
['firmware_label', 'firmware'],]
self.format_labels(inst_type)
self.gen_geometry()
def load_values(self, data):
for i in data:
value = getattr(self, i)
value['text'] = data[i]
def clear_values(self):
for i, j in self.order:
value = getattr(self, j)
value['text'] = ''
class Table(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master, bg='white', highlightbackground="black",
highlightcolor="black", highlightthickness=1)
self.cell_color = '#F5F5F5'
self.gen_table()
def gen_table(self, samples=5):
self.samples = samples
headers = [['setpoint', 'Setpoint\n(%RH)'],
['sp_std', 'Standard\nDeviation'],
['setpoint_tmp', 'Setpoint\nTemperature\n(C)'],
['spt_tmp_std', 'Standard\nDeviation'],
['response', 'Response\n(%RH)'],
['r_std', 'Standard\nDeviation'],
['response_tmp', 'Response\nTemperature\n(C)'],
['r_tmp_std', 'Standard\nDeviation'],
['error','Absolute\nError\n(%RH)'],
['error_tmp', 'Temperature\nError (C)'],
['pass_fail','Pass/Fail'],]
col = 0
row = 0
for i, j in headers:
setattr(self, i, tk.Label(self, text=j, bg='#107dac', fg='white', font=font_label, padx=4, pady=4))
val = getattr(self, i)
val.grid(column=col, row=row, sticky='ewsn')
col+=1
row += 1
self.table_names = ['s_rh', 's_rh_stdev',
's_t', 's_t_stdev',
'i_rh', 'i_rh_stdev',
'i_t', 'i_t_stdev',
'error','error_tmp',
'criteria']
columns = range(self.samples+2)
for j in columns:
col = 0
for i in self.table_names:
cell_name = i + '_' + str(j+1)
if j % 2 == 0:
bg='white'
else:
bg=self.cell_color
setattr(self, cell_name, tk.Label(self, bg=bg, font=font_value))
val = getattr(self, cell_name)
val.grid(column=col, row=row, sticky='ewsn')
if j == columns[-2] and i == 's_rh':
val.config(text='Maximum', font=font_label)
elif j == columns[-1] and i == 's_rh':
val.config(text='Limit', font=font_label)
col += 1
row += 1
def delete_row(self, row):
if hasattr(self, self.table_names[0] + '_' + str(row)):
for name in self.table_names:
val = getattr(self, name + '_' + str(row))
val.destroy()
for i in range(row+1, self.samples+3):
for name in self.table_names:
setattr(self,
name + '_' + str(i-1),
getattr(self, name + '_' + str(i)))
delattr(self, name + '_' + str(i))
self.samples -= 1
else:
print 'row does not exitst'
def resize_tables(self, samples):
while self.samples + 2 > 0:
self.delete_row(1)
self.gen_table(samples)
def restyle_rows(self):
for i in range(self.samples+2):
for name in self.table_names:
val = getattr(self, name + '_' + str(i+1))
if i % 2 == 0:
bg='white'
else:
bg=self.cell_color
val.config(bg=bg)
def insert_row(self, row):
total_rows = self.samples + row
while self.samples + 2 > 0:
self.delete_row(1)
self.gen_table(total_rows)
def load_values(self, row, values):
for name in values:
val = getattr(self, name + '_' + str(row))
val['text'] = str(values[name])
class LineCheck(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master, bg='white', highlightbackground="black",
highlightcolor="black", highlightthickness=1)
self.cell_color = '#F5F5F5'
self.gen_table()
def load_table(self, values):
self.a1_calculated['text'] = values['a1'][0]
self.a1_criteria['text'] = values['a1'][1]
self.x_calculated['text'] = values['|x-min*(a1-1)+a0|'][0]
self.x_criteria['text'] = values['|x-min*(a1-1)+a0|'][1]
self.see_calculated['text'] = values['SEE'][0]
self.see_criteria['text'] = values['SEE'][1]
self.r_squared_calculated['text'] = values['r_squared'][0]
self.r_squared_criteria['text'] = values['r_squared'][1]
class Buttons(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master, bg='white')
self.gen_button()
def gen_button(self):
self.warm = tk.Canvas(self, width=20, height=20,
borderwidth=0, highlightthickness=0, bg="white")
self.warm_item = self.warm.create_oval(1, 1, 19, 19, fill="grey")
self.warm_label = tk.Label(self, text='Status', bg="white", font=font_value, padx=8, pady=2)
self.start_button = tk.Button(self, text='START',
bg='#01796F', fg='white', font=font_label, pady=10, padx=20)
self.close_button = tk.Button(self, text='CLOSE', font=font_label,
pady=10, padx=20 )
self.warm.grid(column=0, row=0, pady=8)
self.warm_label.grid(column=1, row=0, pady=8, sticky='w')
self.start_button.grid(column=0, row=1, padx=8)
self.close_button.grid(column=1, row=1, padx=8)
def ready(self, ready):
if ready:
self.warm.itemconfig(self.warm_item, fill='green')
self.warm_label['text'] = 'Ready'
else:
self.warm.itemconfig(self.warm_item, fill='red')
self.warm_label['text'] = 'Warming up'
def stable(self, stable):
if stable:
self.warm.itemconfig(self.warm_item, fill='green')
self.warm_label['text'] = 'Taking data'
else:
self.warm.itemconfig(self.warm_item, fill='orange')
self.warm_label['text'] = 'Checking stability'
def error(self, error):
if error:
# This will not be used
self.warm.itemconfig(self.warm_item, fill='green')
self.warm_label['text'] = 'Ready'
else:
self.warm.itemconfig(self.warm_item, fill='red')
self.warm_label['text'] = 'Calibration failed!'
class Configuration(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master, bg='white', highlightbackground="black",
highlightcolor="black", highlightthickness=1)
self.forms()
def forms(self):
self.load_fluke_usb()
self.load_inst_adacs()
def load_fluke_usb(self):
self.fluke_clear_usb()
self.fluke_clear_ts()
self.fluke_usb()
def load_fluke_ts(self):
self.fluke_clear_usb()
self.fluke_clear_ts()
self.fluke_ts()
def load_inst_adacs(self):
self.inst_clear_adacs()
self.inst_clear_ip()
self.inst_adacs()
def load_inst_ip(self):
self.inst_clear_adacs()
self.inst_clear_ip()
self.inst_ip()
def fluke_usb(self):
self.fluke_entry_var = tk.StringVar()
if os.name == 'nt':
self.fluke_entry_var.set('COM3')
else:
self.fluke_entry_var.set('/dev/ttyUSB0')
self.fluke_config = tk.Label(self, text='USB Port:',
bg='white', font=font_label, padx=8, pady=2)
self.fluke_entry = tk.Entry(self, textvariable=self.fluke_entry_var)
self.fluke_config.grid(row=0, column=0, sticky='W')
self.fluke_entry.grid(row=0, column=1)
def fluke_clear_usb(self):
if hasattr(self, 'fluke_entry_var'):
#self.fluke_entry_var.destroy()
delattr(self, 'fluke_entry_var')
if hasattr(self, 'fluke_config'):
self.fluke_config.destroy()
delattr(self, 'fluke_config')
if hasattr(self, 'fluke_entry'):
self.fluke_entry.destroy()
delattr(self, 'fluke_entry')
def fluke_ts(self):
self.entry_var_port = tk.StringVar()
self.entry_var_port.set('8001')
self.fluke_entry_var = tk.StringVar()
self.fluke_entry_var.set('TS')
self.fluke_config = tk.Label(self, text='Fluke TS IP:',
bg='white', font=font_label, padx=8, pady=2)
self.fluke_entry = tk.Entry(self, textvariable=self.fluke_entry_var)
self.fluke_config.grid(row=0, column=0, sticky='W')
self.fluke_entry.grid(row=0, column=1)
self.fluke_port = tk.Entry(self, textvariable=self.entry_var_port, width=5)
self.fluke_port.pack_propagate(0)
self.fluke_port.grid(row=0, column=2)
def fluke_clear_ts(self):
if hasattr(self, 'entry_var_port'):
#self.entry_var_port.destroy()
delattr(self, 'entry_var_port')
if hasattr(self, 'fluke_port'):
self.fluke_port.destroy()
delattr(self, 'fluke_port')
if hasattr(self, 'fluke_config'):
self.fluke_config.destroy()
delattr(self, 'fluke_config')
if hasattr(self, 'fluke_entry'):
self.fluke_entry.destroy()
delattr(self, 'fluke_entry')
def inst_adacs(self):
self.adacs_rh_var = tk.StringVar()
self.adacs_tmp_var = tk.StringVar()
self.adacs_rh_var.set("vaisala.RH")
self.adacs_tmp_var.set("vaisala.Temp")
self.adacs_rh_label = tk.Label(self, text='ADACS RH pt.:',
bg='white', font=font_label, padx=8, pady=2)
self.adacs_rh = tk.Entry(self, textvariable=self.adacs_rh_var)
self.adacs_tmp_label = tk.Label(self, text='ADACS Tmp pt.:',
bg='white', font=font_label, padx=8, pady=2)
self.adacs_tmp = tk.Entry(self, textvariable=self.adacs_tmp_var)
self.adacs_rh_label.grid(row=1, column=0, sticky='W')
self.adacs_rh.grid(row=1, column=1)
self.adacs_tmp_label.grid(row=2, column=0, sticky='W')
self.adacs_tmp.grid(row=2, column=1)
def inst_clear_adacs(self):
if hasattr(self, 'adacs_rh_var'):
#self.adacs_rh_var.destroy()
delattr(self, 'adacs_rh_var')
if hasattr(self, 'adacs_tmp_var'):
#self.adacs_tmp_var.destroy()
delattr(self, 'adacs_tmp_var')
if hasattr(self, 'adacs_rh_label'):
self.adacs_rh_label.destroy()
delattr(self, 'adacs_rh_label')
if hasattr(self, 'adacs_rh'):
self.adacs_rh.destroy()
delattr(self, 'adacs_rh')
if hasattr(self, 'adacs_tmp_label'):
self.adacs_tmp_label.destroy()
delattr(self, 'adacs_tmp_label')
if hasattr(self, 'adacs_tmp'):
self.adacs_tmp.destroy()
delattr(self, 'adacs_tmp')
def inst_ip(self):
self.inst_entry_var = tk.StringVar()
self.inst_entry_var_port = tk.StringVar()
self.inst_entry_var_port.set('23')
self.inst_config = tk.Label(self, text='Inst. IP', bg='white', font=font_label, padx=8, pady=2)
self.inst_entry = tk.Entry(self, textvariable=self.inst_entry_var)
self.inst_entry_port = tk.Entry(self, textvariable=self.inst_entry_var_port, width=5)
self.inst_config.grid(row=1, column=0, sticky='W')
self.inst_entry.grid(row=1, column=1)
self.inst_entry_port.pack_propagate(0)
self.inst_entry_port.grid(row=1, column=2)
def inst_clear_ip(self):
if hasattr(self, 'inst_entry_var'):
#self.inst_entry_var.destroy()
delattr(self, 'inst_entry_var')
if hasattr(self, 'inst_entry_var'):
#self.inst_entry_var_port.destroy()
delattr(self, 'inst_entry_var')
if hasattr(self, 'inst_config'):
self.inst_config.destroy()
delattr(self, 'inst_config')
if hasattr(self, 'inst_entry'):
self.inst_entry.destroy()
delattr(self, 'inst_entry')
if hasattr(self, 'inst_entry_port'):
self.inst_entry_port.destroy()
delattr(self, 'inst_entry_port')
class Filler(tk.Frame):
def __init__(self, master=None, t_width=65):
tk.Frame.__init__(self, master, bg='white')
self.label = tk.Label(self, text='', bg='white', width=t_width)
self.label.grid(row=0,column=0)
class HUMICAL:
def __init__(self):
self.root = tk.Tk()
self.root.configure(background='white', padx=8, pady=8)
self.root.title("HUMICAL V-0.2")
# Setup frame layout
self.standard = Info(master=self.root, inst_type='Standard')
self.instrument = Info(master=self.root, inst_type='Instrument')
self.controls = Controls(master=self.root)
self.buttons = Buttons(master=self.root)
self.table = Table(master=self.root)
self.filler = Filler(master=self.root)
self.configuration = Configuration(master=self.root)
self.controls.pack_propagate(0)
self.controls.grid( column=0, row=0, padx=4, pady=4, sticky='n')
self.configuration.grid(column=0, row=1, padx=4, pady=4, sticky='nw')
self.buttons.grid( column=0, row=2, padx=4, pady=4, sticky='w')
self.standard.grid( column=1, row=0, padx=4, pady=4, sticky='w')
self.instrument.grid(column=2, row=0, padx=4, pady=4)
self.filler.pack_propagate(0)
self.filler.grid(column=3, row=0, padx=4, pady=4)
self.table.grid(column=1, row=1, columnspan=3, rowspan=2, padx=4, pady=4)
self.root.bind("<<GLin>>", self.gen_lin_check)
self.root.bind("<<DLin>>", self.del_lin_check)
self.buttons.start_button.configure(command=self.start)
# remove adacs as an option for instrument
if 'adacs' not in sys.modules:
self.controls.inst_conn.set('TCP/IP')
self.controls.update_inst_settings('TCP/IP')
self.root.mainloop()
def gen_lin_check(self, value):
self.lin_checks = LineCheck(master=self.root)
self.lin_checks.grid(column=1, row=3, padx=4, pady=4, columnspan=3, sticky='w')
self.filler_bottom = Filler(master=self.root, t_width=20)
self.filler_bottom.pack_propagate(0)
self.filler_bottom.grid(column=0, row=3, padx=4, pady=4)
def del_lin_check(self, value):
if hasattr(self, 'lin_checks'):
self.lin_checks.destroy()
self.filler_bottom.destroy()
delattr(self, 'lin_checks')
delattr(self, 'filler_bottom')
def start(self):
self.thread = Thread(target=self.run)
self.thread.start()
def run(self):
# Load meta data
self.load()
# Run As Found
self.calibrate()
self.RH_Cal.generate_report('As Found')
# If as found failed
if not self.RH_Cal.last_cal_pass:
# Wait for the adjustment mode to be switched on
tkMessageBox.showinfo(
"Failed",
"Open the transmitter and switch on the adjustment mode")
# Calibrate Vaisala Unit
try:
self.RH_Cal.update_instrument()
except:
tkMessageBox.showinfo("Error", "Retry Calibration")
self.RH_Cal.instrument.cal_mode = False
del self.RH_Cal.instrument.conn
self.RH_Cal.update_instrument()
# Wait for the adjustment mode to be switched off
tkMessageBox.showinfo(
"Ready",
"Switch off adjusment mode and close the transmitter")
self.clear_table()
# Re-Run Calibration
self.calibrate()
self.RH_Cal.generate_report('New Calibration')
# Set setpoint low
self.RH_Cal.fluke.set(15)
tkMessageBox.showinfo(
"Complete",
"Calibration finished")
self.RH_Cal.close()
self.controls.cal_type_menu.config(state='enable')
self.controls.stnd_conn_menu.config(state='enable')
self.controls.inst_conn_menu.config(state='enable')
def load(self):
stnd_conn_type = self.controls.fluke_conn.get()
ubs_port = self.configuration.fluke_entry_var.get()
inst_conn_type = self.controls.inst_conn.get()
if 'adacs' in inst_conn_type.lower():
adacs= True
inst_ip = []
else:
adacs = False
inst_ip = [self.configuration.inst_entry_var.get(),
self.configuration.inst_entry_var_port.get()]
# Initiate calibrator
self.RH_Cal = RH_Cal('',
conn_type=[stnd_conn_type, ubs_port],
adacs=adacs, inst_ip=inst_ip)
# Load metadata
stnd = {'barcode':self.RH_Cal.fluke.meta_data['serial_number'],
'model':self.RH_Cal.fluke.meta_data['brand'] \
+ ' ' +\
self.RH_Cal.fluke.meta_data['model'],
'serial_number':self.RH_Cal.fluke.meta_data['serial_number'],
'firmware':self.RH_Cal.fluke.meta_data['firmware'],}
inst = {'barcode':self.RH_Cal.instrument.meta_data['serial_number'],
'model':self.RH_Cal.instrument.meta_data['model'],
'serial_number':self.RH_Cal.instrument.meta_data['serial_number'],
'firmware':self.RH_Cal.instrument.meta_data['firmware'],}
self.standard.load_values(stnd)
self.instrument.load_values(inst)
# Check if standard is ready
self.buttons.ready(self.RH_Cal.fluke.ready)
# Turn on controls back on
self.controls.cal_type_menu.config(state='disable')
self.controls.stnd_conn_menu.config(state='disable')
self.controls.inst_conn_menu.config(state='disable')
def calibrate(self):
# Check ready status
time.sleep(1)
self.buttons.ready(self.RH_Cal.fluke.ready)
# Do not calibrate until the fluke is warm
while not self.RH_Cal.fluke.ready:
time.sleep(30)
# Change ready status
self.buttons.ready(self.RH_Cal.fluke.ready)
type_of_cal = self.controls.cal_type.get()
if 'standard' in type_of_cal:
cal_points = 5
else:
cal_points = 10
# Initiate calibrations
self.RH_Cal.calibrate(cal_points=cal_points)
# Tell gui if its stable
self.S = Thread(target=self.check_stability)
self.S.start()
# Cycle through every set point
while self.RH_Cal.cal_index <= self.RH_Cal.cal_points-1:
# Run one calibration cycle
self.RH_Cal.cal_point()
# Store data in dict format to upload to gui
val = {'s_rh':self.RH_Cal.calibration['setpoint'][-1],
's_rh_stdev':self.RH_Cal.calibration['setpoint_stdv'][-1],
's_t':self.RH_Cal.calibration['setpoint_tmp'][-1],
's_t_stdev':self.RH_Cal.calibration['setpoint_tmp_stdv'][-1],
'i_rh':self.RH_Cal.calibration['response'][-1],
'i_rh_stdev':self.RH_Cal.calibration['response_stdv'][-1],
'i_t':self.RH_Cal.calibration['response_tmp'][-1],
'i_t_stdev':self.RH_Cal.calibration['response_tmp_stdv'][-1],
'error':self.RH_Cal.calibration['error'][-1],
'error_tmp':self.RH_Cal.calibration['t_error'][-1],
'criteria':self.RH_Cal.calibration['pass/fail'][-1]}
# Load values into tables
self.table.load_values(self.RH_Cal.cal_index, val)
# Find maximum errors
self.RH_Cal.find_max()
# Retrieve maximum tolerances
val_max = {'s_rh_stdev':self.RH_Cal.max_error['setpoint_stdv'],
's_t_stdev':self.RH_Cal.max_error['setpoint_tmp_stdv'],
'i_rh_stdev':self.RH_Cal.max_error['response_stdv'],
'i_t_stdev':self.RH_Cal.max_error['response_tmp_stdv'],
'error':self.RH_Cal.max_error['error'],
'error_tmp':self.RH_Cal.max_error['t_error'],}
# Load tolerances into table
self.table.load_values(self.RH_Cal.cal_index+1, val_max)
# Retrieve limits
val_limit = {'s_rh_stdev':self.RH_Cal.maximum_specs['stimulus_stdv'],
's_t_stdev':self.RH_Cal.maximum_specs['stimulus_tmp_stdv'],
'i_rh_stdev':self.RH_Cal.maximum_specs['response_stdv'],
'i_t_stdev':self.RH_Cal.maximum_specs['response_tmp_stdv'],
'error':self.RH_Cal.maximum_specs['error'],
'error_tmp':self.RH_Cal.maximum_specs['t_error'],}
# Load limits into table
self.table.load_values(self.RH_Cal.cal_index+2, val_limit)
if cal_points == 10:
# Run the linearity checks
self.RH_Cal.lin_check()
val_lin = {'a1' :[round(self.RH_Cal.lin_check_results['data']['a1y'],3),
'pass' if self.RH_Cal.lin_check_results['checks']['a1'] else 'fail'],
'|x-min*(a1-1)+a0|':[round(self.RH_Cal.lin_check_results['data']['|x-min*(a1-1)+a0|'],3),
'pass' if self.RH_Cal.lin_check_results['checks']['|x-min*(a1-1)+a0|'] else 'fail'],
'SEE' :[round(self.RH_Cal.lin_check_results['data']['SEE'],3),
'pass' if self.RH_Cal.lin_check_results['checks']['SEE'] else 'fail'],
'r_squared' :[round(self.RH_Cal.lin_check_results['data']['r_squared'],4),
'pass' if self.RH_Cal.lin_check_results['checks']['r_squared'] else 'fail'],}
# Load linearity checks into table
self.lin_checks.load_table(val_lin)
def check_stability(self):
# Check stabilization while the cal is not finished
while self.RH_Cal.cal_index <= self.RH_Cal.cal_points-1 and self.thread.isAlive():
self.buttons.stable(self.RH_Cal.stable)
time.sleep(1)
# Check if thread died prematurely
if self.RH_Cal.cal_index <= self.RH_Cal.cal_points-1 and not self.thread.isAlive():
self.buttons.error(self.thread.isAlive())