class Rumba

This library has a TON of annoying constants… we have quarantined them here to save your eyes

Define the Rumba “DSL” Lots of easy to use methods for basic tasks

Sensor-related code is all here!

Attributes

serial[RW]

Public Class Methods

new(port, baud=57600, &block) click to toggle source
# File lib/rumba.rb, line 197
def initialize(port, baud=57600, &block)
  @leds = {
    advance:   false,
    play:      false,
    color:     0,
    intensity: 0
  }
  
  # Initialize the serialport
  # 115200 for Roomba 5xx
  # 57600 for older models (and iRobot Create)
  @serial = SerialPort.new(port, baud)
  @serial.read_timeout = 15
  self.start

  # initialize the "DSL" here!
  if block_given?
    instance_eval(&block)

    # clean up after ourselves (this is a Roomba, after all!)
    self.power_off
  end
end

Public Instance Methods

battery_percentage() click to toggle source
# File lib/rumba.rb, line 172
def battery_percentage
  sensors = get_sensors(3)
  ((sensors[:battery_charge].to_f / sensors[:battery_capacity].to_f) * 100).to_i
end
convert_int(int) click to toggle source

Convert integer to two’s complement signed 16 bit integer. Note that the Roomba is big-endian…I need to fix this code to make it portable across different architectures.

# File lib/rumba.rb, line 64
def convert_int(int)
  [int].pack('s').reverse
end
drive(velocity, radius) click to toggle source
# File lib/rumba.rb, line 83
def drive(velocity, radius)
  raise RangeError if velocity < -500 || velocity > 500
  raise RangeError if (radius < -2000 || radius > 2000) && radius != 0xFFFF
  
  velocity = convert_int(velocity)
  radius   = convert_int(radius)
  write_chars([DRIVE, velocity, radius])
end
drive_direct(left, right) click to toggle source
# File lib/rumba.rb, line 92
def drive_direct(left, right)
  raise RangeError if left  < -500 || left  > 500
  raise RangeError if right < -500 || right > 500
  
  left  = convert_int(left)
  right = convert_int(right)
  
  write_chars([DRIVE_DIRECT])
  write_raw([right, left])
end
full_mode() click to toggle source
# File lib/rumba.rb, line 77
def full_mode
  safe_mode
  write_chars([FULL_MODE])
  sleep(0.2)
end
halt() click to toggle source
# File lib/rumba.rb, line 164
def halt
  drive(0,0)
end
lights() click to toggle source
# File lib/rumba.rb, line 160
def lights
  write_chars([139, 9, 0, 128])
end
play_song(song_number) click to toggle source
# File lib/rumba.rb, line 136
def play_song(song_number)
  raise RangeError if song_number < 0 || song_number > 15
  write_chars([PLAY_SONG,song_number])
end
power_off() click to toggle source
# File lib/rumba.rb, line 168
def power_off
  @serial.close
end
safe_mode() click to toggle source

COMMANDS #

# File lib/rumba.rb, line 72
def safe_mode
  write_chars([SAFE_MODE])
  sleep(0.2)
end
set_leds(args) click to toggle source

Turn LEDs on and off Arguments are a hash in the following format: :advance => true/false | sets the “advance” LED (the >> one) :play => true/false | sets the “play” LED (the > one) :color => 0-255 | sets the color of the power LED (0 = green, 255 = red) :intensity => 0-255 | sets the intensity of the power LED (0 = off)

# File lib/rumba.rb, line 109
def set_leds(args)
  @leds[:advance]   = args[:advance]   unless args[:advance].nil?
  @leds[:play]      = args[:play]      unless args[:play].nil?
  @leds[:color]     = args[:color]     unless args[:color].nil?
  @leds[:intensity] = args[:intensity] unless args[:intensity].nil?
  led_bits  = 0b00000000
  led_bits |= 0b00001000 if @leds[:advance]
  led_bits |= 0b00000010 if @leds[:play]
  
  write_chars([LEDS, led_bits, @leds[:color], @leds[:intensity]])
end
song(song_number, notes) click to toggle source

Songs are cool. Here’s the format: The song number designates which song this is so you can recall it later. The notes are specified in the NOTES hash, and are fed into the program as a 2D array, where the first element is the note number and the second is the duration of the note. The duration is specified in seconds. Example:

[note1,5], [note2,6]
# File lib/rumba.rb, line 128
def song(song_number, notes)
  raise RangeError if song_number < 0 || song_number > 15
  
  notes.map! { |n| [NOTES[n[0]],n[1]*64] }
  # The protocol requires us to send the number of notes and the song number first
  write_chars([SONG, song_number, notes.size] + notes.flatten)
end
spin_left(speed) click to toggle source
# File lib/rumba.rb, line 150
def spin_left(speed)
  speed = convert_int(speed)
  write_chars([DRIVE, speed, convert_int(1)])
end
spin_right(speed) click to toggle source
# File lib/rumba.rb, line 155
def spin_right(speed)
  speed = convert_int(speed)
  write_chars([DRIVE, speed, convert_int(-1)])
end
start_all_motors() click to toggle source
# File lib/rumba.rb, line 181
def start_all_motors
  write_chars([MOTORS,MOTORS_MASK_SIDE_BRUSH|MOTORS_MASK_VACUUM|MOTORS_MASK_MAIN_BRUSH])
end
start_main_brush_motor() click to toggle source
# File lib/rumba.rb, line 193
def start_main_brush_motor
  write_chars([MOTORS,MOTORS_MASK_MAIN_BRUSH])
end
start_side_brush_motor() click to toggle source
# File lib/rumba.rb, line 185
def start_side_brush_motor
  write_chars([MOTORS,MOTORS_MASK_SIDE_BRUSH])
end
start_vacumm_motor() click to toggle source
# File lib/rumba.rb, line 189
def start_vacumm_motor
  write_chars([MOTORS,MOTORS_MASK_VACUUM])
end
stop_all_motors() click to toggle source
# File lib/rumba.rb, line 177
def stop_all_motors
  write_chars([MOTORS,0])
end
straight(speed) click to toggle source

Convenience methods #

# File lib/rumba.rb, line 145
def straight(speed)
  speed = convert_int(speed)
  write_chars([DRIVE, speed, convert_int(32768)])
end
write_chars(data) click to toggle source

Converts input data (an array) into bytes before sending it over the serial connection.

# File lib/rumba.rb, line 21
def write_chars(data)
  data.map! do |c|
    if c.class == String
      result = c.bytes.to_a.map { |b| [b].pack("C") }
    else
      result = [c].pack("C")
    end
    
    result
  end
  
  data = data.flatten.join
  
  @serial.write(data)
  @serial.flush
end
write_chars_with_read(data) click to toggle source

Write data then read response

# File lib/rumba.rb, line 39
def write_chars_with_read(data)
  data.map! do |c|
    if c.class == String
      result = c.bytes.to_a.map { |b| [b].pack("C") }
    else
      result = [c].pack("C")
    end
    
    result
  end
  
  data = data.flatten.join
  
  @serial.write(data)
  sleep(0.05)
  data=""
  while(data.length==0)
    data += @serial.read
  end
  data
end