Asked — Edited

Servo (Stop) / Servo Stop - How To Stop A Servo At A Specific Adc Value

Hello,

i have one ( i hope easy) question.

i have a pressure sensor.

Work fine on the ADC!

Now i have one problem.

If the value for the ADC port is under 180 the servo must stop ( hold his position)

my idea of a script :


:loop
$CurrVoltage = GetADC(ADC0) 
if ($CurrVoltage <= 180)
servo (d0, "stop")
sleep(300)
endif
goto (loop)

But the command servo (d0, "stop") dont exist

So with command i can take what tells the servo he must stop and HOLD his position.

Thanx a lot for helping

AND FOR ALL A HAPPY NEW YEAR!

AND BIGGER ROBOTS NEXT YEAR!


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.

PRO
Synthiam
#1  

that's not how servos work. There is a tutorial that explains how servos work in the learn section - it will be an important read. Here's the direct link: https://synthiam.com/Tutorials/Lesson/48?courseId=6

There have been discussions in the forum regarding this question in the past. Here is the most popular answer:


REPEAT ($pos, 0, 70, 5)

  servo(d0, $pos)

  IF (GetADC(adc0) &lt;= 180)
    halt()
  ENDIF

   sleep(50)

ENDREPEAT

#2  

Will this work Boris?


:loop
$CurrVoltage = GetADC(ADC0) 
if ($CurrVoltage &lt;= 180)
servo (d0, $CurrVoltage)
halt()
sleep(300)
endif
goto (loop)

#3  

Hello Richard,

thanx for your idea! It works a little bit.

The biggest problem the reaction time. If i press the Sensor it takes seconds until the script stop.

@DJ what this numbers ($pos, 0, 70, 5) here means

Min Pos/ Max Pos/Speed or what?

Happy new year! Boris

#4  

From the script cheat sheet:

Repeat( variableName, startValue, endValue, increment )

so this script will start a servo at 0, go to 70, in increments of 5 every 50 ms and stop if the ADC reads less than or equal to 180.

Alan

#5  

Hello Alan!

Ok now i understand this, but one question.

Now i have this script:



repeat ($pos, 180, 0, 15 )
  servo(d0, $pos)

  if (GetADC(adc0) &lt;= 75) or (GetADC(adc1) &lt;= 175)
  
    halt()
    
  endif
sleep(50)


endrepeat



This means:

Start @ 180 End @ 0 in 15 Steps/increments every 50ms

now the question. The Step takes not 50ms - the steps take almoust 1 second each step/increment. Or it means that the ADC check every 50ms?

Is this correct?

Boris

#6  

It should be doing both every 50ms, but if your servo is moving slowly, you may have a servospeed() in another script that has slowed it down.

Alan

#7  

Hello Alan,

no i have extra a script for servoSpeed (d0, 0) what i run first.

On a normal servo position ( servo d0, 5) the servo runs his fastest speed.

Now i was also thinking every 50ms ( and 50 ms seconds its really fast - not a second or more)

Boris

#8  

I know what you are trying to do now....:) This is for your inMoov's hand so he can grasp an object, sense his grip so as not to burn his servos out... Good idea man... Too bad there isn't an easy way to read the current the servos are using... That way you can stop the servo before it would normally over stress and burnout....

#9  

Hello Alan

i made a complete new project and copy the script into this and now it works with the 50ms. Ahhhhhhh Something was wrong!

@Richard yes not only for burning servo, also for holding eggs and not break it!

It works slowly almoust like my idea was, but now the next problem to put the presssure sensors to good positions to the finger where they can get a good pressure! and at which value the servo stops. to weak it stops to early to strong it not stops.

If i have a good result i will inform you.

But first happy new year to all!

#10  

As well as the pressure sensors, you might want to add a little foam so there is some "give" in the grip as well as a little texture to hold onto things.

Alan

PRO
Synthiam
#11  

Only getadc() one time, otherwise it's needless queries to the ez-b. Also, the IF statement is redundant because it will always be below 175.

My initial example was the best so far. Simply change the REPEAT to have the max and min values of the gripper.

#12  

DJ, he is looking at the value of two different ADC ports, and if either value is true he wants the script to halt. I think the script is correct. Am I missing something that you see, or did you miss that it is two different adc ports with two different thresholds?

Alan

#13  

@DJ it works fine with two ADC ports

@Alan You are right!

Boris

#14  

Hello Boris;

I get what is trying to be done, but I'm not sure I understand the programming part of the problem correctly, so I'll ask some questions.

Are there two separate scripts running? That is, one script which is making the servo move however it should, and a second script that is monitoring the pressure sensors voltage? Then, when the voltage drops below 180 (or whatever) the second, "stop" script, stops the servo and the servo then holds the position it has at the moment it is stopped?

Also, is the stopping script supposed to stop the servo even if it is currently moving due to being sent a servo() command (or whatever) to make it move? In other words, let's say the command Servo(D4, 155) is sent, and the servo is slowly moving to the 155 degree position, is the stop script supposed to stop it dead before it gets to 155?

#15  

Hello WBS00001!

HAPPY NEW YEAR TO YOU!

Long time not hearing from you! I am happy to see you again!

To you question.

Yes it will be the best if i will have a monitoring script to check out which value the ADC ports have and when the value reach his point the script will stop the servo.

To understand here is a photo from my Inmoov Palm with the first finger who has 2 pressure sensors.

User-inserted image

DJ Script works, but first problem the move is not smooth, because the servo moves now in 15 steps every 50ms and this is not smooth! And the second problem, its better to have a monitoring script, now i must copy the DJ Script in every moving script for the fingers what i have.

I hope this explains what i want to do.

Boris

#16  

Hey Boris... try slowing the servo down instead of "stepping" it...

EDIT.... On second thought never mind my idea won't work

#17  

Hi Richard!

Happy new year!

How i slow down the servo in DJ´s Script?


repeat ($pos, 180, 0, 15 )
  servo(d0, $pos)

  if (GetADC(adc0) &lt;= 75) or (GetADC(adc1) &lt;= 175)
  
    halt()
    
  endif
sleep(50)


endrepeat

#18  

@Boris... Could you use the release command and a slow moving servo .... although releasing a servo means resetting servo speeds again.....


servospeed(D0,3) # slowly close hand... lower is faster, higher is slower
  servo(d0, $pos)
:top
  if (GetADC(adc0) &lt;= 75) or (GetADC(adc1) &lt;= 175)
  
  release(D0)
    halt()
  endif
sleep(50)
goto(Top)

#19  

Hello Richard!

And from where the Servo/the variable knows to move to which position?

($pos, 180, 0, 15 )

Boris

EDIT:

Or work your script like a monitoring script (i am not near my Inmoov)

#20  

@Boris.... You give $pos any value you want for example...


$pos = 30 #closed finger

servospeed(D0,3) # slowly close hand... lower is faster, higher is slower
  servo(d0, $pos)
:top
  if (GetADC(adc0) &lt;= 75) or (GetADC(adc1) &lt;= 175)
  
  release(D0)
    halt()
  endif
sleep(50)
goto(Top)

#21  

Hi Richard,

i understand now!

I will try in 2-3 hours, then i am back!

Boris

PS. And then i tell you if it works!

#22  

Hello Richard,

sorry it not works. If the value for the ADC is under the servo release not HOLD the Position! So this means if the Hand will hold something it will fall down.

The servo must hold his postions!

The best way until now is still the way from DJ!

Boris

PRO
Synthiam
#23  

Boris, no one can give you the complete solution catered to your application. We can only lend a hand and provide the template for you to work from. It's up to you to learn from the examples we provide. Keep at it and it'll come together for you :)

#24  

Hello DJ!

Everything OK! I never was thinking to get a completer Robot!

Thats why i am asking! Do you know "Sesame Street"? Who not ask, will stay stupid!

Again Everything ok, you understand something wrong! Relax!

Boris

#25  

Hello again Boris, and a Frohes Neues Jahr. to you as well. :)

The basic problem here is that there seems to be no way to stop a servo (and get it to hold position) once it has been given the command to move to a certain position. This is why the solutions given have all involved a loop that tests the status of the pressure sensor as the hand is closed one small step at a time.

So, it seems to me the best way to do this would be to call a "Close Hand" script to make the hand close via a CommandControl instruction. Something like this:


ServoSpeed(D0,5)  #Set to whatever you want 
CC(&quot;Close Hand&quot;,ScriptStartWait, &quot;Hand Close&quot; )

"Close Hand" would be the name of a Script Manager which contains the "Hand Close" script described below. But you could put it in any script manager you wish.

Then the "Hand Close" script would be something like the ones already shown. My own would be:


:CheckADCPort
  ServoUp(D0,1) #Close the minimum increment
  if (GetADC(adc0) &lt;= 75) or (GetADC(adc1) &lt;= 175)
    Goto(TheExit)  #Stop and hold at this point
  endif
  Sleep(20)
  Goto(CheckADCPort)

:TheExit

The Sleep(20) statement may not be needed at all. You could try it with and without it in there. Or at least play with different values of sleep.

I have tested this with a JD claw, but I don't have a pressure sensor so I don't know how well it will work with the hand.

#26  

Hello WBS00001,

i check you script and it works a little bit better then from DJ (smoother, but still not the best)

But i found out the problem. If i run you script without the ADC check, the finger moves best off! If i let check the ADC Ports the finger will move not so smooth.

So its the reaction time of reading the ADC, who is not the best. I think at this point nobody can make it better.

I am not lucky with the choppy/juddery way of closing the fingers, but on other hand i think its a soloution for a not profi Home-Robot-Builder.

If someone has a idea, to maybe source out the ADC reading or else, i am open everytime for new tests!

Boris

PS: I will got some new servo for the Hand and more pressure Sensor. If i finish one Hand i will post a video.

#27  

Sounds like the issue is with the read of the ADC port. Have you tried to adjust how often the port reads the value? I'm thinking two things may be happening;

  1. The port is reading too fast and flooding the commutations link.
  2. The port is reading too slow and each time it checks the servo needs to jerk forward to catch up to the reading.

I'm not sure that this method will control the speed of the ADC check in EZ scripts that you write but; In each of the 3 ADC port controls there is a interval setting. It's usually set at 500 ms. setting. It's usually set at 500 ms. After adding that control to your project and setting it to the port, try adjusting that up and down.

There may be other ways to get the ADC port to check values at different intervals. The repeat script command comes to mind. It has a interval setting.

Also, I've found if you leave these ADC controls running and checking ADC status they will slow down your system. Keep them paused till you really need to see performance.

Just some random thoughts on a couple things to try. Good luck.

#28  

I've been working on a ADC issue all day today. It's somewhat similar to yours. I'm trying to stop a motor through EZB's UART port with a opto switch that's attached to an ADC port. I've tried all the suggested scripts and still wasn't satisfied with the responce. Nothing seemed to act fast enough. Couldn't get a good balance between speed and ACD readings.

Anyway, I found that using the ADC_Wait gave me the best responce and got everything working smoothly.


ADC_Wait (adcPort, higher/lower/equals, value, [delay ms])
Wait until ADC port is higher or lower than specified value
The optional parameter Delay MS is the millisecond delay for checking. This value determines the delay between checks.
Example: ADC_Wait(ADC0, HIGHER, 50)
Example: ADC_Wait(ADC0, HIGHER, 50, 50)

Here's another one that may work for you:


ADC_Wait_Between (adcPort, low, high, [delay ms])
Wait (pauses script) until ADC port is between the specified values. Soon as the ADC port is between the low and high values, it will stop waiting.
The optional parameter Delay MS is the millisecond delay for checking. This value determines the delay between checks.
Example: ADC_Wait_Between(ADC0, 20, 50)
Example: ADC_Wait_Between(ADC0, 20, 50, 50)

#29  

Hi Boris;

I don't understand what the difference in the results using the Inmoov hand and my tests using JD's claw. In my tests the claw closes smoothly while checking ADC0 and ADC1 in the test loop. Are you moving several servos to close the Inmoov's hand or just one? Do you have other things running at the same time that may actually be causing the problem? You may want to make a new test project with just the hand closing script in it to see if it runs smoothly then.

Running speed trials, I see it takes a bit less than 14ms to execute a GetADC instruction. A little less than 27 ms to execute the test statement (GetADC(adc0) <= 75) or (GetADC(adc1) <= 175) checking the two ADC ports. That should be plenty fast enough for smooth hand closing.

Are you using the latest version of ARC? JD has recently made changes that make the script execution much faster?

#30  

Hello WBS00001,

NO, i use a complete new clean Project, no other scripts are running.

I think i will make a video, then you can see more.

But that you got a smooth closing with you JD claw, brings me again a little bit hope!

I will check tommorow afternoon and i will report you.

Thanx for your Help!

@Dave yes i am also not lucky with the speed from the ADC port! I will also check your scripts and i will report.

Boris