def __init__(self, name, lamps=None, parent=None): Logging.logEvent("Debug", "Status Update", { "message": "Creating ZoneControlStub: {}".format(name), "level": 3 }) self.zoneProfile = ProfileInstance.getInstance().zoneProfiles.getZone( name) self.lamps = lamps self.name = name self.parent = parent self.temp_temperature = None self.pid = PID() if lamps: # These are the PID settings for the lamps proportional_gain = .2 integral_gain = 0 derivative_gain = 0 else: # These are the PID settings for the heaters in the platen proportional_gain = .4 integral_gain = 0 derivative_gain = 0 self.pid.setKp(proportional_gain) self.pid.setKi(integral_gain) self.pid.setKd(derivative_gain)
def logPressureData(self): coloums = "( profile_I_ID, guage, pressure, time )" values = "( \"{}\",{},{},\"{}\" ),\n".format( self.zoneProfiles.profileUUID, self.gauges.get_cryopump_address(), self.gauges.get_cryopump_pressure(), datetime.datetime.fromtimestamp(time.time())) values += "( \"{}\",{},{},\"{}\" ),\n".format( self.zoneProfiles.profileUUID, self.gauges.get_chamber_address(), self.gauges.get_chamber_pressure(), datetime.datetime.fromtimestamp(time.time())) values += "( \"{}\",{},{},\"{}\" )".format( self.zoneProfiles.profileUUID, self.gauges.get_roughpump_address(), self.gauges.get_roughpump_pressure(), datetime.datetime.fromtimestamp(time.time())) sql = "INSERT INTO tvac.Pressure {} VALUES {};".format(coloums, values) mysql = MySQlConnect() try: mysql.cur.execute(sql) mysql.conn.commit() except Exception as e: print(sql) Logging.debugPrint( 1, "Error in logPressureData, PfeifferGaugeUpdater: {}".format( str(e))) if Logging.debug: raise e
def adc_fifo_status(self): self.pc104.seek(self.Adc16Addr(0x08)) # ADCSTAT b1 = self.pc104.read_byte() b2 = self.pc104.read_byte() Logging.debugPrint(6, "ADC FIFO Status: 0x{:x} 0x{:x}".format(b1,b2)) return ((b1 & 0x3e) >> 1, # FFHEAD: Channel on head of fifo. It increments to (num_chan*2)+1 then wraps to 0 ((b2 & 0xff) << 2) | ((b1 & 0xC0) >> 6)) # Number of elements in fifo
def wait_for_next_Multipule(self, m): # m in seconds sleep_time = self.time_test - time.time() if sleep_time > 0: time.sleep(sleep_time) self.time_test += m Logging.debugPrint( 6, "Ts Registers Sleep Time: {:0.6f}s".format(sleep_time))
def __init__(self): if ProfileInstance.__instance != None: raise Exception("This class is a singleton!") else: Logging.logEvent("Debug", "Status Update", { "message": "Creating ProfileInstance", "level": 2 }) self.zoneProfiles = ZoneCollection(self) # System Wide stats self.activeProfile = False self.vacuumWanted = False # TODO: When Profile aborted is vacuumWanted cleared? self.currentSetpoint = None self.recordData = False self.inRamp = False self.inHold = False self.inPause = False self.getStatusFromDB() self.systemStatusQueue = [] ProfileInstance.__instance = self
def __init__(self): if HardwareStatusInstance.__instance != None: raise Exception("This class is a singleton!") else: Logging.logEvent("Debug", "Status Update", { "message": "Creating HardwareStatusInstance", "level": 2 }) self.Thermocouples = ThermocoupleCollection() self.PfeifferGuages = PfeifferGaugeCollection() self.ShiCryopump = ShiCryopumpCollection() self.Shi_MCC_Cmds = [] # ['cmd', arg, arg,... arg] self.Shi_Compressor_Cmds = [] # 'cmd' self.TdkLambda_PS = TdkLambdaCollection() self.TdkLambda_Cmds = [] # ['cmd', arg, arg,... arg] self.PC_104 = PC_104_Instance.getInstance() # System Wide Stats if os.name == "posix": userName = os.environ['LOGNAME'] else: userName = "******" if "root" in userName: self.OperationalVacuum = False # self.OperationalVacuum = True else: self.OperationalVacuum = True self.VacuumState = None # self.VacuumState = "Operational Vacuum" HardwareStatusInstance.__instance = self
def setPC104_Digital(self, data): pins = HardwareStatusInstance.getInstance().PC_104 Logging.debugPrint(3, "POST: setPC104_Digital '%s'" % data) pins.digital_out.update(data) Logging.debugPrint( 4, "Digital out data: '%s'" % pins.digital_out.getJson()) return "{'result':'success'}"
def loadThermalProfiles(self, profileName, zone): ''' This is a helper medthod for LoadProfile, this will load thermal profiles ''' sql = "SELECT * FROM tvac.Thermal_Profile WHERE profile_name=\"{}\" AND zone=\"{}\";".format( profileName, zone) mysql = MySQlConnect() try: mysql.cur.execute(sql) mysql.conn.commit() except Exception as e: Logging.debugPrint(3, "sql: {}".format(sql)) Logging.debugPrint( 1, "Error in loadThermoProfiles, zoneCollection: {}".format( str(e))) if Logging.debug: raise e results = mysql.cur.fetchall() thermalprofiles = [] for result in results: TP = {} TP['thermalsetpoint'] = int(result['set_point']) TP['tempgoal'] = float(result['temp_goal']) TP['soakduration'] = int(result['soak_time']) TP['ramp'] = int(result['ramp_time']) thermalprofiles.append(TP) return thermalprofiles
def loadThermoCouples(self, profileName, zone): ''' This is a helper medthod for LoadProfile, this will load thermocouples tied to this profile ''' sql = "SELECT * FROM tvac.TC_Profile WHERE profile_name=\"{}\" AND zone=\"{}\";".format( profileName, zone) mysql = MySQlConnect() try: mysql.cur.execute(sql) mysql.conn.commit() except Exception as e: Logging.debugPrint(3, "sql: {}".format(sql)) Logging.debugPrint( 1, "Error in loadThermoCouples, zoneCollection: {}".format( str(e))) if Logging.debug: raise e2 results = mysql.cur.fetchall() TCs = [] tcList = HardwareStatusInstance.getInstance().Thermocouples.tcList for result in results: TCs.append(int(result['thermocouple'])) for tc in tcList: if tc.Thermocouple in TCs: tc.update({ "zone": "zone" + str(int(result['zone'])), "userDefined": True }) return TCs
def __init__(self): # self.zoneThreadDict = self.createZoneCollection() self.dutyCycleThread = DutyCycleControlStub(parent=self) self.hardwareInterfaceThreadDict = self.createHardwareInterfaces( parent=self) self.safetyThread = SafetyCheck(parent=self) self.zoneProfiles = ProfileInstance.getInstance().zoneProfiles self.runThreads() # if there is a half finished profile in the database result = self.returnActiveProfile() Logging.debugPrint(3, "Active Profile?: {}".format(result)) if result: Logging.debugPrint( 1, "Unfinished profile found: {}".format( str(result['profile_name']))) # load up ram (zone collection) with info from the database and the given start time self.zoneProfiles.load_profile(result['profile_name'], result['profile_Start_Time'], result['thermal_Start_Time'], result['first_Soak_Start_Time']) # after it's in memory, run it! self.runProfile(firstStart=False)
def state_00(self): # Chamber: Atm; CryoP: Vac if (self.cryoPumpPressure > self.pres_atm) and \ (self.chamberPressure > self.pres_atm): self.state = 'Chamber: Atm; CryoP: Atm' if self.chamberPressure < self.pres_ruffon: self.state = 'Non-Operational Vacuum' if self.profile.vacuumWanted and ( not self.hw.ShiCryopump.is_regen_active()): if self.cryoPumpPressure < self.pres_cryoP_Prime: self.hw.Shi_MCC_Cmds.append(['Close_PurgeValve']) self.hw.Shi_MCC_Cmds.append(['Close_RoughingValve']) self.hw.Shi_Compressor_Cmds.append('on') self.hw.Shi_MCC_Cmds.append(['FirstStageTempCTL', 50, 2]) self.hw.Shi_MCC_Cmds.append(['SecondStageTempCTL', 10]) self.hw.Shi_MCC_Cmds.append(['Turn_CryoPumpOn']) self.state = 'PullingVac: CryoCool; Rough Chamber' else: if not self.hw.PC_104.digital_in.getVal('RoughP_Powered'): self.hw.PC_104.digital_out.update( {'RoughP Pwr Relay': True}) Logging.debugPrint( 3, "Vacuum Ctl (@Atm): Applying power to the Ruffing Pump" ) else: if not self.hw.PC_104.digital_in.getVal('RoughP_On_Sw'): self.hw.PC_104.digital_out.update( {'RoughP Start': True}) # Turn on Roughing Pump self.hw.PC_104.digital_out.update( {'RoughP PurgeGass': True}) Logging.debugPrint( 3, "Vacuum Ctl (@Atm): Switching on the Ruffing Pump") else: self.state = 'PullingVac: Start'
def __init__(self): Logging.logEvent("Debug", "Status Update", { "message": "Creating PfeifferGaugeCollection", "level": 2 }) self.pfGuageList = self.buildCollection() self.time = datetime.now()
def __init__(self, parent): Logging.debugPrint(2, "Creating ZoneCollection") self.zoneDict = self.buildCollection() self.updatePeriod = 10 self.profileUUID = uuid.uuid4() self.profileName = None self.parent = parent self.thermalStartTime = None
def __init__(self): Logging.logEvent( "Debug", "Status Update", { "message": "Creating TDK Lambda DC Power Supplies Collection ", "level": 2 }) self.TdkLambda_ps = self.buildCollection() self.time = datetime.now()
def state_09(self): # Operational Vacuum if self.chamberPressure > self.pres_opVac: self.state = 'Non-Operational Vacuum' elif self.hw.ShiCryopump.get_mcc_status('PumpOn?') and \ (not self.hw.ShiCryopump.cryopump_needs_regen()) and \ (self.cryoPumpPressure < self.chamberPressure) and \ (not self.hw.ShiCryopump.is_regen_active()): if (not self.hw.PC_104.digital_in.getVal('CryoP_GV_Closed')) or \ self.profile.vacuumWanted: self.hw.PC_104.digital_out.update({'CryoP GateValve': True}) self.state = 'Operational Vacuum: Cryo Pumping' Logging.debugPrint( 3, "Vacuum Ctl (@OpVac): Switching from OV to OV:CP") time.sleep(4) else: self.hw.PC_104.digital_out.update({'CryoP GateValve': False}) elif self.profile.vacuumWanted and \ (not self.hw.ShiCryopump.is_regen_active()) and \ (not self.hw.ShiCryopump.get_mcc_status('PumpOn?')): # self.hw.PC_104.digital_out.update({'CryoP GateValve': False}) if self.cryoPumpPressure < self.pres_cryoP_Prime: self.hw.Shi_MCC_Cmds.append(['Close_PurgeValve']) self.hw.Shi_MCC_Cmds.append(['Close_RoughingValve']) self.hw.Shi_Compressor_Cmds.append('on') self.hw.Shi_MCC_Cmds.append(['FirstStageTempCTL', 50, 2]) self.hw.Shi_MCC_Cmds.append(['SecondStageTempCTL', 10]) self.hw.Shi_MCC_Cmds.append(['Turn_CryoPumpOn']) time.sleep(5) self.hw.PC_104.digital_out.update({'RoughP Pwr Relay': False}) Logging.debugPrint( 3, "Vacuum Ctl (@OpVac): Starting the Cryo Pump; Roughing Pump Off." ) else: if self.hw.PC_104.digital_in.getVal('RoughP_Powered'): if self.hw.PC_104.digital_in.getVal('RoughP_On_Sw'): self.hw.Shi_MCC_Cmds.append(['Close_PurgeValve']) self.hw.Shi_MCC_Cmds.append(['Open_RoughingValve']) Logging.debugPrint( 3, "Vacuum Ctl (@OpVac): Ruffing the Cryo Pump") else: self.hw.PC_104.digital_out.update( {'RoughP Start': True}) # Turn on Roughing Pump self.hw.PC_104.digital_out.update( {'RoughP PurgeGass': True}) Logging.debugPrint( 3, "Vacuum Ctl (@OpVac): Switching on the Ruffing Pump" ) else: self.hw.PC_104.digital_out.update( {'RoughP Pwr Relay': True}) Logging.debugPrint( 3, "Vacuum Ctl (@OpVac): Applying power to the Ruffing Pump" ) else: self.hw.PC_104.digital_out.update({'CryoP GateValve': False})
def __init__(self): if ThreadCollectionInstance.__instance != None: raise Exception("This class is a singleton!") else: Logging.logEvent("Debug", "Status Update", { "message": "Creating ThreadCollectionInstance", "level": 2 }) self.threadCollection = ThreadCollection() ThreadCollectionInstance.__instance = self
def __init__(self, num=120): Logging.logEvent("Debug", "Status Update", { "message": "Creating ThermocoupleCollection", "level": 2 }) self.tcList = self.buildCollection(num) self.time = datetime.now() self.ValidTCs = [] self.InvalidTCs = [] for tc in self.tcList: self.updateValidTCs(tc)
def __init__(self, parent=None): Logging.logEvent("Debug", "Status Update", { "message": "Creating DutyCycleControlStub", "level": 2 }) self.zoneProfiles = ProfileInstance.getInstance().zoneProfiles self.parent = parent Thread.__init__(self) self.updatePeriod = ProfileInstance.getInstance( ).zoneProfiles.updatePeriod self.d_out = HardwareStatusInstance.getInstance().PC_104.digital_out self.zones = { "zone1": ZoneControlStub(name='zone1', lamps=['IR Lamp 1', 'IR Lamp 2'], parent=self), "zone2": ZoneControlStub(name='zone2', lamps=['IR Lamp 3', 'IR Lamp 4'], parent=self), "zone3": ZoneControlStub(name='zone3', lamps=['IR Lamp 6', 'IR Lamp 5'], parent=self), "zone4": ZoneControlStub(name='zone4', lamps=['IR Lamp 7', 'IR Lamp 8'], parent=self), "zone5": ZoneControlStub(name='zone5', lamps=['IR Lamp 9', 'IR Lamp 10'], parent=self), "zone6": ZoneControlStub(name='zone6', lamps=['IR Lamp 12', 'IR Lamp 11'], parent=self), "zone7": ZoneControlStub(name='zone7', lamps=['IR Lamp 13', 'IR Lamp 14'], parent=self), "zone8": ZoneControlStub(name='zone8', lamps=['IR Lamp 15', 'IR Lamp 16'], parent=self), # zone9 is the platen "zone9": ZoneControlStub(name='zone9', parent=self) } self.currentSetpoint = 1 self.ramp = False self.soak = False
def __init__(self, ThreadCollection): if LN2ControlStub.__instance != None: # correct to carry over from TCU.py? raise Exception("This class is a singleton!") else: Logging.logEvent("Debug","Status Update", {"message": "LN2: Creating LN2ControlStub", "level":2}) LN2ControlStub.__instance = self self.ThreadCollection = ThreadCollection self.hardwareStatus = HardwareStatusInstance self.SLEEP_TIME = 5 # will be 30 seconds super(LN2ControlStub, self).__init__()
def releaseHoldThread(): ProfileInstance.getInstance().inHold = False sql = "UPDATE System_Status SET in_hold=0;" mysql = MySQlConnect() try: mysql.cur.execute(sql) mysql.conn.commit() except Exception as e: Logging.debugPrint(3, "sql: {}".format(sql)) Logging.debugPrint( 1, "Error in ThreadCollection, holdThread: {}".format(str(e))) if Logging.debug: raise e
def __init__(self): if PC_104_Instance.__instance != None: raise Exception("This class is a singleton!") else: Logging.logEvent("Debug", "Status Update", { "message": "Creating PC_104_Instance", "level": 2 }) self.digital_in = DigitalInContract() self.digital_out = DigitalOutContract() self.analog_in = AnalogInContract() self.analog_out = AnalogOutContract() PC_104_Instance.__instance = self
def SendHwCmd(self, data): if type(data) is not list: return '{"result":"Needs a json dictionary of a cmds."}' hw = HardwareStatusInstance.getInstance() Logging.debugPrint(3, "POST: SendHwCmd '%s'" % data) if data[0] == "Shi_MCC_Cmds": # ['cmd', arg, arg,... arg] hw.Shi_MCC_Cmds.append(data[1:]) elif data[0] == "Shi_Compressor_Cmds": # 'cmd' hw.Shi_Compressor_Cmds.append(data[1]) elif data[0] == "TdkLambda_Cmds": # ['cmd', arg, arg,... arg] hw.TdkLambda_Cmds.append(data[1:]) else: return '{"result":"Unknown Hardware Target."}' return '{"result":"success"}'
def runThreads(self): # Starts all the hw threads try: for key in sorted(self.hardwareInterfaceThreadDict.keys()): self.hardwareInterfaceThreadDict[key].daemon = True self.hardwareInterfaceThreadDict[key].start() self.safetyThread.daemon = True self.safetyThread.start() self.dutyCycleThread.daemon = True self.dutyCycleThread.start() except Exception as e: Logging.debugPrint( 1, "Error in runThreads, ThreadCollections: {}".format(str(e))) if Logging.debug: raise e
def updateDBwithEndTime(self): sql = "update tvac.Profile_Instance set endTime=\"{}\" where endTime is null;".format( datetime.datetime.fromtimestamp(time.time())) mysql = MySQlConnect() try: mysql.cur.execute(sql) mysql.conn.commit() except Exception as e: Logging.debugPrint( 1, "Error in updateDBwithEndTime, Duty Cycle control: {}".format( str(e))) if Logging.debug: raise e
def checkHold(self): ''' This is a helper function that keeps the loop held in same temp. It recreates the expected values with updated times at the end TODO: NOTE: if a hold is held less than updateTime it might not recalculate or even get in here ''' try: if ProfileInstance.getInstance().inHold: startHoldTime = int(time.time()) Logging.logEvent( "Event", "Hold Start", { "message": "In hold for first time", "ProfileInstance": ProfileInstance.getInstance() }) while ProfileInstance.getInstance().inHold: for zone in self.zones: if self.zones[zone].zoneProfile.activeZoneProfile: zone = self.zones[zone] # self.temp_temperature = zone.updateDutyCycle() time.sleep(.5) endHoldTime = int(time.time()) holdTime = endHoldTime - startHoldTime self.startTime = self.startTime + holdTime Logging.logEvent( "Event", "HoldEnd", { "message": "Just Left hold", "ProfileInstance": ProfileInstance.getInstance() }) Logging.logEvent( "Debug", "Status Update", { "message": "Leaving hold after {} seconds in hold, new startTime {}" .format(holdTime, self.startTime), "ProfileInstance": ProfileInstance.getInstance(), "level": 2 }) # regenerate expected time, moving things forward to account for hold for zone in self.zones: if self.zones[zone].zoneProfile.activeZoneProfile: self.zones[ zone].expected_temp_values, self.expected_time_values = self.zones[ zone].createExpectedValues( self.zones[zone].zoneProfile. thermalProfiles, startTime=self.startTime) except Exception as e: Logging.debugPrint( 1, "DCCS: Error in check Hold, Duty Cycle: {}".format(str(e))) if Logging.debug: raise e
def updateThermalStartTime(self, thermalStartTime): ''' This is a helper function that is called either when a profile begins the thermal section (when it is in a vacuum) or when the the server is restarted. ''' # This loop is to hold the program here until the temperature vaules have been loaded if os.name == 'posix': userName = os.environ['LOGNAME'] else: userName = "******" tmpStr = "" for zone in self.zoneDict: if self.zoneDict[zone].activeZoneProfile: if "root" in userName: while True: currentTemp = self.zoneDict[zone].getTemp( self.zoneDict[zone].average) Logging.debugPrint( 4, "Zone Col.: currentTemp: {}".format(currentTemp)) if not math.isnan( currentTemp) and int(currentTemp) != 0: break time.sleep(.5) else: currentTemp = self.zoneDict[zone].getTemp( self.zoneDict[zone].average) tmpStr += "{}_Temp = {},".format(zone, currentTemp) tmpStr = tmpStr[:-1] sql = "UPDATE tvac.Profile_Instance set thermal_Start_Time=\"{}\",{} where thermal_Start_Time is null;".format( datetime.datetime.fromtimestamp(thermalStartTime), tmpStr) print(sql) mysql = MySQlConnect() try: mysql.cur.execute(sql) mysql.conn.commit() except Exception as e: Logging.debugPrint( 1, "Error in updateDBwithEndTime, Duty Cycle control: {}".format( str(e))) if Logging.debug: raise e
def run_get_cmd(self, fun, key): val = fun() if val['Error']: Logging.logEvent( "Debug", "Status Update", { "message": 'Shi MCC Get_"%s" Error Response: %s' % (key, val), "level": 3 }) else: if 'Data' in val: self.hw.ShiCryopump.update({'MCC Params': {key: val['Data']}}) else: self.hw.ShiCryopump.update( {'MCC Params': { key: val['Response'] }})
def run_set_cmd(self, fun, cmd): if len(cmd) <= 1: val = fun() elif len(cmd) == 2: val = fun(cmd[1]) elif len(cmd) == 3: val = fun(cmd[1], cmd[2]) else: raise Exception('run_cmd has to many arguments') if val['Error']: Logging.logEvent( "Debug", "Status Update", { "message": 'Shi MCC Set_"%s" Error Response: %s' % (cmd[0], val), "level": 3 })
def updateDutyCycle(self): ''' Given that temp_temperature is assigned to a value, this will update the duty cycle for the lamps ''' self.pid.SetPoint = self.temp_temperature # TODO: Don't leave this hardcoded self.pid.update(self.zoneProfile.getTemp(self.zoneProfile.average)) self.dutyCycle = self.pid.error_value / self.maxTempRisePerUpdate # TODO: pick what lamp you want to use if self.lamps: self.parent.d_out.update( {self.lamps[1] + " PWM DC": self.dutyCycle}) self.parent.d_out.update( {self.lamps[0] + " PWM DC": self.dutyCycle}) else: # for zone 9, the platen HardwareStatusInstance.getInstance().TdkLambda_Cmds.append( ['Platen Duty Cycle', self.dutyCycle]) Logging.debugPrint( 2, "{}: avg ({})\goal({}) -- {}".format( self.name, self.zoneProfile.getTemp(self.zoneProfile.average), self.temp_temperature, self.dutyCycle)) # Logging.logEvent("Debug","Status Update", # {"message": "{}: Current temp: {}".format(self.name,self.zoneProfile.getTemp(self.zoneProfile.average)), # "level":2}) # Logging.logEvent("Debug","Status Update", # {"message": "{}: Temp Goal temperature is {}".format(self.name,self.temp_temperature), # "level":2}) # Logging.logEvent("Debug","Status Update", # {"message": "{}: Current duty Cycle: {}".format(self.name,self.dutyCycle), # "level":2}) Logging.logExpectedTemperatureData({ "expected_temp_values": [self.temp_temperature], "expected_time_values": [time.time()], "zone": self.name, "profileUUID": self.zoneProfile.profileUUID, "ProfileInstance": ProfileInstance.getInstance() })
def logEvent(self, error): errorInList = False if self.errorList: for tempError in self.errorList: if error["event"] == tempError["event"]: if error["item"] == tempError["item"]: if error['itemID'] == tempError['itemID']: errorInList = True if not errorInList: # debugPrint(1, error["details"]) self.errorList.append(error) # print(self.errorList) Logging.debugPrint(4, "Running Safety Checker Thread") # Not sure what to do with this if not self.errorDict[error["event"]]: # The error has not been on, and is now on # Log SQL stuff pass