Build your own SUMO-2Build your own 3kg SUMO (part 2).
This is the second article about my 3kg sumo robot Master of Disaster. Here I want to describe all changes and upgrades I made to my robot, and to disclose full code. No joke, 100% complete code which was used at "BalticRobotSumo 2009 Klaipeda CUP" event. I think this article might be useful for our robotic community, because it will help you to build better, stronger, faster robots. More, more robots!
Mechanical design:
First version of Master of Disaster's chassis had two main disadvantages.
1. Front of the robot was much heavier than its back, so back wheels could easily loose contact with ground.
2. Front scoop served as a rest point of the chassis (similar like caster wheels). Any damage or displacement of the front scoop could greatly worsen robot traction.
Solution: I cutted some metal from the front and attached these pieces on the back trying to move center of mass as close to middle wheels as possible. Now all 6 wheels have stable contact with surface even with front scoop removed.
Click on thumbnails to see full-size images
Electronics:
Master of Disaster suffered from many electric/electronical problems:
1. Master of Disaster performed without line sensors at "BalticRobotSumo 2008 Riga CUP". Although staying on the ring without line sensors may impress spectators, it is better to have them onboard. I upgraded Master of Disaster with two TCRT1000 optoreflectors. They are placed 1mm from the ground and have output levels 0.5V/4.5V on black/white surface. You may need to adjust proper output signal levels with potentiometer, but it is one-time job. TCRT1000 sensors work well on different rings without need of readjusting them. Of course, you must shield sensors from exterior light with some kind of covers.
Click on thumbnail to see full-size image
2. Master of Disaster uses two 2-Cell lipo in series (equal to 4-Cell lipo) as a power source for the motors. Tantalum capacitors on the motor control board turned to be very sensitive to overloads. I used 16V 100uF tantalum caps on the main power line for space-saving reasons. Three of these caps burned during the testing (one with colourful sparks and fire). I decided to replace them with 25V 470uF electrolytic caps. I had to cut holes in the top cover to make them fit, but no more "Fire onboard", I hope.
Click on thumbnails to see full-size images
3. TSOP17xx based sensors have totally unacceptable performance, unpredictable in different lighting conditions.
First upgrade was to replace them with GP2D12 infrared sensors and add SRF08 ultrasonic sensors. GP2D12 is good for front vision, because its narrow beam allow precise centering on the enemy. SRF08 is good for side vision, because its wide beam covers large area and doesn't allow enemy to approach unnoticed from the sides. GP2D12 (and many similar models) do one measurement in ~30msec. SRF08 do one measurement in ~60msec, but it can work twice faster with reduced sensor’s gain. Master of Disaster used two GP2D12 as front sensors and two SRF08 with reduced gain as side sensors at "BalticRobotSumo 2008 Tallinn CUP". This setup works well on medium speeds, but on high speeds sensors are not able to update their outputs fast enough. This leads to noticeable overshoots during fast turns when trying to center on the opponent. It is obvious that you need not only fast motors, but also fast sensors if you want to push your robot to the limits.
Second upgrade was to use fast GP2Y0D340K sensors. They do one measurement in approximately 5msec, which is six times faster than regular GP2D12. No more overshoots, but for the cost of reduced range (40cm instead of 80cm). I decided to sacrifice sensor's range to be able to be extremely fast. I upgraded my robot with six GP2Y0D340K sensors: two in front, two on sides and two on the back. Old two GP2D12 and two SRF08 also were onboard. Master of Disaster performed with this setup at "BalticRobotSumo 2009 Klaipeda CUP".
Click on thumbnails to see full-size images
4. I removed Bluetooth module - it worked poorly without its original antenna (which I lost somewhere). I also removed strategy selector with TV remote. Too many strategies may lead to human-factor mistakes, as it was at "BalticRobotSumo 2008 Riga CUP". I was too nervous before the final fight, I selected wrong strategy and my robot was defeated by Slayer. In my opinion, the only proper strategy for 3kg sumo: find and attack as soon as possible.
Software:
Believe it or not, but the program onboard Master of Disaster is surprisingly simple (see full code below). If somebody asks me to describe my approach in robot programming, I would say: "Simplicity rules". In the main loop I collect sensor's data and put it in one variable, bit by bit. Later on I analyze this variable and issue commands to motors. Motor control subroutines are taken from Larry Barello webpage.
Every robot builder knows how many troubles can cause false triggerings of the sensors. They can occur accidentally under certain light conditions and your robot gets crazy or jumps away from the ring. I put a lot of efforts trying to fight with false triggerings, but one day I realized that they may be my friends, not foes. "Spin" subroutine is used for that. In normal mode robot drives straight, checking both slow and fast sensors. When any sensor "sees" something (even for a single measurement), Master of Disaster enters "Spin" sub and makes fast turn in corresponding direction searching for the enemy. "Spin" sub checks only two front GP2Y0D340K sensors, so robot is able to center on the opponent without overshoot. If no opponent is detected during 360 degree turn, Master of Disaster continues to cruise the ring in normal mode. This approach appears to the spectators like a very complex programming algorithm, but now you know the truth!
Click on thumbnail to see full-size image
Sumo robot building is a perfect example of mechatronics. To build a successful robot you need to do your best in mechanical, electrical and control engineering. Of course, you need a bit of luck to be the first. Feel free to use any solutions described in this article. Master of Disaster will be happy to inspire you.
I wish your robot to be fast, to be smart, to be the winner!
See you at next BalticRobotSumo competition!
'
' Author: Rodman, vitalijrodnov@gmail.com
' motor control subs are taken from www.barello.net
' compiler: BascomAVR at www.mcselec.com
'-------------------------------------------------------------------------------------
$regfile = "m16def.dat"
$crystal = 10000000
Dim Cycles As Word
Dim Obj As Integer
Dim I As Word , J As Word
Dim Range As Byte , Gain As Byte
Dim L_lsb As Byte , L_msb As Byte
Dim R_lsb As Byte , R_msb As Byte
Dim L_range As Word , L_distance As Word
Dim R_range As Word , R_distance As Word
Declare Sub Spin
Declare Sub Sonar_init
Declare Sub L_motor(byval Pwm As Integer)
Declare Sub R_motor(byval Pwm As Integer)
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc
L_340_1 Alias Pina.3 : Config Pina.3 = Input 'additional GP2Y0D340K sensors
L_340_2 Alias Pind.7 : Config Pind.7 = Input
L_340_3 Alias Pinc.2 : Config Pinc.2 = Input
R_340_1 Alias Pina.2 : Config Pina.2 = Input
R_340_2 Alias Pinb.1 : Config Pinb.1 = Input
R_340_3 Alias Pinb.4 : Config Pinb.4 = Input
L_line_out Alias Pinc.0 : Config Portc.0 = Input 'Left LINE out(INT1)
R_line_out Alias Pinc.1 : Config Portc.1 = Input 'Right LINE out(INT0)
L_motor_pwm Alias Pwm1b : Config Portd.4 = Output 'Left motors PWM(OC1A)
R_motor_pwm Alias Pwm1a : Config Portd.5 = Output 'Right motors PWM(OC1B)
L_motor_dir Alias Portd.3 : Config Portd.3 = Output 'Left motors DIR
R_motor_dir Alias Portd.6 : Config Portd.6 = Output 'Right motors DIR
Config Timer1 = Pwm , Pwm = 8 ,Compare A Pwm = Clear Up ,Compare B Pwm = Clear Up ,Prescale = 8
R_motor_pwm = 0 : R_motor 0
L_motor_pwm = 0 : L_motor 0
Config Scl = Portd.2
Config Sda = Portd.1
Sonar_init
Wait 5
Enable Interrupts
If L_340_2 = 0 Then 'enemy detected on the left side
L_motor -255 : R_motor 255
Cycles = 200
Call Spin 'spins CW/CCW after Start
Else
L_motor 255 : R_motor -255
Cycles = 200
Call Spin
End If
Do
'----------------------------GP2D12 Left and Right------------------------------
R_range = Getadc(5)
L_range = Getadc(4)
If R_range > 120 Then Obj.4 = 1
If L_range > 120 Then Obj.5 = 1
'----------------------------TCRT1000 Left and Right----------------------------
If L_line_out = 1 Then
L_motor -200 : R_motor -200 : Waitms 200
L_motor 200 : R_motor -200 : Waitms 200
End If
If R_line_out = 1 Then
L_motor -200 : R_motor -200 : Waitms 200
L_motor -200 : R_motor 200 : Waitms 200
End If
'----------------------------GP2Y0D340K SHARPS ---------------------------------
If R_340_3 = 0 Then Obj.0 = 1
If R_340_2 = 0 Then Obj.1 = 1
If R_340_1 = 0 Then Obj.3 = 1
If L_340_1 = 0 Then Obj.6 = 1
If L_340_2 = 0 Then Obj.8 = 1
If L_340_3 = 0 Then Obj.9 = 1
'----------------------------SRF08 Left and Right-------------------------------
I2cstart : I2cwbyte 0 : I2cwbyte 0 : I2cwbyte 81 : I2cstop
Waitms 20
I2cstart : I2cwbyte 224 : I2cwbyte 2
I2cstart : I2cwbyte 225 : I2crbyte L_msb , Ack : I2crbyte L_lsb , Nack : I2cstop
L_distance = Makeint(l_lsb , L_msb)
I2cstart : I2cwbyte 226 : I2cwbyte 2
I2cstart : I2cwbyte 227 : I2crbyte R_msb , Ack : I2crbyte R_lsb , Nack : I2cstop
R_distance = Makeint(r_lsb , R_msb)
If R_distance <= 50 Then Obj.2 = 1
If L_distance <= 50 Then Obj.7 = 1
'----------------------------EVALUATION-----------------------------------------
Select Case Obj
Case 0
L_motor 150 : R_motor 150 'nothing
'-----------------------------
Case 1 'R3_340 back-right
L_motor 255 : R_motor -255
Cycles = 300
Call Spin
'-----------------------------
Case 2 'R2_340 side-right
L_motor 255 : R_motor -255
Cycles = 200
Call Spin
'-----------------------------
Case 4
L_motor 255 : R_motor -255 'R_ultrasonic side-right
Cycles = 200
Call Spin
'-----------------------------
Case 128
L_motor -255 : R_motor 255 'L_ultrasonic side-left
Cycles = 200
Call Spin
'-----------------------------
Case 256 'L2_340 side-left
L_motor -255 : R_motor 255
Cycles = 200
Call Spin
'-----------------------------
Case 512 'L3_340 back-left
L_motor -255 : R_motor 255
Cycles = 300
Call Spin
'-----------------------------
Case 8 To 120 ' any combination of front sensors
If L_line_out = 1 Then 'line detection priority
L_motor -200 : R_motor -200 : Waitms 200
L_motor 200 : R_motor -200 : Waitms 200
End If
If R_line_out = 1 Then
L_motor -200 : R_motor -200 : Waitms 200
L_motor -200 : R_motor 200 : Waitms 200
End If
L_motor 255 : R_motor 255
'-----------------------------
Case 6 'R2_340 + R_ultrasonic
L_motor 255 : R_motor -255
Cycles = 200
Call Spin
'-----------------------------
Case 384 'L2_340 + L_ultrasonic
L_motor -255 : R_motor 255
Cycles = 200
Call Spin
'-----------------------------
Case 513 'L3_340 + R3_340
L_motor -255 : R_motor 255
Cycles = 300
Call Spin
'-----------------------------
End Select
'-------------------------------------------------------------------------------
Obj = 0
Loop
End
Sub Spin
For I = 1 To Cycles
For J = 1 To Cycles
If L_340_1 = 0 Then Goto Exit_spin
If R_340_1 = 0 Then Goto Exit_spin
Next J
Next I
Exit_spin:
End Sub
Sub Sonar_init
I2cinit
Range = 60
I2cstart : I2cwbyte 224 : I2cwbyte 2 : I2cwbyte Range : I2cstop
I2cstart : I2cwbyte 226 : I2cwbyte 2 : I2cwbyte Range : I2cstop
Gain = 30
I2cstart : I2cwbyte 224 : I2cwbyte 1 : I2cwbyte Gain : I2cstop
I2cstart : I2cwbyte 226 : I2cwbyte 1 : I2cwbyte Gain : I2cstop
End Sub
Sub L_motor(byval Pwm As Integer)
If Pwm >= 0 Then
L_motor_dir = 0
Tccr1a.com1b0 = 0 'normal PWM
Else
L_motor_dir = 1
Tccr1a.com1b0 = 1
Pwm = -pwm 'inverted PWM
End If
L_motor_pwm = Pwm
End Sub
Sub R_motor(byval Pwm As Integer)
If Pwm >= 0 Then
R_motor_dir = 0
Tccr1a.com1a0 = 0 'normal PWM
Else
R_motor_dir = 1
Tccr1a.com1a0 = 1
Pwm = -pwm 'inverted PWM
End If
R_motor_pwm = Pwm
End Sub
|