#!/usr/bin/python #control program for megacup aka tinman at byg.dtu.dk # version history: #climch2008.py 2008-12-28 # major change to weighing beam manipulation 20081124 # climch101, 22.5.2007 - program for climate chamber # changes 08.07.2004: # logs also strain gage input voltage, changed also climch_rc_old.py # changes 2007: change open file directory # import time, string import climch_cc # dictionary of control constants from serport import SerialPort # serial port controller from climch_rc import * # dictionary of data logger instructions from climch_defs import * # calculation functions # # Connect to data logger a = SerialPort("/dev/ttyS0") # set up serial port as a file # # Initiate history list which contains # the present and the previous sets of data # needed for PID (proportional) control hist0 = [1]*20 hist1 = [1]*20 # #Send initiation instructions for b in InitiateMeasurements: #from climch_rc print b, a.dialog(b) #send message to serial port time.sleep(0.2)#gives time to check logger response #set up the starting values saveFlag = 1 # time to save to file startCycle = 1# first measurement cycle saveTime = time.time()+ 600 startPointInCycle = climch_cc.Cc['startAtTime'] timeOffset = startPointInCycle * 3600 pidTime = 60 # secs PID cycle halfTime = pidTime/2 heat = 25 # secs warming autoClose = 0 # set to 1 if peltier overheats pV = climch_cc.Cc['peltierVolts'] while 1: # main loop try: now = time.time() # rotate cam to release weighing beam a.dialog('rout:open (@214)\n') #stop fan a.dialog('rout:clos (@215)\n') #pulse cam motor time.sleep(0.25) a.dialog('rout:open (@215)\n') time.sleep(8) # wait for air and weighing beam to settle # is it time to save to file? if now > saveTime: # set timer to next ten minute point saveTime = now - (now%600) + 600 saveFlag = 1 reload(climch_cc) # check for new instructions if startPointInCycle != climch_cc.Cc['startAtTime']: startPointInCycle = climch_cc.Cc['startAtTime'] timeOffset = startPointInCycle * 3600 datestamp = time.gmtime(now) print 'month %s day %s hr %s min %s ' % datestamp[1:5] if saveFlag: df = open('./data.txt', 'a') df.write('\n%s, %s, %s, %s, %s, ' % datestamp[0:5]), df.write( str(climch_cc.Cc['run_id'] )), df.write(', ') k = 0 # Index into hist* arrays hist0 = hist1[:] #overwrite older data a.dialog('init\n') #scan datalogger time.sleep(7) # scan takes some time # rotate cam to force water container onto heat sink a.dialog('rout:clos (@216)\n') #pulse motor time.sleep(0.25) a.dialog('rout:open (@216)\n') a.dialog('rout:clos (@214)\n') #start fan for b in DataMeasurements: #collect results c = a.dialog(b) s = str(c) num = 1.0 if s: try: num = float(s) hist1[k] = num k = k + 1 except ValueError, e: hist1[k] = ' error ' continue #write some data. Note that the dewpoint in #hist1[1] is later overrwritten with rh print ' ch_t %0.1f dp %0.1f ' % (hist1[0],hist1[1]), if saveFlag: df.write('%0.1f, %0.1f, ' % (hist1[0], hist1[1])), # refine data and set control values if startCycle: #only on the first measurement cycle hist0 = hist1[:] #write present data to prev data startCycle = 0 tPrev = hist0[0] tNow = hist1[0] #check beam position if hist1[2] < 5: #beam probably in wrong position print 'Alert: wrong beam position, ', #a.dialog('rout:close (@215)\n') #time.sleep(2) #a.dialog('rout:open (@215)\n') hist1[2] = hist0[2] #use old data print 'using old data' #peltiercooling tracks dewpoint sink = hist1[3] - 2.0 #2.0 is the default print ' heatx_t %0.1f' % hist1[3], if sink < hist1[1]: a.dialog('rout:open (@207)\n') print ' x_cool off', else: a.dialog('rout:close (@207)\n') print ' x_cool on', #check for overheating print ' ht_snk_t %0.1f' % hist1[4] if hist1[4] > 35: #may need some changing in hot weather, default 30 autoClose = 1 #temperature control: set PID heating time thisTime = now + timeOffset tTarget = setTarget(thisTime,climch_cc.Cc['tPeriod'],\ climch_cc.Cc['tAvg'],climch_cc.Cc['tHalfAmp']) nextTime = now + timeOffset + 60 #seconds tNext = setTarget(nextTime, climch_cc.Cc['tPeriod'],\ climch_cc.Cc['tAvg'], climch_cc.Cc['tHalfAmp']) print ' trgt_t %0.1f' % tNext heat = heat + \ piddle(tPrev, tNow, tTarget, tNext,\ climch_cc.Cc['tCorrC'], climch_cc.Cc['tTrendC']) #moisture control rh = dpToRh(hist1[0], hist1[1]) hist1[1] = rh print ' rh %i' % rh, # add polarity to measured Peltier V if pV < 0: hist1[5]= -hist1[5] print ' rh %i' % rh, if climch_cc.Cc['rhControl']: #RH control mPrev = hist0[1] mNow = hist1[1] else: #FLUX control mPrev = hist0[2] mNow = hist1[2] thisTime = now + timeOffset mTarget = setTarget(thisTime,climch_cc.Cc['mPeriod'],\ climch_cc.Cc['mAvg'],climch_cc.Cc['mHalfAmp']) nextTime = now + timeOffset + 60 #seconds mNext = setTarget(nextTime, climch_cc.Cc['mPeriod'],\ climch_cc.Cc['mAvg'], climch_cc.Cc['mHalfAmp']) print ' m_tgt %0.1f' % mNext, pV = pV + \ piddle(mPrev, mNow, mTarget, mNext,\ climch_cc.Cc['mCorrC'], climch_cc.Cc['mTrendC']) print ' p_volts_now %0.1f pV_nxt %0.1f' % (hist1[5], pV), if autoClose: print 'Peltier overheating. closing...' pV = 0.0 #set Peltier limits, can be changed but there is #a risk of overheating. Chnage only when #system is running reliably! if pV > 3.0: pV = 3.0 if pV < (-7.0): pV = (-7.0) vToB(pV, a)#sends new voltage to Peltier if autoClose: break #end program #write more values to screen and file print ' wt %0.2f' % hist1[2], print ' water_tank_t %0.1f' % hist1[8], print ' s.g._input_V %0.1f' % hist1[9], if saveFlag: for j in (1,2,3,4,5): df.write('%0.1f, ' % hist1[j]), #room t and rh need refining rm_t = thermistor(hist1[6]) df.write('%0.1f, ' % rm_t), rm_m = H_RH(hist1[7], rm_t) df.write('%0.1f, ' % rm_m), #water tank temperature df.write('%0.1f, ' % hist1[8]), #strain gage input voltage, added 090104 by RHP #df.write('%0.1f, ' % hist1[9]), print ' ' # if saveFlag: # df.write('\n') saveFlag = 0 #control chamber temperature if heat > pidTime: heat = pidTime if heat < (-pidTime): heat = (-pidTime) invHeat = pidTime - abs(heat) print 'INVHEAT', print invHeat timeLeft = pidTime - (time.time() - now) if timeLeft < 0: timeLeft = 0 print 'TIME LEFT:', print timeLeft if heat == -pidTime: #continuous cooling a.dialog('rout:close (@206)\n') a.dialog('rout:open (@209)\n') print 'cooling 100%' time.sleep(timeLeft) elif heat == pidTime: # continuous heating a.dialog('rout:close (@209)\n') a.dialog('rout:open (@206)\n') print 'heating 100%' time.sleep(timeLeft) elif heat < (-halfTime): #mostly cooling a.dialog('rout:open (@206,209)\n') print 'cooling %i' % (abs(heat) / pidTime * 100) time.sleep(invHeat) a.dialog('rout:close (@206)\n') snooze = timeLeft -invHeat if snooze < 0: snooze = 0 time.sleep(snooze) elif heat > (halfTime): #mostly warming a.dialog('rout:open (@206,209)\n') print 'heating %i' % (heat / pidTime * 100) time.sleep(invHeat) a.dialog('rout:close (@209)\n') snooze = timeLeft -invHeat if snooze < 0: snooze = 0 time.sleep(snooze) elif heat < 0: #a little cooling a.dialog('rout:close (@206)\n') a.dialog('rout:open (@209)\n') print 'cooling %i' % (abs(heat) / pidTime * 100) time.sleep(abs(heat)) a.dialog('rout:open (@206)\n') snooze = timeLeft - abs(heat) if snooze < 0: snooze = 0 time.sleep(snooze) elif heat > 0: # a little heating a.dialog('rout:close (@209)\n') a.dialog('rout:open (@206)\n') print 'heating %i' % (heat / pidTime * 100) time.sleep(heat) a.dialog('rout:open (@209)\n') snooze = timeLeft - heat if snooze < 0: snooze = 0 time.sleep(snooze) except: # on any un-caught exception print 'Unexpected error. Closing down' vToB(-0.5, a)# sets Peltier to low volts break # end of while loop #close safely vToB(-0.5, a)# sets Peltier to low volts a.dialog('rout:open (@206:220)\n') # end of program