United Kingdom
Asked — Edited

Ir Object Avoidance

Another script I've been writing is for the IR object avoidance as the built in control for IR doesn't work correctly with my IR sensor. I'm also trying to get to grips with EZ-Script so playing around is always a great idea in my book.

Adjust and/or comment on as you see fit. I've written it so it can be easily adjusted to suit your settings (and to show how variables can be used to make for easy adjustment over different projects/people)


# IR Detector Script
# Object avoidance using IR sensor on ADC port

# Adjust values below for configuration
$iradcport = ADC6 # Change for ADC Port with sensor attached
$maxirdistance = 35 # Change for maximum distance from object before avoiding in units
$irreverseturn = 0 # Reverse before turn? 0 = no, 1 = yes
$irturndirection = 0 # Change 0 = left or 1 = right
$irturnamount = 500 # Change for how long to turn for in ms
$irreverseamount = 500 # Change for how long to reverse for in ms (if applicable)
$irmovementspeed = 255 # Change for movement speed


# -- Do not modify below this line --
Goto(detect)

:avoid
IF ($irreverseturn = 1)
  reverse($irmovementspeed,$irreverseamount)
ELSEIF ($irturndirection = 0)
  Left($irmovementspeed,$irturnamount)
ELSE 
  Right($irmovementspeed,$irturnamount)
ENDIF 
Return()

:detect
$currirdistance = GetADC($iradcport)
IF ($currirdistance >= $maxirdistance)
  Goto(avoid)
ENDIF 
Sleep (50)
Goto(detect)

Also available on the EZ-Cloud here


ARC Pro

Upgrade to ARC Pro

With ARC Pro, your robot is not just a machine; it's your creative partner in the journey of technological exploration.

United Kingdom
#1  

The :Detect should be a label called detect but I guess the forum thought putting the d next to a : meant I was grinning;)

PRO
Synthiam
#2  

Hahahaha! That's funny... And fixed:)

Now i have to fix the real smilies

Edit: there good to go!

United Kingdom
#3  

DJ always on the ball even with the smallest of issues. Although I kinda liked the :D in the code, it gave character.

Updated the code (although not the EZ-Cloud version yet as I am at work... don't tell the boss), it had problems with the reverse before turn, as in I had an ELSEIF after it not an ENDIF, so it would back up when detecting an object but didn't turn.

This is why I like sections and posts specifically for scripting, hopefully this will help show others how things work:) Anyway, updated code is as follows (changed in original post also changed back in original post so others can follow the changes);


# IR Detector Script
# Object avoidance using IR sensor on ADC port

# Adjust values below for configuration
$iradcport = ADC6 # Change for ADC Port with sensor attached
$maxirdistance = 35 # Change for maximum distance from object before avoiding in units
$irreverseturn = 0 # Reverse before turn? 0 = no, 1 = yes
$irturndirection = 0 # Change 0 = left or 1 = right
$irturnamount = 500 # Change for how long to turn for in ms
$irreverseamount = 500 # Change for how long to reverse for in ms (if applicable)
$irmovementspeed = 255 # Change for movement speed


# -- Do not modify below this line --
Goto(detect)

:avoid
IF ($irreverseturn = 1)
  reverse($irmovementspeed,$irreverseamount)
ENDIF
IF ($irturndirection = 0)
  Left($irmovementspeed,$irturnamount)
ELSE 
  Right($irmovementspeed,$irturnamount)
ENDIF 
Return()

:detect
$currirdistance = GetADC($iradcport)
IF ($currirdistance >= $maxirdistance)
  Goto(avoid)
ENDIF 
Sleep (50)
Goto(detect)

PRO
Synthiam
#4  

Nice:)

I would recommend putting the :Detect code above the :Avoid... That way it jumps right into :Detect and you won't need the Goto(Detect) anymore. Your way works, of course... It's just one less command

United Kingdom
#5  

For the life of me I don't know why I structured it around that way, I can only think I was tired when I wrote it or had other intentions (very possibly as part of my roaming script I plan to write that this will be a part of). Although it does demonstrate the Goto and Return commands.

I'll reorganise it later I expect as I want to add in the option to only check when moving forwards, which I think should be a simple IF command using the $Direction global variable.

I may also add in options for additional detectors, servo mounting, capturing images and video (and anything else anyone can think of to throw in the mix)... more for educational purposes than function - it makes it fun learning that way:)

United Kingdom
#6  

version 1.4 Added in option to only check while moving forwards using the global variable $Direction. Restructured. Commands in CAPS, variables and labels in lowercase.


# IR Detector Script
# Object avoidance using IR sensor on ADC port

# Adjust values below for configuration
$iradcport = ADC6 # Change for ADC Port with sensor attached
$maxirdistance = 35 # Change for maximum distance from object before avoiding in units
$ironlyforward = 0 # Only if moving forwards? 0 = no, 1 = yes
$irreverseturn = 0 # Reverse before turn? 0 = no, 1 = yes
$irturndirection = 0 # Change 0 = left or 1 = right
$irturnamount = 500 # Change for how long to turn for in ms
$irreverseamount = 500 # Change for how long to reverse for in ms (if applicable)
$irmovementspeed = 255 # Change for movement speed


# -- Do not modify below this line --

# The detection script
:detect
IF ($ironlyforward = 1)
  IF ($Direction = "Forward")
    GOTO (detectstart)
  ELSE 
    GOTO (detect)
  ENDIF 
ELSE 
  :detectstart
  $currirdistance = GETADC($iradcport)
  IF ($currirdistance >= $maxirdistance)
    GOTO(avoid)
  ENDIF 
  SLEEP (50)
  GOTO(detect)
ENDIF 

# The avoidance script
:avoid
IF ($irreverseturn = 1)
  reverse($irmovementspeed,$irreverseamount)
ENDIF 
IF ($irturndirection = 0)
  LEFT($irmovementspeed,$irturnamount)
ELSE 
  RIGHT($irmovementspeed,$irturnamount)
ENDIF 
RETURN()

Updated on the cloud too:)

I'm not sure on the best way around for the GOTO(detect), ENDIF after SLEEP(50) in the detectstart script, as far as I can tell it doesn't matter but would be interested in knowing which way around is considered the best practice, if there is such a thing...

Canada
#7  

Rich, is it much work to make this script for two IR, one for each side, on a 45 facing in for a full view? Thanks. I have been trying. and im still new. lol, Thanks

#8  

Here's an example for 3 IR units and a front bump switch with thanks from Rich:

# Three IR units, Left_IR, Center_IR, and Right_IR will
# be monitored for possible collision from objects in 
# front of a moving robot.  If those IR units fail to
# detect then the single bump sensor will activate on
# a collision.

# Once detected then drive motor control will be adjusted 
# to avoid collision

# Normal values for an ADC port are from 0 to 255
# Collision value should be 100 or less
$Collision = 100

# Any value below 100 will indicate a possible collision
# Also the robot is set to move Forward at a speed of 60
# Speed can be 0 - 255

# Read the port values of the 3 IR units as well as the
# one bumper sensor.

:Read_ADC
Forward(60)

$Read_Center_IR = GetADC(ADC0)
$Read_Left_IR = GetADC(ADC1)
$Read_Right_IR = GetADC(ADC2)
$Read_Bump = GetDigital(D8)

print(GetDigital(D8))
print(GetADC(ADC0))
print(GetADC(ADC1))
print(GetADC(ADC2))

IF ($Read_Left_IR <= $Collision)
Stop()
Goto(Avoid)

Elseif ($Read_Center_IR <= $Collision)
Stop()
Goto(Avoid)

Elseif ($Read_Right_IR <= $Collision)
Stop()
Goto(Avoid)

Elseif ($Read_Bump = 0)
Stop()
Goto(Avoid)
EndIf

GoTo(Read_ADC)

#Avoid subroutine
:Avoid
Reverse(60,500)
Left(60, 500)
#print(GetADC(ADC0))
#print(GetADC(ADC1))
#print(GetADC(ADC2))
#Sleep(200)
Return()

United Kingdom
#10  

# IR Detector Script
# Object avoidance using 2 IR sensors on 2 ADC ports

# Adjust values below for configuration
$iradcport1 = ADC6 # Change for ADC Port with sensor 1 attached
$iradcport2 = ADC7 # Change for ADC Port with sensor 2 attached
$maxirdistance = 35 # Change for maximum distance from object before avoiding in units
$ironlyforward = 0 # Only if moving forwards? 0 = no, 1 = yes
$irreverseturn = 0 # Reverse before turn? 0 = no, 1 = yes
$irturndirection = 0 # Change 0 = left or 1 = right
$irturnamount = 500 # Change for how long to turn for in ms
$irreverseamount = 500 # Change for how long to reverse for in ms (if applicable)
$irmovementspeed = 255 # Change for movement speed


# -- Do not modify below this line --

# The detection script
:detect
IF ($ironlyforward = 1)
  IF ($Direction = "Forward")
    GOTO (detectstart)
  ELSE 
    GOTO (detect)
  ENDIF 
ELSE 
  :detectstart
  $currirdistance1 = GETADC($iradcport1)
  $currirdistance2 = GETADC($iradcport2)
  IF ($currirdistance1 >= $maxirdistance OR $currirdistance2 >= $maxirdistance)
    GOTO(avoid)
  ENDIF 
  SLEEP (50)
  GOTO(detect)
ENDIF 

# The avoidance script
:avoid
IF ($irreverseturn = 1)
  reverse($irmovementspeed,$irreverseamount)
ENDIF 
IF ($irturndirection = 0)
  LEFT($irmovementspeed,$irturnamount)
ELSE 
  RIGHT($irmovementspeed,$irturnamount)
ENDIF 
RETURN()

That should do it I think, however it is untested (and I really need to revisit this code to change a few things I dislike about how I wrote it - which don't change how it works, it's just me being picky)

Edit: Or use Robot-Docs script (that'll teach me to post and eat dinner at the same time, I missed the updates...)

Canada
#11  

LoL thanks. I will try it out and see. The more I'm looking at it. The more sense the code makes. LoL know what I mean.

United Kingdom
#12  

Yep, I know exactly what you mean. That is what I try to achieve with my scripts too, hence the comments throughout most of them.

Give it a go, see what happens, I'm usually around to guide you if you get stuck.

Canada
#13  

:D hey Rich it works great. man, thanks, and i know i will be asking a few more questions later

#14  

Is the green face supposed to be:D or D Is the yellow face supposed to be;) or )

Canada
#15  

green is : D yellow is " )

Canada
#16  

no spaces, but it might not matter...

United Kingdom
#17  

Yeah, sorry that's an issue with the forum formatting for emoticons.

The:D should be : with a D next to it (no space) The;) should be " with ) after it (no space) - the forums leave the " so just change the;) for a )

The;) I don't think the space matters but the:D does.

This is why I usually upload to pastebin too but didn't get chance last night.

#18  

Here are some pieces of code that was in servo Mag. You could do it smartly. But, this is all written in RobotBasic and would have to be converted to EZ-Script.

******a subroutine

Action5: // hard left for i=1 to 10 rForward 1 if rFeel()then break next for i=1 to 70 rTurn -1 if rSense() then break next return Action6: // hard right for i=1 to 10 rForward 1 if rFeel()then break next for i=1 to 70 rTurn 1 if rSense() then break next return

**************************another sub

Action1: // easy left rForward 1 rTurn -1 return Action2: // easy right rForward 1 rTurn 1 return Action3: // medium left rForward 1 rTurn -3 return Action4: // medium right rForward 1 rTurn 3 return Action5: // Hard left rForward 1 rTurn -6 return Action6: // Hard right rForward 1 rTurn 6 return

***************************another sub main: gosub Init while 1 gosub RoamAndObserve wend end RoamAndObserve: // genetically turn away from walls if rFeel() then rTurn (140+Random(80)) if rSense() // something got our attention gosub ReactAndAnalyze else if !rFeel() then rForward 1 endif return *******************Next program below

ReactAndAnalyze: CurState = rSense() // see if CurState is in memory InMemory=false if NumStates>0 for p=0 to NumStates-1 if GoodState[p]=CurState InMemory = True break endif next endif if InMemory // react as expected based on past experience // perform the action associated with the current state gosub "Action"+ActionToTake[p] // decide if the action still produces good outcome NewState = rSense() Reward=false if NewState&2 then Reward=True // Also reward if this NewState is in memory if !Reward and NumStates>0 for i=0 to NumStates-1 if NewState=GoodState[i] Reward=True break endif next endif if !Reward // old memory does not seem to be valid ConfidenceLevel[p]-- if ConfidenceLevel[p]=0 for i=p to NumStates-1 // delete memory GoodState[i]=GoodState[i+1] ActionToTake[i]=ActionToTake[i+1] ConfidenceLevel[i]=ConfidenceLevel[i+1] next NumStates-- endif else // increase confidence of memory (up to 2) if ConfidenceLevel[p]<3 then ConfidenceLevel[p]++ endif else // try something new NewAction = Random(6)+1 gosub "Action"+NewAction // now see if the New Action produced good results NewState = rSense() Reward=false if NewState&2 then Reward=True // gave direct reward // Also reward if this NewState is in memory if !Reward and NumStates>0 for i=0 to NumStates-1 if NewState=GoodState[i] Reward=True break endif next endif if Reward // good result so add to memory if not there already // CurState is what initiated this action so add to memory // NewAction is what we did to get rewarding results GoodState[NumStates]=CurState ActionToTake[NumStates]=NewAction ConfidenceLevel[NumStates]=1 NumStates++ endif endif return

Hope that this heled.

United Kingdom
#19  

@Mel, what does that code do? What does it do better than the code posted (or the ping roam code which is a more advanced method than the older IR code posted). And what is "Robot basic"? Any links to the language?

#20  

This code came from RobotBasic and the Robot Programmer's Bonanza, and servo Magazine.

Now, parts of it are just printing stufff on the screen. But, some of it are sniplets of A.I. programming where the robot has a confidense level and stores good moves in memory. Evently, it will become a self-programming robot programmed by it's environment. I would write the code myself, but I am not there yet. Read the article in Oct. 2013 servo magazine. Look at some of the code and you will see what i am talking about. Making intelligent decisions based on past mistakes. It is written in Basic, but could be transferred into EZ-Script, I am guessing. (That's where you or some top notch programmer comes in.) I am not saying that the other programs you wrote were bad. I just put this here to assist the robot to go further with A.I.

When I said "Smartly" I wasn't referring to you. I was referring to the robot. Your code is good and I respect you. You can download RobotBasic Free and play with it. It does lots of good stuff on the screen, but I want the robot to do it, him or herself.

:)

United Kingdom
#21  

I still don't see why or how it would need to learn. The Ping Roam code, which is the advanced version of this IR code, detects obstructions and moves 100% correctly 100% of the time. There is no learning required, there is no guessing required. Either the obstruction is there or it isn't and the sensor(s) are enough for it to know which direction the obstruction is in.

The currently released version of the Ping Roam is intelligent enough to avoid objects, escape from a boxed in situation by itself and avoid getting stuck in loops bouncing backwards and forwards over the same area. The next version (which is still waiting to be tested properly) has "smart avoidance" where the turns are based on the sensor readings rather than the timings.

In other words, avoidance code shouldn't make a bad decision therefore learning is not required (unless you purposely code it to make bad decisions, which there is no benefit in at all), hence the confusion over why the code was posted as I cannot see it being required.

Canada
#22  

Hey Rich. Any of your ping roam scripts have the ping sensor stationary ? I like the IR code. And used your ping roam for a test bot. I will use the ping roam for my omnibot. But the IR was used in my wall-e. I will attach a picture of my wall-e and wear the sensors are. Need help with the scripts.

User-inserted image

#23  

Well, Rich, they say if it 'aint Broke, don't fix it. If it works good we will leave it alone. I am always trying to get a machine to Learn and demonstrate artificial intelligence. Evidently, this little program doesn't need it. It was just a thought. You did a good job. I am sorry about the confusion.

The link you asked for:

robotBasic

:)

United Kingdom
#24  

Don't get me wrong Mel, it wasn't a complaint or anything along those lines, all input is always welcome:) And thanks for the link, I'll have a look at robotBasic.

@vhs896, This original IR code was for a single fixed sensor. The Ping one hasn't been for fixed since it needs to "look" left and right too. You could adjust it for a fixed ping sensor pretty easily, rather than GetADC() use GetPing() and reverse the If statement (IR works backwards to Ping so any less thans need to be greater than and vice versa)

Canada
#25  

OK. Thanks. I will give it a go. .. I might try and get the ping to swing LoL with a micro servo.

#26  

I have one ping that pans and more will be stationary. All of my IRs do not pan.

@Rich, you are the man!