In a previous post, http://smokespark.blogspot.co.uk/2013/04/15-programming-attiny85-with.html I experimented with RGB LEDs and control of LED brightness using Pulse Width Modulation (PWM). That post includes explanations of how our human Persistence of Vision (POV) enables us to perceive a flashing LED as having less than maximum brightness. That was using the ATMega 328 (Arduino) chip to program an ATTiny85 microchip to produce Pulse Width Modulation.
The difference here, of course, is that we are programming the Raspberry Pi in the Python language. Not only are there coding differences, but we are working with 3V3 from the Pi's GPIO logic levels instead of 5V.
The circuit is a bit simpler than the last post at
http://smokespark.blogspot.co.uk/2014/10/55-exploring-pis-gpio-ports.html. The switches have been removed as there are now no input GPIO ports, only outputs corresponding to the red, green and blue anodes of the RGB LED. So the RGB LED is wired exactly the same as before - with its common cathode going to GND through a 325Ω resistor. You may have noticed that I still have wires running to GPIO ports 21, 22 and 23. These are not connected to anything on the breadboard - I just forgot to remove them when I took off the switches!
What the experiment does is simply to increase the brightness of the red LED from zero to maximum, decrease it back to zero, move on the green LED, do the same, and then do this all over again for the blue LED. The routine is in an infinite loop, but can be terminated gracefully by pressing CTRL-C on the keyboard:
For this video, I turned the ambient lighting down, as the LED colours all look white to the camera, in bright light. You can see that there is a little bit of flicker, and this is intentional. With a frequency of 40 hertz (40 Hz), my personal vision can detect flicker when the LEDs are in the dim part of their cycle. A higher frequency will easily remove this flicker.
It's interesting that this looping program doesn't use much in the way of processor resources. You can see from the above image of the Pi's desktop, that the Raspberry Pi's CPU indicator is fairly activity-free, presumably because the code keeps the processor in the idle state for most of the time with the sleep() command.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python2.7 | |
# script by Sparks N Smoke for SOFTWARE control of LEDs with Pulse Width Modulation | |
import RPi.GPIO as GPIO | |
from time import sleep | |
GPIO.setmode(GPIO.BCM) | |
GPIO.setup(24, GPIO.OUT) # LED Red PWM port - can use any GPIO port ! | |
GPIO.setup(25, GPIO.OUT) # LED Green PWM port | |
GPIO.setup(26, GPIO.OUT) # LED Blue PWM port | |
frequency = 40 # set the LED pulse cycle frequency (40 Hertz) | |
delay = 0.02 # set no of secs to wait on duty cycle change | |
Red = GPIO.PWM(24, frequency) # set port 24 to 40 Hertz | |
Green = GPIO.PWM(25, frequency) # set port 13 to 40 Hertz | |
Blue = GPIO.PWM(26, frequency) # set port 18 to 40 Hertz | |
Red.start(0) # start with 0% duty cycle | |
Green.start(0) | |
Blue.start(0) | |
try: | |
while True: | |
for i in range (0, 101, 1): # 100 is the last value executed | |
Red.ChangeDutyCycle(i) # change duty cycle to the value of i (going UP) | |
sleep(delay) # linger a while at each step with RED | |
for i in range (100, -1, -1): # 0 is the last value executed | |
Red.ChangeDutyCycle(i) # value of duty cycle going DOWN | |
sleep(delay) | |
sleep(delay*5) # linger a bit longer with the LED off completely | |
for i in range (0, 101, 1): # now deal with GREEN | |
Green.ChangeDutyCycle(i) | |
sleep(delay) | |
for i in range (100, -1, -1): | |
Green.ChangeDutyCycle(i) | |
sleep(delay) | |
sleep(delay*5) | |
for i in range (0, 101, 1): # now deal with BLUE | |
Blue.ChangeDutyCycle(i) | |
sleep(delay) | |
for i in range (100, -1, -1): | |
Blue.ChangeDutyCycle(i) | |
sleep(delay) | |
sleep(delay*5) | |
except KeyboardInterrupt: | |
print " CTRL-C detected" | |
Red.stop() | |
Green.stop() | |
Blue.stop() | |
GPIO.cleanup() # Reset ports on CTRL-C | |
* servos require accurately timed pulses - which software alone cannot always provide, but GPIO18 with special software can (not sure I understand the subtleties here).
No comments:
Post a Comment