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
Raspberry Pi Stack Exchange is a question and answer site for users and developers of hardware and software for Raspberry Pi. It only takes a minute to sign up.
Sign up to join this communityI 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
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()
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
pigpio
python bindings. The 40-pin models do have 4 PWM pins.
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
.
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)