Robobuilder
(Difference between revisions)
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== | ||
− | + | 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 | ||
− | + | 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 | ||
− | # | + | # @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. | + | # sleep 0.2 |
data | data | ||
end | end | ||
Line 121: | Line 127: | ||
motion ATTACK_RIGHT | motion ATTACK_RIGHT | ||
end | end | ||
− | def | + | 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. | + | 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
Contents |
Gallery
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
- Robobuilder Ltd. (Korean manufacturer)
- Robosavvy (UK distributor)