Is there any possible way to get pwm in dragonboard


#1

At present i am working in a project that needs pwm to control servo motor. Is there any way to get pwm from dragonboard to control servo motor. i am using linaro debian version.


#2

Unfortunately neither the SoC nor the board have PWM devices.

An option would be using a real-time supported kernel and soft-generate the PWM signal required to control the servo motor.

I validated the concept on the Dragon 410c and the Hikey 96 Boards using Xenomai/Cobalt as the real-time provider and the Grove motor that comes with the 96Boards Sensor Kit.

You can find the rtdm driver in my Xenomai tree together with a test program

The issue with this approach however is that Xenomai doesnt track the kernel tip (only stable) while the Dragon 410c doesn’t maintain a stable branch, so you would have to use a relatively old kernel (replacing the kernel in release 15.07 )


#3

Much easier to control servos with a PCA9685 IC over the I2C bus. The PCA9685 was originally intended to drive LEDs but can generate the appropriate PWM waves to control up to 16 servos simulataneously. A breakout board for it is available from Adafruit among other places.


#4

Of course you can hook a PWM device to the i2c bus or the usb bus [1] or simply use a uart[2] to control it. And of course using dedicated pwm hardware will be safer and probably more stable (is it necessary to state the obvious?)

But you can also use the CPU and one of the gpios to generate a pwm signal for prototyping (and who knows, depending on the use case this might be a good enough solution). That alternative was my point. Maybe this blog entry might help clarifying with some of the complexity.

[1] http://hackaday.com/2015/12/16/taking-the-pulse-width-modulation-of-an-fpga/
[2] http://hackaday.com/2015/12/18/a-tiny-servo-motor-controller/


#5

@santhosh

One user asked about using the PWM_SLICE register area to generate a PWM signal
(pg 717 of https://developer.qualcomm.com/download/sd410/pm8916-hardware-register-description.pdf)

Maybe you can have a look? I don’t think anyone is using this region in the Debian release (I did ask the Qualcomm folks but got no responses from them)


#6

So it looks like DragonBoard DOES have PWM output on the “Multi Purpose” Pin. Which is also the only ADC input. The schematic says that this pin on the PM8916 is intended to control white backlight LED, which a DragonBoard project might not need. So how general purpose is this output?

The PM8916 doc that @ldts-jro pointed to documents a PWM_SLICE set of values. Do these pertain to the PWM MPP output, or do they pertain to the PWM involved in the LDO voltage regulators? Supposing the former, the registers look like they can set a wide range of frequency. Meanwhile, for pulse width, the PWM_VALUE settings appear to take 9 bits, though the SYNC_PWM variable refers to “6/9-bit PWM value”.

Any comments on whether it’s practical to use this output for general purpose PWM, and also specifically to control low-cost (“hobby”) servos that use nominally 1ms +/- 0.5ms pulses within a 50ms repetition rate? (So a relatively small baseline pulse proportion, for which this output might lack fine granularity.)


#7

Hello Gwideman,
Can you help me to access the PWM_slice register access via function call for android version.


#8

Hello,

In android, LPG(Light Pulse Driver) is already upstreamed which can be used to generate PWM using PM8916. You can find the device tree binding for the same here.

Although the driver is intended to control backlight for displays, it can be used to control some low end servos also.

Hope this helps!

Thanks,
Mani


#9

Mani, it sounds like you know something about control of servos. So I’ll repeat the question I asked almost two years ago, and that is how suitable is this PWM output for driving a servo? Bear in mind that such servos needs a pulse in the range of 0.5ms to 1.5ms (or possibly 1 to 2 ms), on 20ms intervals. That is to say, the range of the servo is spread over just 5% of the duty cycle. In a typical application one would want to be able to control a 120 degree servo to say 5 deg or better, so that’s 5%/24, so about a 0.2% step in the PWM duty cycle. From the tech docs it was not clear that the PWM output could achieve that resolution. Bottom line, it would be useful to know what the PWM resolution is for that output.


#10

Hello Mani,

thank you for your reply, I’m trying to enable the GPIO_QPNP_PIN via kernelconfig by default it is disable. how to enable the GPIO_QPNP_PIN? i used the kernel stack which u mentioned in earlier message.

thanks in advance,
regards,
Chaithra


#11

Hi @gwideman,

Your requirement for controlling servos is nominal as most of the servos would require 1.5ms duty cycle and 20ms pulse duration. But as far as I can see from the aosp driver [1] the minimum supported pulse frequency seems to be 1KHz (1 ms). So, I don’t think it can drive this requirement. But I may be wrong, it would be better to get the answer from @ljking on the hardware capability.

As I said before, this LPG module is truly designed for backlight control so no surprise!

[1] https://android.googlesource.com/kernel/msm/+/android-msm-angler-3.10-marshmallow-dr/drivers/pwm/pwm-qpnp.c


#12

Hi @chaithra.abhimanyu,

For getting this driver, you need to enable CONFIG_PWM_QPNP Kconfig option in defconfig [1].

[1] https://android.googlesource.com/kernel/msm/+/android-msm-angler-3.10-marshmallow-dr/arch/arm64/configs/msm_defconfig


#13

Ah, very good point. If the longest interval that can be set is 1ms, this will not work with widely available hobby servos, regardless of resolution of the duty cycle.


#14

From the documentation we have:

pwm_frequency = clock / ((2 ^ exp) * divide)

where clock can be 1kHz, 32kHz or 19.2MHz, exponent can be 0-7 and divide can be 1, 3, 5 or 6

As such the minimum frequency should be 1000 / (2^7 * 6), which looks to be a
minimum duty cycle of 760ms. The pwm size can be specified as either 6 or 9
bits, which if I interpret the documentation correctly defines the period.

So I think the longest period you can set is 393 seconds (512 * 1/freq), with
duty being a multiple of 760ms. So I believe you should be able to find some
configuration inbetween that suits your timing needs.