conflict with ultra & servo commands

jims

Senior Member
I'm developing a program to control a simple robot. This picture and code show what I'm doing. Problem is that when I try to use the "ultra" command it disrupts the servos and they run/stop/run/stop, etc.. Without the "ultra" command (commenting it out) they run smoothly. Any hints to help me solve this? Thank you, JimS

Code:
[color=Green]'***************************************************************
'* Drive a continuous servo Robot forward with Picaxe 20M2.
'***************************************************************

;   20M2    Robot Controller               
;.---------.              
;|         |                
'|     B.0 |18 ----330 ohm--> Servo 1, Left Wheel.
;|     B.4 |14 ----330 ohm--> Servo 3, Right Wheel.              
'|         |
'|         |                                SRF004
'|         |                              +-------+
'|         |                    +5VDC+--->| +5VDC |
'|         |                              |       |
'|     C.0 | Pin 10 +-----------+-------->| Trig  |
'|         |                    |         |       |
'|         |                  +-+--+      |       |
'|         |                  |    |      |       |
'|         |                  |1.5K|      |       |
'|         |                  |ohm |      |       |
'|         |                  +----+<-----| Echo  |
'|         |                              |       |
'|         |                              |       |
'|         |                    0VDC +--->| 0VDC  |
'|         |                              +-------+
'+---------+[/color]


[color=Blue]symbol ping     [/color][color=DarkCyan]=[/color][color=Blue]C.0    [/color][color=Green]'pin 10, Ultra input.[/color]
[color=Blue]Symbol servo_1 [/color][color=DarkCyan]= [/color][color=Blue]B.0    [/color][color=Green]'pin 18, left wheel.[/color]
[color=Blue]Symbol servo_3 [/color][color=DarkCyan]= [/color][color=Blue]B.2    [/color][color=Green]'pin 16, Right Wheel.[/color]
[color=Blue]Symbol [/color][color=Purple]IRdata[/color][color=DarkCyan]=[/color][color=Purple]b1[/color]
[color=Blue]symbol [/color][color=Purple]rangeCM [/color][color=DarkCyan]=[/color][color=Purple]w1      [/color][color=Green]'Range in cm.

'* Constants:[/color]
[color=Blue]symbol LWstop   [/color][color=DarkCyan]= [/color][color=Navy]149   [/color]
[color=Blue]symbol LWfwd    [/color][color=DarkCyan]= [/color][color=Navy]165   [/color]
[color=Blue]symbol RWstop   [/color][color=DarkCyan]= [/color][color=Navy]145   [/color]
[color=Blue]symbol RWfwd    [/color][color=DarkCyan]= [/color][color=Navy]126   


#picaxe [/color][color=Black]20m2[/color]

[color=Navy]#macro [/color][color=Black]scan
    [/color][color=Blue]ultra Ping[/color][color=Black],[/color][color=Purple]RangeCM[/color][color=Black]:[/color][color=Blue]pause [/color][color=Navy]100
    [/color][color=Blue]ultra Ping[/color][color=Black],[/color][color=Purple]RangeCM[/color][color=Black]:[/color][color=Blue]pause [/color][color=Navy]100 [/color][color=Green]' pause 100 ms [/color]
[color=Navy]#endmacro[/color]

[color=Black]init:   [/color]
[color=Blue]Pause [/color][color=Navy]1000          [/color][color=Green]'PAUSE TO INITIALIZE SYSTEM.
    [/color][color=Blue]Servo B.0[/color][color=Black], [/color][color=Blue]LWstop   [/color][color=Green]' INITIALISE SERVO_1, PIN 18, LEFT WHEEL Null/stop.
    [/color][color=Blue]Servo B.2[/color][color=Black], [/color][color=Blue]RWstop   [/color][color=Green]' INITIALISE SERVO_3, PIN 16, RIGHT WHEEL Null/stop.
        [/color]
[color=Black]main: [/color][color=Green]'*MoveRobot Forward.
    [/color][color=Blue]do
     Servopos servo_1[/color][color=Black],[/color][color=Blue]LWfwd    [/color][color=Green]; move Left Wheel Forward.
     [/color][color=Blue]Servopos servo_3[/color][color=Black],[/color][color=Blue]RWfwd     [/color][color=Green]; move Right Wheel Forward.
     [/color][color=Black]scan
    [/color][color=Blue]loop[/color]
 

inglewoodpete

Senior Member
Hi Jim, The cause of the problem you are having is documented in Appendix 4 of Manual 2. It is related to the strict timing required for the Infra firmware to work correctly.

As far as I'm aware, the simplest solution is to use a dedicated chip (Eg 08M2) to handle either the Infra or servo interworking.

Either way, there are still some challenges getting the data flowing between the 20M2 and 08M2 due to the need to use time-critical commands. One way is to use serial data with handshaking between the chips to minimise the interruption to the Servo interworking. However, there will still be a small interruption.
 

jims

Senior Member
Thank you ....inglewoodpete.... I never think to look in Appendix 4. It clearly identifies "servo" as a possible conflict. I also found an earlier post named "sonar test" by erco on 07-02-2016. he describes it as "herky-jerky" motion. I'll just try to find an acceptable work-around. JimS
 

jims

Senior Member
I've replaced the ultrasonic sensor with an IR compound eye and updated my code to use the "eye". This actually simplified the code and the robot runs very smoothly. Did discover that when I use the sertxd command during testing, there is jerky motion of the wheel servos. I comment out the sertxd after testing.
Thanks for all your help. JimS
 

jims

Senior Member
OK, I'll byte. What's an IR compound eye?
erco... this is a real thing. You can find see images of it by searching for "compound eye sensor" on GOOGLE images.
Also described in the Gordon McComb 'Robot Builder's Bonanza" fourth edition starting on page 596. I'm consistently sensing barriers in the range of 8 to 10 inches and taking evasive action. Bought mine from Jameco but they're available from many vendors including POLOLU. JimS
 

Andrei IRL

Senior Member
hi Jims.
This is a Robot i have built last year.
[video]https://youtu.be/4RQFuK5j1XY[/video]
It uses both ultrasonic sensor and servos and works fine.
My Code below for you to have a look at. Im not 100% sure if this was my final code but would be very close to it worst case.
Hope this helps
Code:
`picaxe 08m
`9th July 2015 - Andrei Reaboi Autonomous Bot
disablebod
setfreq m4
			`Specifying Inputs and Outputs`
symbol motorL=4		`servo output pins		- pin 4
symbol motorR=0		`servo output pins		- pin 2
symbol motorN=2		`servo output pins 		- pin 0
symbol sonic=1		`output pin for ultrasonic    - pin 1

			`Specifying Variables`
symbol distance=w6	`result from ultrasonic
symbol distleft=w5	`distance when looking left
symbol distright=w4	`distance when looking righ
symbol distcenter=w3	`distance when looking straight ahead

			`Specifying Constants`
symbol forwardL=170	`Left servo position signal for forward
symbol forwardR=153	`Right servo position signal for forward
symbol reverseL=110	`Left servo position signal for reverse
symbol reverseR=195	`Right servo position signal for reverse
symbol motorLstop=158	`STOP signal position for Left Servo
symbol motorRstop=164	`STOP signal position for Right Servo
symbol blocked=40		'minimum safe distance 40cm

			`Servo initiating`
servo motorN,152		`move the NECK left
pause 1000			`pause 1sec
servopos motorN,192	`move the neck RIGHT
pause 1000			`pause 1sec
servopos motorN,172	`move the NECK straight ahead
pause 1000			`pause 1sec
servo motorL,forwardL	`set pins as servo outputs - forwards
servo motorR,forwardR	`set pins as servo outputs - forwards
pause 10
 
Main:
	gosub look	`initiate LOOK subroutine	
	if distcenter>blocked and distleft>blocked and distright>blocked then
		gosub ahead	`if distance to any object to the left, ahead or right
		goto main	`is greater then BLOCKED then initiate 
	endif			`AHEAD Subroutine
				`If the above is not met then move to the next line 48	
	if distleft<blocked and distright<blocked  then		
		gosub backwards	`if distance to an abject to the left
		gosub spin180	`and to the right is smaller then BLOCKED
		goto main		`then initiate BACKWARD Subroutine
	end if			`and then SPIN180 Subroutine
    					`If the above is not met then move to next line 55
	if distleft>distright then			
		gosub turnleft	`If distance to an object on the left is biger
		goto main		`then distance to the object on the right then
	end if			`initiate TURNLEFT subroutine
	gosub turnright		`If the above is not met then initiate
	goto main			`TURNRIGHT Subroutine
	


look:
	servopos motorN,210	` turn the head to the left
	pause 300			`wait 300ms for servo to move
	gosub ping			`initiate PING subroutine
	let distleft=distance	`assign measured distance to left distance
	`sertxd("The value of distleft is ",#distleft,13,10)
	`#terminal 4800
	
	servopos motorN,172	`return the head to centre
	pause 300			`wait 300ms for servo to move
	gosub ping			`initiate PING subroutine
	let distcenter=distance	`assign measured distance to ahead distance
	`sertxd("The value of distcenter is ",#distcenter,13,10)
	`#terminal 4800
    
	servopos motorN,120	`turn the head to the right
	pause 300			`wait 300ms for servo to move
	gosub ping			`initiate PING subroutine	
	let distright=distance  `assign measured distance to right distance
	`sertxd("The value of distright is ",#distright,13,10)
	`#terminal 4800	
	return			`return back to line 42
    
ping:
	ultra sonic, distance 	`issue coman for measuring distance
	pause 50			`wait 50ms for the signal
	return			`return to line 69/76/83
    
ahead:
	servo motorL,forwardL	`turn left servo forward
	servo motorR,forwardR	`turn right servo forward
	return			`return to line 44


backwards:
	servo motorL,reverseL	`turn left servo in reverse
	servo motorR,reverseR	`turn right servo in reverse
	pause 500			`keep turning servos for 500ms
	return			`return to line 51

turnright:
	servo motorL,165		`turn left servo forward
	servo motorR,168		`turn right sevo in reverse
	pause 1			`keep turning servos for 1ms
	return			`return to line 61
    
turnleft:
	servo motorL,155		`turn left servo in reverse
	servo motorR,161		`turn right servo forward
	pause 1			`keep turning servos for 1ms
	return			`return to line 58
    
spin180:
	servo motorL,155		`turn left servo in reverse
	servo motorR,160		`turn right servo forward
	pause 50			`keep turning servos for 50ms
	return			`return to line 52
 
Last edited:

hbl2013

Senior Member
I've replaced the ultrasonic sensor with an IR compound eye and updated my code to use the "eye". This actually simplified the code and the robot runs very smoothly. Did discover that when I use the sertxd command during testing, there is jerky motion of the wheel servos. I comment out the sertxd after testing.
Thanks for all your help. JimS
I stumbled on this posting looking for ideas for autonomous robot cars. Would you tell me how you used the compound eyes? It sounds interesting and I like to try it. A sample of your code using this board would be helpfull.
 

jims

Senior Member
I stumbled on this posting looking for ideas for autonomous robot cars. Would you tell me how you used the compound eyes? It sounds interesting and I like to try it. A sample of your code using this board would be helpfull.
hbl2013...I no longer use the "compound eye". Have since switched to to a Sharp GPY0A21YKF0F analog IR Ranging Sensor mounted on a servo to sweep from left to right. Works fast and reliably. Sorry but I can't find my old code for the "compound eye". It was quite simple to drive the EYE. As I remember..... 1. Turn on the LEDS. 2. Read analog values from the eyes and store the analog values. 3. Analyze data with lookdown command to find highest value. 3 make decision based on highest value. Here's a routine I used to test the "EYE".JimS

Code:
[color=Green]'***********************************************
'* Use to test "compound eye" module.
'* Comment and uncomment as needed to customize. 
'* *********************************************
 


;   20M2                  
;.---------.              
'|         |                   Compound Eye 
'|     C.5 |Pin 5 ------>|--IR LEDS-------------| 
'|     C.3 |Pin 7 <------|--IR Sensor--right eye 1&2---|
'|     C.2 |Pin 8 <------|--IR Sensor--top eye 7&8-----|
'|     C.1 |Pin 9 <------|--IR Sensor--left eye 5&6----|
'|     C.7 |Pin 3 <------|--IR Sensor--bottom eye 3&4--|
'|         |
'|         |
'|     C.4 |Pin 6 <-------Clicker
'.---------.[/color]

[color=Blue]symbol Eye12        [/color][color=DarkCyan]= [/color][color=Blue]C.3   [/color][color=Green]'pin 7, right.[/color]
[color=Blue]symbol Eye78        [/color][color=DarkCyan]= [/color][color=Blue]C.2   [/color][color=Green]'pin 8, top.[/color]
[color=Blue]symbol Eye56        [/color][color=DarkCyan]= [/color][color=Blue]C.1   [/color][color=Green]'pin 9, left.[/color]
[color=Blue]symbol Eye34        [/color][color=DarkCyan]= [/color][color=Blue]C.7   [/color][color=Green]'pin 3, bottom.[/color]
[color=Blue]symbol IRLEDs [/color][color=DarkCyan]= [/color][color=Blue]C.5 [/color][color=Green]'pin 5[/color]
[color=Blue]symbol clicker [/color][color=DarkCyan]= [/color][color=Blue]C.4 [/color][color=Green]'pin 6

'Variables:[/color]
[color=Blue]symbol [/color][color=Purple]IRData   [/color][color=DarkCyan]= [/color][color=Purple]b0[/color]
[color=Blue]symbol [/color][color=Purple]maxval   [/color][color=DarkCyan]= [/color][color=Purple]b10[/color]
[color=Blue]symbol [/color][color=Purple]varindex [/color][color=DarkCyan]= [/color][color=Purple]b11[/color]

[color=Navy]#picaxe [/color][color=Black]20m2[/color]

[color=Blue]pause [/color][color=Navy]1000  [/color][color=Green]'pause to initialize system.

'* Any Clicker key starts autorun routine.
'* Watch compound eye values on serial terminal.[/color]
[color=Black]autorun:
    [/color][color=Blue]high B.6[/color][color=Black]:[/color][color=Blue]low B.7
    do
     irin clicker[/color][color=Black], [/color][color=Purple]IRData
     [/color][color=Blue]call [/color][color=Black]scan[/color][color=Green]'
     [/color][color=Blue]sertxd([/color][color=Red]"Max value: "[/color][color=Black], #[/color][color=Purple]maxval[/color][color=Black], [/color][color=Blue]cr[/color][color=Black], [/color][color=Blue]lf )
     sertxd([/color][color=Red]"Compound Right 1&2:  "[/color][color=Black],#[/color][color=Purple]b1[/color][color=Black], [/color][color=Blue]cr[/color][color=Black], [/color][color=Blue]lf )
     sertxd([/color][color=Red]"Compound Top 7&8:  "[/color][color=Black],#[/color][color=Purple]b2[/color][color=Black], [/color][color=Blue]cr[/color][color=Black], [/color][color=Blue]lf )
     sertxd([/color][color=Red]"Compound Bottom 3&4:  "[/color][color=Black],#[/color][color=Purple]b4[/color][color=Black], [/color][color=Blue]cr[/color][color=Black], [/color][color=Blue]lf )
     sertxd([/color][color=Red]"Compound Left 5&6:  "[/color][color=Black],#[/color][color=Purple]b3[/color][color=Black], [/color][color=Blue]cr[/color][color=Black], [/color][color=Blue]lf[/color][color=Black],[/color][color=Blue]cr[/color][color=Black],[/color][color=Blue]lf )
     pause [/color][color=Navy]500
    [/color][color=Blue]loop
    return[/color]
[color=Black]scan:
    [/color][color=Blue]high IRLEDs [/color][color=Green]'C.2
    [/color][color=Blue]readadc eye12[/color][color=Black], [/color][color=Purple]b1 [/color][color=Green]'C.3 pin 7; (right).
    [/color][color=Blue]readadc eye78[/color][color=Black], [/color][color=Purple]b2 [/color][color=Green]'C.2 pin 8; (top).
    [/color][color=Blue]readadc eye56[/color][color=Black], [/color][color=Purple]b3 [/color][color=Green]'C.1 pin 9; (left).
    [/color][color=Blue]readadc eye34[/color][color=Black], [/color][color=Purple]b4 [/color][color=Green]'C.7 pin 3; (bottom).
    [/color][color=Blue]low irleds
        
    [/color][color=Green]REM Find the variable holding largest value
    [/color][color=Blue]lookdown [/color][color=Purple]maxval[/color][color=Black], [/color][color=Blue]( [/color][color=Purple]b1[/color][color=Black], [/color][color=Purple]b2[/color][color=Black], [/color][color=Purple]b3[/color][color=Black],[/color][color=Purple]b4 [/color][color=Blue])[/color][color=Black], [/color][color=Purple]varindex
    maxval [/color][color=DarkCyan]= [/color][color=Purple]b1 [/color][color=DarkCyan]min [/color][color=Purple]b2 [/color][color=DarkCyan]min [/color][color=Purple]b3 [/color][color=DarkCyan]min [/color][color=Purple]b4
    
    [/color][color=Blue]return
        [/color]
 
Last edited:

hbl2013

Senior Member
Thanks, jms. That was just what I was looking for. I bought a "GENERAL" car, (It uses this Compound Eye) and could not get it to work using an 28X2. (instead of an original 28X1) Now I might be able to check the eye by it self, and see at least if that is working correctly.
It looks like from your expierence that the Sharp IR is a much better component to use for the same purpose. Like to try that out and see how that performs.
Would you mind posting the code using that sensor instead?
 

jims

Senior Member
hbl2013...My code is over 10,000 characters and FORUM will not let me post it. However here is a routine that I use to determine the "coverage pattern". It will give you an idea of how I'm doing it. JimS
Code:
[color=Green]'***************************************************************
'* Picaxe 20M2 drives a normal servo with an attached Sharp
'* 2Y0A21 Range Sensor. Takes series of readings while sweeping
'* the sensor. Configure to find the sensor coverage pattern.
'***************************************************************


;   20M2     
;.---------.              
;|         |                
'|     B.5 |Pin 13 ----330 ohm--> Servo 3, Range sensor.
'|         |
'|     C.7 |Pin 3 <-------|--Sharp Range Sensor ---| 
'|         |
'|         |
'|     C.4 |Pin 6 <------ IR Clicker
'+---------+[/color]


[color=Blue]Symbol clicker      [/color][color=DarkCyan]= [/color][color=Blue]C.1   [/color][color=Green]'pin 9.[/color]
[color=Blue]Symbol servo_3      [/color][color=DarkCyan]= [/color][color=Blue]B.5   [/color][color=Green]'pin 13, Range sensor servo.[/color]
[color=Blue]symbol RangeSensor  [/color][color=DarkCyan]= [/color][color=Blue]C.7   [/color][color=Green]'pin 3, Range sensor.

'* Variables:[/color]
[color=Blue]Symbol [/color][color=Purple]IRdata   [/color][color=DarkCyan]=   [/color][color=Purple]b1[/color]
[color=Blue]symbol [/color][color=Purple]range    [/color][color=DarkCyan]=   [/color][color=Purple]b2[/color]
[color=Blue]symbol [/color][color=Purple]position [/color][color=DarkCyan]=   [/color][color=Purple]b3[/color]

[color=Navy]#picaxe [/color][color=Black]20m2

init:   [/color]
[color=Blue]Pause [/color][color=Navy]1000          [/color][color=Green]'PAUSE TO INITIALIZE SYSTEM.
    [/color][color=Blue]let [/color][color=Purple]position [/color][color=DarkCyan]= [/color][color=Navy]146  [/color][color=Green]'Mid point for my robot.
    [/color][color=Blue]Servo B.5[/color][color=Black], [/color][color=Purple]position         [/color][color=Green]' INITIALISE SERVO_3, PIN 12 Range servo null.
    
    [/color][color=Blue]Pause [/color][color=Navy]500   [/color][color=Green]'Initialize system

REM...Use clicker to select routine.[/color]
[color=Black]Main:
    [/color][color=Blue]do
     let [/color][color=Purple]position [/color][color=DarkCyan]= [/color][color=Navy]146
     [/color][color=Blue]servopos B.5[/color][color=Black], [/color][color=Purple]position
     [/color][color=Blue]IrIn clicker[/color][color=Black], [/color][color=Purple]IRData
     [/color][color=Blue]select case [/color][color=Purple]IRData
      [/color][color=Blue]case [/color][color=Navy]21 [/color][color=Blue]reset [/color][color=Green]REM power key resets chip.
      [/color][color=Blue]case [/color][color=Navy]51 [/color][color=Blue]call [/color][color=Black]checkright
      [/color][color=Blue]case [/color][color=Navy]52 [/color][color=Blue]call [/color][color=Black]checkleft
      [/color][color=Blue]case [/color][color=Navy]116 [/color][color=Blue]call [/color][color=Black]checkfwd
     [/color][color=Blue]endselect
    loop
     [/color]
[color=Black]checkright: [/color][color=Green]REM find object to right of robot. 
    [/color][color=Blue]do
     servopos B.5[/color][color=Black],[/color][color=Purple]position  [/color][color=Green]'*Look center.
     [/color][color=Blue]pause [/color][color=Navy]150
     [/color][color=Blue]readadc C.7[/color][color=Black], [/color][color=Purple]range [/color][color=Green]'C.7 pin 3.
     [/color][color=Blue]pause [/color][color=Navy]5
     [/color][color=Blue]sertxd ([/color][color=Black]#[/color][color=Purple]position[/color][color=Black],[/color][color=Red]"  "[/color][color=Black],#[/color][color=Purple]range[/color][color=Black],[/color][color=Blue]cr[/color][color=Black],[/color][color=Blue]lf)
     dec [/color][color=Purple]position
     [/color][color=Blue]pause [/color][color=Navy]50
    [/color][color=Blue]loop until [/color][color=Purple]range [/color][color=DarkCyan]=>[/color][color=Navy]40
    [/color][color=Blue]return
    [/color]
[color=Black]checkleft:  [/color][color=Green]REM find object to Left of robot. 
    [/color][color=Blue]do
     servopos B.5[/color][color=Black],[/color][color=Purple]position  [/color][color=Green]'*Look center.
     [/color][color=Blue]pause [/color][color=Navy]150
     [/color][color=Blue]readadc C.7[/color][color=Black], [/color][color=Purple]range [/color][color=Green]'C.7 pin 3.
     [/color][color=Blue]pause [/color][color=Navy]5
     [/color][color=Blue]sertxd ([/color][color=Black]#[/color][color=Purple]position[/color][color=Black],[/color][color=Red]"  "[/color][color=Black],#[/color][color=Purple]range[/color][color=Black],[/color][color=Blue]cr[/color][color=Black],[/color][color=Blue]lf)
     inc [/color][color=Purple]position
     [/color][color=Blue]pause [/color][color=Navy]50
    [/color][color=Blue]loop until [/color][color=Purple]range [/color][color=DarkCyan]=>[/color][color=Navy]40
    [/color][color=Blue]return[/color]

[color=Black]checkfwd:   [/color][color=Green]REM find width of object in front of robot. 
    [/color][color=Blue]let [/color][color=Purple]position [/color][color=DarkCyan]= [/color][color=Navy]146  [/color][color=Green]REM mid point
    [/color][color=Blue]do
      servopos B.5[/color][color=Black],[/color][color=Purple]position [/color][color=Green]'*Look center.
      [/color][color=Blue]pause [/color][color=Navy]150
      [/color][color=Blue]readadc C.7[/color][color=Black], [/color][color=Purple]range [/color][color=Green]'C.7 pin 3.
      [/color][color=Blue]pause [/color][color=Navy]5
      [/color][color=Blue]sertxd ([/color][color=Black]#[/color][color=Purple]position[/color][color=Black],[/color][color=Red]"  "[/color][color=Black],#[/color][color=Purple]range[/color][color=Black],[/color][color=Blue]cr[/color][color=Black],[/color][color=Blue]lf)
      inc [/color][color=Purple]position
      [/color][color=Blue]pause [/color][color=Navy]500
    [/color][color=Blue]loop until [/color][color=Purple]range [/color][color=DarkCyan]=> [/color][color=Navy]40
    [/color][color=Blue]do
     servopos B.5[/color][color=Black],[/color][color=Purple]position  [/color][color=Green]'*Look center.
     [/color][color=Blue]pause [/color][color=Navy]150
     [/color][color=Blue]readadc C.7[/color][color=Black], [/color][color=Purple]range [/color][color=Green]'C.7 pin 3.
     [/color][color=Blue]pause [/color][color=Navy]5
     [/color][color=Blue]sertxd ([/color][color=Black]#[/color][color=Purple]position[/color][color=Black],[/color][color=Red]"  "[/color][color=Black],#[/color][color=Purple]range[/color][color=Black],[/color][color=Blue]cr[/color][color=Black],[/color][color=Blue]lf)
     inc [/color][color=Purple]position
     [/color][color=Blue]pause [/color][color=Navy]500
    [/color][color=Blue]loop until [/color][color=Purple]range [/color][color=DarkCyan]=<[/color][color=Navy]40
    [/color][color=Blue]return[/color]
 
Top