Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PWM/servo update during active pulse leads to erratic servo movment #18

Open
Heideachim opened this issue Nov 21, 2020 · 5 comments
Open

Comments

@Heideachim
Copy link

Heideachim commented Nov 21, 2020

When using the PWM module to drive a servo motor there is some erratic movement of the motor shaft at arbitrary times. This is best observed when issuing very small increments of the motor's position, e. g. by 1°:
grafik

This happens when the update of the PWM pulsewidth collides with the on pulse. Cf. the following screenshot: The left and right impulses are the correct ones. The middle one is distorted, since it is cut short by the update of the PWM register (the left impulse is "1° shorter" then the right impulse). The yellow curve is the PWM output to the servo while the blue one is the motor supply. As you can see, 2ms after the too-short pulse the servo tries to attain the wrong pulse length.

grafik

Is this known behaviour?

I digged into the DAL but had to stop in MicroBitPin.cpp: the function MicroBitPin::setServoPulseUs() ends in a call to DynamicPwm::pulsewidth_us() which I could not locate anywhere. If someone could point to into the right direction...?

@Heideachim
Copy link
Author

Jetzt habe ich das Gleiche mit einem micro:bit ausprobiert - da funktioniert es! Damit sollte sich die Ursache für Calliopes Servo-"Stottern" schnell finden lassen, indem man die (doch recht ähnliche, oder?) Bibliotheken vergleicht. Kann da jemand helfen?

@joernalraun
Copy link
Member

This is a new finding, at least to me. I don't see a reason why there should be a different library for using a servo. I hope I will find some time to compare things next week. However, maybe someone else is quicker?

@Heideachim
Copy link
Author

Here is a video of the same program running on a micro:bit and on a Calliope: https://youtu.be/mbcGppGzQGw
On the Calliope, there is some erratic behaviour. It occurs not always, it seems to be a beat effect between the disturbance and the setting of a new PWM value.
The micro:bit works as expected.

@Heideachim
Copy link
Author

Heideachim commented Nov 28, 2020

Oszillograph of Calliope and micro:bit look the same. Top curve (yellow) is Calliope, bottom (blue) one is micro:bit:
grafik
On Calliopes input line you can see the disturbance created by the servo's spike movement.

@Heideachim
Copy link
Author

Here is a summary of my findings:

  • It is independent of the servo (a servo working with the micro:bit shows erratic behaviour with Calliope and vice versa).
  • It does not change with servo supply voltage.
  • It only occurs when updating the pulse length. If there is no update, the servo is perfectly stable. If there is a repeated update with the same value (so you should not get any movement), the servo will behave erratically.
  • Even when a pulse is cut short, the period of the PWM is 20ms.
  • The behavour is the some for PAD0 and PAD1. If Pin4 is used, the signal is even more disturbed.

Here is the call stack of an update of the pulse length:

  • MicroBitPin::setServoValue(int value, int range, int center): calls setServoPulseUs(scaled / 1000);
  • int MicroBitPin::setServoPulseUs(int pulseWidth):
    • calls ((DynamicPwm *)pin)->setPeriodUs(MICROBIT_DEFAULT_PWM_PERIOD) if the pulsewidth is not correct
    • calls ((DynamicPwm *)pin)->pulsewidth_us(pulseWidth);
  • DynamicPwm is derived from mbed's PwmOut, so PwmOut::pulswidth_us(int us) is called (documentation: os.mbed.com)

This code is almost identical for the micro:bit and the Calliope (MicroBitPin.cpp, DynamicPwm.cpp, and DynamicPwm.h are the same; MicroBitPin.h has different pin names). I assume, the PwmOut::pulswidth_us is really widely proven, so this shouldn't be the problem. But then, where does it come from?? Are there repeated calls to setPeriodUs()? I may output servo PWM to C4 as well - but this is already used for the 5x5 LEDs. And the signal of C4 is heavily distorted - is there something going on with a refresh operation somewhere else??

IMHO, someone should try to repeat this setup. The most simple program to reproduce this error is the following:

grafik

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants