Robobuilder

(Difference between revisions)
Jump to: navigation, search
m (Using the RBC controller)
m (Using the RBC controller)
Line 10: Line 10:
 
=Ruby Examples=
 
=Ruby Examples=
 
==Using the RBC controller==
 
==Using the RBC controller==
The serial communication does not work reliably for some reason :(
+
You need to make sure that your serial controller is capable of 115200 Baud!!!
 
<pre>
 
<pre>
 
#!/usr/bin/env ruby
 
#!/usr/bin/env ruby
Line 16: Line 16:
 
# http://robosavvy.org/forum/viewtopic.php?p=20035
 
# http://robosavvy.org/forum/viewtopic.php?p=20035
 
# http://robosavvy.com/RoboSavvyPages/Robobuilder/RBC_over_Serial_Protocol_v1.13.pdf
 
# http://robosavvy.com/RoboSavvyPages/Robobuilder/RBC_over_Serial_Protocol_v1.13.pdf
require 'rubygems'
+
Kernel::require 'serialport'
require 'serialport'
+
 
class Array
 
class Array
 
   def checksum
 
   def checksum
Line 40: Line 39:
 
   ATTACK_RIGHT = 11
 
   ATTACK_RIGHT = 11
 
   def initialize( serial_device = '/dev/ttyUSB0' )
 
   def initialize( serial_device = '/dev/ttyUSB0' )
 +
    puts "Opening port #{serial_device}"
 
     @serial = SerialPort.new serial_device, RATE, BITS, STOP_BITS, PARITY
 
     @serial = SerialPort.new serial_device, RATE, BITS, STOP_BITS, PARITY
     # command 0x10, 1
+
     # @serial.flow_control = SerialPort::SOFT
 +
    # @serial.read_timeout = 1 # milliseconds
 +
    # @serial.write_timeout = 2000 # milliseconds
 
   end
 
   end
 
   def header
 
   def header
Line 62: Line 64:
 
       contents.pack( 'C' * contents.size ) + [ contents.checksum ].pack( 'C' )
 
       contents.pack( 'C' * contents.size ) + [ contents.checksum ].pack( 'C' )
 
     @serial.write cmd
 
     @serial.write cmd
     @serial.flush
+
     # @serial.flush
 +
    read_back( type )
 +
  end
 +
  def read_back( type )
 
     synchronise
 
     synchronise
 
     #if feedback[ 0 ... 8 ] != header
 
     #if feedback[ 0 ... 8 ] != header
Line 77: Line 82:
 
     @serial.read( 1 )
 
     @serial.read( 1 )
 
     size = @serial.read( 4 ).unpack( 'N' ).first
 
     size = @serial.read( 4 ).unpack( 'N' ).first
 +
    # puts "#{size} bytes of data"
 
     data = @serial.read size
 
     data = @serial.read size
 
     checksum = @serial.read( 1 ).unpack( 'C' ).first
 
     checksum = @serial.read( 1 ).unpack( 'C' ).first
 
     if data.unpack( 'C' * data.size ).checksum != checksum
 
     if data.unpack( 'C' * data.size ).checksum != checksum
       puts 'Problem with checksum'
+
       # puts 'Problem with checksum'
 
     end
 
     end
     sleep 0.1
+
     # sleep 0.2
 
     data
 
     data
 
   end
 
   end
Line 121: Line 127:
 
     motion ATTACK_RIGHT
 
     motion ATTACK_RIGHT
 
   end
 
   end
   def sound( n )
+
   def run( n )
 +
    case n
 +
    when 1 .. 10
 +
      motion n + 11
 +
    when 11 .. 20
 +
      motion n + 22
 +
    else
 +
      raise "Program number must be in 1 .. 20 (was #{n})"
 +
    end
 +
  end
 +
  def serial_number
 +
    command( 0x0C, 1 ).to_i
 +
  end
 +
  def firmware
 +
    command( 0x12, 1 ).unpack 'CC'
 +
  end
 +
  def voice( n )
 
     command( 0x15, n ).unpack( 'C' ).first
 
     command( 0x15, n ).unpack( 'C' ).first
 +
  end
 +
  def distance # problem when lower than 20 cm
 +
    command( 0x16, 1 ).unpack( 'n' ).first / 256.0
 +
  end
 +
  def sound( min )
 +
    data = [ min ].pack( 'n' ).unpack 'CC'
 +
    command( 0x17, *data ).unpack( 'S' ).first
 +
  end
 +
  def button
 +
    command( 0x18, 1 ).unpack( 'S' ).first
 +
  end
 +
  def remote
 +
    command( 0x19, 1 ).unpack( 'S' ).first
 +
  end
 +
  def accelerometer
 +
    command( 0x1A, 1 ).unpack( 'sss' )
 
   end
 
   end
 
   def direct( on )
 
   def direct( on )
Line 130: Line 168:
 
     else
 
     else
 
       @serial.write [ 0xFF, 0xE0, 0xFB, 0x01, 0x00, 0x1A ].pack( 'C' * 6 )
 
       @serial.write [ 0xFF, 0xE0, 0xFB, 0x01, 0x00, 0x1A ].pack( 'C' * 6 )
       @serial.flush
+
       # @serial.flush
 
     end
 
     end
 
   end
 
   end
 
end
 
end
robot = Robot.new
+
robot = Robot.new '/dev/ttyS1'
robot.basic
+
# robot.basic
robot.forward
+
for i in 1 .. 1000
 +
  puts "#{i}: #{ "%20s" % robot.accelerometer.inspect } #{ "%10d" % robot.distance}"
 +
end
 +
# robot.basic
 +
# robot.backward
 
# robot.direct true
 
# robot.direct true
 
# robot.direct false
 
# robot.direct false

Revision as of 20:06, 30 September 2009

Working.gif

Contents

Gallery

The Robobuilder Kit contains components for assembling a humanoid robot
Assembled Robobuilder Huno

Ruby Examples

Using the RBC controller

You need to make sure that your serial controller is capable of 115200 Baud!!!

#!/usr/bin/env ruby
# http://robosavvy.com/forum/viewtopic.php?p=19030
# http://robosavvy.org/forum/viewtopic.php?p=20035
# http://robosavvy.com/RoboSavvyPages/Robobuilder/RBC_over_Serial_Protocol_v1.13.pdf
Kernel::require 'serialport'
class Array
  def checksum
    inject( 0 ) { |a,b| a ^ b }
  end
end
class Robot
  RATE = 115200
  BITS = 8
  STOP_BITS = 1
  PARITY = SerialPort::NONE
  GETUP_A = 1
  GETUP_B = 2
  TURN_LEFT = 3
  MOTION_FORWARD = 4
  TURN_RIGHT = 5
  MOVE_LEFT = 6
  MOTION_BASIC_POSTURE = 7
  MOVE_RIGHT = 8
  ATTACK_LEFT = 9
  MOVE_BACKWARD = 10
  ATTACK_RIGHT = 11
  def initialize( serial_device = '/dev/ttyUSB0' )
    puts "Opening port #{serial_device}"
    @serial = SerialPort.new serial_device, RATE, BITS, STOP_BITS, PARITY
    # @serial.flow_control = SerialPort::SOFT
    # @serial.read_timeout = 1 # milliseconds
    # @serial.write_timeout = 2000 # milliseconds
  end
  def header
    [ 0xFF, 0xFF, 0xAA, 0x55, 0xAA, 0x55, 0x37, 0xBA ].pack 'C' * 8
  end
  def synchronise
    x = nil
    begin
      x = @serial.read( 1 ).unpack( 'C' ).first
      # puts "%X" % x
    end until x == 0x37
    x = nil
    begin
      x = @serial.read( 1 ).unpack( 'C' ).first
      # puts "%X" % x
    end until x == 0xBA
  end
  def command( type, *contents )
    cmd = header + [ type, 0x00, contents.size ].pack( 'CCN' ) +
      contents.pack( 'C' * contents.size ) + [ contents.checksum ].pack( 'C' )
    @serial.write cmd
    # @serial.flush
    read_back( type )
  end
  def read_back( type )
    synchronise
    #if feedback[ 0 ... 8 ] != header
    #  puts 'Problem with header'
    #  raise "Error executing command 0x#{ "%X" % type }:\n" +
    #    "Send    : " + cmd.unpack( 'C' * cmd.size ).
    #    collect { |x| "%X" % x }.join( ' ' ) + "\n" +
    #    "Received: " + feedback.unpack( 'C' * feedback.size ).
    #    collect { |x| "%X" % x }.join( ' ' )
    # end
    if @serial.read( 1 ).unpack( 'C' ).first != type
      puts 'Problem with command feedback'
    end
    @serial.read( 1 )
    size = @serial.read( 4 ).unpack( 'N' ).first
    # puts "#{size} bytes of data"
    data = @serial.read size
    checksum = @serial.read( 1 ).unpack( 'C' ).first
    if data.unpack( 'C' * data.size ).checksum != checksum
      # puts 'Problem with checksum'
    end
    # sleep 0.2
    data
  end
  def motion( n )
    command( 0x14, n ).unpack( 'C' ).first
  end
  def a
    motion GETUP_A
  end
  def b
    motion GETUP_B
  end
  def turn_left
    motion TURN_LEFT
  end
  def forward
    motion MOTION_FORWARD
  end
  def turn_right
    motion TURN_RIGHT
  end
  def left
    motion MOVE_LEFT
  end
  def basic
    motion MOTION_BASIC_POSTURE
  end
  def right
    motion MOVE_RIGHT
  end
  def attack_left
    motion ATTACK_LEFT
  end
  def backward
    motion MOVE_BACKWARD
  end
  def attack_right
    motion ATTACK_RIGHT
  end
  def run( n )
    case n
    when 1 .. 10
      motion n + 11
    when 11 .. 20
      motion n + 22
    else
      raise "Program number must be in 1 .. 20 (was #{n})"
    end
  end
  def serial_number
    command( 0x0C, 1 ).to_i
  end
  def firmware
    command( 0x12, 1 ).unpack 'CC'
  end
  def voice( n )
    command( 0x15, n ).unpack( 'C' ).first
  end
  def distance # problem when lower than 20 cm
    command( 0x16, 1 ).unpack( 'n' ).first / 256.0
  end
  def sound( min )
    data = [ min ].pack( 'n' ).unpack 'CC'
    command( 0x17, *data ).unpack( 'S' ).first
  end
  def button
    command( 0x18, 1 ).unpack( 'S' ).first
  end
  def remote
    command( 0x19, 1 ).unpack( 'S' ).first
  end
  def accelerometer
    command( 0x1A, 1 ).unpack( 'sss' )
  end
  def direct( on )
    if on
      # Alternatively press and hold button PF2 and then turn on the RBC.
      command 0x10, 1
    else
      @serial.write [ 0xFF, 0xE0, 0xFB, 0x01, 0x00, 0x1A ].pack( 'C' * 6 )
      # @serial.flush
    end
  end
end
robot = Robot.new '/dev/ttyS1'
# robot.basic
for i in 1 .. 1000
  puts "#{i}: #{ "%20s" % robot.accelerometer.inspect } #{ "%10d" % robot.distance}"
end
# robot.basic
# robot.backward
# robot.direct true
# robot.direct false

External Links

Bookmark and Share

Personal tools
Namespaces
Variants
Actions
Navigation
Toolbox