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.
$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;
$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.
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;
$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.
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.
FORWARD(255,5000)
And that's it. As simple as that. So the code so far should look like;
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_LabelGoto( 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;
:runaway
LEFT(255,1800)
FORWARD(255,5000)
RETURN()
And then we add in the Goto to the first part of the code we wrote;
$proxsense = GetADC(adc0)
$proxclose = 50
IF($proxsense > $proxclose)
GOTO(runaway)
ENDIF
And when we put it all together;
$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.
: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.
: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.
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.
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,
[email protected], 602-246-1246(H)
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.
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 ?
[email protected], 602-246-1246(H)
P.S. This would solve your Employment Problem with EZ-Robot.com, and SOLVE The Long Commute !
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.
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.
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;
First let's think about the configuration variables;
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;
For good measure, and in case it needs tweaking on individual sensors the $proxclose variable is also to be renamed and two extra added;
Throw it all together and we have;
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.
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.
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
Or we can do it by checking one, then the other, then the last with IF and ELSEIF
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
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.
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;
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.