3

I've been working on a project using the Pi ... I need to give PWM output but every one says that only one GPIO pin is compartible with PWM but i need 4 is there any way to give PWM output using 4 GPIO pins...

Plese help

5 Answers 5

2

An alternative way is to add hardware that can do the PWM, example PCA9685.

1

I for myself have made bad experiences using the pi and python for pwm. The software pwm the RPi.GPIO library provides is very prone to 'hick-ups' when ever any additional workload appears. In my case for example opening a ssh connection immediately caused an irregular flicker. It will work with any gpio the way Deepesh descibed. But you must not be sensitive to occasional failures in your motor speed/light intensity/what ever. Python on the raspberry pi will not do its purpose in case of pwm if you want to achieve good results! When using the Raspberry for pwm I would highly recommend using C for coding (if you are able to do so, use assembler. It's not so hard to implement pwm with assembler ;). Then using 4 or 5 pins for seperate pwm funktions should not be a problem, I guess. But - believe me - no python

1

Here is a pigpio version to send PWM at one frequency but with selected phase and duty cycle.

It may use as many GPIO as are available on the expansion header and should be glitch free. Since this way is based on pigpio class, you need to run the pigpio daemon before executing the following code.

sudo    pigpiod

By starting pigpio daemon, a number of setings are determined e.g. sample rate (1, 2, , 4, 5, 8, or 10 us, default 5 us).

#!/usr/bin/env python

import time
import pigpio  # http://abyz.me.uk/rpi/pigpio/
import wavePWM # http://abyz.me.uk/rpi/pigpio/code/wavePWM_py.zip

GPIO=[5, 6, 7, 8, 9, 10]

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

pwm = wavePWM.PWM(pi)

pwm.set_frequency(100)

for g in range(len(GPIO)):
   pwm.set_pulse_start_in_fraction(GPIO[g], g/6.0)

while True:
   try:

      for i in range(51):
         for g in range(len(GPIO)):
            pwm.set_pulse_length_in_fraction(GPIO[g], i/100.0)
         pwm.update() # apply the changes
         time.sleep(0.1)

      for i in range(51):
         for g in range(len(GPIO)):
            pwm.set_pulse_length_in_fraction(GPIO[g], (100-i)/100.0)
         pwm.update() # apply the changes
         time.sleep(0.1)

   except KeyboardInterrupt:
      break

pwm.cancel()

pi.stop()

enter image description here

0

Never mind, I found a way
Have a look at this:

import time
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)
GPIO.setup(4,GPIO.OUT)

while True:
    GPIO.output(4,True)
    time.sleep(0.00001)#1
    GPIO.output(4,False)
    time.sleep(0.02)#2
#This is how PWM works

Just increase the number of zeres after '.' in 1 to make the LED or whatever glow dimmer

12
  • 1
    Could we see the code you use for four LEDs with different brightness?
    – joan
    Aug 18, 2016 at 10:10
  • 1
    This will work to do a relatively crude form of PWM that's effective to control the brightness of an LED -- but anything with a granularity finer than 10 ms will probably be visibly inconsistent, and rack up processor time (i.e. waste system resources). It will never work to do the more precise sort of PWM required for servos, etc. If you have a 26 pin model and you want to do PWM on more than pin 18 you should probably look into the pigpio python bindings. The 40-pin models do have 4 PWM pins.
    – goldilocks
    Aug 18, 2016 at 12:44
  • @goldilocks I can't find any info that the 40-pin model has 4 PWM pins...
    – stevieb
    Aug 18, 2016 at 14:26
  • See here; the pins crossed out are only on 40-pin models. The only one that isn't crossed out which has a "PWM" function (they're light blue) is pin 18, but there are three more that are crossed out: 12, 13, and 19. I'm not a python user so I can't say how to use RPi.GPIO for this, but it involves setting the mode of the pin to something other than input or output, then configuring a PWM clock. There are potentially other ways to create a PWM pulse, but they require some more complex low level hacking which is why I recommended you try pigpio.
    – goldilocks
    Aug 18, 2016 at 14:34
  • 1
    @goldilocks Re PWM pins. GPIO 12/13/18/19 (and others on the compute module) may be set to PWM mode. However there are only two PWM channels. 12 and 18 share a channel so have exactly the same PWM settings, similarly 13 and 19 share a channel.
    – joan
    Aug 18, 2016 at 16:53
0

If you need to get a six step pwm for three phase inverter using Python, you can use the following code which creates six commutation signals. Each output has 60 degrees lag with the previous one (p1, p2, p3, p4, p5, p6). The firing signals are issued over GPIO2, GPIO3, GPIO4, GPIO17, GPIO27 and GPIO 22 which are the first lower left pins of the second row of raspberry pi IO pins.

Note that in practice as mentioned before, there are “hick-ups” or irregular flickers in the output pulses. If you are not required to have the duty cycle changes every 100 ms, simply comment out lines under While loop.

Python time sleep function is used to add delay in the execution of a program. We can use python sleep function to halt the execution of the program for given time in seconds. Notice that python time sleep function actually stops the execution of current thread only, not the whole program. Python sleep() is a method of python time module. So, first we have to import the time module then we can use this method.

The code compilation will be fine using "python3" in command line or Thonny in Raspbian Stretch (2019-04-08) if the indentation in the following lines is messy, get the .py file from here:

# pwm for 6 step firing with 100 Hz  frequency and 
changing duty cycle from 0 - 100%
import RPi.GPIO as IO         #calling header file which 
help us use GPIO'S of PI
import time   #calling time to provide delays in program
IO.setwarnings(False)       #don't show any warnings

#setting 6 GPIO pins as output for 6 step commutation
IO.setmode(IO.BCM)      #WE ARE PROGRAMMING THE gpio BY 
BCN PIN NUMBERS. (PIN35 AS 'GPIO19')
IO.setup(2,IO.OUT)      #initialize GPIO2 as an output
IO.setup(3,IO.OUT)      #initialize GPIO3 as an output
IO.setup(4,IO.OUT)      #initialize GPIO4 as an output
IO.setup(17,IO.OUT)      #initialize GPIO17 as an output
IO.setup(27,IO.OUT)      #initialize GPIO27 as an output
IO.setup(22,IO.OUT)      #initialize GPIO22 as an output

fr4pwm = 100
p1 = IO.PWM(2,fr4pwm)   #GPIO2 as PWM output with 100 HZ frequency
p2 = IO.PWM(3,fr4pwm)   #GPIO3 as PWM output with 100 HZ frequency
p3 = IO.PWM(4,fr4pwm)   #GPIO4 as PWM output with 100 HZ frequency
p4 = IO.PWM(17,fr4pwm)   #GPIO17 as PWM output with 100 HZ frequency
p5 = IO.PWM(27,fr4pwm)   #GPIO27 as PWM output with 100 HZ frequency
p6 = IO.PWM(22,fr4pwm)   #GPIO22 as PWM output with 100 HZ frequency


fireinterval = 1/(6*fr4pwm)
print(fireinterval)

p1.start(0)  #generate PWM signal with 0% duty cycle on 
GPIO2
time.sleep(fireinterval);   # interval bw firing pulses
p2.start(0)  #generate PWM signal with 0% duty cycle on 
GPIO3
time.sleep(fireinterval);   # interval bw firing pulses
p3.start(0)  #generate PWM signal with 0% duty cycle on 
GPIO4
time.sleep(fireinterval);   # interval bw firing pulses
p4.start(0)  #generate PWM signal with 0% duty cycle on 
GPIO17
time.sleep(fireinterval);   # interval bw firing pulses
p5.start(0)  #generate PWM signal with 0% duty cycle on 
GPIO27
time.sleep(fireinterval);   # interval bw firing pulses
p6.start(0)  #generate PWM signal with 0% duty cycle on 
GPIO22


try:
    while 1:    #execute loop forever
        for x in range(50): #execute loop for 50 times, x being incremented from 0 to 49.
            p1.ChangeDutyCycle(x)    # change duty cycle 
for varying the speed of ac motor.
            p2.ChangeDutyCycle(x)    # change duty cycle 
for varying the speed of ac motor.
            p3.ChangeDutyCycle(x)    # change duty cycle 
for varying the speed of ac motor.
            p4.ChangeDutyCycle(x)    # change duty cycle 
for varying the speed of ac motor.
            p5.ChangeDutyCycle(x)    # change duty cycle 
for varying the speed of ac motor.
            p6.ChangeDutyCycle(x)    # change duty cycle 
for varying the speed of ac motor.

            time.sleep(0.1) #sleep for 100 milli seconds

        for x in range(50): #EXECUTE LOOP FOR  50 TIMES 
X BEING INCREMENTED FROM 0 TO 49
            p1.ChangeDutyCycle(100-x)        #change 
duty cycle for changing the speed of ac motor.
            p2.ChangeDutyCycle(100-x)        #change 
duty cycle for changing the speed of ac motor.
            p3.ChangeDutyCycle(100-x)        #change 
duty cycle for changing the speed of ac motor.
            p4.ChangeDutyCycle(100-x)        #change 
duty cycle for changing the speed of ac motor.
            p5.ChangeDutyCycle(100-x)        #change 
duty cycle for changing the speed of ac motor.
            p6.ChangeDutyCycle(100-x)        #change 
duty cycle for changing the speed of ac motor.

            time.sleep(0.1) #sleep for 100 milli seconds
except KeyboardInterrupt:    # KeyboardInterrupt : user 
signal executed by user; by pressing Ctrl+C the 
following lines are executed
    p1.stop()  # stop pwm 1
    p2.stop()  # stop pwm 2
    p3.stop()  # stop pwm 3
    p4.stop()  # stop pwm 4
    p5.stop()  # stop pwm 5
    p6.stop()  # stop pwm 6
    IO.cleanup()  # sets the GPIO's to inital states 
(some High some Low)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.