Spain
Asked — Edited

Script Manager And Script Pauseon

You can pause a script and then unpause? I'm trying to run my personal radar control and I have a script that moves the servo ping sensor, but I would like to pause the movement when turning to avoid obstacle and then unpause to move forward. I have proven this if successful: CC ("Script Manager" ScriptPauseOn, "radar") Not if it is misspelled or does not exist the command "PauseOn" for Script Manager I have also proven with the command PauseMS but seems not to work. Thanks in advance for your answers :)


ARC Pro

Upgrade to ARC Pro

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

United Kingdom
#1  

Try PauseOn rather than ScriptPauseOn. I don't know if it'll work, I am guessing based on the documentation for EZ-Script. All I have personally used are ScriptStart and ScriptStop.

Could you not add in an IF to the script to only execute the commands IF($direction = "forward")?

Spain
#2  

I can only say one thing: you're a genius Rich, PauseOn not work but if you have had success: IF ($ direction = "forward") at the top of the script of radar, and Endif below. I'm getting closer to my personal radar, just polish some details, Thank you!

Spain
#3  

Now is also the script ping servo motion:

User-inserted image

Only not really pause the program, rather what for and when you run it again it does in the last position that was left, but starts from the beginning. This makes the robot in a loop between senseless and not be able to exit a corner quickly. I'll try to add up the total travel time of the radar (1360ms) in a complete cycle, and set the time and time reverse rotation of the robot to match the 1360ms, so maybe the ping sensor servo Start from the last position that was left.

United Kingdom
#4  

I'm sure we can fix it starting from the beginning too, I'm just short on time at the moment but will look when I get home later :)

United Kingdom
#5  

OK, so from what I understand you want the the servo to pan left and right while moving forwards and pause while turning or not moving? And then to continue from where it left off after pausing.

This one is pretty straight forward as it's going to need to move to one of 3 positions. Either 25, 52 or 77. The part to think about is the direction in which it needs to move when it hits the middle location, so a variable can be used to store the previous position.

First start with the label and goto;


:inicio
GOTO(inicio)

Now add in the code to only work while it is moving forwards using the $direction variable;


:inicio
IF($direction = "forward")
ENDIF
GOTO(inicio)

Now we need to make the new variable for the previous position;


:inicio
IF($direction = "forward")
$previousposition = GetServo(D14)
ENDIF
GOTO(inicio)

Next we want to tell it where to go based on current position and previous position


:inicio
IF($direction = "forward")
  IF(GetServo(D14) = 25)
    Servo(D14,52)
  ELSEIF(GetServo(D14) = 52 and $previousposition = 25)
    Servo(D14,77)
  ELSEIF(GetServo(D14) = 52 and $previousposition = 77)
    Servo(D14,25)
  ELSEIF(GetServo(D14) = 77)
    Servo(D14,52)
  ENDIF
$previousposition = GetServo(D14)
ENDIF
GOTO(inicio)

You will also need to add in a starting position for the servo to move to on first run;


$previousposition = 25
Servo(D14,52)
:inicio
IF($direction = "forward")
  IF(GetServo(D14) = 25)
    Servo(D14,52)
  ELSEIF(GetServo(D14) = 52 and $previousposition = 25)
    Servo(D14,77)
  ELSEIF(GetServo(D14) = 52 and $previousposition = 77)
    Servo(D14,25)
  ELSEIF(GetServo(D14) = 77)
    Servo(D14,52)
  ENDIF
$previousposition = GetServo(D14)
ENDIF
GOTO(inicio)

Due to position 52 requiring to know a previous position it's easier not to start at position 52 however adding in the $previousposition variable before the loop label avoids this complication.

And finally to let it sleep between moving, add in the comments if you like to and we have the final script that should only work when moving forwards, pause when stopped, turning left, turning right or reversing and then continue from where it left off when it resumes it's forward movement.


# Set a starting point for the servo
$previousposition = 25
Servo(D14,52)
# Set a loop label
:inicio
# Only execute the commands while moving forwards
IF($direction = "forward")
# Move the servo the correct direction and to the correct location
  IF(GetServo(D14) = 25)
    Servo(D14,52)
  ELSEIF(GetServo(D14) = 52 and $previousposition = 25)
    Servo(D14,77)
  ELSEIF(GetServo(D14) = 52 and $previousposition = 77)
    Servo(D14,25)
  ELSEIF(GetServo(D14) = 77)
    Servo(D14,52)
  ENDIF
  $previousposition = GetServo(D14)
ENDIF
SLEEP(340)
GOTO(inicio)

This will initially set the servo to position 52 and tell it that the previous position was 25. When movement forwards begins it will look up the servo position, check it and see it's 52. It will then check the $previousposition and see it is 25 therefore moving D14 to position 77.

From there it will check again, see that D14 is in position 77 and move to position 52.

Then it will check again, see D14 in position 52 and the previous position is 77 so will execute the command to move the servo to position 25.

And so on :)

Spain
#6  

Fantastic answer, I will try to assimilate the program and prove it tomorrow, anyway I'll have to integrate the scripts which takes a turn when the ping sensor provides a reading of less than 10 inches (for example), I have a script for the center , another dash to the left and one for the right script, plus I have another script to move the ping sensor servo Then I have another script that activates all scripts and another script that paralyzes all Will attach the file so that you can visualize. And thank you very much for the research and development work :)

United Kingdom
#8  

I will check it out later. And no thanks are necessary, I find scripting very enjoyable and soothing :-)

United Kingdom
#9  

Edit: Scrap all I just said (which you can't see now as I'm editing the post :))

Why not use the Radar Scan control? It should do most, if not all of what you want.

Spain
#10  

The control "Radar Scan" is great, and corrects the direction to the opposite side of the obstacle (guess which bisects the "cone" or total angle radar scan, and take decisions based on that half of the sweep is) My idea is to divide the total sweep angle in three parts

  • left
  • center
  • right User-inserted image

To take advantage of the ability to decide to stand in the front, does not have to be a left or right turn or have to be equal-time spin, reverse or detected distance, can be a script that includes a complete maneuver to dodge . I also like the idea of experimenting with a single ping sensor, while I practice and learn ez-scripts :)

United Kingdom
#11  

Fair enough :)

It would probably pay to look at my IR detection script and adjust it to suit. Using GetPing rather than GetADC and adding in some servo movement parts.

IR Object Avoidance

Also, my introduction to scripting was written around an IR detection script but explained a lot better.

An Introduction To Scripting

United Kingdom
#12  

It looks like today will be a busy day so I'll break it up in to smaller chunks.

The IR Object Avoidance script converted to Ping/Echo.


# Ping Object Avoidance
# Using Ultra Sonic Ping Sensor on servo for avoidance

# Adjust values below for configuration
$pingport = D0 # Change for Ping Port
$echoport = D1 # Change for Echo Port
$maxdistance = 35 # Change for maximum distance from object before avoiding in units
$onlyforward = 0 # Only if moving forwards? 0 = no, 1 = yes
$reverseturn = 0 # Reverse before turn? 0 = no, 1 = yes
$centreturndirection = 0 # Change 0 = left or 1 = right
$turnamount = 500 # Change for how long to turn for in ms
$reverseamount = 500 # Change for how long to reverse for in ms (if applicable)
$movementspeed = 255 # Change for movement speed


# -- The Script --

# Check if only to detect when moving forwards
:detect
IF ($onlyforward = 1)
  IF ($Direction = "Forward")
    GOTO (detectstart)
  ELSE 
    GOTO (detect)
  ENDIF 
ELSE 
  :detectstart
  $currentdistance = GetPing($pingport, $echoport)
  IF ($currentdistance <= $maxdistance)
    GOTO(avoid)
  ENDIF 
  SLEEP (50)
  GOTO(detect)
ENDIF 

# The avoidance script
:avoid
IF ($reverseturn = 1)
  reverse($movementspeed,$reverseamount)
ENDIF 
IF ($centreturndirection = 0)
  LEFT($movementspeed,$turnamount)
ELSE 
  RIGHT($movementspeed,$turnamount)
ENDIF 
RETURN()

Next we need to add in the servo sweep code which shouldn't be too difficult, then have it check the servo position to determine if it's a left or a right turn that is needed, and even by how much with a bit more code too.

United Kingdom
#13  

NOTE: This has been done in bits while working on other things and is unchecked. I will check it later when I get home however until then I cannot be 100% certain it is correct (it should be).

The code for sweeping the servo to the correct location, in the right direction.


# New variables for the top of the script
$sweepmin = 25 # Change for min limit
$sweepmax = 77 # Change for max limit
$sweepcenter = 52 # Change for center position
$sweepservo = "D3" # Change for servo port
$sweepprevious = "none" # Do not change

# The sweep sub routine to be inserted at the end of the script
:sweep

# Check for previous position, if no position assume to be $sweepmax
IF($sweepprevious = "none")
  $sweepprevious = $sweepmax
ENDIF

# Get the current position
$sweepcurrent = GetServo($sweepservo)

# Move in the correct direction and store previous position
IF($sweepcurrent = $sweepmin)
  $sweepprevious = $sweepcurrent
  Servo($sweepservo, $sweepcenter)
ELSEIF($sweepcurrent = $sweepcenter and $sweepprevious = $sweepmin)
  $sweepprevious = $sweepcurrent
  Servo($sweepservo, $sweepmax)
ELSEIF($sweepcurrent = $sweepcenter and $sweepprevious = $sweepmax)
  $sweepprevious = $sweepcurrent
  Servo($sweepservo, $sweepmin)
ELSE
  $sweepprevious = $sweepcurrent
  Servo($sweepservo, $sweepcenter)
ENDIF

# Return back to the main script
Return()

This can then be called from the main script with a Goto(sweep) command. So the code now would look like this;


# Ping Object Avoidance
# Using Ultra Sonic Ping Sensor on servo for avoidance

# Adjust values below for configuration
$pingport = D0 # Change for Ping Port
$echoport = D1 # Change for Echo Port
$maxdistance = 35 # Change for maximum distance from object before avoiding in units
$onlyforward = 0 # Only if moving forwards? 0 = no, 1 = yes
$reverseturn = 0 # Reverse before turn? 0 = no, 1 = yes
$centreturndirection = 0 # Change 0 = left or 1 = right
$turnamount = 500 # Change for how long to turn for in ms
$reverseamount = 500 # Change for how long to reverse for in ms (if applicable)
$movementspeed = 255 # Change for movement speed

# Sweep variables
$sweepmin = 25 # Change for min limit
$sweepmax = 77 # Change for max limit
$sweepcenter = 52 # Change for center position
$sweepservo = "D3" # Change for servo port
$sweepprevious = "none" # Do not change

# -- The Script --

# Check if only to detect when moving forwards
:detect
IF ($onlyforward = 1)
  IF ($Direction = "Forward")
    GOTO (detectstart)
  ELSE 
    GOTO (detect)
  ENDIF 
ELSE 
  :detectstart
  $currentdistance = GetPing($pingport, $echoport)
  IF ($currentdistance <= $maxdistance)
    GOTO(avoid)
  ENDIF 

# Sweep the servo to the next position
  GOTO(sweep)

  SLEEP (50)
  GOTO(detect)
ENDIF 

# The avoidance script
:avoid
IF ($reverseturn = 1)
  reverse($movementspeed,$reverseamount)
ENDIF 
IF ($centreturndirection = 0)
  LEFT($movementspeed,$turnamount)
ELSE 
  RIGHT($movementspeed,$turnamount)
ENDIF 
RETURN()

# The sweep script

# Check for previous position, if no position assume to be $sweepmax
IF($sweepprevious = "none")
  $sweepprevious = $sweepmax
ENDIF

# Get the current position
$sweepcurrent = GetServo($sweepservo)

# Move in the correct direction and store previous position
IF($sweepcurrent = $sweepmin)
  $sweepprevious = $sweepcurrent
  Servo($sweepservo, $sweepcenter)
ELSEIF($sweepcurrent = $sweepcenter and $sweepprevious = $sweepmin)
  $sweepprevious = $sweepcurrent
  Servo($sweepservo, $sweepmax)
ELSEIF($sweepcurrent = $sweepcenter and $sweepprevious = $sweepmax)
  $sweepprevious = $sweepcurrent
  Servo($sweepservo, $sweepmin)
ELSE
  $sweepprevious = $sweepcurrent
  Servo($sweepservo, $sweepcenter)
ENDIF

# Return back to the main script
Return()

Next will be to determine the turn direction based on the sweep servo's location when an object is detected. Very simple to implement but I am out of time again so will cover that later.

United Kingdom
#14  

I have a few more minutes than what I thought so a few notes for myself about the next part, and the code will follow later on.

Because of how I wrote the script to start with the direction of turn is pretty easy to integrate.

It may not have made much sense until now why there was a variable for the centre turn direction, this will become apparent now. As when the sweep servo is in the centre position the turn direction could be either, depending on who writes the script. I always tend to turn left when centre as this is the direction I personally turn when I need to do a 180. However, a further idea that just popped in to my head is to check the left and right positions when a centre object is detected and use that information to determine the turn direction.

So what we need to do is figure out which area the object is in when detected. User-inserted image

For the purposes of this script I will assume the 0 position of the servo is on the left and 100 is on the right.

So first we need to think, if an object is in the left zone the robot doesn't want to turn towards it but needs to turn away from it, so turning right. If it's in the right zone then it needs to turn left. If it's in the centre zone we need to check both the left and the right zones and turn the opposite direction to where the object is. Not forgetting to move the sweep servo back to the centre position.

It's the avoidance script which now needs to be altered to suit this.


# The avoidance script
:avoid
IF ($reverseturn = 1)
  reverse($movementspeed,$reverseamount)
ENDIF 
IF ($centreturndirection = 0)
  LEFT($movementspeed,$turnamount)
ELSE 
  RIGHT($movementspeed,$turnamount)
ENDIF 
RETURN()

We will leave the reverse before turn option available as some like it, others can do without it but it's an option that is easily turned on or off from the configuration variables at the beginning of the script.

We can do away with the $centreturndirection variable if we opt for checking left and right after a centre detection.

We also need to decide of we want the robot to just turn and continue going straight on that new path or turn, move forward slightly and turn back. So either alter the path completely or adjust the path to go around the object. This option could be added in as a configuration variable and both pieces of code written, which would allow for extra code to be written which lets the robot decide based on information it receives. But for now I will just tackle the driving around the object code.

United Kingdom
#15  

Let's make changes to the avoidance routine to suit the new brief.

We want to turn right if the object is to the left;


IF($currentposition = $sweepmin)
  RIGHT($movementspeed,$turnamount)
ENDIF

And we want to turn left if the object is to the right;


IF($currentposition = $sweepmax)
  LEFT($movementspeed,$turnamount)
ENDIF

And for the middle zone we want to check left and right, return to the middle and move in the other direction to where the object is.


IF($currentposition = $sweepcenter)
  Servo($sweepservo,$sweepmin)
  $pingmin = GetPing($pingport, $echoport)
  Servo($sweepservo,$sweepmax)
  $pingmax = GetPing($pingport, $echoport)
  Servo($sweepservo,$sweepcenter)
  IF($pingmin > $pingmax)
    Goto(moveright)
  ELSE
    Goto(moveleft)
  ENDIF
ENDIF

For simplicity I've assumed the robot will move left if the object is dead centre in front and equal distance from both left and right. This can be improved but I will cover that at a later time.

To combine them for less code


IF($currentposition = $sweepmin)
  RIGHT($movementspeed,$turnamount)
ELSEIF($currentposition = $sweepmax)
  LEFT($movementspeed,$turnamount)
ELSE
  Servo($sweepservo,$sweepmin)
  $pingmin = GetPing($pingport, $echoport)
  Servo($sweepservo,$sweepmax)
  $pingmax = GetPing($pingport, $echoport)
  Servo($sweepservo,$sweepcenter)
  IF($pingmin > $pingmax)
    RIGHT($movementspeed,$turnamount)
  ELSE
    LEFT($movementspeed,$turnamount)
  ENDIF
ENDIF

Now to put it all together one more time and the new code should look like;


# Ping Object Avoidance
# Using Ultra Sonic Ping Sensor on servo for avoidance

# Adjust values below for configuration
$pingport = D0 # Change for Ping Port
$echoport = D1 # Change for Echo Port
$maxdistance = 35 # Change for maximum distance from object before avoiding in units
$onlyforward = 0 # Only if moving forwards? 0 = no, 1 = yes
$reverseturn = 0 # Reverse before turn? 0 = no, 1 = yes
# centreturndirection removed
$turnamount = 500 # Change for how long to turn for in ms
$reverseamount = 500 # Change for how long to reverse for in ms (if applicable)
$movementspeed = 255 # Change for movement speed

# Sweep variables
$sweepmin = 25 # Change for min limit
$sweepmax = 77 # Change for max limit
$sweepcenter = 52 # Change for center position
$sweepservo = "D3" # Change for servo port
$sweepprevious = "none" # Do not change

# -- The Script --

# Check if only to detect when moving forwards
:detect
IF ($onlyforward = 1)
  IF ($Direction = "Forward")
    GOTO (detectstart)
  ELSE 
    GOTO (detect)
  ENDIF 
ELSE 
  :detectstart
  $currentdistance = GetPing($pingport, $echoport)
  IF ($currentdistance <= $maxdistance)
    GOTO(avoid)
  ENDIF 

# Sweep the servo to the next position
  GOTO(sweep)

  SLEEP (50)
  GOTO(detect)
ENDIF 

# The avoidance script
:avoid
IF ($reverseturn = 1)
  reverse($movementspeed,$reverseamount)
ENDIF 
IF($currentposition = $sweepmin)
  RIGHT($movementspeed,$turnamount)
ELSEIF($currentposition = $sweepmax)
  LEFT($movementspeed,$turnamount)
ELSE
  Servo($sweepservo,$sweepmin)
  $pingmin = GetPing($pingport, $echoport)
  Servo($sweepservo,$sweepmax)
  $pingmax = GetPing($pingport, $echoport)
  Servo($sweepservo,$sweepcenter)
  IF($pingmin > $pingmax)
    RIGHT($movementspeed,$turnamount)
  ELSE
    LEFT($movementspeed,$turnamount)
  ENDIF
ENDIF
RETURN()

# The sweep script

# Check for previous position, if no position assume to be $sweepmax
IF($sweepprevious = "none"
  $sweepprevious = $sweepmax
ENDIF

# Get the current position
$sweepcurrent = GetServo($sweepservo)

# Move in the correct direction and store previous position
IF($sweepcurrent = $sweepmin)
  $sweepprevious = $sweepcurrent
  Servo($sweepservo, $sweepcenter)
ELSEIF($sweepcurrent = $sweepcenter and $sweepprevious = $sweepmin)
  $sweepprevious = $sweepcurrent
  Servo($sweepservo, $sweepmax)
ELSEIF($sweepcurrent = $sweepcenter and $sweepprevious = $sweepmax)
  $sweepprevious = $sweepcurrent
  Servo($sweepservo, $sweepmin)
ELSE
  $sweepprevious = $sweepcurrent
  Servo($sweepservo, $sweepcenter)
ENDIF

# Return back to the main script
Return()

As mentioned, again this us unchecked so may have some bugs and errors in it. Please feel free to check it for me, to use it, to alter it, to follow it and attempt to write it yourself. It is offered as an aid to help you learn.

I will revisit this again when I have more time to play and will test it when I have an EZB and battery which I can set up to test this.

Spain
#16  

The truth is that I'm impressed with your ability to this written code, and I like the idea of checking distances left and right when it detects an obstacle in front, I wanted to address this concept later but you've advance (things of genius). I copied and pasted your last code, and tested on ARC, the first error message told me that it was the "GOTO (sweep)", so I added "sweep" in this part assuming missing write here :

........................................................................................................

The sweep script

: sweep

Check for previous position, if position not assume to be $ sweepmax

IF ($ sweepprevious = "none") $ sweepprevious = $ sweepmax ENDIF

Get the current position

$ sweepcurrent = GetServo ($ sweepservo) ......................................................................................................... But then I have received this error when checking code in the console:

User-inserted image This looks like a great team, you can write code and I practiced so I test. :)

United Kingdom
#17  

Yeah you got me, I missed the :sweep and also missed a closed bracket on IF($sweepprevious = "none"

I know where the problem is, and I can't believe I did it...

The $sweepprevious is set to "none" near the start. It cannot then be changed to a number. Easy fix for that though.

Also I just found that I've got muddled with variable names too, so re-written to correct the minor mistakes (only variable names and rookie mistakes, the method displayed above is still correct but I'll correct that too when I get chance).

Bear with me while I correct the code and check it (this time)

United Kingdom
#18  

# Ping Object Avoidance
# Using Ultra Sonic Ping Sensor on servo for avoidance

# Adjust values below for configuration
$pingport = D0 # Change for Ping Port
$echoport = D1 # Change for Echo Port
$maxdistance = 35 # Change for maximum distance from object before avoiding in units
$onlyforward = 0 # Only if moving forwards? 0 = no, 1 = yes
$reverseturn = 0 # Reverse before turn? 0 = no, 1 = yes
# centreturndirection removed
$turnamount = 500 # Change for how long to turn for in ms
$reverseamount = 500 # Change for how long to reverse for in ms (if applicable)
$movementspeed = 255 # Change for movement speed

# Sweep variables
$sweepmin = 25 # Change for min limit
$sweepmax = 77 # Change for max limit
$sweepcenter = 52 # Change for center position
$sweepservo = "D3" # Change for servo port
$sweepprevious = 1000 # Do not change

# -- The Script --

GOTO(sweep)

# Check if only to detect when moving forwards
:detect
IF ($onlyforward = 1)
  IF ($Direction = "Forward")
    GOTO (detectstart)
  ELSE 
    GOTO (detect)
  ENDIF 
ELSE 
  :detectstart
  $currentdistance = GetPing($pingport, $echoport)
  IF ($currentdistance <= $maxdistance)
    GOTO(avoid)
  ENDIF 

# Sweep the servo to the next position
  GOTO(sweep)

  SLEEP (50)
  GOTO(detect)
ENDIF 

# The avoidance script
:avoid
IF ($reverseturn = 1)
  reverse($movementspeed,$reverseamount)
ENDIF 
IF($sweepcurrent = $sweepmin)
  RIGHT($movementspeed,$turnamount)
ELSEIF($sweepcurrent = $sweepmax)
  LEFT($movementspeed,$turnamount)
ELSE
  Servo($sweepservo,$sweepmin)
  $pingmin = GetPing($pingport, $echoport)
  Servo($sweepservo,$sweepmax)
  $pingmax = GetPing($pingport, $echoport)
  Servo($sweepservo,$sweepcenter)
  IF($pingmin > $pingmax)
    RIGHT($movementspeed,$turnamount)
  ELSE
    LEFT($movementspeed,$turnamount)
  ENDIF
ENDIF
RETURN()

# The sweep script
:sweep
# Check for previous position, if no position assume to be $sweepmax
IF($sweepprevious = 1000)
  $sweepprevious = $sweepmax
ENDIF

# Get the current position
$sweepcurrent = GetServo($sweepservo)

# Move in the correct direction and store previous position
IF($sweepcurrent = $sweepmin)
  $sweepprevious = $sweepcurrent
  Servo($sweepservo, $sweepcenter)
ELSEIF($sweepcurrent = $sweepcenter and $sweepprevious = $sweepmin)
  $sweepprevious = $sweepcurrent
  Servo($sweepservo, $sweepmax)
ELSEIF($sweepcurrent = $sweepcenter and $sweepprevious = $sweepmax)
  $sweepprevious = $sweepcurrent
  Servo($sweepservo, $sweepmin)
ELSE
  $sweepprevious = $sweepcurrent
  Servo($sweepservo, $sweepcenter)
ENDIF

# Return back to the main script
Return()

This at least runs and loops. I've not tested it with an EZB setup with a servo and ping sensor though.

The main problems were I had overlooked the fact that it would check the $sweepcurrent variable before it was defined. So calling for the script to immediately go to sweep resolved that. It could have been resolved by setting the variable at the start of the script too (like the $sweepprevious) I had also gotten mixed up between the variable name for $sweepcurrent and wrote it as $currentposition, so the variable didn't exist and it threw an error. These are the problems with trying to multitask :)

I also missed the :sweep label and missed a ) at the end of one of the IFs.

All have been corrected above. I have run it in ARC and it loops fine but I have not tested on an EZB with the sensor etc. Let me know if it operates correctly or not.

Spain
#20  

Okay, I've checked your file and set the ping sensor ports, servo and sensing distance, but seems not to work at all. When active the script, the ping sensor servo starts moving too fast and not reaching the specified reccorrido (25,52,77), seems as if time were missing breaks between each position. The script does not start the robot forward by default, I guess with a forward () somewhere is solved, but then when I press a Convenience key to go forward and reaches an obstacle it dodges, but also stops, also quick scan stops the ping servo.

Spain
#21  

This is the video of the robot executing your code:VIDEO.zip

and that the files you download from the cloud (your code) with the modified parameters for my servo ports.RADAR.EZB

United Kingdom
#22  

Sorry I should have explained that this only detects and avoids, it doesn't start the movement nor will it continue it should something disrupt the movement panels action.

You could create another script with the forward command and then a ControlCommand() to start the avoidance script. Loop it and I think it would work.

From memory I can't remember the ControlCommand syntax so please replace that line with the correct syntax.


:loop
Forward()
ControlCommand(WindowName, ScriptStart)
Goto(loop)

DJ has now added Pause and WaitForChange to EZ-Script as of today's update. These will be very useful in this example (I suspect he saw this post and added the command). It means each of the sub routines can be made in to their own scripts and called, paused and resumed when required. When time permits I will post an example.

A WaitForChange could be used along side a variable in the other script as a flag so the above script doesn't keep calling the script to start or calling for the forward movement when it doesn't need to.

Spain
#23  

He has become prove their code by adding a script with: ...................................................................... : loop Forward () ControlCommand (script name, ScriptStart) Goto (loop) ...................................................................... This script starts another forward but suspect "goto (loop)" causes a loop at high speed and only moving forward without control. Furthermore, although not advancing forward the ping sensor servo seems to reach no fixed route, just shake near the center position, I think that setting the servo positions (25,52,77) and consider the it takes the servo to reach each position, the script assumes that you have reached the position instantly, and it is not. Maybe we should add something like this in the appropriate place:

............................................ Servo_Servo_Wait (equals, 25) Servo_Servo_Wait (equals, 52) Servo_Servo_Wait (equals, 77) .......................................... What do you think?

United Kingdom
#24  

I'll have a good look at it when I get home. My other EZB should be with me tomorrow (should have been today but I wasn't home) so I'll knock up a test rig and get it sorted:) This is the problem when I try scripting while at work without ARC or an EZB to test with...

As for the the sweeping servo, I think I may have missed out some sleep commands. After the Servo($sweepservo, $sweepmin) (and center and max) commands try adding in a Sleep(250) and see how that works.

Spain
#25  

I've inserted the 250-ms sleeps under each line and it worked fine, now the servo moves sweep across his rrecorrido and does it well. The trouble is that when it detects a ojeto turns and stops, and only corrected to the left, then sweep the servo stops moving, and forward and goto function from an external script (which we discussed earlier) enters a loop and voids the rest of your code. The good thing is that every time we are closer, sure with the ez-b in their hands will see everything more clearly, seeing what he did without being able to experience it physically:)

Spain
#26  

Incidentally this is your code with my servo ports assigned and added the "sleep (250)":RADAR.EZB

United Kingdom
#27  

I will put together a test rig and check it out. I may even add the ping sensor and servo to my hearoid (since I need to anyway) if I get time tonight. If not I'll work on it over the weekend with a test rig.

United Kingdom
#28  

Right, just having a good ol' look at this now for the next 20 minutes or so (10 now). I've set it up with the floor map so I can see a virtual robot moving. I've slightly edited the code so the ping is a random number to save me needing to connect an EZB up.

It works fine, and then it stops. Currently I have only a rough idea of where it goes wrong but why it goes wrong I need to find. Basically you'll probably find that it moves around OK and then it will suddenly stop sweeping the servo.

So that's where I'm going to start looking.

Also, the updated code with the sleep fixed (it was in there but only 50ms so hardly counted) and forward commands added in. More of a roaming script than a detection script now :)

And I found the problem is in the code for detection direct ahead, it throws off the sweep code. I'll delve in to that better later on but have to be out in 10 minutes so it'll wait.

Here is the code all changed, it has some extra "testing" variables and options in it, I'll leave them there so you can see how I went about finding the problem. I'll explain it all later when I have time.


# Ping Object Avoidance
# Using Ultra Sonic Ping Sensor on servo for avoidance

# Adjust values below for configuration
$pingport = D0 # Change for Ping Port
$echoport = D1 # Change for Echo Port
$maxdistance = 75 # Change for maximum distance from object before avoiding in units
$onlyforward = 1 # Only if moving forwards? 0 = no, 1 = yes
$reverseturn = 0 # Reverse before turn? 0 = no, 1 = yes
$turnamount = 500 # Change for how long to turn for in ms
$reverseamount = 500 # Change for how long to reverse for in ms (if applicable)
$movementspeed = 255 # Change for movement speed

# Sweep variables
$sweepmin = 25 # Change for min limit
$sweepmax = 77 # Change for max limit
$sweepcenter = 52 # Change for center position
$sweepservo = "D3" # Change for servo port
$sweepprevious = $sweepmax # Do not change
$sweepcurrent = $sweepcenter # Do not change

# Testing Options
$testmode = 1 # Change to 1 if testing without PING sensor
$SweepErrorFlag = 0 # Do not change

# -- The Script --
Servo($sweepservo, $sweepcenter)
FORWARD()
GOTO(sweep)

# Check if only to detect when moving forwards
:detect
IF ($onlyforward = 1)
  IF ($Direction = "Forward")
    GOTO (detectstart)
  ELSE 
    GOTO (detect)
  ENDIF 
ELSE 
  :detectstart
  IF($testmode=0)
    $currentdistance = GetPing($pingport, $echoport)
  ELSE
    $currentdistance = GetRandom(0,255)
  ENDIF
  IF ($currentdistance <= $maxdistance)
    GOTO(avoid)
  ENDIF 

# Sweep the servo to the next position
  GOTO(sweep)

  SLEEP (750)
  GOTO(detect)
ENDIF 

# The avoidance script
:avoid
IF ($reverseturn = 1)
  Reverse($movementspeed,$reverseamount)
ENDIF 
IF($sweepcurrent = $sweepmin)
  RIGHT($movementspeed,$turnamount)
  FORWARD()
ELSE
  LEFT($movementspeed,$turnamount)
  FORWARD()
ENDIF
RETURN()

# The sweep script
:sweep
# Get the current position
$sweepcurrent = GetServo($sweepservo)

# Move in the correct direction and store previous position
IF($sweepcurrent = $sweepmin)
  $sweepprevious = $sweepcurrent
  Servo($sweepservo, $sweepcenter)
ELSEIF($sweepcurrent = $sweepcenter and $sweepprevious = $sweepmin)
  $sweepprevious = $sweepcurrent
  Servo($sweepservo, $sweepmax)
ELSEIF($sweepcurrent = $sweepcenter and $sweepprevious = $sweepmax)
  $sweepprevious = $sweepcurrent
  Servo($sweepservo, $sweepmin)
ELSEIF($sweepcurrent = $sweepmax)
  $sweepprevious = $sweepcurrent
  Servo($sweepservo, $sweepcenter)
ELSE
  $SweepErrorFlag = 1
SLEEP(10000)
ENDIF

# Return back to the main script
Return()

Also, see the attached ezb file (merge it to import the script in to your current project)pingroam.EZB

NOTE: Testing mode is set to on. Change the variable at the start for testing to 0 if you want to test with an actual PING sensor

United Kingdom
#29  

A quick video of it working away...

It doesn't check left and right after detection in the centre position yet as I think that's where another bug lies and I want to sort that part with an actual sensor fitted to a moving robot. My new EZB should be turning up tomorrow (should have been today, why was I out?!) so I can do that tomorrow evening :)

Although feel free to attempt it yourself, hopefully you are gaining some knowledge in scripting through this topic.

Spain
#30  

The truth is that I'm learning about scripts with this topic, I realize that the best way is to type it and practice. Also I have also learned a lot by practicing on the mobile platform in a practical, write and test. I have seen reactions "ghostly" so to speak, of the robot reactions that had nothing to do with the program, and course corrections when the sensor did not detect anything, and stuff. And as changing a parameter, others are modified unintentionally is something mysterious, but certainly has a logic I do not understand yet. By the way, do not understand how you run the program without ultrasonic sensor readings. Include random numbers to simulate sensor readings?

United Kingdom
#31  

Yes, random numbers, so the actual floor map is a bit unrealistic but it runs though and tests the if statements, sometimes meeting the requirements to run the commands other times it doesn't.

Anyway, I got impatient...


# Ping Object Avoidance
# Using Ultra Sonic Ping Sensor on servo for avoidance

# Adjust values below for configuration
$pingport = D0 # Change for Ping Port
$echoport = D1 # Change for Echo Port
$maxdistance = 75 # Change for maximum distance from object before avoiding in units
$onlyforward = 1 # Only if moving forwards? 0 = no, 1 = yes
$reverseturn = 0 # Reverse before turn? 0 = no, 1 = yes
$turnamount = 500 # Change for how long to turn for in ms
$reverseamount = 500 # Change for how long to reverse for in ms (if applicable)
$movementspeed = 255 # Change for movement speed

# Sweep variables
$sweepmin = 25 # Change for min limit
$sweepmax = 77 # Change for max limit
$sweepcenter = 52 # Change for center position
$sweepservo = "D3" # Change for servo port
$sweepprevious = $sweepmax # Do not change
$sweepcurrent = $sweepcenter # Do not change

# Testing Options
$testmode = 0 # Change to 1 if testing without PING sensor
$SweepErrorFlag = 0 # Do not change

# -- The Script --
Servo($sweepservo, $sweepcenter)
FORWARD()
GOTO(sweep)

# Check if only to detect when moving forwards
:detect
IF ($onlyforward = 1)
  IF ($Direction = "Forward")
    GOTO (detectstart)
  ELSE 
    GOTO (detect)
  ENDIF 
ELSE 
  :detectstart
  IF ($testmode=0)
    $currentdistance = GetPing($pingport, $echoport)
  ELSE 
    $currentdistance = GetRandom(0,255)
  ENDIF 
  IF ($currentdistance <= $maxdistance)
    GOTO(avoid)
  ENDIF 
    
    # Sweep the servo to the next position
  GOTO(sweep)
  
  SLEEP (750)
  GOTO(detect)
ENDIF 
  
  # The avoidance script
:avoid
IF ($reverseturn = 1)
  Reverse($movementspeed,$reverseamount)
ENDIF 
IF ($sweepcurrent = $sweepmin)
  RIGHT($movementspeed,$turnamount)
  FORWARD()
ELSEIF ($sweepcurrent = $sweepmax)
  LEFT($movementspeed,$turnamount)
  FORWARD()
ELSE 
  Goto(sweepcenter)
ENDIF 
RETURN()

# The sweep script
:sweep
# Move in the correct direction and store previous position
IF ($sweepcurrent = $sweepmin)
  $sweepprevious = $sweepcurrent
  Servo($sweepservo, $sweepcenter)
  $sweepcurrent = GetServo($sweepservo)
ELSEIF ($sweepcurrent = $sweepcenter and $sweepprevious = $sweepmin)
  $sweepprevious = $sweepcurrent
  Servo($sweepservo, $sweepmax)
  $sweepcurrent = GetServo($sweepservo)
ELSEIF ($sweepcurrent = $sweepcenter and $sweepprevious = $sweepmax)
  $sweepprevious = $sweepcurrent
  Servo($sweepservo, $sweepmin)
  $sweepcurrent = GetServo($sweepservo)
ELSEIF ($sweepcurrent = $sweepmax)
  $sweepprevious = $sweepcurrent
  Servo($sweepservo, $sweepcenter)
  $sweepcurrent = GetServo($sweepservo)
ELSE 
  $SweepErrorFlag = 1
  SLEEP(10000)
ENDIF 
  # Return back to the main script
Return()

:sweepcenter
$SweepCenterFlag = 1
Servo($sweepservo,$sweepmin)
IF ($testmode=0)
  $pingmin = GetPing($pingport, $echoport)
ELSE 
  $pingmin = GetRandom(0,255)
ENDIF 
Sleep(400)
Servo($sweepservo,$sweepmax)
IF ($testmode=0)
  $pingmax = GetPing($pingport, $echoport)
ELSE 
  $pingmax = GetRandom(0,255)
ENDIF 
Sleep(400)
Servo($sweepservo,$sweepcenter)
IF ($pingmin > $pingmax)
  RIGHT($movementspeed,$turnamount)
  FORWARD()
ELSE 
  LEFT($movementspeed,$turnamount)
  FORWARD()
ENDIF 
Return()

I had to move a few things around, mainly concerning the previous and current position variables. The way I had them didn't work correctly (although I haven't figured out why, as far as I can see they should have but I am probably missing something obvious). Then I needed to add in the forward commands missed out of the sweepcenter sub routine and also add in the testing code for using a random number rather than the GetPing in the sweepcenter sub routine.

But it all seems to be working well now... I left it running the test while I went for a shower and it was still working when I got out :)

pingroam.EZB

Some of the code could be tidied up a little and the sweepcenter routine could be moved in to the IF statement rather than using a goto since it is the only place it's called from.

We got there in the end though. Although totally untested with a ping sensor so the direction may be backwards or it may trigger when far away from an object rather than close to one - I'm unsure which way around the ping sensor reports the value. Easy fix if it is wrong though, it's just a case of changing a couple of ifs.

I have a video of it running too but the screen recorder decided it doesn't like encoding or compressing so it is 9.3Gb for only a few minutes... So I wont be posting that tonight (although it is uploading to youtube as I type this so maybe I will).

Edit: Video

United Kingdom
#32  

Since I have a few minutes to spare at the moment some quick notes on how I went about testing the script without connecting to an EZB or any sensors.

To emulate the sweep servo was pretty simple. Adding a control for a horizontal servo and setting it to the sweep servo port number will visually display the servo position within the control. This allowed me to be able to see that it was sweeping correctly.

Adding a movement control panel allowed visual indication of the direction in which the robot was moving.

Adding the floor map was just another indication of the robot moving however it was not required.

Replacing the GetPing for GetRandom supplied random numbers for the sensor data allowing random checking of the conditions in the IF statements.

The Variable Watcher control is also a very important tool. It allows to keep an eye on the variables so I could see what was changing. Also with the error flag variables it would indicate when the script had failed to perform the if conditions correctly. Adding a long sleep command after the flag change also helped indicate when the problem occurred.

And finally, in the script dialogue pressing the run button will show the debug information to the right which can be read through to check it is functioning correctly, where it runs astray or where there are problems.

However, that said, nothing beats checking scripts on an EZB with an actual robot.

To fix the script from the initial buggy code was a case of breaking it down section by section and finding where the script was going wrong, checking the code and adjusting it to suit.

As this shows I am still learning and often have bugs in code. Don't be disheartened if you have buggy code to begin with, we all do:) Trial and error will prevail.

Spain
#33  

Well, I've run your code on the robot movements have changed panel by panel h-bridge servo movements for my robot, assigned the servos and sensor ports, set some variables as $ maxDistance = 15 to work closer walls. I have also changed sleep (750) for sleep (250) to increase the scanning speed servo. The code works great! Anyone can use simple adjusting various parameters. I will post a video of my robot running your code pair delight. You did a great job, sure when you try it on your robot will still modifying code to refine details. Also is an open platform for experienced or continue adding lines of code. (Video later):) :) :)

United Kingdom
#34  

Funny you should mention refining the code, I was about to take a look at that. There are bits of code that are a little sloppy and messy which I want to fix, re-organise the configuration variables at the start to make it easier for others to use, remove the testing code and flags and adjust the sleep delays (as I needed them slow for my eyes to keep up with the code when testing).

I also have other ideas of how to add to the script too, using different turn rates depending on sweep position and ping distance. Using a different Movement Panel to go around the object rather than just turning... Lot's of additions can be made and everyone is welcome to make them :)

Great news that it works on a robot though.

Spain
#35  

Also I have some ideas to share, it would be great to integrate them into your code, for example: -Idea 1: Balance of distances (very useful for hallways and rooms): The robot moves forward while the sensor takes distances left and right lateral distances sum to set the width of the corridor, based on the total width divides it by half tries and knowing this side measurements are the same and making small course corrections to circulate through the center of the hall. This process is constantly repeated to recalculate the total width of the passageway at all times. -Idea 2: dead end, sometimes the robot is at a dead end and try to exit from the front or left or right but it does not, if the rotation time set to "$ turnamount" is very high, has more success to exit, but a high number causes your browsing more vague, more degrees running turns and prone to navigation in zic-zac or waveform. To retain more precision in navegcion and retain a $ turnamount small figure, it would be interesting to read a script: If you've tried out the alley for two attempts and still can not go forward, then turn 180 degrees. They are ideas in the search for a combination of integrated solutions. (video almost ready) :)

United Kingdom
#36  

All very achievable with a little thought.

The script as it stands is the backbone of a much more complex script. Once I've built the test robot this weekend (my new EZB has been delivered! :)) I can test it out with trial and error, set up some test courses for it to travel down etc.

Mapping with the sweep servo position and storing the values as variables, running some simple maths to work out how far from the centre line of the corridor and adjusting the speed of the one side of the drive wheels to level up is one way to achieve it. So rather than stopping, turning, moving, turning and continuing it can move forwards but veer off to the one side (imagine if left hand drive wheel moves slower than the right hand, it'll ARC around to the left slightly)

A lot more thought needs to be put in to it to work out what needs to happen but then it's just a case of adding in the right bits of code in the right places.

Dead end escape I have a different idea from what I've already seen. If we base it on the current code, it will detect an object dead centre in a dead end situation, it'll check left and right positions and turn appropriately. Now, after this we need to add in some code that if it instantly detects an object again then to slowly turn in the direction it last turned in, waiting for the ping to be over a certain amount indicating an escape is possible by driving forwards.

Reason I said to waituntil is because 180 degree rotation is not accurate when using time based movement commands. But waiting until the path ahead is clear ensures escape without error.

Just a few ideas floating around in my head, I have many more (some of which may not work, some may work, trial and error again will prove which ideas fall in to which categories :))

Spain
#37  

Video ready, at twice the rate of reproduction :)

United Kingdom
#38  

That's great. It gets a little stuck in a couple of places but then I guessed it would since there is no "boxed in" escape routine (yet).

I can't wait to get home and build the shoebox bot for testing this out so it can be expanded on:) I know Ultra Sonic isn't great in my house so I expect to almost immediately add in code for a Sharp IR sensor too.

Spain
#39  

I'm eager to see the result of your evidence; robot and shoebox. This could soon become a thread for advanced navigation. :)

United Kingdom
#40  

Shoebox was too big... box my LiPo battery come in, perfect size :)

Although I'm not happy with it using 4 modified servos to drive it, it works but it isn't great.

A sneek peek at the test bot User-inserted image

Needs batteries though and it's not anywhere near up to my standards even for a test bot... but it works.

Spain
#41  

Cool, ultra portable robot. Batteries and me neither friends since we discovered lipo batteries a few years ago, but for a vehicle of evidence; aceptaria even duct tape :)

United Kingdom
#42  

The whole thing is put together and secured by tape :)

I could fit a 5000mAh LiPo in the white box (one come in the white box) but I don't want to use a LiPo on this as I always worry about them going under voltage.

The 6xAA battery holder fits on the back nicely or under the EZB, so I'll be using that. Also, the camera has now been added too. I'll do a project showcase for it when it's all done and looking pretty and stuff.

Australia
#43  

Hi Rich, I use Lipo on my robot, Hobby king sell an under voltage alarm for use with electrical planes. This has a warning LED when its getting low and then a Pizo alarm when it hits rock bottom for the cell. $3.49 US http://www.hobbyking.com/hobbyking/store/__7226__hobby_king_battery_monitor_5s.html

You could take the signal to the pizo and piggy back an alarm to the EZB or alternatively hard wire a master power relay so this alarm will cut power to the entire bot. The alarm connects to the cell monitoring port not the Battery cables them selves so it monitors one of the individual cells for the min voltage.

regards ghost

United Kingdom
#44  

Just made a new post with a new idea in it :)

Hopefully it'll work.

P.S. I have one of those alarms but I've already had to split my balance port to 2 (1 for charger and 1 for monitor), I'm reluctant to split it to three.