Welcome to Synthiam!

Program robots using technologies created by industry experts. ARC is our free-to-use robot programming software that makes features like vision recognition, navigation, and artificial intelligence easy.

Get Started
United Kingdom
Asked — Edited

An Introduction To Scripting

All script examples are on the EZ-Cloud for download and updated after each additional post Download Now

Index
Part 1 - You are here
Part 2 - Page 1 Post #6
Part 3 - Page 1 Post #8
Part 4 - Page 2 Post #6
Part 5 - Page 2 Post #9
Part 6 - Page 3 Post #5
Part 7 - Page 4 Post #3

I have some time on my hands and nobody seems to be asking questions at the moment so I though I'd just write up a nice and simple introduction in to EZ-Script. I may write more in the future but we will see how received this is first.

EZ-Script is a powerful scripting language with a wide variety of commands. The command user manual is displayed to the right of the EZ-Script environment within ARC and a PDF version of the manual is maintained and downloadable from here.

Scripting needn't be difficult. A lot of people see lines and lines of code in the examples and are overcome by this however the number one rule in scripting, at least for me is to think logically, dumb it down and tackle one piece at a time.

I will go through how to write an example script in a logical manner and have a working script as an end result. In this example we will define variables, look at If statements, control devices attached to the EZB and read data from the EZB.

First we need to work out the algorithm for the task we want to achieve. Think of it as you think of a recipe when making a meal. It's a sequence of events in a specific order to achieve the overall result.

This example we will make our robot scared of contact and run away when anyone or anything comes in close proximity. In order to achieve this there are some hardware requirements;
Drive motors or servos
Proximity detector

For this example we will assume the robot is driven by DC motors via a 4 wire HBridge, with a correctly set-up HBridge Movement Panel in ARC and for proximity detection a low range infra red sensor connected via the ADC port ADC0.

So first, we need to think about what it is we are doing. We need to know if anything is coming in close proximity to the robot so we need to read the information supplied to the EZB via the infra red detector.

EZ-Script has a neat command for this, the GetADC command;

Quote:


GetADC( Port )
Returns the ADC value of the specified port
Example: GetADC(adc0)


So the first part of our code would be to get that ADC value and store it in a variable for ease of use. We will call this variable $proxsense. Notice the $ symbol preceding the variable name, this is required for all variables.

Code:


$proxsense = GetADC(adc0)

The value of ADC0 is now stored as the variable $proxsense.

So now that we have the value of the proximity sensor we need to use it. We need to know if someone or something is in close proximity to the robot, so we need to compare the value of ADC0 to a known close proximity ADC value. This varies on different hardware and testing may be required for accurate results. For the benefit of this example we will assume an ADC value of 50 or less is close proximity.

So let's add this as another variable;

Code:


$proxclose = 50


Easy right? It doesn't get much harder either:)

So we have the current sensed proximity value and the minimum allowed proximity value stored as variables. We want to be able to do something if the sensed proximity is more than the maximum allowed proximity. If you read that sentence you may be able to work out the next command we need to look at...

The IF command;

Quote:


If (Value Condition Value )
IF condition can support multiple comparisons and functions.
Condition tree must be closed with an ENDIF
See the Functions section of this document.
Condition can be =, , =, , AND, OR
Example:
If (GetDigital(D0) = 1)
Print("One")
EndIf
Example:
If ($Day = 2 AND $Hour = 3)
Print("Hello")
EndIf


So let's look at this logically, we have the sensed proximity, the maximum allowed proximity and want to see if one is higher than the other.

Code:


IF($proxsense > $proxclose)
ENDIF


This will look at $proxsense, check it against $proxclose and if it is greater than (>) $proxclose it will run the next commands. If not then it will jump down to the endif command. All if statements must be finished by an endif command.

So the code so far should look like this;

Code:


$proxsense = GetADC(adc0)
$proxclose = 50
IF($proxsense > $proxclose)
ENDIF


While the code will compare the values it still doesn't do anything. Nothing has been defined in the if statement. But what we have achieved is for the script to now be able to find out if someone, or something is in close proximity to the robot.

So now we want to have the robot do something if the statement is true. The next question is what do we want it to do if someone or something is too close? We want it to run away, all scared and full of panic.

So how do we do that?

First we decide if we want the robot to just reverse away, as if running backwards. We could, but do you run backwards? No, you turn and run. So we will make the robot turn 180 degrees (roughly) and run away.

How do we do this in EZ-Script? Easily!..

EZ-Script has all five of the Movement Panel commands. Forward, Reverse, Stop, Left and Right;

Quote:


Forward( [speed], [milliSeconds] )
Using a Movement Panel Control, this will start your robot in the Forward direction.
Optionally, you can provide the speed and/or number of milliseconds to move.
You will require at least one Movement Panel to be configured within the project. This function will control that movement panel.
Speed is a number between 0 and 255
Example: Forward()
Example: Forward(200)
Example: Forward(255, 5000)

Reverse( [speed], [milliSeconds] )
Using a Movement Panel Control, this will start your robot in the Reverse direction.
Optionally, you can provide the speed and/or number of milliseconds to move.
You will require at least one Movement Panel to be conf igured within the project. This func tion will control that movement panel.
Speed is a number between 0 and 255
Example: Reverse()
Example: Reverse(200)
Example: Reverse(255, 5000)

Stop()
Using Movement Panel Control, this will stop your robot.
You will require at least one Movement Panel to be configured within the project. This
function will control a movement panel.
Example: Stop()

Left( [speed], [milliSeconds] )
Using a Movement Panel Control, this will turn your robot left.
You will require at least one Movement Panel to be configured within the project. This function will control that movement panel.
Optionally, you can specify the speed and/or number of milliseconds to turn.
Speed is a number between 0 and 255
Example #1: Left()
Example #2: Left(200)
Example #2: Left(200, 5000)

Right( [speed], [milliSeconds] )
Using a Movement Panel Control, this will turn your robot right.
You will require at least one Movement Panel to be configured within the project. This function will control that movement panel.
Optionally, you can specify the speed and/or number of milliseconds to turn.
Speed is a number between 0 and 255
Example #1: Right()
Example #2: Right(200)
Example #2: Right(200, 5000)


Direction of turn doesn't matter so either the left or the right command would be suitable. For the purpose of this example we will turn left. To turn 180 degrees is not an exact science since the robot has no means of knowing it's direction. Turning is time based and this must be calculated by timing your robot for how long it takes to rotate 180 degrees. For the purpose of this script we will assume the robot rotates 1 degree in 0.1 milliseconds or 180 degrees in 1800 milliseconds.

Code:


LEFT(255,1800)


Now that the robot has done an about turn and is facing away from the scary thing in front of it it needs to run forwards to get away. So a forward command is issued. We will make it run away for 5 seconds.

Code:


FORWARD(255,5000)


And that's it. As simple as that. So the code so far should look like;

Code:


LEFT(255,1800)
FORWARD(255,5000)


Now let's put it all together. We can do this a couple of ways. One way would be to put the left and forward commands inside the if statement, and if you have a basic script there is nothing wrong with that at all but I want to show you the Label, Goto and Return commands too;

Quote:


:Label
Defines a label for a GOTO() command
Example: :My_Label

Goto( label )
Goto a specific :Label location
Example: Goto(My_Label)

Return()
Return from a Goto()
If you jump to a position of code with a Goto(), the Return statement will allow you to return back to that piece of code following the last Goto()
If you attempt to Return() with an empty stack, nothing will happen. The script will ignore the Return() statement.
Example: Return()


These commands can be used to set up what I like to call Sub Routines. A small piece of code which can be called up from many places within the code. These are great if your script is long and manages many different tasks that all may require the same sub routine.

So we set up the "runaway" sub routine;

Code:


:runaway
LEFT(255,1800)
FORWARD(255,5000)
RETURN()


And then we add in the Goto to the first part of the code we wrote;

Code:


$proxsense = GetADC(adc0)
$proxclose = 50
IF($proxsense > $proxclose)
GOTO(runaway)
ENDIF


And when we put it all together;

Code:


$proxsense = GetADC(adc0)
$proxclose = 50
IF($proxsense < $proxclose)
GOTO(runaway)
ENDIF

:runaway
LEFT(255,1800)
FORWARD(255,5000)
RETURN()


At this point there is an obvious problem. Once the script runs and the if statement is run it follows on to run the runaway code, regardless of the outcome of the if statement. It also only runs once. This is taken care of with another label and another goto command. The label at the start of the script and a goto after the endif. This loops the script around forever.

The code should now look like this.

Code:


:loop
$proxsense = GetADC(adc0)
$proxclose = 50
IF($proxsense > $proxclose)
GOTO(runaway)
ENDIF
GOTO(loop)

:runaway
LEFT(255,1800)
FORWARD(255,5000)
RETURN()


The last thing to tackle is the demand the script above may have on the hardware and your PC. Reading from the ADC port can be demanding on the system. The way to overcome this is with a Sleep command, which pauses the script for the desired time.

Quote:


Sleep (milliseconds)
Pauses for specified milliseconds
Example sleeps for 1 second: Sleep(1000)


To restrict the number of reads of the ADC port we will add in the sleep right before it loops around, giving a sleep command for 1 second.

Code:


:loop
$proxsense = GetADC(adc0)
$proxclose = 50
IF($proxsense > $proxclose)
GOTO(runaway)
ENDIF
SLEEP(1000)
GOTO(loop)

:runaway
LEFT(255,1800)
FORWARD(255,5000)
RETURN()


And there we have it, the completed script. It's simple yet effective. The script will run, it will then check the value of ADC0, check if this is less than the minimum allowed value, if it is then it will jump down to the "runaway" sub routine, turn left, run forwards and return back to the main script. If not then it just loops around and around forever.

This post has not been written with the intention of showing a detection script but more for showing how to tackle writing any script. I hope you can now take what I have shared above and start creating your own scripts and routines to make the robot perform the tasks you require it to perform.

If you have any specific tasks that you would like to achieve but cannot quite figure out where to start please mention them and we can all discuss the way to do this, break it down piece by piece like the above and find you your solution.


ARC Pro

Upgrade to ARC Pro

Unleash your creativity with the power of easy robot programming using Synthiam ARC Pro

#1  
Thanks so very much Rich. This is exactly what I need. I am at the point now in my build where this will help me bring my project to life. All I need is a guiding hand.

Looking forward to more of your script classes and working with you on the Auto Docking Project:)

Rex
United Kingdom
#2  
All I need is ideas, I'm itching to write some scripts. Although prefer giving everyone a menu and saying "pick your own meal" than spoon feeding them. It's just my way of giving back to this awesome community.

While I haven't used many yet I'll look in to doing something with all of the global variables such as the $direction, $CameraIsTracking etc. but first I need to use them and understand them myself (which wont take long, I pick stuff really quickly)

The auto docking project should be an interesting script, it needs to do a lot all at the same time and will use a few of the global variables. I'm really excited to start working on that one but until the navigation method is sorted I can't do more than the battery monitor part.
Ireland
#3  
This is an excellent idea
now our very own in house scripting lesson

well done
#4  
Give a man a fish, he'll eat for a day.
Teach a man to script, and he'll code his robot to fish and possibly take over the world.
:D
United Kingdom
#5  
Part 2: Script versatility

If anyone has ever looked at the scripts I have written and shared (or even the ones I don't share yet) they will notice that I make them as versatile as is possible so that anyone can pick them up and use them with minimum of effort.

Not only is this done for versatility but it is also done to make my life easier when it comes to testing out the script on the robot. There is nothing worse than having to go through hundreds of lines of scripts and change every line where a sleep value or the ms of a movement command.

So I'm going to explain how I do this.

We will use the example script from the first post;

Code:


:loop
$proxsense = GetADC(adc0)
$proxclose = 50
IF($proxsense > $proxclose)
GOTO(runaway)
ENDIF
SLEEP(1000)
GOTO(loop)

:runaway
LEFT(255,1800)
FORWARD(255,5000)
RETURN()


If we look at it there are a lot of values in this tiny script that may need to be changed for someone else to use it on their robot. The first step is to look at it and pick out all of these values.

Working our way down from the top to the bottom we have;
An ADC port
The minimum distance
The delay for the main loop
The turn speed
The turn length
The forward speed
The forward length

All of these can be replaced for variables at the start of the script which are easy to locate and change depending on your requirements.

I start a script off with the following as a rule;

Code:


# Script Title
# Script Version

# Script configuration - change the values below to suit


And then a bunch of variables with comments to explain each one.

Code:


# Scaredy Cat Robot Script
# Version 1.1

# Script configuration - change the values below to suit
$adcport = ADC0 # Change to required ADC port
$proxclose = 50 # Change for minimum distance
$delay = 1000 # Change for delay between reading distance
$turnspeed = 255 # Change for turn speed (1-255)
$turnlength = 1800 # Change for length of turn in ms
$forwardspeed = 255 # Change for forward speed (1-255)
$forwardlength = 5000 # Change for length of forward movement in ms


After which I usually place another comment warning the user not to change anything below. And then the script with the newly added variables inserted where the values once were.

Code:


# Scaredy Cat Robot Script
# Version 1.1

# Script configuration - change the values below to suit
$adcport = ADC0 # Change to required ADC port
$proxclose = 50 # Change for minimum distance
$delay = 1000 # Change for delay between reading distance
$turnspeed = 255 # Change for turn speed (1-255)
$turnlength = 1800 # Change for length of turn in ms
$forwardspeed = 255 # Change for forward speed (1-255)
$forwardlength = 5000 # Change for length of forward movement in ms

# Do not change anything below this line

:loop
$proxsense = GetADC($adcport)
IF($proxsense > $proxclose)
GOTO(runaway)
ENDIF
SLEEP($delay)
GOTO(loop)

:runaway
LEFT($turnspeed, $turnlength)
FORWARD($forwardspeed, $forwardlength)
RETURN()


And now the code can be easily adjusted by anyone to suit their specific robot, environment etc. While it may not look like that big a deal with the above script I'm sure you can imagine just how much of a time saver it can be for a large script with many lines of code, various IF statements to perform actions which all have similar values - for instance turning left or right depending on the surroundings.

Next time... Adding in options to either run or not run based on configuration variables and we will add in more sensors and turn in a direction to suit the values of the sensors. This will also show the importance of the variables added in this post :).

Again, this is not intended to provide a working avoidance script but show an example of how to write any script.
#6  
from looking at your examples RICH it looks good,will have to try them soon
United Kingdom
#7  
Part 3 - Options

Again, any who have seen my scripts will notice that some have options. For instance an option for reversing before turning in the Object Avoidance script, or for testing in the Ping Sensor/Sweep script.

These options can be very useful when sharing scripts. Not everyone will want their robot to act the same so giving an option of only working if moving forward, reversing before turning or even turn direction makes scripts extremely versatile.

Another advantage is having a $testmode option if like me you write the scripts before physically building the robot. I first showed this in the Ping Sensor/Sweep script so that I could emulate the readings from the Ping sensor without having one set up and then could view the behaviour of the robot.

On second thoughts I will hold off on the $testmode until another post. Please ignore any references to it which I may have missed below.

How this works is very simple. First you set your configuration variables at the start of the script.

Code:


$turndirection = 0 # Change for turn direction 0 = left 1 = right
$onlyforwards = 0 # Change for if only to run while moving forwards 0 = off 1 = on


So now the code should look like;

Code:


# Scaredy Cat Robot Script
# Version 1.2

# Script configuration - change the values below to suit
$adcport = ADC0 # Change to required ADC port
$proxclose = 50 # Change for minimum distance
$delay = 1000 # Change for delay between reading distance
$turnspeed = 255 # Change for turn speed (1-255)
$turnlength = 1800 # Change for length of turn in ms
$forwardspeed = 255 # Change for forward speed (1-255)
$forwardlength = 5000 # Change for length of forward movement in ms
$turndirection = 0 # Change for turn direction 0 = left 1 = right
$onlyforwards = 0 # Change for if only to run while moving forwards 0 = off 1 = on

# Do not change anything below this line

:loop
$proxsense = GetADC($adcport)
IF($proxsense > $proxclose)
GOTO(runaway)
ENDIF
SLEEP($delay)
GOTO(loop)

:runaway
LEFT($turnspeed, $turnlength)
FORWARD($forwardspeed, $forwardlength)
RETURN()


Alone those variables would do nothing but what they do add is the ability to run an IF condition on specific portions of the script and only execute that part if the conditions are met.

We will change the script to check if it should only work when moving forwards. For this we need to add an IF around the main portion of the code.

Code:


IF($onlyforwards=1)
ENDIF


Anything between the IF and the ENDIF will only be executed if the conditions within the if, $onlyforwards=1 is met.

So the code now looks like;

Code:


$turndirection = 0 # Change for turn direction 0 = left 1 = right
$onlyforwards = 0 # Change for if only to run while moving forwards 0 = off 1 = on


So now the code should look like;

Code:


# Scaredy Cat Robot Script
# Version 1.2

# Script configuration - change the values below to suit
$adcport = ADC0 # Change to required ADC port
$proxclose = 50 # Change for minimum distance
$delay = 1000 # Change for delay between reading distance
$turnspeed = 255 # Change for turn speed (1-255)
$turnlength = 1800 # Change for length of turn in ms
$forwardspeed = 255 # Change for forward speed (1-255)
$forwardlength = 5000 # Change for length of forward movement in ms
$turndirection = 0 # Change for turn direction 0 = left 1 = right
$onlyforwards = 0 # Change for if only to run while moving forwards 0 = off 1 = on

# Do not change anything below this line

:loop
IF($onlyforwards=1)
$proxsense = GetADC($adcport)
IF($proxsense > $proxclose)
GOTO(runaway)
ENDIF
SLEEP($delay)
ENDIF
GOTO(loop)

:runaway
LEFT($turnspeed, $turnlength)
FORWARD($forwardspeed, $forwardlength)
RETURN()


With the current configuration the main loop will not execute the code to check the sensor or to runaway. There is currently no code for the script to know it is moving forwards. So we need to add it. There is a global variable available called $direction which stores the current direction of movement, either "forward", "reverse", "left", "right" or "stop". So we need to use this and check that the robot is moving forwards. Another IF condition to add in.

Code:


IF($direction="forward")
ENDIF


There are two ways in which we can add this to the script. The first way is to add the condition to the $onlyforwards IF using an AND operator.

Code:


IF($onlyforwards=1 and $direction="forward")
ENDIF


Or how I prefer to do it, by nesting another if inside the $onlyforwards IF.

Code:


IF($onlyforwards=1)
IF($direction="forward")
ENDIF
ENDIF


Reasons why I prefer the second option, despite it resulting in more code is it allows for future additions and changes much easier than when using the first option. It also reduces the length of the line of code however that is purely an aesthetic reason.

For this example I will use the second option (for reasons which will become apparent in future updates). So the code now needs to include the two statements.

Code:


# Scaredy Cat Robot Script
# Version 1.2

# Script configuration - change the values below to suit
$adcport = ADC0 # Change to required ADC port
$proxclose = 50 # Change for minimum distance
$delay = 1000 # Change for delay between reading distance
$turnspeed = 255 # Change for turn speed (1-255)
$turnlength = 1800 # Change for length of turn in ms
$forwardspeed = 255 # Change for forward speed (1-255)
$forwardlength = 5000 # Change for length of forward movement in ms
$turndirection = 0 # Change for turn direction 0 = left 1 = right
$onlyforwards = 0 # Change for if only to run while moving forwards 0 = off 1 = on

# Do not change anything below this line

:loop
IF($onlyforwards=1)
IF($direction="forward")
$proxsense = GetADC($adcport)
IF($proxsense > $proxclose)
GOTO(runaway)
ENDIF
SLEEP($delay)
ENDIF
ENDIF
GOTO(loop)

:runaway
LEFT($turnspeed, $turnlength)
FORWARD($forwardspeed, $forwardlength)
RETURN()


But now what happens if the $onlyforwards variable is set to 0 so it works all of the time? No code would be executed and it would loop from :loop to GOTO(loop) infinitely. Not a useful script. So we need to take out the sensor checking code and put it as another sub routine, this allows for us to call it with a GOTO rather than having to write the code multiple times.

So take out the code and make it a sub routine, and add in the GOTO where the code once was. And also add in the ELSE for when the variable isn't set for it to only execute when moving forwards.

Code:


# Scaredy Cat Robot Script
# Version 1.2

# Script configuration - change the values below to suit
$adcport = ADC0 # Change to required ADC port
$proxclose = 50 # Change for minimum distance
$delay = 1000 # Change for delay between reading distance
$turnspeed = 255 # Change for turn speed (1-255)
$turnlength = 1800 # Change for length of turn in ms
$forwardspeed = 255 # Change for forward speed (1-255)
$forwardlength = 5000 # Change for length of forward movement in ms
$turndirection = 0 # Change for turn direction 0 = left 1 = right
$onlyforwards = 0 # Change for if only to run while moving forwards 0 = off 1 = on

# Do not change anything below this line

:loop
IF($onlyforwards=1)
IF($direction="forward")
GOTO(sensorcheck)
ENDIF
ELSE
GOTO(sensorcheck)
ENDIF
GOTO(loop)

:runaway
LEFT($turnspeed, $turnlength)
FORWARD($forwardspeed, $forwardlength)
RETURN()

:sensorcheck
$proxsense = GetADC($adcport)
IF($proxsense > $proxclose)
GOTO(runaway)
ENDIF
SLEEP($delay)
RETURN()


Now the code will first check if the configuration is set to only execute while moving forwards, if it is it will check the direction variable and if met will run the sensorcheck code. If, on the other hand the configuration variable isn't set to check only if moving forwards the code goes directly to the sensorcheck code.

We also added in two other variables, $turndirection and $testmode. Let's take a look at turn direction.

The $turndirection is commented with 0 for left and 1 for right. So, in order for the script to know which way we want to turn we need to run a check on that variable in the :runaway code. There is one minor problem which is that the user may enter something other than 0 or 1. Rather than throw an error due to this we will counter the problem by having the robot turn left for anything other than a 1, where it turns right.

This will use the ELSE command rather than an ELSEIF. The ELSE doesn't require any parameters after it, what happens is if the condition of the IF is not met then the code below the ELSE is run.

So let's look at the :runaway code and add in the commands for direction checking and acting accordingly.

Code:


:runaway
LEFT($turnspeed, $turnlength)
FORWARD($forwardspeed, $forwardlength)
RETURN()


First we need to add in the IF and the condition to check for.

Code:


IF($turndirection=1)
# Right Turn
ELSE
# Left Turn
ENDIF


So let's wrap our existing code in a new IF blanket:)

Code:


:runaway
IF($turndirection=1)
RIGHT($turnspeed, $turnlength)
ELSE
LEFT($turnspeed, $turnlength)
ENDIF
FORWARD($forwardspeed, $forwardlength)
RETURN()


Simple, now it checks the configuration and turns in the right direction. The $turnspeed and $turnlength variables from last time come in to play and allow us to adjust the turn and run by changing a single value rather than the same value multiple times.

The full code now looks like;

Code:


# Scaredy Cat Robot Script
# Version 1.2

# Script configuration - change the values below to suit
$adcport = ADC0 # Change to required ADC port
$proxclose = 50 # Change for minimum distance
$delay = 1000 # Change for delay between reading distance
$turnspeed = 255 # Change for turn speed (1-255)
$turnlength = 1800 # Change for length of turn in ms
$forwardspeed = 255 # Change for forward speed (1-255)
$forwardlength = 5000 # Change for length of forward movement in ms
$turndirection = 0 # Change for turn direction 0 = left 1 = right
$onlyforwards = 0 # Change for if only to run while moving forwards 0 = off 1 = on

# Do not change anything below this line

:loop
IF($onlyforwards=1)
IF($direction="forward")
GOTO(sensorcheck)
ENDIF
ELSE
GOTO(sensorcheck)
ENDIF
GOTO(loop)

:runaway
IF($turndirection=1)
RIGHT($turnspeed, $turnlength)
ELSE
LEFT($turnspeed, $turnlength)
ENDIF
FORWARD($forwardspeed, $forwardlength)
RETURN()

:sensorcheck
$proxsense = GetADC($adcport)
IF($proxsense > $proxclose)
GOTO(runaway)
ENDIF
SLEEP($delay)
RETURN()


Part 4 - Adding in those extra sensors (including options for different types). Coming soon...
Part 5 - Adding test mode and debug flags.

And, as always, this is not intended to provide a working avoidance script but show an example of how to write any script. If you have any questions please ask.
Canada
#8  
Rich,

Thanks for doing this.

I'm learning lots. Just discovered the world of $variables!
United Kingdom
#9  
No thanks is necessary (although it is nice to hear/read), you're all very welcome. The more who learn how to script the more scripts should pop up and I'm running short on ideas of scripts for my robot:) Plus it helps me learn too, thinking about what, how and why commands work makes it stick, I'm now almost to the point I can write scripts from memory (which helps when I'm stuck at work with nothing good to do).

I love my $variables:) I do end up with a variable watcher that's far too big though but it makes everything so much easier, especially when it comes to fine tuning speeds, times, delays etc.
#10  
Tuesday, 19 March 2013

Good Morning EZ-Scripters !

Rich, Thank You for Scripting Examples !

I had been requesting something like in previous EZ-Forum Posts.

Friday, 1 February 2013

Good Morning Fellow EZ-Robot Scripters !

Is anyone available to colaborate on EZ-Scrpts and write simple Test Code Examples to become familar with Using the EZ-Script Instruction Set ?


In response to I have some time on my hands and nobody seems to be asking questions at the moment , would you please consider letting ARC Connect to the PC's generic RS-232 COM1, just for testing purposes ?

I realize that defeats the sale of EZ-B's, but it sure would make troubleshooting Roomba Scripts Easier.

I really like the NEW Active Debug Window and IT's Always Show Feature !

Thank You All, & Best Wishes From Phoenix,

DougPope@cox.net, 602-246-1246(H)
United Kingdom
#11  
Thanks Doug. I had seen your questions but thought you were talking SDK and C# which I am not familiar with (yet - give it time), I must have missed that post.

Be aware that I am unable to make changes to ARC, I do not work for EZ-Robot Inc. I just contribute to the community in any way I can. You would need to discuss that request with @DJ Sures.
#12  
Rich ?

Have YOU Considered running a Microsoft Visual Studio 2012 Class ON LINE, via VNC, TeamViewer, or Skype ?

Not for Free, but say $20 Per Hour Per Student ?

DougPope@cox.net, 602-246-1246(H)

P.S. This would solve your Employment Problem with EZ-Robot.com, and SOLVE The Long Commute !
Spain
#13  
Great tutorial Rich, I think an effective method of learning step by step and easy for everyone and a good reference for an eye's take when one is lost.
United Kingdom
#14  
Doug, I am not yet familiar with Visual Studio or C#. They are on my list for the future though.

When it comes to EZ-Robot/EZ-B/ARC I will never charge for anything I offer. I saw the work ethic of EZ-Robots immediately when I discovered the EZ-B and was very impressed. I can see that they value their customers and the community, which is becoming harder and harder to see these days. Once I figured out how to do things with the software and hardware I decided I would give back to the community in any way I can and ride on EZ-Robot's coat tails:) Financially speaking I do not have any need nor desire to profit from this, as soon as it becomes about that I can see things changing... this is a hobby not a job:) It's a welcomed break from working (the only kind of break for a workaholic). The thanks I receive on and off the forums is enough for me.
United Kingdom
#15  
Part 4 - Multiple Sensors
So far we have a robot which is only running a single infra red sensor to detect something approaching. In this part we will increase the number of sensors from one to three.

The (virtual) robot will have an ir sensor on the front left, front centre and front right of it's body. This means that we must make changes to the variables of the existing code to include the two new sensors, plus renaming one of the variables for consistency.

Let's remind ourselves of the code as it stands;

Code:


# Scaredy Cat Robot Script
# Version 1.2

# Script configuration - change the values below to suit
$adcport = ADC0 # Change to required ADC port
$proxclose = 50 # Change for minimum distance
$delay = 1000 # Change for delay between reading distance
$turnspeed = 255 # Change for turn speed (1-255)
$turnlength = 1800 # Change for length of turn in ms
$forwardspeed = 255 # Change for forward speed (1-255)
$forwardlength = 5000 # Change for length of forward movement in ms
$turndirection = 0 # Change for turn direction 0 = left 1 = right
$onlyforwards = 0 # Change for if only to run while moving forwards 0 = off 1 = on

# Do not change anything below this line

:loop
IF($onlyforwards=1)
IF($direction="forward")
GOTO(sensorcheck)
ENDIF
ELSE
GOTO(sensorcheck)
ENDIF
GOTO(loop)

:runaway
IF($turndirection=1)
RIGHT($turnspeed, $turnlength)
ELSE
LEFT($turnspeed, $turnlength)
ENDIF
FORWARD($forwardspeed, $forwardlength)
RETURN()

:sensorcheck
$proxsense = GetADC($adcport)
IF($proxsense > $proxclose)
GOTO(runaway)
ENDIF
SLEEP($delay)
RETURN()


First let's think about the configuration variables;

Code:


# Script configuration - change the values below to suit
$adcport = ADC0 # Change to required ADC port
$proxclose = 50 # Change for minimum distance
$delay = 1000 # Change for delay between reading distance
$turnspeed = 255 # Change for turn speed (1-255)
$turnlength = 1800 # Change for length of turn in ms
$forwardspeed = 255 # Change for forward speed (1-255)
$forwardlength = 5000 # Change for length of forward movement in ms
$turndirection = 0 # Change for turn direction 0 = left 1 = right
$onlyforwards = 0 # Change for if only to run while moving forwards 0 = off 1 = on


The first thing we notice is the variable $adcport which will not make much sense with more than one port being required so this is renamed and two more added for the other ports;

Code:


$irleft = ADC0 # Change to required ADC port for left IR sensor
$ircenter = ADC1 # Change to required ADC port for center IR sensor
$irright = ADC2 # Change to required ADC port for right IR sensor


For good measure, and in case it needs tweaking on individual sensors the $proxclose variable is also to be renamed and two extra added;

Code:


$maxirleft = 50 # Change for the maximum reading on the left IR sensor
$maxircenter = 50 # Change for the maximum reading on the left IR sensor
$maxirright = 50 # Change for the maximum reading on the left IR sensor


Throw it all together and we have;

Code:


# Scaredy Cat Robot Script
# Version 1.3

# Script configuration - change the values below to suit
$irleft = ADC0 # Change to required ADC port for left IR sensor
$ircenter = ADC1 # Change to required ADC port for center IR sensor
$irright = ADC2 # Change to required ADC port for right IR sensor
$maxirleft = 50 # Change for the maximum reading on the left IR sensor
$maxircenter = 50 # Change for the maximum reading on the left IR sensor
$maxirright = 50 # Change for the maximum reading on the left IR sensor
$delay = 1000 # Change for delay between reading distance
$turnspeed = 255 # Change for turn speed (1-255)
$turnlength = 1800 # Change for length of turn in ms
$forwardspeed = 255 # Change for forward speed (1-255)
$forwardlength = 5000 # Change for length of forward movement in ms
$turndirection = 0 # Change for turn direction 0 = left 1 = right
$onlyforwards = 0 # Change for if only to run while moving forwards 0 = off 1 = on

# Do not change anything below this line

:loop
IF($onlyforwards=1)
IF($direction="forward")
GOTO(sensorcheck)
ENDIF
ELSE
GOTO(sensorcheck)
ENDIF
GOTO(loop)

:runaway
IF($turndirection=1)
RIGHT($turnspeed, $turnlength)
ELSE
LEFT($turnspeed, $turnlength)
ENDIF
FORWARD($forwardspeed, $forwardlength)
RETURN()

:sensorcheck
$proxsense = GetADC($adcport)
IF($proxsense > $proxclose)
GOTO(runaway)
ENDIF
SLEEP($delay)
RETURN()


If you tried to run that code now it would be riddled with errors due to the variable changes. Believe it or not it is a good thing. Now it should be pretty easy to see where the code needs changing to allow for the extra sensors. Mainly the :sensorcheck sub routine.

Code:


:sensorcheck
$proxsense = GetADC($adcport)
IF($proxsense > $proxclose)
GOTO(runaway)
ENDIF
SLEEP($delay)
RETURN()


Since the variable $adcport no longer exists and neither does $proxclose we know that we have to make changes to these two lines. But we also need to include code to check more than one sensor. It all happens in the same place.

Again, the variable $proxsense makes little sense when we need to check three sensors, so we will rename and add in two more.

Code:


$irleftreading = GetADC($irleft)
$ircenterreading = GetADC($ircenter)
$irrightreading = GetADC($irright)


Now we have the data from the sensors stored in three variables. And now we can update the condition within the IF. There are a few ways we can do this.

The first by using the OR operator

Code:


IF($irleftreading > $maxirleft or $ircenterreading > $maxircenter or $irrightreading > $maxirright)
GOTO(runaway)
ENDIF


Or we can do it by checking one, then the other, then the last with IF and ELSEIF

Code:


IF($irleftreading > $maxirleft)
GOTO(runaway)
ELSEIF($ircenterreading > $maxircenter)
GOTO(runaway)
ELSEIF($irrightreading > $maxirright)
GOTO(runaway)
ENDIF


The advantages of the second method with the ELSEIF is you could point it to different sub routines depending on which reading was high. For now though we don't need this so we will use the OR operator.

Whatever sensor is detecting proximity it will jump to the runaway sub routine. So now we need to adjust the runaway code to check which sensor detected the proximity and act accordingly. This is done again with IF and using the $irleftreading, $ircenterreading and $irrightreading variables.

The original runaway code is

Code:


:runaway
IF($turndirection=1)
RIGHT($turnspeed, $turnlength)
ELSE
LEFT($turnspeed, $turnlength)
ENDIF
FORWARD($forwardspeed, $forwardlength)
RETURN()


Now, we can remove the now redundant $turndirection check and replace it with the code to check which sensor is detecting proximity. We do this by checking which of the three variables is reading highest through an IF and ELSEIF with AND operators.

Code:


:runaway
IF($irleftreading > $ircenterreading and $irleftreading > $irrightreading)
RIGHT($turnspeed, $turnlength)
ELSEIF($ircenterreading > $irleftreading and $ircenterreading > $irrightreading)
LEFT($turnspeed, $turnlength)
ELSE
LEFT($turnspeed, $turnlength)
ENDIF
FORWARD($forwardspeed, $forwardlength)
RETURN()


Notice how the last part of the IF is an ELSE rather than an ELSEIF. This is because of eliminating the other two statements, if neither are true then the only other option would be to move away from the right. You could use an ELSEIF and write the entire condition but it would be wasted code and time. It also defaults to moving away from the right should the proximiry be equally detected across all three sensors.

Also, where proximity is higher in the center it defaults to turning away to the left, this is personal choice, you could choose to turn right it's up to you.

So now we have code that will check three sensors and move away in the appropriate direction. The final code for this part should look a little something like this;

Code:


# Scaredy Cat Robot Script
# Version 1.3

# Script configuration - change the values below to suit
$irleft = ADC0 # Change to required ADC port for left IR sensor
$ircenter = ADC1 # Change to required ADC port for center IR sensor
$irright = ADC2 # Change to required ADC port for right IR sensor
$maxirleft = 50 # Change for the maximum reading on the left IR sensor
$maxircenter = 50 # Change for the maximum reading on the left IR sensor
$maxirright = 50 # Change for the maximum reading on the left IR sensor
$delay = 1000 # Change for delay between reading distance
$turnspeed = 255 # Change for turn speed (1-255)
$turnlength = 1800 # Change for length of turn in ms
$forwardspeed = 255 # Change for forward speed (1-255)
$forwardlength = 5000 # Change for length of forward movement in ms
$turndirection = 0 # Change for turn direction 0 = left 1 = right
$onlyforwards = 0 # Change for if only to run while moving forwards 0 = off 1 = on

# Do not change anything below this line

:loop
IF($onlyforwards=1)
IF($direction="forward")
GOTO(sensorcheck)
ENDIF
ELSE
GOTO(sensorcheck)
ENDIF
GOTO(loop)

:runaway
IF($irleftreading > $ircenterreading and $irleftreading > $irrightreading)
RIGHT($turnspeed, $turnlength)
ELSEIF($ircenterreading > $irleftreading and $ircenterreading > $irrightreading)
LEFT($turnspeed, $turnlength)
ELSE
LEFT($turnspeed, $turnlength)
ENDIF
FORWARD($forwardspeed, $forwardlength)
RETURN()

:sensorcheck
$irleftreading = GetADC($irleft)
$ircenterreading = GetADC($ircenter)
$irrightreading = GetADC($irright)
IF($irleftreading > $maxirleft or $ircenterreading > $maxircenter or $irrightreading > $maxirright)
GOTO(runaway)
ENDIF
SLEEP($delay)
RETURN()
Spain
#16  
Awesome, I think it will be easy to change a bit the code for use with ultrasonic sensors, I will write it down as a pending task and buy several sensors.
United Kingdom
#17  
Ultrasonic is next R2D2:)

But, in the mean time (as I plan to take a few days away this weekend) feel free to try it yourself. Hint: Ping is the other way around to IR, so anything that is less than needs to change to greater than and vice versa). If you aren't bothered about variable names being wrong it's a very easy change, 6 lines of code is all that would need changing, literally a 2 second job.

All of the scripts are in the EZ-Cloud for easy downloading and altering. All of them are saved in script manager, named part 1, part 2, part 3 and part 4 so should be easy to alter.
United Kingdom
#18  
@R2D2. I got impatient again/

Part 5 - Ultra Sonic Sensor

So far we have been using the IR sensor and GetADC to find out if there is anything or anyone in close proximity to the robot but HC-SR04 Ultra Sonic is the more popular option. So let's take a look at what we need to change to use HC-SR04 Ultra Sonic sensors.

We will start off with the script from Part 3 with one sensor. A little "challenge" for you would be to update the last script in part 4 to accept ultra sonic rather than IR if you fancy a quick test:)

Anyway, the code as it was;

Code:


# Scaredy Cat Robot Script
# Version 1.2

# Script configuration - change the values below to suit
$adcport = ADC0 # Change to required ADC port
$proxclose = 50 # Change for minimum distance
$delay = 1000 # Change for delay between reading distance
$turnspeed = 255 # Change for turn speed (1-255)
$turnlength = 1800 # Change for length of turn in ms
$forwardspeed = 255 # Change for forward speed (1-255)
$forwardlength = 5000 # Change for length of forward movement in ms
$turndirection = 0 # Change for turn direction 0 = left 1 = right
$onlyforwards = 0 # Change for if only to run while moving forwards 0 = off 1 = on

# Do not change anything below this line

:loop
IF($onlyforwards=1)
IF($direction="forward")
GOTO(sensorcheck)
ENDIF
ELSE
GOTO(sensorcheck)
ENDIF
GOTO(loop)

:runaway
IF($turndirection=1)
RIGHT($turnspeed, $turnlength)
ELSE
LEFT($turnspeed, $turnlength)
ENDIF
FORWARD($forwardspeed, $forwardlength)
RETURN()

:sensorcheck
$proxsense = GetADC($adcport)
IF($proxsense > $proxclose)
GOTO(runaway)
ENDIF
SLEEP($delay)
RETURN()


The first thing to look at would be the way we check the proximity. Currently we use the GetADC command as explained in part 1 but that is not the correct command when using a HC-SR04 Ultra Sonic sensor. There is a special command written just for the sensor called GetPing

Quote:

GetPing( trigger port, echo port )
Return the Ping HC-SR04 value of the specified port
Example: GetPing(d0, d1)


So we need to replace the GetADC parts with GetPing...

Code:


:sensorcheck
$proxsense = GetPing($adcport)
IF($proxsense > $proxclose)
GOTO(runaway)
ENDIF
SLEEP($delay)
RETURN()


Now, if you tried running that code or clicking on the check syntax button it would tell you there is a problem. The GetPing needs two ports to be defined. One for the Trigger and one for the Echo. So we need to update that line and we need a couple more new variables to define.

Code:


:sensorcheck
$proxsense = GetPing($trigport, $echoport)
IF($proxsense > $proxclose)
GOTO(runaway)
ENDIF
SLEEP($delay)
RETURN()


And update the configuration variables to suit the new variables and remove the old redundant ADC variable. We may as well update the version number while we are at it too.

Code:


# Scaredy Cat Robot Script
# Version 1.2.5

# Script configuration - change the values below to suit
$trigport = D0 # Change to required port for Trig
$echoport = D1 # Change to required port for Echo
$proxclose = 50 # Change for minimum distance
$delay = 1000 # Change for delay between reading distance
$turnspeed = 255 # Change for turn speed (1-255)
$turnlength = 1800 # Change for length of turn in ms
$forwardspeed = 255 # Change for forward speed (1-255)
$forwardlength = 5000 # Change for length of forward movement in ms
$turndirection = 0 # Change for turn direction 0 = left 1 = right
$onlyforwards = 0 # Change for if only to run while moving forwards 0 = off 1 = on


So now we have the code checking the HC-SR04, the code checking the value against the pre-set distance value and acting accordingly... Well, almost!..

One more thing that needs to change is the IF which checks the values. The IR sensor's value increases when it gets closer to an object but the HC-SR04 sensor's value decreases. So we need to turn that condition around;

Code:


IF($proxsense > $proxclose)


becomes

Code:


IF($proxsense < $proxclose)


And when it's all put together you will end up with something a little bit like this.

Code:


# Scaredy Cat Robot Script
# Version 1.2.5

# Script configuration - change the values below to suit
$trigport = D0 # Change to required port for Trig
$echoport = D1 # Change to required port for Echo
$proxclose = 50 # Change for minimum distance
$delay = 1000 # Change for delay between reading distance
$turnspeed = 255 # Change for turn speed (1-255)
$turnlength = 1800 # Change for length of turn in ms
$forwardspeed = 255 # Change for forward speed (1-255)
$forwardlength = 5000 # Change for length of forward movement in ms
$turndirection = 0 # Change for turn direction 0 = left 1 = right
$onlyforwards = 0 # Change for if only to run while moving forwards 0 = off 1 = on

# Do not change anything below this line

:loop
IF($onlyforwards=1)
IF($direction="forward")
GOTO(sensorcheck)
ENDIF
ELSE
GOTO(sensorcheck)
ENDIF
GOTO(loop)

:runaway
IF($turndirection=1)
RIGHT($turnspeed, $turnlength)
ELSE
LEFT($turnspeed, $turnlength)
ENDIF
FORWARD($forwardspeed, $forwardlength)
RETURN()

:sensorcheck
$proxsense = GetPing($trigport, $echoport)
IF($proxsense < $proxclose)
GOTO(runaway)
ENDIF
SLEEP($delay)
RETURN()


In Part 6 I will go through updating the code with 3 sensors and adding in options in the configuration to choose if it uses IR, Ping or both. Feel free to take a crack at it yourself.

The same principal can be used for other sensor types. Light sensors to act when it gets either dark or light. Gas sensors to act in the event of a gas detection. The camera with color detection or face detection. There are endless possibilities and I hope to see them on your robots :).
Spain
#19  
@ Rich, your scripts are so versatile and adaptable to many robots, it's like going to the supermarket i choose the meal.
The variables seem to offer endless possibilities, although, also require a large brain squeezed at times.
I'm eager to see the next chapters:)
PRO
New Zealand
#20  
Hey @Rich

Very impressed with your work and may well grab it for my students at school....

Since this is being shared far and wide have you considered adding a description box and adding your name?

Eg.
_____________________________________________

Code:


# Scaredy Cat Robot Script
# Version 1.2
# Created by @Rich
# Date: 12/12/2013

# +------------------------------------+
# | This script will make your robot |
# | perform the spin on the spot |
# | and possibly make you look a |
# | whole lot smarter... NOT! |
# +------------------------------------+



Identification of authorship here is intended to help direct questions to the author and not for copyright or ownership purposes.... lol

@Tameion
United Kingdom
#21  
I have considered that and have full header information in my scripts in my project (and pretty much any other scripts or code I have ever written) however in these tutorials I didn't bother as the pages and posts are very long as it is.

If you download the project with the scripts in you are greeted with a nifty little notepad control though with a bit more information in it :).
PRO
New Zealand
#22  
It is as I expected it would be....

Keep up the good work $)

BTW the cleanup you did of the time script was impressive.... just trashed mine and replaced it with yours - Lol
United Kingdom
#23  
Any time you want to use these for your students feel free by the way. If you want to pay for me to come and talk to them I'd be up for that too;)

Thanks for the kind words
United Kingdom
#24  
Part 6 - Multiple Ultrasonic Sensors

Last time we went through changing the IR sensor to Ultrasonic. Now we will change the script for 3 IR sensors to give the option of 3 IR or Ultrasonic Sensors.

So we start of with the code for 3 IR sensors from Part 4;

Code:


# Scaredy Cat Robot Script
# Version 1.3

# Script configuration - change the values below to suit
$irleft = ADC0 # Change to required ADC port for left IR sensor
$ircenter = ADC1 # Change to required ADC port for center IR sensor
$irright = ADC2 # Change to required ADC port for right IR sensor
$maxirleft = 50 # Change for the maximum reading on the left IR sensor
$maxircenter = 50 # Change for the maximum reading on the left IR sensor
$maxirright = 50 # Change for the maximum reading on the left IR sensor
$delay = 1000 # Change for delay between reading distance
$turnspeed = 255 # Change for turn speed (1-255)
$turnlength = 1800 # Change for length of turn in ms
$forwardspeed = 255 # Change for forward speed (1-255)
$forwardlength = 5000 # Change for length of forward movement in ms
$turndirection = 0 # Change for turn direction 0 = left 1 = right
$onlyforwards = 0 # Change for if only to run while moving forwards 0 = off 1 = on

# Do not change anything below this line

:loop
IF($onlyforwards=1)
IF($direction="forward")
GOTO(sensorcheck)
ENDIF
ELSE
GOTO(sensorcheck)
ENDIF
GOTO(loop)

:runaway
IF($irleftreading > $ircenterreading and $irleftreading > $irrightreading)
RIGHT($turnspeed, $turnlength)
ELSEIF($ircenterreading > $irleftreading and $ircenterreading > $irrightreading)
LEFT($turnspeed, $turnlength)
ELSE
LEFT($turnspeed, $turnlength)
ENDIF
FORWARD($forwardspeed, $forwardlength)
RETURN()

:sensorcheck
$irleftreading = GetADC($irleft)
$ircenterreading = GetADC($ircenter)
$irrightreading = GetADC($irright)
IF($irleftreading > $maxirleft or $ircenterreading > $maxircenter or $irrightreading > $maxirright)
GOTO(runaway)
ENDIF
SLEEP($delay)
RETURN()


The key areas to adjust in this script are the variables, to allow for the option of IR or Ultrasonic and the runaway and sensorcheck sub routines.

We already know, from Part 5 that the ultrasonic sensors require 2 digital ports, one for Trigger and the other for Echo. So we know that we need some variables for these ports added at the top of the script. We also want to add in the option variable for choosing IR or Ultrasonic.

So we visit the variable area of the script;

Code:


# Script configuration - change the values below to suit
$irleft = ADC0 # Change to required ADC port for left IR sensor
$ircenter = ADC1 # Change to required ADC port for center IR sensor
$irright = ADC2 # Change to required ADC port for right IR sensor
$maxirleft = 50 # Change for the maximum reading on the left IR sensor
$maxircenter = 50 # Change for the maximum reading on the left IR sensor
$maxirright = 50 # Change for the maximum reading on the left IR sensor
$delay = 1000 # Change for delay between reading distance
$turnspeed = 255 # Change for turn speed (1-255)
$turnlength = 1800 # Change for length of turn in ms
$forwardspeed = 255 # Change for forward speed (1-255)
$forwardlength = 5000 # Change for length of forward movement in ms
$turndirection = 0 # Change for turn direction 0 = left 1 = right
$onlyforwards = 0 # Change for if only to run while moving forwards 0 = off 1 = on


Since it's getting big, and it's all about making things as easy as possible while we are here we will also restructure it to make it easy.

First we want to set out the Options such as sensor type and only when moving forward;

Code:


# Options
$irsensor = 1 # Change for if to use IR sensors 0 = off 1 = on
$pingsensor = 1 # Change for if to use Ultrasonic Ping sensors 0 = off 1 = on
$onlyforwards = 0 # Change for if only to run while moving forwards 0 = off 1 = on
$turndirection = 0 # Change for turn direction when applicable 0 = left 1 = right


Next we will set up the movement configuration;

Code:


#Movement Configuration
$delay = 1000 # Change for delay between reading distance
$turnspeed = 255 # Change for turn speed (1-255)
$turnlength = 1800 # Change for length of turn in ms
$forwardspeed = 255 # Change for forward speed (1-255)
$forwardlength = 5000 # Change for length of forward movement in ms


Then we will set out all of the Port Configuration including the 6 new variables for the Ultrasonic sensors.

Code:


# Port Configuration
$trigleft = D0 # Change to required Digital port for Left Trigger if required
$echoleft = D1 # Change to required Digital port for Left Echo if required
$trigcenter = D2 # Change to required Digital port for Center Trigger if required
$echocenter = D3 # Change to required Digital port for Center Echo if required
$trigright = D4 # Change to required Digital port for Right Trigger if required
$echoright = D5 # Change to required Digital port for Right Echo if required

$irleft = ADC0 # Change to required ADC port for left IR sensor if required
$ircenter = ADC1 # Change to required ADC port for center IR sensor if required
$irright = ADC2 # Change to required ADC port for right IR sensor if required


And finally we need to put down the detection sensitivity configuration

Code:


# Sensitivity Configuration
$maxirleft = 50 # Change for the maximum value for the left IR sensor if applicable
$maxircenter = 50 # Change for the maximum value for the center IR sensor if applicable
$maxirright = 50 # Change for the maximum value for the right IR sensor if applicable
$maxpingleft = 200 # Change for the maximum value for the left Ping sensor if applicable
$maxpingcenter = 200 # Change for the maximum value for the center Ping sensor if applicable
$maxpingright = 200 # Change for the maximum value for the right Ping sensor if applicable


Now it looks like a really complex script but really all we have done is set up a bunch of variables. This shows my point about breaking down code to figure it out, a lot of the time it will look a lot worse than it is.

Combine all of the smaller pieces of the configuration to give you the start of the script;

Code:


# Scaredy Cat Robot Script
# Version 1.4

# Script configuration - change the values below to suit
# Options
$irsensor = 1 # Change for if to use IR sensors 0 = off 1 = on
$pingsensor = 1 # Change for if to use Ultrasonic Ping sensors 0 = off 1 = on
$onlyforwards = 0 # Change for if only to run while moving forwards 0 = off 1 = on
$turndirection = 0 # Change for turn direction when applicable 0 = left 1 = right

#Movement Configuration
$delay = 1000 # Change for delay between reading distance
$turnspeed = 255 # Change for turn speed (1-255)
$turnlength = 1800 # Change for length of turn in ms
$forwardspeed = 255 # Change for forward speed (1-255)
$forwardlength = 5000 # Change for length of forward movement in ms

# Port Configuration
$trigleft = D0 # Change to required Digital port for Left Trigger if required
$echoleft = D1 # Change to required Digital port for Left Echo if required
$trigcenter = D2 # Change to required Digital port for Center Trigger if required
$echocenter = D3 # Change to required Digital port for Center Echo if required
$trigright = D4 # Change to required Digital port for Right Trigger if required
$echoright = D5 # Change to required Digital port for Right Echo if required

$irleft = ADC0 # Change to required ADC port for left IR sensor if required
$ircenter = ADC1 # Change to required ADC port for center IR sensor if required
$irright = ADC2 # Change to required ADC port for right IR sensor if required

# Sensitivity Configuration
$maxirleft = 50 # Change for the maximum value for the left IR sensor if applicable
$maxircenter = 50 # Change for the maximum value for the center IR sensor if applicable
$maxirright = 50 # Change for the maximum value for the right IR sensor if applicable
$maxpingleft = 200 # Change for the maximum value for the left Ping sensor if applicable
$maxpingcenter = 200 # Change for the maximum value for the center Ping sensor if applicable
$maxpingright = 200 # Change for the maximum value for the right Ping sensor if applicable

# Do not change anything below this line


Now we have the variables all set up it's time to tackle the sub routines.

We will want to look at the sensor check routine first as without it the runaway routine wouldn't know the direction to turn in. So we have the routine from Part 4

Code:


:sensorcheck
$irleftreading = GetADC($irleft)
$ircenterreading = GetADC($ircenter)
$irrightreading = GetADC($irright)
IF($irleftreading > $maxirleft or $ircenterreading > $maxircenter or $irrightreading > $maxirright)
GOTO(runaway)
ENDIF
SLEEP($delay)
RETURN()


In to that we need to add a few things. First the code for checking the ultrasonic sensors and second the commands to decide which sensors to check.

Adding in the code for the ultrasonic sensors is pretty much the same as Part 5 changing the code. But in this case we leave the IR code in there also.

The code to check a ultrasonic sensor is;

Code:


GetPing(Trig,Echo)


We want to assign these to variables like the IR readings so for all three sensors we would have something like;

Code:


$pingleftreading = GetPing($trigleft, $echoleft)
$pingcenterreading = GetPing($trigcenter, $echocenter)
$pingrightreading = GetPing($trigright, $echoright)


But, we only want those commands run if the configuration says so. The same goes for the IR code. So we add in another IF to check on the option and run the code if it is turned on.

Code:


IF($irsensor = 1)
$irleftreading = GetADC($irleft)
$ircenterreading = GetADC($ircenter)
$irrightreading = GetADC($irright)
ENDIF
IF($pingsensor = 1)
$pingleftreading = GetPing($trigleft, $echoleft)
$pingcenterreading = GetPing($trigcenter, $echocenter)
$pingrightreading = GetPing($trigright, $echoright)
ENDIF


So now the code to check the ADC and Ping will only run if the configuration is set to check them. And that's almost it for the sensorcheck sub routine, all that is left is the code to run the runaway code;

Code:


IF($irleftreading > $maxirleft or $ircenterreading > $maxircenter or $irrightreading > $maxirright)
GOTO(runaway)
ENDIF


Simply add it to the above code;

Code:


IF($irsensor = 1)
$irleftreading = GetADC($irleft)
$ircenterreading = GetADC($ircenter)
$irrightreading = GetADC($irright)
IF($irleftreading > $maxirleft or $ircenterreading > $maxircenter or $irrightreading > $maxirright)
GOTO(runaway)
ENDIF
ENDIF
IF($pingsensor = 1)
$pingleftreading = GetPing($trigleft, $echoleft)
$pingcenterreading = GetPing($trigcenter, $echocenter)
$pingrightreading = GetPing($trigright, $echoright)
IF($pingleftreading < $maxpingleft or $pingcenterreading < $maxpingcenter or $pingrightreading < $maxpingright)
GOTO(runaway)
ENDIF
ENDIF


Now the code will check the sensors as specified in the config and if any of them fall within the conditions it will run the runaway code.

So now we need to look at the runaway code. The final part of this.

Code:


:runaway
IF($irleftreading > $ircenterreading and $irleftreading > $irrightreading)
RIGHT($turnspeed, $turnlength)
ELSEIF($ircenterreading > $irleftreading and $ircenterreading > $irrightreading)
LEFT($turnspeed, $turnlength)
ELSE
LEFT($turnspeed, $turnlength)
ENDIF
FORWARD($forwardspeed, $forwardlength)
RETURN()


So it's already set up for the IR sensors from Part 4 but we need to add in the same kind of checks as the sensorcheck code had added while on the other hand avoiding any rouge commands from unused sensors. A few more IFs come in to play here again, just like the sensorcheck.

Code:


:runaway
IF($irsensor = 1)
IF($irleftreading > $ircenterreading and $irleftreading > $irrightreading)
RIGHT($turnspeed, $turnlength)
ELSEIF($ircenterreading > $irleftreading and $ircenterreading > $irrightreading)
LEFT($turnspeed, $turnlength)
ELSEIF($irrightreading > $irleftreading and $irrightreading > $ircenterreading)
LEFT($turnspeed, $turnlength)
ENDIF
ENDIF
IF($pingsensor = 1)
IF($pingleftreading < $pingcenterreading and $pingleftreading < $pingrightreading)
RIGHT($turnspeed, $turnlength)
ELSEIF($pingcenterreading < $pingleftreading and $pingcenterreading < $pingrightreading)
LEFT($turnspeed, $turnlength)
ELSEIF($pingrightreading < $pingleftreading and $pingrightreading < $pingcenterreading)
LEFT($turnspeed, $turnlength)
ENDIF
ENDIF
FORWARD($forwardspeed, $forwardlength)
RETURN()


And then put all of that together and you have the final code for Part 6

Code:


# Scaredy Cat Robot Script
# Version 1.4

# Script configuration - change the values below to suit
# Options
$irsensor = 1 # Change for if to use IR sensors 0 = off 1 = on
$pingsensor = 1 # Change for if to use Ultrasonic Ping sensors 0 = off 1 = on
$onlyforwards = 0 # Change for if only to run while moving forwards 0 = off 1 = on
$turndirection = 0 # Change for turn direction when applicable 0 = left 1 = right

# Movement Configuration
$delay = 1000 # Change for delay between reading distance
$turnspeed = 255 # Change for turn speed (1-255)
$turnlength = 1800 # Change for length of turn in ms
$forwardspeed = 255 # Change for forward speed (1-255)
$forwardlength = 5000 # Change for length of forward movement in ms

# Port Configuration
$trigleft = D0 # Change to required Digital port for Left Trigger if required
$echoleft = D1 # Change to required Digital port for Left Echo if required
$trigcenter = D2 # Change to required Digital port for Center Trigger if required
$echocenter = D3 # Change to required Digital port for Center Echo if required
$trigright = D4 # Change to required Digital port for Right Trigger if required
$echoright = D5 # Change to required Digital port for Right Echo if required

$irleft = ADC0 # Change to required ADC port for left IR sensor if required
$ircenter = ADC1 # Change to required ADC port for center IR sensor if required
$irright = ADC2 # Change to required ADC port for right IR sensor if required

# Sensitivity Configuration
$maxirleft = 50 # Change for the maximum value for the left IR sensor if applicable
$maxircenter = 50 # Change for the maximum value for the center IR sensor if applicable
$maxirright = 50 # Change for the maximum value for the right IR sensor if applicable
$maxpingleft = 200 # Change for the maximum value for the left Ping sensor if applicable
$maxpingcenter = 200 # Change for the maximum value for the center Ping sensor if applicable
$maxpingright = 200 # Change for the maximum value for the right Ping sensor if applicable

# Do not change anything below this line

:loop
IF ($onlyforwards=1)
IF ($direction="forward")
GOTO(sensorcheck)
ENDIF
ELSE
GOTO(sensorcheck)
ENDIF
GOTO(loop)

:runaway
IF ($irsensor = 1)
IF ($irleftreading > $ircenterreading and $irleftreading > $irrightreading)
RIGHT($turnspeed, $turnlength)
ELSEIF ($ircenterreading > $irleftreading and $ircenterreading > $irrightreading)
LEFT($turnspeed, $turnlength)
ELSEIF ($irrightreading > $irleftreading and $irrightreading > $ircenterreading)
LEFT($turnspeed, $turnlength)
ENDIF
ENDIF
IF ($pingsensor = 1)
IF ($pingleftreading < $pingcenterreading and $pingleftreading < $pingrightreading)
RIGHT($turnspeed, $turnlength)
ELSEIF ($pingcenterreading < $pingleftreading and $pingcenterreading < $pingrightreading)
LEFT($turnspeed, $turnlength)
ELSEIF ($pingrightreading < $pingleftreading and $pingrightreading < $pingcenterreading)
LEFT($turnspeed, $turnlength)
ENDIF
ENDIF
FORWARD($forwardspeed, $forwardlength)
RETURN()

:sensorcheck
IF ($irsensor = 1)
$irleftreading = GetADC($irleft)
$ircenterreading = GetADC($ircenter)
$irrightreading = GetADC($irright)
IF ($irleftreading > $maxirleft or $ircenterreading > $maxircenter or $irrightreading > $maxirright)
GOTO(runaway)
ENDIF
ENDIF
IF ($pingsensor = 1)
$pingleftreading = GetPing($trigleft, $echoleft)
$pingcenterreading = GetPing($trigcenter, $echocenter)
$pingrightreading = GetPing($trigright, $echoright)
IF ($pingleftreading < $maxpingleft or $pingcenterreading < $maxpingcenter or $pingrightreading < $maxpingright)
GOTO(runaway)
ENDIF
ENDIF
SLEEP($delay)
RETURN()


Now I have deliberately left one minor bug in the code somewhere. I will reveal it and tackle it in a later post but I figured if I was getting tired of writing this then you would be getting tired of reading it, so digest the above until next time. See if you can find the bug and feel free to post about it (I leave myself open for other bugs doing this but hey, all of us are learning including me).

Adding in test mode may well be the next part and overcoming the minor bug mentioned. Both should tie in nicely together.

As always this script example, while will run fine and function correctly is not supposed to be a working example for a useful function but supposed to explain the methods used to have actions and commands run depending on circumstance.
#25  
I would like to see a script in digital outputs for bcd decoding
I have a project that needs to decode a digital circuit using bcd 1,2,4 and 8 using 4 digital I/0.

ANY help would be cool
United Kingdom
#26  
Also, just to answer any questions anyone may be thinking about "Why would I want to allow for two different types of sensors in my robot?" since I've not addressed that yet other than purely for flexibility in sharing scripts.

It's leading up to this but with the variables and the IF nests to only check and run code depending on the variable we will eventually be able to use $time and $date or even other sensors, locations etc. to have the robot decide for itself which sensors to use.

A typical example is the IR sensor which dislikes natural light, or sunlight. Not a problem in the UK, we haven't seen the sun other than in movies or on TV. But if it's daytime you could have your robot only use the UltraSonic sensors. When it gets dark out it changes over to IR.
#27  
I don't see where you're enabling the "Runaway" script...no GOTO(runaway). Is that the bug?
United Kingdom
#28  
Have I missed that?.. Oops... time for an edit (the disadvantage of doing it in parts and having to piece it back together)

That wasn't it, although good eye:) It seems I completely messed up the :sensorcheck part somehow...

All fixed:) I just messed up the :sensorcheck subroutine in the final script. The call for runaway was in the snippets above it all but I copied and pasted the wrong bits. And that's why it pays to triple check before posting.
#29  
Thanks for these lessons Rich. They will be tremendously helpful to me during the next stage of my build. You are providing us with a stepping stone into the wonderful world of scripting and I am grateful for that. I am sure I will have many questions for you :D

I am following your robot build with great interest. It's going to be very cool.


Rex
Spain
#30  
Rich's work is always impressive, I think it's a good job for everyone, you could afford to order some customized shirts with the words "Doctor script"
:)
United Kingdom
#31  
It fills me with joy whenever I read how well received this is. They do say that helping is it's own reward and I have to admit they were right when they said that. Besides, it is something that I can get lost in and it helps me unwind and escape, forgetting the problems of the day:)

And additionally, if it results in more people being able to put together scripts it means there are going to be loads of scripts for all to use, all doing different awesome functions.

I have plenty of plans for the small tutorials so expect them to continue coming for a while longer yet. There are things I've not yet touched on, there are things I have not even used myself yet but all will be covered eventually.

I'm waiting on my serial LCD display currently, I have a few plans for tutorials for using one of those with variables and making it display information or even animate text (if I can figure it out myself - I wont know until it turns up though).

Math functions are also something I want to cover too. The idea from the ping avoidance with sweeping servo script for having the robot center itself in a corridor is one I can't wait to explore and sharing that should be both informative and fun.

The best thing though is by explaining each step of the way I am finding I learn more too, and it gets committed to memory. Which is great as I can write script ideas while at work and figure out what's required, in what order etc.

Once again, thank you everyone for the kind words, they mean a lot. It's nice to see the appreciation after some things that have been popping up recently.
United Kingdom
#32  
Part 7 - IF conditions

Quote:

Now I have deliberately left one minor bug in the code somewhere. I will reveal it and tackle it in a later post but I figured if I was getting tired of writing this then you would be getting tired of reading it, so digest the above until next time. See if you can find the bug and feel free to post about it


While a big bug was spotted it wasn't the one I was referring to. But due to the way I am writing these I kinda messed up while piecing the code back together - the code in the project file on the EZ-Cloud was correct (in my defence).

But the bug I was referring to is in this part of the code;

Code:


:runaway
IF ($irsensor = 1)
IF ($irleftreading > $ircenterreading and $irleftreading > $irrightreading)
RIGHT($turnspeed, $turnlength)
ELSEIF ($ircenterreading > $irleftreading and $ircenterreading > $irrightreading)
LEFT($turnspeed, $turnlength)
ELSEIF ($irrightreading > $irleftreading and $irrightreading > $ircenterreading)
LEFT($turnspeed, $turnlength)
ENDIF
ENDIF
IF ($pingsensor = 1)
IF ($pingleftreading < $pingcenterreading and $pingleftreading < $pingrightreading)
RIGHT($turnspeed, $turnlength)
ELSEIF ($pingcenterreading < $pingleftreading and $pingcenterreading < $pingrightreading)
LEFT($turnspeed, $turnlength)
ELSEIF ($pingrightreading < $pingleftreading and $pingrightreading < $pingcenterreading)
LEFT($turnspeed, $turnlength)
ENDIF
ENDIF
FORWARD($forwardspeed, $forwardlength)
RETURN()


What could happen is a double runaway. The code first checks if IR sensors are active, if they are it will check to see which way to run away. Execute the run away (if required) and then check if Ping sensors are active, if they are will run away again.

I left this in as it lead on to the next part I wish to explain and example. The conditions that can be used within IF commands.

If we refer to the EZ-Script manual under IF we are told that;

Quote:

If (Value Condition Value )
IF condition can support multiple comparisons and functions.
Condition tree must be closed with an ENDIF
See the Functions section of this document.
Condition can be =, <, >, <=, >=, <>, AND, OR

I'm assuming the forums have replaced some of the conditions due to the formatting, but if it has just look in the EZ-Script Reference Manual. You will find it on page 5.

The conditions we need to look at are AND and OR. We want to combine the code above so that if both sensor types are enabled it will perform an AND and an OR check. Currently it just checks for AND, to ensure that two of the sensors are either higher or lower than the other (depending on sensor type) to determine which sensor has the closest proximity.

Using AND and OR in the same condition is pretty straight forward but you must write the condition correctly. Think about it logically, imagine someone is giving you instruction for instance "if the time is 12am and it's a monday or if the time is 4am and it's a saturday you should be asleep in bed" two separate conditions combined in one. It wouldn't make much sense if it was "if the time is 12am or the time is 4am and it's a monday or a saturday..."as you wouldn't know which time goes with which day.

So, let's take a look at the code and change it to avoid the bug. My way of doing this may be different to someone else's way but I'm a firm believer in stick with what you know. My way would be to adjust the whole routine and rather than use two different IF conditions which run one after the other to use one IF condition with ELSEIF so that if the first is true then the rest don't matter, if the first is false it checks the second, and so on.

We will also need to add in a further condition to check if both sensor types are to be used. In an effort to save the post becoming very long I will only post the outline of the code for now.

Code:


:runaway
IF ($irsensor = 1 and $pingsensor = 1)
# Run code for both sensors
ELSEIF ($irsensor = 1)
# Run code for only the IR sensor
ELSEIF ($pingsensor = 1)
# Run code for only the Ping sensor
ENDIF
FORWARD($forwardspeed, $forwardlength)
RETURN()


So now the code will have a choice of three options. The final ELSEIF could be just an ELSE, I prefer ELSEIF to ensure it only runs if the condition is met, it's personal preference really.

The code within the ELSEIF ($irsensor = 1) and ELSEIF ($pingsensor = 1) remains as it was however in the new code for both sensors at once we will need to combine the two.

This is where the AND and OR conditions come in to play. We need to work out what it is that needs to be true to run what code.

We know that;
If the left hand sensors detect proximity we need to move right
If the center sensors detect proximity we need to move left
If the right hand sensors detect proximity we need to move left

We also know that;
If the left hand IR reading is higher than the center IR reading and the left hand IR reading is higher than the right hand IR reading then something is to the left.
If the left hand Ping reading is lower than the center ping reading and the left hand Ping reading is lower than the right hand Ping reading then something is to the left.
If the center IR reading is higher than the left hand IR reading and the center IR reading is higher than the right hand IR reading then something is in front.
If the center Ping reading is lower than the left hand Ping reading and the center Ping reading is lower than the right hand Ping reading then something is in front.
If the right hand IR reading is higher than the left hand IR reading and the right hand IR reading is higher than the center IR reading then something is to the right.
If the right hand Ping reading is lower than the left hand Ping reading and the right hand Ping reading is lower than the center Ping reading then something is to the right.

So let's put that as IF conditions (very long if conditions);

Code:


IF ($irleftreading > $ircenterreading and $irleftreading > $irrightreading or $pingleftreading < $pingcenterreading and $pingleftreading < $pingrightreading)
# Something is to the left
ELSEIF ($ircenterreading > $irleftreading and $ircenterreading > $irrightreading or $pingcenterreading < $pingleftreading and $pingcenterreading < $pingrightreading)
# Something is in front
ELSEIF ($irrightreading > $irleftreading and $irrightreading > $ircenterreading or $pingrightreading < $pingleftreading and $pingrightreading < $pingcenterreading)
# Something is to the right
ENDIF


So now it checks if the left IR is higher than the other two or the left Ping is lower than the other two. The same for the center and the same for the right.

And then it is just a case of adding in the code for turning the robot in the right direction, and putting it all back together:)

Also, the sensorcheck code needs a slight adjustment;

Code:


:sensorcheck
IF ($irsensor = 1)
$irleftreading = GetADC($irleft)
$ircenterreading = GetADC($ircenter)
$irrightreading = GetADC($irright)
IF ($irleftreading > $maxirleft or $ircenterreading > $maxircenter or $irrightreading > $maxirright)
GOTO(runaway)
ENDIF
ENDIF
IF ($pingsensor = 1)
$pingleftreading = GetPing($trigleft, $echoleft)
$pingcenterreading = GetPing($trigcenter, $echocenter)
$pingrightreading = GetPing($trigright, $echoright)
IF ($pingleftreading < $maxpingleft or $pingcenterreading < $maxpingcenter or $pingrightreading < $maxpingright)
GOTO(runaway)
ENDIF
ENDIF
SLEEP($delay)
RETURN()


This code will currently run checks on the IR if applicable, then could run the runaway code without knowing the ping sensor readings. Then it will run the runaway code after receiving the Ping sensor readings again (if applicable), that's if it hasn't halted on error.

To overcome it is very simple with IF. First we need to check which sensors are active with the

Code:


IF ($irsensor = 1 and $pingsensor = 1)
ELSEIF ($irsensor = 1)
ELSEIF ($pingsensor = 1)
ENDIF

much like in the above routine.

Then the required code for checking only the sensors used added in to the IF and ELSEIF conditions, with the code for both sensors having the IF condition for running the runaway code checking all three IR sensors and all three Ping sensors, if any are true then runaway.

Code:


:sensorcheck
IF ($irsensor = 1 and $pingsensor = 1)
$irleftreading = GetADC($irleft)
$ircenterreading = GetADC($ircenter)
$irrightreading = GetADC($irright)
$pingleftreading = GetPing($trigleft, $echoleft)
$pingcenterreading = GetPing($trigcenter, $echocenter)
$pingrightreading = GetPing($trigright, $echoright)
IF ($irleftreading > $maxirleft or $ircenterreading > $maxircenter or
$irrightreading > $maxirright or $pingleftreading < $maxpingleft or
$pingcenterreading < $maxpingcenter or $pingrightreading < $maxpingright)
GOTO(runaway)
ENDIF
ELSEIF ($irsensor = 1)
$irleftreading = GetADC($irleft)
$ircenterreading = GetADC($ircenter)
$irrightreading = GetADC($irright)
IF ($irleftreading > $maxirleft or $ircenterreading > $maxircenter or $irrightreading > $maxirright)
GOTO(runaway)
ENDIF
ELSEIF ($pingsensor = 1)
$pingleftreading = GetPing($trigleft, $echoleft)
$pingcenterreading = GetPing($trigcenter, $echocenter)
$pingrightreading = GetPing($trigright, $echoright)
IF ($pingleftreading < $maxpingleft or $pingcenterreading < $maxpingcenter or $pingrightreading < $maxpingright)
GOTO(runaway)
ENDIF
ENDIF
SLEEP($delay)
RETURN()


You could, if you wanted to, add in two new sub routines for getting the Ping and getting the IR sensor readings and replacing the code for Gotos however with only using the same code twice I have opted to just add it in twice. It's personal preference, personally once or twice I will type it all out, three or more and I like to make sub routines. I digress, but if you want to test what you are learning a good exercise would be to make the routines and call them up.

Now that the sensorcheck code is also fixed it's time to piece all of the bug fixed code together. You should end up with something a little bit like this;

Code:


# Scaredy Cat Robot Script
# Version 1.5

# Script configuration - change the values below to suit
# Options
$irsensor = 1 # Change for if to use IR sensors 0 = off 1 = on
$pingsensor = 1 # Change for if to use Ultrasonic Ping sensors 0 = off 1 = on
$onlyforwards = 0 # Change for if only to run while moving forwards 0 = off 1 = on
$turndirection = 0 # Change for turn direction when applicable 0 = left 1 = right

# Movement Configuration
$delay = 1000 # Change for delay between reading distance
$turnspeed = 255 # Change for turn speed (1-255)
$turnlength = 1800 # Change for length of turn in ms
$forwardspeed = 255 # Change for forward speed (1-255)
$forwardlength = 5000 # Change for length of forward movement in ms

# Port Configuration
$trigleft = D0 # Change to required Digital port for Left Trigger if required
$echoleft = D1 # Change to required Digital port for Left Echo if required
$trigcenter = D2 # Change to required Digital port for Center Trigger if required
$echocenter = D3 # Change to required Digital port for Center Echo if required
$trigright = D4 # Change to required Digital port for Right Trigger if required
$echoright = D5 # Change to required Digital port for Right Echo if required

$irleft = ADC0 # Change to required ADC port for left IR sensor if required
$ircenter = ADC1 # Change to required ADC port for center IR sensor if required
$irright = ADC2 # Change to required ADC port for right IR sensor if required

# Sensitivity Configuration
$maxirleft = 50 # Change for the maximum value for the left IR sensor if applicable
$maxircenter = 50 # Change for the maximum value for the center IR sensor if applicable
$maxirright = 50 # Change for the maximum value for the right IR sensor if applicable
$maxpingleft = 200 # Change for the maximum value for the left Ping sensor if applicable
$maxpingcenter = 200 # Change for the maximum value for the center Ping sensor if applicable
$maxpingright = 200 # Change for the maximum value for the right Ping sensor if applicable

# Do not change anything below this line

:loop
IF ($onlyforwards=1)
IF ($direction="forward")
GOTO(sensorcheck)
ENDIF
ELSE
GOTO(sensorcheck)
ENDIF
GOTO(loop)

:runaway
IF ($irsensor = 1 and $pingsensor = 1)
IF ($irleftreading > $ircenterreading and $irleftreading > $irrightreading or $pingleftreading < $pingcenterreading and pingleftreading < $pingrightreading)
RIGHT($turnspeed, $turnlength)
ELSEIF ($ircenterreading > $irleftreading and $ircenterreading > $irrightreading or $pingcenterreading < pingleftreading and $pingcenterreading < $pingrightreading)
LEFT($turnspeed, $turnlength)
ELSEIF ($irrightreading > $irleftreading and $irrightreading > $ircenterreading or $pingrightreading < $pingleftreading and $pingrightreading < $pingcenterreading)
LEFT($turnspeed, $turnlength)
ENDIF
ELSEIF ($irsensor = 1)
IF ($irleftreading > $ircenterreading and $irleftreading > $irrightreading)
RIGHT($turnspeed, $turnlength)
ELSEIF ($ircenterreading > $irleftreading and $ircenterreading > $irrightreading)
LEFT($turnspeed, $turnlength)
ELSEIF ($irrightreading > $irleftreading and $irrightreading > $ircenterreading)
LEFT($turnspeed, $turnlength)
ENDIF
ELSEIF ($pingsensor = 1)
IF ($pingleftreading < $pingcenterreading and $pingleftreading < $pingrightreading)
RIGHT($turnspeed, $turnlength)
ELSEIF ($pingcenterreading < $pingleftreading and $pingcenterreading < $pingrightreading)
LEFT($turnspeed, $turnlength)
ELSEIF ($pingrightreading < $pingleftreading and $pingrightreading < $pingcenterreading)
LEFT($turnspeed, $turnlength)
ENDIF
ENDIF
FORWARD($forwardspeed, $forwardlength)
RETURN()

:sensorcheck
IF ($irsensor = 1 and $pingsensor = 1)
$irleftreading = GetADC($irleft)
$ircenterreading = GetADC($ircenter)
$irrightreading = GetADC($irright)
$pingleftreading = GetPing($trigleft, $echoleft)
$pingcenterreading = GetPing($trigcenter, $echocenter)
$pingrightreading = GetPing($trigright, $echoright)
IF ($irleftreading > $maxirleft or $ircenterreading > $maxircenter or
$irrightreading > $maxirright or $pingleftreading < $maxpingleft or
$pingcenterreading < $maxpingcenter or $pingrightreading < $maxpingright)
GOTO(runaway)
ENDIF
ELSEIF ($irsensor = 1)
$irleftreading = GetADC($irleft)
$ircenterreading = GetADC($ircenter)
$irrightreading = GetADC($irright)
IF ($irleftreading > $maxirleft or $ircenterreading > $maxircenter or $irrightreading > $maxirright)
GOTO(runaway)
ENDIF
ELSEIF ($pingsensor = 1)
$pingleftreading = GetPing($trigleft, $echoleft)
$pingcenterreading = GetPing($trigcenter, $echocenter)
$pingrightreading = GetPing($trigright, $echoright)
IF ($pingleftreading < $maxpingleft or $pingcenterreading < $maxpingcenter or $pingrightreading < $maxpingright)
GOTO(runaway)
ENDIF
ENDIF
SLEEP($delay)
RETURN()
United Kingdom
#33  
Ignore this, the forum update fixed the problem. I'll use this post for something else:)
#34  
Wow! Thanks so much for taking the time to do this:) Im on a 2 week vacation and had planned out my days accordingly, each with a new set of tasks with the EZB4 Kit.
Today and tomorrow were nothing but scripting basics, but was feeling a little lost. I've worked with Arduino and C++ a bit, and with tons of tutorials and videos available it was simple to get started with the basic principles do's and dont's.
Now I've found my lesson plan in your Lesson/Thread!
Blown away everyday by such an community and product! DJ, keep up the amazing work that you do! Love your passion:)
#35  
If you can write C++ code for Arduino, you will find EZ-Robot scripting to be a piece of cake. It is much simpler.

That being said, it is possible you will find something you can't do. If that happens, there is a .NET SDK that can either totally replace ARC (lots of work) or communicate with ARC (in my opinion, the preferred direction).

About the only thing that an Arduino can do that would be very difficult with an EZ-B are very timing sensitive automation actions like a balance bot. However, if you you find you need something like that you could combine your existing Arduino skills with your new EZ-Robot skills by having the two devices communicate with each other via the UART port, so EZ give the commands and Arduino follows them and returns data. @Luis Vazquez gives a great example here: http://www.ez-robot.com/Community/Forum/Thread?threadId=6577

Alan
#36  
Thanks:) Yes, im finding that as i move through the Tutorial, again, awesome job DJ!, great product. And the combination of the EZB4 and the Arduino is exactly the direction of the project.
The Master controller is the EZB4 of course, but many functions will be handled by Arduinos coupled with a PCduino to allow multi platform programming to access/control various parts of the robot.
Simple thing, rules can trip people up when learning a programming language, such as,

int yellowOnTime=250

Example: Once you know it, it seems obvious, but knowing that a Cap letter must used in the word On and Time in this string is a must, but without knowing that it is an actual rule, you could easily mistake it for a typo, an not realize how important it is. "basic principles do's and dont's".

So thats my mission today, is to understand the basic elements, and rules.
#37  
Great comment about programming language rules. In EZ-Script, case sensitivity is not a rule. Where you see mixed case it is just for better readability. Proper use of parentheses, commas and quotation marks is where a lot of people get messed up.

Alan
#38  
I can see this to be very true. But the way DJ set this up with IntelliSense like programs like Atmel Studio, It will reduce the mistakes to a minimum. But oddly enough that seems to be half the fun when learning, is hunting down and finding that tiny little mistake:)
#40  
It would not take much to change the script commands that use speech to instead use ControlCommand to the soundboard using variables to decide which MP3 to play. I wasn't offering it up as a complete solution, but rather a direction.

If you want me (or Rich) to write the script for you, I can add it to my already too long todo list, but you could figure it out a lot faster than waiting on me to get around to doing it for you;)

Alan
#41  
@Rich Hope I'm not missing it, getting tired :O But i noticed that the proxsense isn't declared in your variables list. Is there a reason why it isn't really necessary?
United Kingdom
#42  
You only need to declair variables before they are used. You don't need to declair all variables at the start of a script.

Proxsense is the value of the sensor and is fetched from the sensor so doesn't need the initial declaration.


@Anthony, that would be a very simple script adaptation to the time script I posted a few weeks back. The sound file played back can be a variable. Use ifs to piece together yhe phrase and ControlCommand to make it play the correct files in the correct order. It wont be as fluid as text to speech though.

I'm still away at the moment but when I get back home I'll add it to the to do list.
#43  
Ah ok, Loving this! Thanks Rich:)