Servo constantly buzzing when small load

I have read that there is a simple way to avoid the buzzing of the servo when even the tiniest of torque is applied by going back a few degrees or so.

Does anybody have an idea how to node this ?

You could create a wrapper for servo to do this, perhaps called servo-debuzz. There are several things it would have to do:

  1. determine which way is “back”. In some cases, this will be the reverse direction just moved. Other times it will be in the direction of the load, which might be obvious (like a robot arm where servo always fights gravity), or might depend on external forces you won’t be able to calculate
  2. save previous value so you know when value has changed (and perhaps calculate which direction it moved so you know which way is “back”)
  3. give the servo time to reach its new position before moving “back”. This could be hard coded, or calculated based on how far the servo had to move (which would need to know previous position)
  4. decide how far “back” to move. This could be hard coded, or might depend on how far servo moved, or how much load is on the servo (which you probably won’t be able to calculate in most cases).

At a minimum, you will need a buffer storing old value so you know when servo moves (unless you recode in C++ to check when position pin has changed), pass new value to servo and start delay node, pass new “back” position to servo when timer expires. At some point, you need to update buffer with new position; when depends on how you want to handle position change before “back” delay has expired (most likely you want to skip moving “back” if a new position is requested, so you will update buffer when you start delay timer, but this can cause problems if you calculate “back” based on direction moved or you calculate delay based on how far the servo moved; the servo may never have reached the previous requested position). To avoid buzzing, it will also help to ignore “very small” move requests. You would have to determine what “very small” is; it will depend on the servo and how it is being used.

As you can see, something as trivial as “moving back a few degrees” can end up being very hard to code. If you move the wrong direction, or wrong amount, you might end up causing the servo to buzz more often instead is less often. Most servos have no feed back, so it is impossible to determine in code if servo is buzzing. With a load large enough to overcome gearing and push the motor, the servo will either buzz or move out of position, so moving “back” will not help anyway.

This all assumes you are looking for a generic solution. There might be very specific cases with restricted, repeatable input/output options that make it very easy to “go back a few degrees”. If you are stepping through a series of values and holding each value for a specific time, and servo always buzzes at one point, just add another stopping point “back a few degrees” and adjust the hold times appropriately.

1 Like

Jesus! :slight_smile:

Thank you.

I get it now.

Now that I’ve made it sound almost impossible to do…here is sample code :slight_smile:

Note that some nodes are Calc *…probably requiring a series of nodes to perform the calculation. I also didn’t bother adding “obvious” stuff like passing PORT, UPD, and outputs. I guess I also left out T for delay node; this could be hard-coded to max time for servo to travel from one extreme to the other, or calculated based on last position (buffer) and how far to new POS.

This patch does have a bug if you are calculating “back” based on POS & buffer…buffer gets updated to match POS as soon as POS changes, so difference will always be zero.

Note that like the servo node itself, you cannot “reuse” this node for a single servo in a patch. For example, if you have a robot with range-finder on a servo, you cannot create a “look left” node that calls this node and a “look right” node that also uses this node for the same servo. If you do, both nodes will try to control the servo all the time, so the servo will just spasm, trying to bounce between the two positions very quickly. This was the reason I created the gweimer/servo/servo-enable node to disable the servo in the inactive nodes. You can’t just replace servo with servo-enable for this node because the buffer node will always have the same value in each copy (the POS for “look left” in one and the POS for “look right” in the other), so things will still be broken.

There are two ways to resolve this issue. One is to only use one copy of this patch for each servo, changing what value gets passed in. The other is to switch to the servo-enable and pull the buffer for old POS outside the node & pass it in. This would allow all copies of the node to use the same buffer (but can get pretty ugly with wires running everywhere to set & pass the buffer value, and will likely need additional nodes for control of the buffer [like select node to determine which value to pass to buffer]).

Sometimes this can be simplified. For example, when programming my robot to use range-finder on a servo, I needed to wait for servo to reach its new position before checking range. I could always wait max time for servo to move from one extreme to the other, or calculate how long it would take to reach its new position. Looking forward was always middle, so servo would never have to move more than 1/2 way to get there. Looking left would always happen after looking forward, so servo would only have to move 1/2 way. Looking right would always happen after looking left, so it would always have to move full range of servo. Instead of needing to know last position, I could use this pattern to hard-code how long it would take to move the servo to the new position. If servo can randomly move to any position at any time, then you would need to calculate time to move that far (needing to know previous position), or always allow for maximum motion to reach new position.

2 Likes

From a completely different point of view, it could be a hardware problem. A buzzing servo usually means a faulty servo. Maybe try a different servo?

yes i already ordered some bigger ones

i am just starting out with all of this, so thank you all for the kind support and patients

some day i dream of making an arm thats covered in buttons / proximity sensors (like skin) that responds (goes limp) at collisions

so i can outsource some repetitive tasks of my mundane job and not get injured and or eventually brake it

but i guess thats more of a raspberry pi thing and real coding

Some thoughts about how to respond to robot arm collision: If you disable servos and the arm collapses, that might be worse than continuing in some cases. Ideally, the arm would stop all motion if it collides with something. This would be a lot easier to program with stepper motors than servos. The problem with servos is you don’t know where they are if they hit something while moving, so you don’t know where to tell them to stop. You can sort of simulate a stepper motor by giving servo small steps to move, then checking for collision before taking the next step. You could create a servo wrapper to do the steps for you (and check for collision) instead of just jumping to the final location.

makes sense thank you

I think i saw somewhere a concept where you could have mutliple servos driving a single planetary system. This way when you power down the combined resistance would soften the fall of the arm. For those who dont like steppers like me. Oddly I usually love magnetic stuff and despise medieval gears but the chirping noise…

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.