Maestro icon indicating copy to clipboard operation
Maestro copied to clipboard

How do you immediately stop a servo's movement?

Open flyingw88 opened this issue 4 years ago • 13 comments

I am using the Maestro controller to control animatronics for Halloween and Christmas displays. I had a problem where the display got stuck and the servo kept trying to move it. This is real bad for the servo.

I can detect that the servo did not reach its commanded position, but I cannot figure out how to stop it immediately.

I appreciate any ideas. Thanks,

Paul

flyingw88 avatar Nov 07 '19 22:11 flyingw88

The maestro will continuously send PWM signals to the servo while you are connected to it with your Python code. There is a configuration, through the Maestro Control Center app, that allows you to configure what happens to this signal on startup and error for each channel. If you set the channel you are trying to protect to ‘off’, I think that you may be able to disconnect using the close() method, which will trigger the error condition and effectively disable the servo. Hopefully that works for you.

Steve

Steve


From: flyingw88 [email protected] Sent: Thursday, November 7, 2019 5:03 PM To: FRC4564/Maestro Cc: Subscribed Subject: [FRC4564/Maestro] How do you immediately stop a servo's movement? (#11)

I am using the Maestro controller to control animatronics for Halloween and Christmas displays. I had a problem where the display got stuck and the servo kept trying to move it. This is real bad for the servo.

I can detect that the servo did not reach its commanded position, but I cannot figure out how to stop it immediately.

I appreciate any ideas. Thanks,

Paul

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHubhttps://github.com/FRC4564/Maestro/issues/11?email_source=notifications&email_token=ABIJUXE5PBX4PBHT23272J3QSSGEDA5CNFSM4JKOO4G2YY3PNVWWK3TUL52HS4DFUVEXG43VMWVGG33NNVSW45C7NFSM4HXXRIFQ, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ABIJUXFG732QVF7S53KBX6DQSSGEDANCNFSM4JKOO4GQ.

FRC4564 avatar Nov 09 '19 02:11 FRC4564

Thanks Steve,

Thanks for the quick response.

I set the channel to go OFF on startup and error in the Maestro Control Center.

I did not get it work for me yet, but I am not sure of the syntax for the close() case. Is the correct among the possibilities I've listed below?

close() close(0) # for servo 0 servo.close servo.close(0) # for servo 0 servo.usb.close

Take care, Paul

flyingw88 avatar Nov 09 '19 12:11 flyingw88

Found a good solution: After detecting that the servo has not reached its commanded, position, use its current position to set the new position - it stops about where it got jammed.

Thanks, Paul

flyingw88 avatar Nov 12 '19 17:11 flyingw88

Hi @flyingw88 ,

I think I have a similar issue as you had. Would you mind sharing your code for fixing this? You don't turn off the servo port or use PWM changes to control this, but allow for further position changes to be initiated, right?

Thanks! Vera

vcalukovic avatar Apr 30 '21 09:04 vcalukovic

Hi Vera,

I attached the code I used for my experiment. There is a section that handles the stuck servo.

Good luck,

Paul

From: vcalukovic Sent: Friday, April 30, 2021 5:30 AM To: FRC4564/Maestro Cc: flyingw88; Mention Subject: Re: [FRC4564/Maestro] How do you immediately stop a servo's movement?(#11)

Hi @flyingw88 , I think I have a similar issue as you had. Would you mind sharing your code for fixing this? You don't turn off the servo port or use PWM changes to control this, but allow for further position changes to be initiated, right? Thanks! Vera — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

flyingw88 avatar Apr 30 '21 10:04 flyingw88

Hi Paul,

Thanks for getting back to me so quickly! If you could add the attachment that would be great! 🙂

Thanks a lot, Vera

vcalukovic avatar Apr 30 '21 11:04 vcalukovic

Hopefully this works. Last time the email program must of detected that it was python and stripped it.

Servo Driver v1, 8 November 2019

This program drives two servos. Each servo starts at the center position,

then moves to the farthest extent, then moves back to center. At each juncture

we check to see if the servo arrived; if not, then stop the machine.

import maestro import time import sys

servo = maestro.Controller()

Set servo acceleration and speed

servo.setAccel(0,25) servo.setSpeed(0,60)

servo.setAccel(1,25) servo.setSpeed(1,60)

Set servo positions, temporarily hard-coded

#user_input_center = raw_input("Center position = ") #centerposition = int(user_input_center) centerposition = 6000

#user_input_first = raw_input("first position = ") #firstposition = int(user_input_first) firstposition = 9000

#user_input_second = raw_input("second position = ") #secondposition = int(user_input_second) secondposition = 3000

#user_input_third = raw_input("third position = ") #thirdposition = int(user_input_third) thirdposition = 6000

#user_input_next1 = raw_input("next1 position = ") #next1position = int(user_input_next1) next1position = 4000

Set starting center positions

servo.setTarget(0,centerposition) servo.setTarget(1,centerposition) time.sleep(1)

print user_input_cycles = raw_input("How Many Cycles? ") print time.sleep(1) user_num_cycles = int(user_input_cycles) for num in range(user_num_cycles): print "Cycle =",num+1,centerposition,firstposition,secondposition,thirdposition,next1position # # Adjust servo speed for tests if num+1 == 3: servo.setSpeed(0,25) # servo.setSpeed(1,25) # # Set first servo positions # servo.setTarget(0,firstposition) servo.setTarget(1,firstposition) time.sleep(1) # x = servo.getPosition(0) y = servo.getPosition(1) # # Check whether the servos have arrived at their first positions. If not, then assume # the servo is jammed and stop the machine. # a = servo.isMoving(0) b = servo.isMoving(1) # if a == True: print print "Servo 0 failed at",x,"while going from",centerposition,"to",firstposition print sys.exit(1) if b == True: print print "Servo 1 failed at",y,"while going from",centerposition,"to",firstposition print sys.exit(1) # # Set second servo positions # servo.setTarget(0,secondposition) servo.setTarget(1,secondposition) time.sleep(1.5) # x = servo.getPosition(0) y = servo.getPosition(1) # # Check whether the servos have arrived at their second positions. If not, then assume # the servo is jammed and stop the machine. # a = servo.isMoving(0) b = servo.isMoving(1) # if a == True: print print "Servo 0 failed at",x,"while going from",firstposition,"to",secondposition print sys.exit(1) if b == True: print print "Servo 1 failed at",y,"while going from",firstposition,"to",secondposition print sys.exit(1) # # Set third servo positions # servo.setTarget(0,thirdposition) servo.setTarget(1,thirdposition) time.sleep(1) # x = servo.getPosition(0) y = servo.getPosition(1) # # Check whether the servos have arrived at their third positions. If not, then assume # the servo is jammed and stop the machine. # a = servo.isMoving(0) b = servo.isMoving(1) # if a == True: print print "Servo 0 failed at",x,"while going from",secondposition,"to",thirdposition print sys.exit(1) if b == True: print print "Servo 1 failed at",y,"while going from",secondposition,"to",thirdposition print sys.exit(1) # # Set next1 servo positions # servo.setTarget(0,next1position) servo.setTarget(1,next1position) time.sleep(1) # x = servo.getPosition(0) y = servo.getPosition(1) # # Check whether the servos have arrived at the next1 positions. If not, then assume # the servo is jammed and stop the machine. # a = servo.isMoving(0) b = servo.isMoving(1) # if a == True: print print "Servo 0 failed at",x,"while going from",thirdposition,"to",next1position print sys.exit(1) if b == True: print print "Servo 1 failed at",y,"while going from",thirdposition,"to",next1position print sys.exit(1) # print servo.close # print "Completed Normally" print

From: vcalukovic Sent: Friday, April 30, 2021 7:28 AM To: FRC4564/Maestro Cc: flyingw88; Mention Subject: Re: [FRC4564/Maestro] How do you immediately stop a servo's movement?(#11)

Hi Paul,

Thanks for getting back to me so quickly! If you could add the attachment that would be great! 🙂

Thanks a lot, Vera


From: flyingw88 @.> Sent: Friday, April 30, 2021 12:52 PM To: FRC4564/Maestro @.> Cc: vcalukovic @.>; Comment @.> Subject: Re: [FRC4564/Maestro] How do you immediately stop a servo's movement? (#11)

Hi Vera,

I attached the code I used for my experiment. There is a section that handles the stuck servo.

Good luck,

Paul

From: vcalukovic Sent: Friday, April 30, 2021 5:30 AM To: FRC4564/Maestro Cc: flyingw88; Mention Subject: Re: [FRC4564/Maestro] How do you immediately stop a servo's movement?(#11)

Hi @flyingw88 , I think I have a similar issue as you had. Would you mind sharing your code for fixing this? You don't turn off the servo port or use PWM changes to control this, but allow for further position changes to be initiated, right? Thanks! Vera — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

— You are receiving this because you commented. Reply to this email directly, view it on GitHubhttps://github.com/FRC4564/Maestro/issues/11#issuecomment-830012622, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ATL2CGR2FW5XNJZSD7XUG53TLKDW3ANCNFSM4JKOO4GQ.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

flyingw88 avatar Apr 30 '21 11:04 flyingw88

Hi Paul,

Unfortunately it doesn't fix my problem - the shutter I'm controlling keeps vibrating despite claiming that it's not moving. Thanks a lot though! It's always good to see others' code for inspiration.

Best, Vera

vcalukovic avatar Apr 30 '21 12:04 vcalukovic

Vera,

I never went beyond what you saw in my experiment, but if I were to continue, I would have installed small current sensor in line with the power supply to the servo(s).

If the current increased suddenly beyond some reasonable amount, I would shut the machine down.

Good luck with your application,

Paul

From: vcalukovic Sent: Friday, April 30, 2021 8:20 AM To: FRC4564/Maestro Cc: flyingw88; Mention Subject: Re: [FRC4564/Maestro] How do you immediately stop a servo's movement?(#11)

Hi Paul, Unfortunately it doesn't fix my problem - the shutter I'm controlling keeps vibrating despite claiming that it's not moving. Thanks a lot though! It's always good to see others' code for inspiration. Best, Vera — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

flyingw88 avatar Apr 30 '21 13:04 flyingw88

Good point, will try that! Thanks! Vera

vcalukovic avatar May 03 '21 07:05 vcalukovic

Sorry I'm late to the conversation, but I may be able to provide a bit of insight that could helpful.

The Maestro is controlling servos by sending a Pulse Width Modulated signal about 50 times a seconds. The width of the pulse is what the servo interprets for positioning. Standard pulse widths range between 1 and 2 milliseconds to represent the servos extreme positions, and a pulse width of 1.5 milliseconds represents center.

The Maestro can only send PWM signals to the servo--There is no return signal that indicates the actual servo position. The Maestro can, however, estimate the servo position based on the PWM signal it is sending. When you use the Maestro's Speed and Acceleration parameters, you can slow the change in the PWM output, and if the servo is able to move freely and keep pace with the PWM change, then the Maestro can reasonably predict where the servo is positioned.

This estimation fails to work if the servo motion is impeded or fully stalls. The Maestro will continue to adjust the PWM signal to reach the Target position, unware that the servo is no longer moving in sync with the change. The only way to truly know the servo's position is from some other feedback sensor. That could be a potentiometer or a limit switch, for instance (which the Maestro can actually read on another channel, if wired properly). A current sensor can be used to provide feedback on impeded movement or stall condition, but won't provide any positioning information.

One option you can consider is to disable the servo once you 'think' you have reached the target position. To do this, the servo needs to stop receiving the PWM signal. This will stop the servo motor, so it will no longer stutter or attempt to keep pushing. You can do this by setting the channel's target to 0 (ex: m.setTarget(0,0)).

Hope that helps.

Steve

FRC4564 avatar May 03 '21 15:05 FRC4564

Hi Steve,

Thanks for your explanation! I've tried using servo.setTarget(chan, 0) when the behaviour appeared, but this resets the target position to zero (where there is a chance of jamming again), not stop the jamming at the initial target position. I also tried this by setting the speed to unrestricted, which resulted in the same behaviour as when a speed was specified.

I will try to add a current sensor or something else I can use as switch. Will get back to you on the results.

Thanks for the suggestions! Vera

vcalukovic avatar May 06 '21 07:05 vcalukovic

You could run a wire back down the servo cable to another channel and read in the analog reading off the servos internal potentiometer supposing the voltages agree. This will give you closed loop absolute positioning. However, as said above, basic servos and basic servo control is strictly one way. The green dot in the control center is the position the controller is currently sending (the current PWM duty cycle). There is no possible way for the controller to know where the servo is or what it is doing (in a stock unmodified state), there is also no provision within a stock servo to report where it is in its sweep. This is a common misconception with servos and servo controllers. The servos only read the duty cycle (percentage of high to low across a period of time) it receives on the signal wire (1ms is always high, some percentage of the time between 1ms and 2ms being high with a definite high resetting the timing at 2ms, or there is a high edge every 2ms followed by 1ms high then the actual position value encoded as the percent it stays high before the next high edge 2ms from the last high edge). So, if the signal is to goto 50% of the sweep, the signal would be 1ms high, plus 0.5ms high (1.5ms total), then 0.5ms low, before transitioning back to high at 2ms total time from last raising edge starting the 1ms high stage over again. The servo then takes this duty cycle, compares it to what it reads on the potentiometer via an internal ADC, and activates an H-bridge to drive the motor in the direction of the new position. The slow easy movement is a trick achieved by transmitting small changes in the position. As far as the servo is concerned it will just flip the motor on full bore in the direction it needs to go. Its just that the new position is so close it only pulses the motor for a short period. But the motor is indeed driven full power. Its the position the controller is feeding it that makes it appear to be slow and soft.

Basically, servos be dumb out of the box, but there are ways of making them smarter ;)

Sidenote: if you're getting jitters and you're absolutely positive you are not over loading the servo, there isnt something trying to drive it off position(like trying to pull/compress something elastic, ie foam), and you're not sitting against an end stop, try a clip on ferrous core around the servo wire near the servo. Wrap the wire around the core once before clipping it. Typically jitters (if not due to over loading) are caused by EMI on the signal wire confusing control circuitry inside the servo.

zombieregime avatar Jul 19 '22 11:07 zombieregime