Stopping pwm clean

I seem to have caught a side effect of hw pwm. If you stop/dispose the pwm during a high wave, my servo moves on dispose. I assume because the cut off happens at some random high time. The servo thinks that is next edge and moves to that position and then stops on low.

Seems we need an overload on Dispose (or Stop) that will block until a current high wave goes low and then stay low. I am almost positive this is what is happening. As experimenting with various Sleep/Delay times, will produce different servo moves at end. In this case, using 1002 must have been a low spot, as it does not move on dispose. Change it to 1000, and it moves. I also think you can have similiar behavior when setting next SetPulse() depending on where you are in the wave. This is a bit more dangerous as it can happen in the middle of stream of moves.

ss.SetPosition(center);
Thread.Sleep(1002);
// Allow to center. Note odd sleep time required. Else servo moves on dispose call.
// Would seem to Need an overload to not cut off until current High wave goes low.
ss.Dispose();

To cleanly stop a servo, you need to simply pull the signal low.

How? You can’t assign more than one function to a pin so you would have to dispose of the PWM object before directly driving the pin. Unless you AND to signals together externally. (Edit) Oh! I think I just figured out what you mean Chris, big duh on my part (see below) :smiley:

We are talking about hobby servos here, correct? If you do a:

yourPWMPin.Set(False);

if will force the pin low, then you can dispose it without any glitches

The second case there is exactly what I meant :wink:

The servo doesn’t have enough time to move to the new position before it is forced off by the lack of a proper signal.

Not sure I explained issue fully. That was the first thing I tried. That has same resuts. Taking it low, when it is high, is a new location command to the servo - just not the command you are expecting.

Depending on where on the “high” time line you are, will dictate where is goes. For example, if I am at 1ms into a high pulse and I force it low, the servo would go to zero degree as it sees the 1ms high bar. However, if I was currently holding a 1.5ms center instruction, you get idea of the issue. Disposing and/or going low seem to be same thing in terms of this side effect.

So, to do it cleanly, you can’t stop or overide pwm with next instruction until the current wave is allowed to finish and go low (or high depending on what your doing). In a sense, an individual period needs to be atomic to next instruction. Naturally, for a lot of things, this does may not matter much. But for servos on control surfaces and wheels are another story. Visualizing issue below makes it clearer.

Maybe it’s your servo? I use this method to turn servos off all the time and I never have any ill effects. The servo “instantly” stops in it’s tracks and does not move further. I have a mix of Traxxas and Futaba S3003 servos.

Not sure, maybe your getting lucky on the timing. I got lucky for awhile, until testing was giving me different results and I started looking deeper at the issue. I would think with some experiments, you could repro same thing. If you think about, the servo does not know your turning off, it just sees a new high time and does its deal to move to new position. Maybe higher quality servo electronics demand N number of same cmd before acting or some other noise filter logic.

Well, I can think of a few electrical ways to fix this in hardware, but I might ask first, why do you need to turn the servo off in the first place?

Thanks Chris. Not sure I actually need at this moment. I was doing dynamic create and dispose harness which would not be needed normally. At this point, it is more intellecual curiousity and a vendetta. As a coder, maybe this kind of 1-off issue is just an OCD thing that you think you need resolution on. Ever turn on/off a robot and have it jerk? This is probably reason why. On the other hand, turning off or disposing is not the most serious issue. If new cmds are “overlapping” last cmd, then you have the same potential issue in normal usage when sending new cmd changes which can jerk servo (i.e. back instead of forward) between movements. I ~think I have seen that happen during testing as well, but harder to see unless looking for it.

But how do you prevent the ‘jerk’ when it turns on? The servo is is some position unknown to the controller, chances are when you turn things on the servos will snap to whatever idle position the controller defaults to. If the position of the servo were known to the controller then you could handle it differently.

To prevent the jerk when disposing the object how about first changing the PWM signal to something with a really long low period then forcing it low then disposing it?

[italic]To prevent the jerk when disposing the object how about first changing the PWM signal to something with a really long low period then forcing it low then disposing it?[/italic]

It is a catch-22. Sending a low period or false when current cmd is high is root issue. The only “fix” is to latch new commands somehow. An api overload may be something like below. It will keep wave low when it goes low or return false on timeout. Only way to cleanly finish afaict. Not sure how they would hook the hardware to allow this. As sw pwm would be easy.

public bool TryKeepLow(uint usTimeout) {}
-or-
public bool TrySetPeriodOnLow(uint freqUs, uint period, uint usTimeout);

For the cobra, there is a Match interrupt for each of the 6 PWM channels. So it would be easy to create a synchronized off function.

I don’t have servo’s, but what would happen if you set the duty cycle to 0%? I’ve read in the NXP datasheet that changes to the duty cycle is synchronised with the current PWM signal.

Maybe I’m missing something, but I have several control loops that change the position of the wave many times a second on my servos. I have never seen any issue, same goes for yanking the line low to turn the servo off.

Has anyone actually ever observed any of these “jerks” or is this a purely theoretical discussion?

As from what I understand there is only an issue when stopping the PWM signal. Changing the duty cycle is not a problem since the processor uses shadow registers to synchronise the change.

That’s why I think, changing the duty to 0% could solve this issue.

Here is (bad) video. First snap shows move at end of 90deg center. Using 889 sleep before dispose. You have to experiment to find a delay that will hit right spot on your current wave.

Second shot, shows no finish movement. Only change is 1000ms sleep instead of 889. Can repro many times.

Also, no other method such as Set(false) or SetPulse(freq, 0) works either. Using Set(false) is same as dispose. The issue is not dispose as such. The end result is the same because we are stopping wave in the middle and that translates to a new movement position. You need to find a spot on the wave where it is low already, then stop and no issue. Playing with sleep time you can find the right spots (or other delays such as Print). So, it would not seem to not be accurate that NXP syncs cmds. Unless something else is going on. I don’t have a logic prob yet to show exact effect.

Is that little bit of movement really something to be concerned over?

No so much for this servo experiment, but depends on what your doing with pwm. what about CNC and jerks like that? That was like a 20deg move and could be larger depending on where False cuts off the wave and where your servo is. It could mean a great deal. It is the point of finding if this is an issue with hw PWM in general and syncing cmds to next low (or high). As this could be a latent issue waiting to catch people who use PWM for other things that may be more important then this. I was looking for a confirm and maybe a bug report needs filing.

How about instead of PWM use OutputCompare ?

OC is too unstable to use for servos in my experience. At least, most of my applications require high precision, and OC is not accurate enough for that.