Class: Temper::PID

Inherits:
Object
  • Object
show all
Defined in:
lib/temper.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ PID

Returns a new instance of PID.



7
8
9
10
11
12
13
14
15
16
17
# File 'lib/temper.rb', line 7

def initialize options = {}
  @interval = options[:interval] || 1000
  @last_time = 0.0
  @last_input = 0.0
  @integral_term = 0.0
  @output_maximum = options[:maximum] || 1000
  @output_minimum = options[:minimum] || 0

  set_mode options[:mode] || :auto
  set_direction options[:direction] || :direct
end

Instance Attribute Details

#directionObject

Returns the value of attribute direction.



5
6
7
# File 'lib/temper.rb', line 5

def direction
  @direction
end

#kdObject

Returns the value of attribute kd.



5
6
7
# File 'lib/temper.rb', line 5

def kd
  @kd
end

#kiObject

Returns the value of attribute ki.



5
6
7
# File 'lib/temper.rb', line 5

def ki
  @ki
end

#kpObject

Returns the value of attribute kp.



5
6
7
# File 'lib/temper.rb', line 5

def kp
  @kp
end

#outputObject

Returns the value of attribute output.



5
6
7
# File 'lib/temper.rb', line 5

def output
  @output
end

#setpointObject

Returns the value of attribute setpoint.



5
6
7
# File 'lib/temper.rb', line 5

def setpoint
  @setpoint
end

Instance Method Details

#calculate_derivative(input) ⇒ Object



55
56
57
# File 'lib/temper.rb', line 55

def calculate_derivative input
  @derivative_term = @kd * (input - @last_input)
end

#calculate_integral(error) ⇒ Object



45
46
47
48
49
50
51
52
53
# File 'lib/temper.rb', line 45

def calculate_integral error
  @integral_term += @ki * error

  if @integral_term > @output_maximum
    @integral_term = @output_maximum
  elsif @integral_term < @output_minimum
    @integral_term = @output_minimum
  end
end

#calculate_outputObject



59
60
61
62
63
64
65
66
67
68
69
# File 'lib/temper.rb', line 59

def calculate_output
  @output = @proportional_term + @integral_term - @derivative_term

  if @output > @output_maximum
    @output = @output_maximum
  elsif @output < @output_minimum
    @output = @output_minimum
  end

  @output
end

#calculate_proportional(error) ⇒ Object



41
42
43
# File 'lib/temper.rb', line 41

def calculate_proportional error
  @proportional_term = @kp * error
end

#control(input) ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/temper.rb', line 19

def control input
  return if !@auto # manual mode

  now = Time.now.to_f
  time_change = (now - @last_time) * 1000

  if time_change >= @interval
    error = @setpoint - input

    calculate_proportional error
    calculate_integral error
    calculate_derivative input

    calculate_output

    @last_time = now
    @last_input = input

    @output
  end
end

#modeObject



105
106
107
# File 'lib/temper.rb', line 105

def mode
  @auto ? :auto : :manual
end

#set_direction(direction) ⇒ Object



101
102
103
# File 'lib/temper.rb', line 101

def set_direction direction
  @direction = direction
end

#set_mode(mode) ⇒ Object



97
98
99
# File 'lib/temper.rb', line 97

def set_mode mode
  @auto = mode == :auto
end

#tune(kp, ki, kd) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/temper.rb', line 71

def tune kp, ki, kd
  return if kp < 0 || ki < 0 || kd < 0

  interval_seconds = (@interval / 1000.0)

  @kp = kp
  @ki = ki * interval_seconds
  @kd = kd / interval_seconds

  if @direction != :direct
    @kp = 0 - @kp
    @ki = 0 - @ki
    @kd = 0 - @kd
  end
end

#update_interval(new_interval) ⇒ Object



87
88
89
90
91
92
93
94
95
# File 'lib/temper.rb', line 87

def update_interval new_interval
  if new_interval > 0
    ratio = new_interval / @interval

    @ki *= ratio
    @kd /= ratio
    @interval = new_interval
  end
end