3

I would like to set the motor speed of a RPLidar A3 which requires a 25 kHz PWM. So I played around with the following:

from RPi import GPIO GPIO.setmode(GPIO.BCM) GPIO.setup(12, GPIO.OUT) pwm = GPIO.PWM(12, 1000) pwm.start(50) 

Unfortunately, it seems the frequency is not 1 kHz, but 873 Hz and the jitter is HUUUUGGGE. With htop I make sure my RPI is very idle.

Last but not least, I cannot get a 25 kHz PWM, the highest seems to be 7.2 kHz.

Is that normal?

enter image description here

1
  • Pi.GPIO is updated with hardware PWM Commented Oct 12, 2021 at 0:41

4 Answers 4

4

pigpio supports DMA timed PWM on GPIO 0-31. This has restricted frequencies and resolution.

http://abyz.me.uk/rpi/pigpio/python.html#set_PWM_frequency

pigpio also drives hardware PWM on GPIO 12, 13, 18, and 19. This is more flexible and accurate.

http://abyz.me.uk/rpi/pigpio/python.html#hardware_PWM

There are different function calls for the two types of PWM.

7
  • Where did you get this info? Commented Oct 10, 2021 at 13:53
  • 1
    Added links to the Python API. Commented Oct 10, 2021 at 15:13
  • Damned! I've found this website before, but I thought it wasn't about RPI because of the URL name and the vintage look :) Commented Oct 10, 2021 at 15:16
  • @nowox pigpio is really useful, but my eyes see Pig Pi O not the intended Pi GPIO. Maybe yours did something similar. Commented Oct 11, 2021 at 10:06
  • 1
    @ChrisH Actually you are correct to say the name was for Pi GPIO which conveniently expresses its function. It's just I have always written it as pigpio and internally pronounced it as pig-pee-oh. Commented Oct 11, 2021 at 11:20
2

RPi.GPIO only has software PWM - which by its nature is imprecise.

pigpio has hardware timed PWM which is better (and also hardware PWM if you look hard enough).

bcm2835 has hardware PWM and so does WiringPi (but it is deprecated).

My clone of RPi.GPIO (Pi.GPIO) now has hardware PWM in the final stages of testing expected to be released in the next few days.

Pi.GPIO is updated and can be downloaded :-

git clone https://github.com/Milliways2/Pi.GPIO.git


The following code produces the trace below. (The BitScope is a bit slow to capture edges).

#! /usr/bin/env python3 """ """ import sys, os, time import Pi.GPIO as GPIO PWM0=12 PWM1=13 # Pi3 & earlier have 19.2MHz clock # DIVIDER=15 # gives a precise 10kHz signal # RANGE=128 # Pi4 has 54MHz clock # DIVIDER=36 # gives a precise 10kHz signal # RANGE=150 DIVIDER=45 # gives a precise 10kHz signal RANGE=120 def main(): GPIO.setmode(GPIO.BCM) GPIO.pwm_setmode(0) GPIO.pwm_setClock(DIVIDER) GPIO.pwm_setGpio(PWM0) GPIO.pwm_setGpio(PWM1) GPIO.pwm_setmode(GPIO.PWM_MODE_MS) GPIO.pwm_setRange(PWM1, RANGE) GPIO.pwm_Write(PWM1, RANGE//4) # duty cycle of 25% GPIO.pwm_setRange(PWM0, RANGE) GPIO.pwm_Write(PWM0, RANGE//2) # duty cycle of 50% if __name__ == '__main__': main() 

PWM 50kHz

8
  • Why is the RPI.GPIO not using the hardware PWM by default? I just noticed the pigpio requires the daemon pigpiod to be started. It looks cumbersome, isn't? Commented Oct 10, 2021 at 11:50
  • Also it seems with pi.set_PWM_frequency(12, 25000) I only get 8000. Is this the maximum? I don't find this information in the BCM2711 datasheet. Commented Oct 10, 2021 at 11:51
  • 1
    @nowox You would have the developer of RPI.GPIO, as for pigpio - yes you do need the daemon. I thought it would be relatively simple to add hardware PWM, but 2 months later I am forced to revise that opinion; the documentation is obtuse. Commented Oct 10, 2021 at 11:54
  • @nowox I have been running hardware PWM at 10 kHz for a couple of months (in c code) it is just the python which is causing me problems. There is no reason you can't run at a couple of MHz (although you lose resolution). It would only take a few minutes to test @ 100kHz but not tonight, it is already past bedtime. Commented Oct 10, 2021 at 11:59
  • I feel this is a good and reasonable answer, but I take issue with the claim that wiringPi is deprecated. AIUI, the original developer (Gordon) no longer supports wiringPi, but: 1) wiringPi still runs well on current RPi hardware, firmware & software releases, and 2) the wiringPi library remains available through GitHub, and is supported by a team that has assumed Gordon's role. Commented Oct 11, 2021 at 5:43
1

As Milliways said, you (me) are using the Python GPIO library which uses software emulated PWM, not the hardware PWM.

The easiest solution would be in you case to load the PWM overlay.

dtoverlay pwm pin=12 func=4 

Then export a new PWM channel

echo 0 > /sys/class/pwm/pwmchip0/export 

You can now set the period and the duty-cycle:

echo 40000 > /sys/class/pwm/pwmchip0/pwm0/period echo 10000 > /sys/class/pwm/pwmchip0/pwm0/duty_cycle echo 1 > /sys/class/pwm/pwmchip0/pwm0/enable 

What you have is what you want:

enter image description here

2
  • The sysfs interface is deprecated (although it is unlikely to disappear soon). The PWM is undocumented, and I have always been deterred by "Currently the clock must have been enabled and configured by other means" which is undefined. Commented Oct 11, 2021 at 1:43
  • If you are happy to use the command line interface, you would be better to use PIGS, which is documented and far more flexible. It works well for PWM. Commented Oct 11, 2021 at 1:45
1

I think the best method is to use a PWM HAT (Adafruit does one - but it seems not to work well with DC Servos) instead of using a RPi. This virtúally guarantees good timing and much less "strain" on the RPi.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.