1

I need to control the PWM module on the raspberry pi. I’m now familiar with pigpio, and with hardware_PWM. However, I did not find anywhere where I can control the total duration of the PWM. Example: turn off after 50 clock cycles. Also, what would be the most accurate way in doing so using python?

My pulses can vary in duty cycle, and are between 0-1khz. I tried sing the software pwm but it couldn’t get to 1khz, but when I tried using the hardware_pwm it was honestly perfect. But I can’t control it.

George
  • 99
  • 6
  • For general python PWM programming, the following might help: (1) https://raspberrypi.stackexchange.com/questions/99315/run-the-program-in-the-laptop-and-use-the-raspberry-gpios-pwm-to-control-servos (2) https://raspberrypi.stackexchange.com/questions/102269/rpi4b-pca9685-pwm-controlling-servo-problem (3) https://raspberrypi.stackexchange.com/questions/102115/slight-dip-on-the-gpio-5v-line-when-leds-are-on (4) https://raspberrypi.stackexchange.com/questions/99408/pin-powered-pi-crashes-when-servos-move, / to continue, ... – tlfong01 Feb 14 '20 at 04:08
  • For precise PWM timing, I recommend PCM9685: "RPi4B PCA9685 PWM Controlling Servo Problem": (1) https://raspberrypi.stackexchange.com/questions/99315/run-the-program-in-the-laptop-and-use-the-raspberry-gpios-pwm-to-control-servos – tlfong01 Feb 14 '20 at 04:10
  • 1
    Thank you I will look into these – George Feb 14 '20 at 13:12
  • you are welcome. Cheers – tlfong01 Feb 14 '20 at 13:46
  • Hi @George, And in case you need a very precise sig gen < 150kHz, you might like to consider this: (1) UART Controlled 1Hz to 150kHz PWM Signal Generators Forum Discussion https://raspberrypi.stackexchange.com/questions/104779/how-can-rpi4b-python-uart-talk-to-xy-pwm-signal-generators (2) AliExpress UART Controlled 1Hz to 150kHz PWM Signal Generators - US$2 https://www.aliexpress.com/i/32873543514.html. – tlfong01 Feb 14 '20 at 13:55
  • 1
    I will look into these and see if it's a feasible option. I really wanted to try and use the existing hardware if possible to not add more elements to my circuit. But if all fails, I will have to look into these options. Thank you – George Feb 14 '20 at 14:52
  • Yes, I agree with you. What I suggest is for bench testing to troubleshoot the field version. Actually I also use very space saving through hole Analog Device chips, and from time to time dirt cheap 555 based modules. I forgot if you are using the Rpi's 4 hardware PWM pins, ... You might give me more details and perhaps I can suggest other software workarounds. – tlfong01 Feb 15 '20 at 01:41
  • 1
    Thank you. I'm going to see if the waves option that joan suggested is going to work. I'll get back to the post in a few. – George Feb 15 '20 at 20:49
  • you are welcome. It is always a good idea to explore different directions and solutions, and do engineering trade off and business cost benefit analysis, to find which one is best for your situation and time frame etc. Good luck and cheers. – tlfong01 Feb 16 '20 at 01:19

1 Answers1

0

If the pulses aren't very fast and you don't mind jitter you could do it in software. Untested Python.

def send_PWM(GPIO, pulses, frequency, dutycycle):

   # dutycycle expected to be in range 0.0 to 1.0

   duration = 1.0 / frequency
   on_period = duration * dutycycle
   off_period = duration - on_period

   for i in range(pulses):
      pi.write(GPIO, 1)
      time.sleep(on_period)
      pi.write(GPIO, 0)
      time.sleep(off_period)

If the pulses are fast (say the 100 kHz or less region) and you don't like jitter you could use a wave chain.

There are various examples of using waves at http://abyz.me.uk/rpi/pigpio/examples.html

Here is an example using waves and wave chains.

#!/usr/bin/env python

import time
import pigpio

def tx_pulses(pi, GPIO, frequency, num, dutycycle=0.5):
   assert 1 <= frequency <= 500000
   assert 1 <= num <= 65535
   assert 0.0 <= dutycycle <= 1.0

   duration = int(1000000/frequency)

   on_micros = int(duration * dutycycle)

   num_low = num % 256
   num_high = num // 256

   wf = []

   #                           on      off    time
   wf.append(pigpio.pulse(1<<GPIO,       0, on_micros))
   wf.append(pigpio.pulse(      0, 1<<GPIO, duration - on_micros))

   pi.wave_add_generic(wf)

   wid = pi.wave_create()

   if wid >= 0:
      pi.wave_chain([255, 0, wid, 255, 1, num_low, num_high])
      while pi.wave_tx_busy():
         time.sleep(0.01)
      pi.wave_delete(wid)

pi = pigpio.pi()
if not pi.connected:
   exit()

GPIO=19

pi.set_mode(GPIO, pigpio.OUTPUT)

tx_pulses(pi, GPIO, 100, 25) # 25 pulses @ 100 Hz 50% duty

tx_pulses(pi, GPIO, 1000, 250, 0.1) # 250 pulses @ 1000 Hz 10% duty

tx_pulses(pi, GPIO, 5000, 2391, 0.03) # 2391 pulses @ 5000 Hz 3% duty

pi.stop()
joan
  • 67,803
  • 5
  • 67
  • 102
  • My pulses can vary in duty cycle, and are between 0-1khz. I tried sing the software pwm but it couldn’t get to 1khz, but when I tried using the hardware_pwm it was honestly perfect. But I can’t control it. The wave chain looks neat since I can looo it for an x amount, I’ll need to look more into that. It says it disables the hardwsre_PWM tho – George Feb 14 '20 at 13:16
  • Yes, waves use PWM and PCM so no audio from them. When I get time I will add a wave chain example to the answer. – joan Feb 14 '20 at 14:22