Class: Motor

Inherits:
Brick show all
Defined in:
lib/motor.rb

Overview

Controls an NXT motor.

Example:

m = Motor.new('a')
m.forward(:degrees => 180, :power => 50)

Constant Summary collapse

POLL_INTERVAL =
0.5

Instance Attribute Summary collapse

Attributes inherited from Brick

#log, #port

Instance Method Summary collapse

Constructor Details

#initialize(nxt, port) ⇒ Motor

Returns a new instance of Motor.



33
34
35
36
37
38
39
# File 'lib/motor.rb', line 33

def initialize(nxt, port)
  super(nxt, port)
  
  @port = formalize_motor_port_name(port)
  
  @ratio = 0
end

Instance Attribute Details

#ratioObject

Returns the value of attribute ratio.



31
32
33
# File 'lib/motor.rb', line 31

def ratio
  @ratio
end

Instance Method Details

#backward(options) ⇒ Object

Rotate the motor backwards. See Motor#forward and Motor#run.



71
72
73
74
75
# File 'lib/motor.rb', line 71

def backward(options)
  debug(options, :backward)
  options[:direction] = -1
  return run(options)
end

#forward(options) ⇒ Object

Rotate the motor forwards. See Motor#run. Examples:

m.forward(:degrees => 360, :power => 20)

The above rotates the motor 360 degrees forward at 20% power.

m.forward(:time => 5)

The above rotates the motor forwards for 5 seconds at 25% power (because 25% is the default).



63
64
65
66
67
# File 'lib/motor.rb', line 63

def forward(options)
  debug(options.to_yaml, :forward)
  options[:direction] = 1
  return run(options)
end

#nameObject



41
42
43
44
45
46
47
# File 'lib/motor.rb', line 41

def name
  case self.port
    when NXTComm::MOTOR_A then 'a'
    when NXTComm::MOTOR_B then 'b'
    when NXTComm::MOTOR_C then 'c'
  end
end

#read_stateObject

Return the current state of the motor as a hash. See NXTComm#get_output_state for info on what data is available here.



79
80
81
82
83
84
85
86
87
# File 'lib/motor.rb', line 79

def read_state
  @log.debug(:read_state) { "getting state"}
  state = @nxt.get_output_state(@port)
  @log.debug(:read_state) { "got state" }
  
  debug(state, :state)
  
  return state
end

#reset_tachoObject

Resets the motor’s tachometer movement count (i.e. :degree_count in Motor#state).



212
213
214
215
216
# File 'lib/motor.rb', line 212

def reset_tacho
  @log.debug(:reset_tacho) { "resetting tacho" }
  @nxt.reset_motor_position(@port, false)
  @log.debug(:reset_tacho) { "reset tacho" }
end

#run(options) ⇒ Object

Low-level command for initiating motor rotation. Options is a hash with the following keys:

:power

Power from 0 to 100. Default is 25.

:time

Maximum time to run the motor in seconds. By default there is no time limit. If :degrees is also specified then the motor will only turn as far as :degrees and will stop and wait out the remaining :time has expired.

:regulate

False to disable power regulation. It is true (i.e. on)

by default.
:degrees

The maximum tachometer degrees to turn before automatically

stopping. Use negative values for backward movement (need to
double check that this is in fact true)
:direction

Direction in which the motor should move. 1 for forward,

-1 for backward. The default is 1 (i.e. forward).
:wait_until_complete

If true, the motor will block further commands

until this command is complete. This is true by default when :degrees or :time is specified, false by default otherwise. NOTE: currently this setting is always on and cannot be turned off when :time is specified… this will probably be fixed in the future

:brake_on_stop

If true, the motor will try to hard brake when the

command completes (otherwise when the command finishes the motor may continue to coast for a while – especially at higher power levels). This is true by default when :degrees or :time is specified, false by default otherwise.

Examples:

Rotate backward up to 90 degrees:

m.run(:degrees => 90, :direction => -1)

Rotate forward for 8 seconds at 100% power:

m.run(:time => 8, :power => 100)

Forward for 3 seconds up to 180 degrees at 50% power. If the 180 degree rotation takes only 1 second to complete, the motor will sit there and wait out the full 3 seconds anyway:

m.run(:power => 50, :degrees => 180, :time => 3)

Rotate forward indefinitely (until Motor#stop is called).

m.run


139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/motor.rb', line 139

def run(options)
  debug(options, :run)

  if options[:power]
    power = options[:power].to_i.abs
  else
    power = 25
  end
  
  time = options[:time] || nil
  regulate = options[:regulate] || true
  regulation_mode = options[:regulation_mode] || "speed"
  degrees = options[:degrees] || 0
  ratio = options[:ratio] || self.ratio
  direction = options[:direction] || 1 # 1 is forward, -1 is backward

  brake_on_stop = options.has_key?(:time) || options.has_key?(:degrees)
  wait_until_complete = options.has_key?(:time) || options.has_key?(:degrees)
  
  brake_on_stop = options[:brake_on_stop] if options.has_key?(:brake_on_stop)

  wait_until_complete = options[:wait_until_complete] if options.has_key?(:wait_until_complete)
  # FIXME: wait_until_complete MUST be true if a time period is specified, otherwise we have no way of
  # 				enforcing the time limit (this is a problem with the way threading is implemented...)
  wait_until_complete = true if options.has_key?(:time)
  
  power = direction * power
  
  mode = NXTComm::MOTORON
  mode |= NXTComm::BRAKE if brake_on_stop
  mode |= NXTComm::REGULATED if regulate
  
  if regulate
    case regulation_mode
     when "idle"
       regulation_mode = NXTComm::REGULATION_MODE_IDLE
      when "speed"
  	    regulation_mode = NXTComm::REGULATION_MODE_MOTOR_SPEED
     when "sync"
       regulation_mode = NXTComm::REGULATION_MODE_MOTOR_SYNC
    end
  else
  	regulation_mode = NXTComm::REGULATION_MODE_IDLE
  end

  @log.debug(:run) {"sending run command"}
  @nxt.set_output_state(@port, power, mode, regulation_mode, ratio, NXTComm::MOTOR_RUN_STATE_RUNNING, degrees)

  if time.nil?
  	if wait_until_complete
     @log.debug(:run) {"sleeping until run_state is idle"}
     until read_state[:run_state] == NXTComm::MOTOR_RUN_STATE_IDLE
       sleep(POLL_INTERVAL)
       @log.debug(:run) {"checking run_state again"}
     end
     @log.debug(:run) {"run_state is idle"}
  	end
  else
    @log.debug(:run) {"waiting #{time} seconds until stop"}
    sleep(time)
    @log.debug(:run) {"stopping"}
    self.stop
    @log.debug(:run) {"stopped"}
  end
end

#stopObject

Stop movement.



206
207
208
209
# File 'lib/motor.rb', line 206

def stop
  debug(nil, :stop)
  @nxt.set_output_state(@port, 100, NXTComm::BRAKE, NXTComm::REGULATION_MODE_MOTOR_SPEED, 100, NXTComm::MOTOR_RUN_STATE_IDLE, 0)
end