Asked — Edited
Resolved Resolved by ptp!

Testing Ez-Scripts

I'm a basic and assembler programmer ( PIC MCUs). I'm trying to put ezb scripts at work. I have a pot connected to adc0 (i.e. 0-3.3 V) and move the pot. I write this easy script in movement script, triggered by "forward" action panel :

sayezbwait("man") :auto $av=getadc(adc0) if $av>20 sayezbwait("dog") else sayezbwait("cat") endif goto(auto)

"man" is spoken once. Nothing else happens. I should have missed some banal detail Please help.


ARC Pro

Upgrade to ARC Pro

Subscribe to ARC Pro, and your robot will become a canvas for your imagination, limited only by your creativity.

PRO
Synthiam
#1  

Here you go...


sayezbwait("man")
:auto
$av=getadc(adc0)
if ($av>20)
sayezbwait("dog")
else
sayezbwait("cat")
endif 
Sleep(100)
goto(auto)

where are you executing this script? What is a "forward action panel"?

#2  

I havethe script in movement script. I click "forward" in Hbridge PWM movement control. Motors start correctlly, movement script panel says "forward". Only "man" said by ezb. No more audio. I'd expect "cat" or "dog" said by ezb.

Why you added "sleep(100) ?

PRO
Synthiam
#3  

because you will flood the data channel by querying a port without any delay. It would be higher priority than anything else. It would be like talking at someone and not letting anyone else talk.

On your microchip pic, your code runs linear one command at a time.

With ezrobot your program is threaded. Meaning there's many commands at a time running - like multitasking. You have to provide adequate time for other commands to have room. This is how programming in threaded environments works. The concept of a linear program is for microcontrollers Without an rtos.

PRO
USA
#5  

Leonardo,

If you are using a "Custom Movement"

https://synthiam.com/Tutorials/Help.aspx?id=182

you can't block the code or use cpu intensive scripts

Check the picture:

User-inserted image

solution:

  1. movement script you assign a variable with a direction. creates and sets a variable $direction.

  2. you add a new script control with your script, you start monitoring the variable from point 1, and you can keep a closed loop but you need to keep the delay in the loop to avoid flooding the ezb with multiple requests e.g. analog reads

#6  

You mean I might fix my code adding,e.g., a 100 ms delay after each time consuming operation , such as an a/d conversion ? I love PIC MCUs. No OS to disturb my program, and each statement executed in less than a uS !

#7  

please modify my example code , so I can understand how it had to be written

PRO
USA
#8  

Leonardo,

I don't know what you want to do but i'll provide some examples.

example #1:

script monitors the $direction variable, when the variable changes a specific action (Say) is executed.


:loop

WaitForChange($Direction)

if ($direction="Forward")
  Say("Going forward")
elseif ($direction="Reverse")
  Say("Going Reverse")
elseif ($direction="Left")
  Say("Going Left")
elseif ($direction="Right")
  Say("Going Right")
elseif ($direction="Stop")
  Say("Stopped!")
endif


Goto(loop)

PRO
USA
#9  

example #2:

  1. script detects when the robot is moving
  2. while moving keeps reading the adc port 0
  3. if the adc port reaches a threshold more than 128, stops the robot

#prevMoving is inverted to detect first state as a change
if ($direction="Stop")
  $prevMoving = true
else
  $prevMoving = false
endif

:loop

$delay = false

if ($direction="Stop")
  $moving = false
else
  $moving = true
endif

if ($prevMoving!=$moving AND $moving)
  Say("We are moving!") 
endif

#keep the direction before any stop
$prevDirection = $direction

if ($moving)
  #if moving check a sensor on port Adc0
  $a0=getadc(adc0)
  
  #set a delay because we will keep pulling the adc
  $delay = true
  
  if ($a0>128)
    Say("sensor threshold reached, stopping the robot")
    Stop()

    if ($prevDirection="Forward")
      #shall we try going reverse ?
    elseif ($prevDirection="Reverse")
      #shall we try going forward ?
    endif 

  endif
endif     

if ($delay)
  #add a delay to avoid communication saturation
  Sleep(250)
endif 

$prevMoving = $moving

Goto(loop)

#10  

Hello PTP,

I was looking at this post as I am interested in doing similar things. Just want to clarify what is going on in the following statement line:

if($prevMoving!=$moving AND $moving)

Are we saying here that if the previousMoving state is not equal to moving (false) AND the variable $moving is now equal to true then we are moving?

Also when doing comparisons like if($direction="Stop") shouldn't this statement read: if($direction=="Stop")?

Just curious about these two issues and thanks as always for your clarification and help !Rick :) :)

#11  

PTP, I see I have a lot to learn... despite some decades in programming PICs.

Please, to help, write a few lines, doing simply this:

read adc0, sayezb "up" if >128, or "down" if <128, and do this for ever.

I'd expect a up/down message from ezb whenever the voltage crosses the treshold.

This way I could hopefully understand how to work with EZB.

#12  

I'm going on testing some code , regarding getadc(adc0). I used the control called "read adc", to check the wiring , and I was surprised seeing that there I read , for adc0 , always 1,05 V, (value=82) whatever voltage I input to adc0 (0-to 3.3 V), even with the pin non connected . I have a meter connected to the pin. Same thing happens for other adc pins.

This explains some unexpected behavior of my code.

Can somebody explain why "read adc" doesn't work ? What's going on ?

#13  

Hi,ptp. Never mind about my previous posts. I solved my banal problem myself : some missing parenthesis, and wrong pin for adc. (a0 exchanged with a7 , I thought a0 on the same side as d0, I didn't look at the datasheet). Sorry, I'm a newcomer in EZB.

PRO
USA
#14  

@Rick,

EZ-Script is neither a BASIC or C compliant language, so there are some curiosities:

  1. Equal Operator ( = ) like Basic, C uses ( == )

  2. Not Equal operator ( != ) like C, Basic uses ( <> )

  3. Label is ( :my_label ) , C / BASIC is ( my_label: )

  4. ElseIf, BASIC does not have, C is (else if)

  5. if ( condition ), BASIC does not need braces, C requires braces

making short = is the equal operator

to avoid mistakes you need to rely on the ARC EZ-Script helps or look for examples in the forums.

#15  

Thanks PTP,

Was I correct in my thoughts on the moving statement in my post above? Thanks again ! Rick :)

#16  

Hi, DJ Sures. I wrote some simple code. But often I had unpredictable results, i.e. statements not executed, or executed more than once, or with unpredictable timing, etc. I never worked in a multi tasking environment, and don't understand how to manage many statements working together (as you say, " threaded"). Nothing about this in any tutorials. Can you help? Where to learn such things? Otherwise I'll have to go back to my beloved PICs, where everything is reliable, exactly timed, extremely fast, and no Os to interfere with my code.

PRO
USA
#17  

Rick,

yes

problem solving is not straightforward, a problem can be solved in multiple ways it's important to explain the logic used.

  1. the $direction variable is created and affected by the Movement Control, the control will assign the following values (case sensitive): "Stop", "Forward", "Reverse", "Left", "Right"

  2. $moving and $prevMoving are user(our) script variables

  3. assuming the movement control is in "charge" of the motors, we will use the $direction to detect if the robot is moving, so moving will be true if $direction has a value different from "Stop".

  4. example #1 we have WaitForChange($direction), the script will hold there and wait for a change in variable $direction.

(that is the reason why i didn't add the sleep, unless you are generating multiple direction actions in milliseconds you don't a sleep).

we know the code after of WaitForChange only will run when the $direction changes.

  1. example #2, we want to run actions while the robot is moving, also i wanted to detect when the robot starts moving.

this:


if ($moving)
...
endif

will run multiple times inside the loop while the robot is moving ($moving)

but i wanted to detect the transition between not moving and moving. So the idea is to add another variable $prevMoving (prev = previous) and you keep the value from the previous loop execution.

To achieve that you affect the variable only in the end of the loop, and you need to affect the variable before the loop.

  1. Now we have $moving and $prevMoving.

if ($moving!=$prevMoving) means something changed, the robot stopped or robot started moving.

Adding this to the previous condition

this:


if ($prevMoving!=$moving AND $moving)
...
endif

we can achieve the objective.

7) Scripts Start & Stop are independent, it's not like a monolithic program where everything starts at same time, so the question is should we initialize $prevMoving with true or false ?

makes sense to initialize $prevMoving with the same logic like $moving, so $prevMoving will be true if $direction is different than "Stop".

That will work. So if you start our user script, and then you press Forward, Stop, Reverse, everything works.

If you stop your user script, and you start again, you will notice that the last Movement is reverse, so the robot is moving and your script didn't detect the initial moving.

Maybe is important, maybe not so to detect always the initial move even when the script starts while the robot is moving, I changed the $prevMoving logic (before the loop) to be the opposite of $moving.

Sorry if everything was obvious, but i deal with multiple programmers, and not all the time is obvious each one logic.

#18  

Hello PTP,

Thanks for the detailed and fast and quick clarification to my question ! Very awesome ! Rick

PRO
USA
#19  

Leonardo,

ARC, EZ-Script are high level tools, they allow people to focus on the fun part when building robots without spending time in low level details.

if you are used to low level tools like assembler, C, micro-controllers, it's much more easier for you to get a long with ARC than the opposite.

Can you provide some examples of what is not working or you don't know how to use ?

#20  

PTP, I'm aware of what you say. I'm used with assembler, but for robots there are no strict speed requirements, I use a compiled basic. When I knew EZB, I realized at once its huge power, and I am trying to migrate to it. It's a basic-like language, things should be the same, I thought. But the code written does not execute as I expected. Some statements are not executed. Some work in a random way. DJ Sures says " statements are executed in a multitasking way ("threaded")". I do not understad how to write a program where statements are executed this way. I'm asking him for some explanation. I attach an example for you to see what I'm doing. Thanks for your answer. User-inserted image

PRO
USA
#21  

Leonardo,

Your code has a few errors, statement errors and flow structure errors.

if you pay attention to the debug console you will see the complains.

I can try help cleaning or organizing your logic, some questions:

  1. what kind of sensors are adc0 and adc1 ?

  2. what kind of values (range) are expected for far or close proximity ?

  3. How you want to drive the robot based in the adc readings ?

#22  

I 'm replying only now. we have many hours of difference. Here it was night.

This code is intended to migrate to ezb the basic code that is working well in a simple rover I had made. Certainly the migration is wrong ! I haven't yet learned how to use EZB. There are 3 MaxSonar EZ3-MB1030 proximity sensors. (one in front , one left, one right). I'm using their analog output. The code is started by a Forward command from a Hbridge PWM movement panel. It should work as follows: The front sensor should check the distance. If it's more than a theshold of about 10 inches, motors should keep going forward,saying the wall is "far". Else it should say "near" and go to see at what side it has more space, and command motors to turn to that direction. The scripts for right and left simply say " turning right" or left, and do nothing else. After turning the rover goes forward again until it arrives near another wall, and everything goes on as before.

Extremely simple, it worked well with a basic program in a PIC. Thanks for your help.

#23  

I had forgotten to say that flags $FL and $FL1 are used to avoid instability that may sometimes occur and can cause endless oscillations between right and left. it's like a "Schmitt trigger" circuit, you know. The attached flowchart describes this better than words. User-inserted image

#24  

e.g. if it's turning left, it will go on turning left until it has enough space at the front sensor to be able to go straight. It will not attempt to go right and cause oscillations.

#25  

I think I corrected the flow errors. Here is the new version. It's not yet working. I don't know which are the statement errors. Something case sensitive ? User-inserted image

#26  

I've found that EZ Script is not case sensitive.

Also, line 26 & 27 look odd to me. I'm not sure you should have a label inside an '"If" statement.

PRO
USA
#27  

Leonardo,

Quick feedback.

Dave is right, that is one of the "flow structure errors" if, elseif, else blocks work as logical block.

I understand why you made the mistake, assembly language don't have restrictions to jump to an address.

PRO
USA
#28  

Leonardo,

Can you try this script:


#stop the robot if is moving
Stop()

:loop

if (GetADC(adc0)&gt;50) 
  if ($direction!=&quot;Forward&quot;)
    SayEZB(&quot;Far&quot;) 
    Forward() 
  endif
else
  if ($direction=&quot;Forward&quot;)
    SayEZB(&quot;Near&quot;) 
    Stop()
    
    #check rotation side 
    if (GetADC(ADC1)&gt;GetADC(ADC2))
      Left()
    else
      Right()
    endif 
    
  endif 
endif

Sleep(250)
Goto(loop)

I didn't tested, i just followed your specs. Let me know if it works.

sometimes reading multiple ultrasonic sensors can create interference, but it depends how you setup them (angles).

#29  

No,ptp, it doesn't work. It starts and stops randomly the motors in the forward direction, sensors seem not influncing what's going on.To make it do something you have to click more than once the forward button in the movement panel. No interference among sensors. The same robot with a PIC it worked well.

PRO
USA
#30  

Leonardo,

Can you try this variant:


#stop the robot if is moving
Stop()

DefineArray($adc0_reads, 10, 0)
repeat($adc0_ix, 0, 9, 1)
  $adc0_reads[$adc0_ix]=GetADC(adc0)
  Sleep(100)
endrepeat 

:loop

#read one 
$adc0_ix=$adc0_ix+1
if ($adc0_ix&gt;=10)
  $adc0_ix=0
endif 
$adc0_reads[$adc0_ix]=GetADC(adc0)

#calculate avg last 10 readings
$adc0_avg=0
repeat($x, 0, 9, 1)
  $adc0_avg=$adc0_avg+$adc0_reads[$x]
endrepeat 
$adc0_avg=$adc0_avg/10

if ($adc0_avg&gt;50) 
  if ($direction!=&quot;Forward&quot;)
    SayEZB(&quot;Far&quot;) 
    Forward() 
  endif
else
  if ($direction=&quot;Forward&quot;)
    SayEZB(&quot;Near&quot;) 
    Stop()
    
    #check rotation side 
    if (GetADC(ADC1)&gt;GetADC(ADC2))
      Left()
    else
      Right()
    endif 
    
  endif 
endif

Sleep(250)
Goto(loop)

PRO
USA
#31  

Leonardo,

Did you tried the script ?

#32  

I'm writing .It's a long job. By the way, is there some way to import your code to my ARC without writing it, i.e. such as a sort of executable file ?

PRO
USA
#33  

long job ?

you can copy the text/code "black window" and paste inside the ARC's script editor.

#34  

PTP, just wondering, what is your reasoning for having those three EndIf statements towards the end of your script. I would think that just one would do the trick.

Also, you have two If statements in a row. Is this possible?

if ($adc0_avg>50) if ($direction!="Forward")

PRO
USA
#35  

Dave,

you can simplify:


if ($adc0_avg&gt;50 AND $direction!=&quot;Forward&quot;)
  SayEZB(&quot;Far&quot;) 
  Forward() 
elseif ($adc0_avg&lt;50 AND $direction=&quot;Forward&quot;) 
  SayEZB(&quot;Near&quot;) 
  Stop()
    
  #check rotation side 
  if (GetADC(ADC1)&gt;GetADC(ADC2))
    Left()
  else
    Right()
  endif 
endif

but it looses readability, sometimes is easier to break multiple blocks, for example BASIC does not have elseif, so you need always to think if then else.

do you see other away to rewrite the ifs ?

Can be interesting exercise to see a different logic (I'm biased is my code)

#36  

Fast job ! I didn't know ezb was capable to support copy/paste !...

Code tested. It does no more than stop at once after the forward command. I eliminated the stop() command at the beginning. After that it goes forward, until the front sensor gets near an obstacle and then it stops, after several seconds (a long time!...). The voltage in READ ADC control panel, instead, changes immediately. Other sensors seem to have no influence in what's going on. No change in direction triggered by left/right sensors.

I saw in the code there is some average of adc reads. Could this help ? What had this code to do? Why side sensors not working? I have in ezb screen a voltage panel for each sensor, correctly measuring each distance in real time.

#37  

I forgot to say that ezb never says "near" or "far". It only says "stop", because I have sayezb ("STOP") in stop script.

PRO
USA
#38  

Leonardo,

Can you upload/attach your project ?

#39  

More tests. I eliminated the 2nd stop() statement, (it stopped there !). now it reacts to the side sensors, turning right or left as required. But it keeps turning for ever, even when the loop is executed again with the front sensor without obstacles ("far" situation). It never says near or far. Only says what's in right,left,or stop scripts.

But the worrying issue is : response time is extremely long ! Note that the 3 READ ADC control panels for sensors change in realtime. EZBv4 , instead, reacts after some 2-3 seconds !... I DON'T UNDERSTAND WHY IT'S SO SLOW. This way is useless for controlling a robot !

#41  

PTP, thanks for the answer. I don't want to hijack this thread so no need to respond to my posts on my script questions anymore. However just to answer you; I'm still just a student of easy script and have no advance. I'm just asking questions to learn. I'm amazed at the different ways we can write script and have it do the same thing. For example I thought you could only have one If statements in a block and everything else needed to compare to it. Then each If block needed it's own EndIf statement. I didn't know you could stack them up at the bottom like you do. I write my scripts much like you've second example to my. That's more readable to me. Lol

Anyway, ignore me now. Sounds like the op is getting close to resolution. I wish him luck. ;)

#42  

Leonardo, click the pause box on the adc monitors. This is probably what is slowing down your setup. That feature is very resource hungry. I can't run more than one at a time without seeing my system slow to a crawl. See if this helps.

#44  

OK PTP. Now it works. I'll study your code to learn what you have done.

But the problem now is : WHY it's so slow ? it takes at least 3 seconds to actually change the direction. Within that time the robot will crash against the wall ! The same robot , with a PIC, reacted in milliseconds.

PRO
USA
#45  

@leonardo,

Please try: test_r1.EZB

Changes:

  1. vocal messages removed from the main script
  2. Decreased the delay to 50

*** #1 edit:begin *** 3) Dave suggestion, is very relevant.

I paused all the analog controls, they have short (<1000ms) refresh intervals .

Our focus is to troubleshoot the navigation script. You can try later activate one by one to see if they affect the performance

*** #1 edit:end ***

  1. Important:

as it is, is using a single read on adc0 to use average readings you will need change the code to:


#set true to use average readings
$use_average=true

Please let me know if the results are better.

PS: Congratulations Soccer Euro 2016 - Italy is moving forward ! Conte did a fantastic job beating Spain is not easy!

#46  

As far as being slow, did you see my post above. Give that a try to see if it helps.

#48  

PTP. This version doesn't connect to ezb#0. . timed out. I don't understand what's going on. It connects to other ezbs, #1,2,etcthat I don't have. No test possible.

Thanks for our soccer team. They were really convinced to win.

PRO
USA
#49  

Leonardo,

My ezb has a different address, when you save a project the ip address goes in.

You see a textbox before the connect button, you will need to change the ip address from 192.168.18.84 (mine) to 192.168.1.1 (yours).

Then save the project.

#50  

OK, PTP, much better. Reaction time decreased from 3 sec to 1 sec. Good. It's almost ok. I'll experiment for even better performance.

Another issue for this robot was some code to avoid endless oscillations between right and left occurring in some circumstances. It's necessary, when ,for example, turning right, to disable any attempt to turn left until the front sensor has a free space before it. Turning left should be enabled only after the rover has started to go straight. Same thing should happen for turning left. To do this there were two flags FL and FL1, as you see in the attached flowchart. Can you implement this function in your code ? This would be enough for this thread. User-inserted image

#51  

translation from italian: iniz=initialization libero av=free space before me av =go straight ostac dx=osbtacle at right ostac sx=obstacle at left dx=right sx=left ost= a label

FL and FL1 = Flags

PRO
USA
#52  

Leonardo,

My logic is already doing that, look the code:


if ($adc0_avg&gt;50) 
  #1

  if ($direction!=&quot;Forward&quot;)
    #2  
    Forward() 
  endif

else
  #3

  if ($direction=&quot;Forward&quot;)
    #4 
    Stop()
    
    if (GetADC(ADC1)&gt;GetADC(ADC2))
      #5
      Left()
    else
      #6
      Right()
    endif 
    
  endif 
endif

I put some comments #1-#6

The current logic is:

  1. when the robot detects an obstacle will enter #3
  2. if robot is driving forward not spinning will enter #4, stop, starts spinning left or right based on adc1 or adc2 values

robot keeps spinning same direction (no oscillation) until the forward sensor is ok, once is ok will enter #1 and drives forward.

PRO
USA
#53  

Leonardo,

I added some logic to avoid oscillation going left, forward, right, forward, left.


#stop the robot if is moving
Stop()

#set true to use average readings
$use_average=false

$spin_counter=0

#-1=left; 0-fw; 1=right
$spin_direction=0

if ($use_average)
  DefineArray($adc0_reads, 10, 0)
  repeat($adc0_ix, 0, 9, 1)
    $adc0_reads[$adc0_ix]=GetADC(adc0)
    Sleep(50)
  endrepeat 
endif

:loop


if ($use_average)
  $adc0_ix++
  if ($adc0_ix&gt;=10)
    $adc0_ix=0
  endif 
  $adc0_reads[$adc0_ix]=GetADC(adc0)

  #calculate avg last 10 readings
  $adc0_avg=0
  repeat($x, 0, 9, 1)
    $adc0_avg=$adc0_avg+$adc0_reads[$x]
  endrepeat  
  $adc0_avg=$adc0_avg/10
else
  #read one 
  $adc0_avg=GetADC(adc0)
endif

if ($adc0_avg&gt;50) 
  if ($direction!=&quot;Forward&quot;)
    Forward() 
  endif
else
  if ($direction=&quot;Forward&quot;)
    Stop()
    
    #adjust the value 20 to your needs
    if ($spin_direction!=0 AND $spin_counter&lt;20)
      if ($spin_direction&lt;0)
        Left()
      else
        Right()
      endif
    else
      $spin_counter=0
      if (GetADC(ADC1)&gt;GetADC(ADC2))
        $spin_direction=-1
        Left()
      else
        $spin_direction=1
        Right()
      endif 
    endif
  else
    $spin_counter++
  endif 
endif

Sleep(50)
Goto(loop)

you will need to tweak the value 20 based on your observations, can be higher or low.

relevant lines:


    #adjust the value 20 to your needs
    if ($spin_direction!=0 AND $spin_counter&lt;20)

#54  

very well,PTP, it's running. I will have only to fine tune some parameter to have a performance approaching the very fast one of pic.

Thank you for having shown me what ezb can do. i'll study your code. Programming that way is different from basic or assembly on pics I was used to. I'll try to get the relevant know-how.

One last detail. I'd like to avoid those annoying windows coming out when you start ezb i.e. mounting instructions, fine tune profile, tutorials for robots I will never have,etc. I have to skip or close them every time.

After this thread I will experiment with servos, actions and frames, and will certainly ask for support in other threads.

I'll be reading you there.

#55  

Hi ptp. You're the member who solved ! Now I understand how to use adc reading. To have fast results it's better to use a hardware comparator on board . It can make such operations in 100 nS !.....