2014-10-16 06:01:52 +00:00
import stepper
2014-10-18 19:41:05 +00:00
import time
import random
2014-10-16 06:01:52 +00:00
import warnings
2014-10-15 18:10:54 +00:00
2014-10-20 04:34:17 +00:00
class StateMachine ( object ) :
def __init__ ( self ) :
import stepper
import thermo
self . monitor = thermo . Monitor ( )
self . regulator = stepper . Regulator ( )
2014-10-16 06:01:52 +00:00
class KilnController ( object ) :
2014-10-19 02:48:32 +00:00
def __init__ ( self , schedule , monitor , interval = 5 , start_time = None , Kp = .025 , Ki = .01 , Kd = .001 , simulate = True ) :
2014-10-16 06:01:52 +00:00
self . schedule = schedule
self . monitor = monitor
2014-10-18 19:41:05 +00:00
self . interval = interval
self . start_time = start_time
if start_time is None :
self . start_time = time . time ( )
self . regulator = stepper . Regulator ( simulate = simulate )
self . pid = PID ( Kp , Ki , Kd )
self . simulate = simulate
if simulate :
self . schedule . insert ( 0 , [ 0 , 15 ] )
else :
2014-10-18 20:38:43 +00:00
self . schedule . insert ( 0 , [ 0 , 15 ] )
2014-10-16 06:01:52 +00:00
@property
def elapsed ( self ) :
''' Returns the elapsed time from start in seconds '''
2014-10-18 19:41:05 +00:00
return time . time ( ) - self . start_time
2014-10-16 06:01:52 +00:00
def run ( self ) :
2014-10-18 19:41:05 +00:00
try :
self . regulator . ignite ( )
print self . elapsed , self . schedule [ - 1 ] [ 0 ]
while self . elapsed < self . schedule [ - 1 ] [ 0 ] :
now = time . time ( )
ts = self . elapsed
#find epoch
for i in range ( len ( self . schedule ) - 1 ) :
if self . schedule [ i ] [ 0 ] < ts < self . schedule [ i + 1 ] [ 0 ] :
time0 , temp0 = self . schedule [ i ]
time1 , temp1 = self . schedule [ i + 1 ]
frac = ( ts - time0 ) / ( time1 - time0 )
setpoint = frac * ( temp1 - temp0 ) + temp0
self . pid . setPoint ( setpoint )
2014-10-18 20:38:43 +00:00
print " In epoch %d , elapsed time %f , temperature %f " % ( i , ts , setpoint )
2014-10-18 19:41:05 +00:00
if self . simulate :
temp = setpoint + random . gauss ( - 20 , 15 )
else :
temp = self . monitor . temperature
pid_out = self . pid . update ( temp )
if pid_out < 0 : pid_out = 0
if pid_out > 1 : pid_out = 1
2014-10-18 20:38:43 +00:00
self . regulator . set ( pid_out , block = True )
2014-10-18 19:41:05 +00:00
time . sleep ( self . interval - ( time . time ( ) - now ) )
except :
import traceback
traceback . print_exc ( )
print " Started at %f " % self . start_time
self . regulator . off ( )
2014-10-16 06:01:52 +00:00
class PID ( object ) :
"""
Discrete PID control
#The recipe gives simple implementation of a Discrete Proportional-Integral-Derivative (PID) controller. PID controller gives output value for error between desired reference input and measurement feedback to minimize error value.
#More information: http://en.wikipedia.org/wiki/PID_controller
#
#cnr437@gmail.com
#
####### Example #########
#
#p=PID(3.0,0.4,1.2)
#p.setPoint(5.0)
#while True:
# pid = p.update(measurement_value)
#
#
"""
def __init__ ( self , P = 2.0 , I = 0.0 , D = 1.0 , Derivator = 0 , Integrator = 0 , Integrator_max = 500 , Integrator_min = - 500 ) :
self . Kp = P
self . Ki = I
self . Kd = D
self . Derivator = Derivator
self . Integrator = Integrator
self . Integrator_max = Integrator_max
self . Integrator_min = Integrator_min
self . set_point = 0.0
self . error = 0.0
def update ( self , current_value ) :
"""
Calculate PID output value for given reference input and feedback
"""
self . error = self . set_point - current_value
self . P_value = self . Kp * self . error
self . D_value = self . Kd * ( self . error - self . Derivator )
self . Derivator = self . error
self . Integrator = self . Integrator + self . error
if self . Integrator > self . Integrator_max :
self . Integrator = self . Integrator_max
elif self . Integrator < self . Integrator_min :
self . Integrator = self . Integrator_min
self . I_value = self . Integrator * self . Ki
PID = self . P_value + self . I_value + self . D_value
2014-10-18 19:41:05 +00:00
print " PID: %f , %f , %f : %f " % ( self . P_value , self . I_value , self . D_value , PID )
2014-10-16 06:01:52 +00:00
return PID
def setPoint ( self , set_point ) :
"""
Initilize the setpoint of PID
"""
self . set_point = set_point
self . Integrator = 0
self . Derivator = 0
def setIntegrator ( self , Integrator ) :
self . Integrator = Integrator
def setDerivator ( self , Derivator ) :
self . Derivator = Derivator
def setKp ( self , P ) :
self . Kp = P
def setKi ( self , I ) :
self . Ki = I
def setKd ( self , D ) :
self . Kd = D
def getPoint ( self ) :
return self . set_point
def getError ( self ) :
return self . error
def getIntegrator ( self ) :
return self . Integrator
def getDerivator ( self ) :
return self . Derivator