This feature allows to control LEDs intensity, which can be used with RGB LED to mix colors.
First piece of code (05a-pwm.c) uses Raspberry's one and only hardware PWM pin (P1-12 GPIO 1). It is written in C and uses wiringPi.h library to control pulse width.
#include <wiringpi .h> #include <stdio.h> #include <stdlib.h> #include <stdint.h> int main (void) { int pin ; int l ; printf ("Raspberry Pi wiringPi PWM test program\n") ; if (wiringPiSetup () == -1) exit (1) ; for (pin = 0 ; pin < 8 ; ++pin) { pinMode (pin, OUTPUT) ; digitalWrite (pin, LOW) ; } pinMode (1, PWM_OUTPUT) ; for (;;) { for (l = 0 ; l < 1024 ; ++l) { pwmWrite (1, l) ; delay (1) ; } for (l = 1023 ; l >= 0 ; --l) { pwmWrite (1, l) ; delay (1) ; } } return 0 ; }
However Raspberry Pi offers only one hardware PWM pin, it is possible to use software PWM with other GPIO pins.
Next code (05b-pwm.py) is written in python and it demonstrates how software PWM could be implemented. In this example, one RGB LED is connected to GPIO pins as shown on the following figure.
The pyhon script simply cycles through red, green and blue color and exits.
#!/usr/bin/env python3 # script by Alex Eames http://RasPi.tv #http://RasPi.tv/2013/how-to-use-soft-pwm-in-rpi-gpio-pt-2-led-dimming-and-motor-speed-control # Using PWM with RPi.GPIO pt 2 - requires RPi.GPIO 0.5.2a or higher import RPi.GPIO as GPIO # always needed with RPi.GPIO from time import sleep # pull in the sleep function from time module GPIO.setmode(GPIO.BCM) # choose BCM or BOARD numbering schemes. I use BCM GPIO.setup(17, GPIO.OUT) GPIO.setup(27, GPIO.OUT) GPIO.setup(22, GPIO.OUT) r = GPIO.PWM(17, 50) # create object red for PWM on port 17 at 50 Hertz g = GPIO.PWM(27, 50) # create object green for PWM on port 27 at 50 Hertz b = GPIO.PWM(22, 50) # create object blue for PWM on port 22 at 50 Hertz r.start(0) # start red led on 0 percent duty cycle (off) g.start(0) # start green led on 0 percent duty cycle (off) b.start(0) # start blue led on 0 percent duty cycle (off) # now the fun starts, we'll vary the duty cycle to # dim/brighten the leds, so one is bright while the other is dim pause_time = 0.05 # you can change this to slow down/speed up try: # while True: for i in range(0,101): # 101 because it stops when it finishes 100 r.ChangeDutyCycle(i) sleep(pause_time) for i in range(100,-1,-1): # from 100 to zero in steps of -1 r.ChangeDutyCycle(i) sleep(pause_time) for i in range(0,101): # 101 because it stops when it finishes 100 g.ChangeDutyCycle(i) sleep(pause_time) for i in range(100,-1,-1): # from 100 to zero in steps of -1 g.ChangeDutyCycle(i) sleep(pause_time) for i in range(0,101): # 101 because it stops when it finishes 100 b.ChangeDutyCycle(i) sleep(pause_time) for i in range(100,-1,-1): # from 100 to zero in steps of -1 b.ChangeDutyCycle(i) sleep(pause_time) except KeyboardInterrupt: r.stop() # stop the red PWM output g.stop() # stop the green PWM output b.stop() # stop the blue PWM output GPIO.cleanup() # clean up GPIO on CTRL+C exit
This intensity control is used in the following script (05c-pwn-colors.py) which adds a few features. It enables to control each color (and prints current value of colors from -100 to +100, where -100 and +100 is 0% pulse width and 0 is 100% pulse width).
Usage:
r RED+ e RED- g GREEN+ f GREEN- b BLUE+ b BLUE- a add colors s sub colors h show this help q quit
#!/usr/bin/env python3 import RPi.GPIO as GPIO from time import sleep import signal GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) GPIO.setup(17, GPIO.OUT) GPIO.setup(27, GPIO.OUT) GPIO.setup(22, GPIO.OUT) # define LED connection @ 75Hz r = GPIO.PWM(17, 75) g = GPIO.PWM(27, 75) b = GPIO.PWM(22, 75) r.start(0) g.start(0) b.start(0) # initial values col_r=-100 col_g=-100 col_b=-100 def usage(): print (''' krisko 2014 Script for adjusting RGB LED color intensity (uses software PWM) USAGE: r RED+ e RED- g GREEN+ f GREEN- b BLUE+ b BLUE- a add colors s sub colors h show this help q quit ''') # set color intensity (operation add/sub, col_X -100 - +100, color r/g/b) def col_adjust(op, col_r, col_g, col_b, color): if (op == "add"): if (color == "r") and (col_r < 100): col_r+=1 elif (color == "g") and (col_g < 100): col_g+=1 elif (color == "b") and (col_b < 100): col_b+=1 elif (op == "sub"): if (color == "r") and (col_r > -100): col_r-=1 elif (color == "g") and (col_g > -100): col_g-=1 elif (color == "b") and (col_b > -100): col_b-=1 set_color(col_r, col_g, col_b) return {'col_b':col_b, 'col_g':col_g, 'col_r':col_r} def set_color(col_r, col_g, col_b): if (col_r >= 0): col_r=(col_r*(-1))+100 else: col_r+=100 if (col_g >= 0): col_g=(col_g*(-1))+100 else: col_g+=100 if (col_b >= 0): col_b=(col_b*(-1))+100 else: col_b+=100 r.ChangeDutyCycle(col_r) g.ChangeDutyCycle(col_g) b.ChangeDutyCycle(col_b) def col_spectrum(op, col_r, col_g, col_b): if (op == "add"): if (col_b < 50) and (col_r != 100 ) and (col_g != 100): col_b+=1 return {'col_b':col_b, 'col_g':col_g, 'col_r':col_r} elif (col_b < 100) and (col_r != 100) and (col_g != 100): col_b+=1 col_g+=1 return {'col_b':col_b, 'col_g':col_g, 'col_r':col_r} elif (col_g < 0) and (col_r != 100): col_g+=1 return {'col_b':col_b, 'col_g':col_g, 'col_r':col_r} elif (col_r < 0) and (col_r != 100): col_g+=1 col_r+=1 return {'col_b':col_b, 'col_g':col_g, 'col_r':col_r} elif (col_r < 100) and (col_r != 100) and (col_b == 100): col_r+=1 return {'col_b':col_b, 'col_g':col_g, 'col_r':col_r} elif (col_g == 100) and (col_r > 0) and (col_b > 0): col_b-=1 col_r-=1 return {'col_b':col_b, 'col_g':col_g, 'col_r':col_r} else: return {'col_b':col_b, 'col_g':col_g, 'col_r':col_r} elif (op == "sub"): if (col_r != 100) and (col_b != 100) and (col_g == 100): col_b+=1 col_r+=1 return {'col_b':col_b, 'col_g':col_g, 'col_r':col_r} elif (col_r > 0): col_r-=1 return {'col_b':col_b, 'col_g':col_g, 'col_r':col_r} elif (col_r > -100): col_r-=1 col_g-=1 return {'col_b':col_b, 'col_g':col_g, 'col_r':col_r} elif (col_g > -50): col_g-=1 return {'col_b':col_b, 'col_g':col_g, 'col_r':col_r} elif (col_g > -100): col_b-=1 col_g-=1 return {'col_b':col_b, 'col_g':col_g, 'col_r':col_r} elif (col_b > -100): col_b-=1 return {'col_b':col_b, 'col_g':col_g, 'col_r':col_r} else: return {'col_b':col_b, 'col_g':col_g, 'col_r':col_r} #def signal_handler(signal, frame): # print('You pressed Ctrl+C!') # sys.exit(0) #signal.signal(signal.SIGINT, signal_handler) #def init_worker(): # signal.signal(signal.SIGTERM, signal.SIG_TERM) # do the cleanup before exit def cleanup(): r.stop() g.stop() b.stop() GPIO.cleanup() # read one char from stdin def func(): import sys, tty, termios fd = sys.stdin.fileno() old_settings = termios.tcgetattr(fd) try: tty.setraw(sys.stdin.fileno()) ch = sys.stdin.read(1) finally: termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) if ( ch == "q" ): cleanup() sys.exit(0) return ch print ("Press 'q' to quit, 'h' to show help.") # read stdin in a loop while True: char=func() if char == "r": col_new=col_adjust("add", col_r, col_g, col_b, "r") elif char == "e": col_new=col_adjust("sub", col_r, col_g, col_b, "r") elif char == "g": col_new=col_adjust("add", col_r, col_g, col_b, "g") elif char == "f": col_new=col_adjust("sub", col_r, col_g, col_b, "g") elif char == "b": col_new=col_adjust("add", col_r, col_g, col_b, "b") elif char == "v": col_new=col_adjust("sub", col_r, col_g, col_b, "b") elif char == "a": col_new=col_spectrum("add", col_r, col_g, col_b) elif char == "s": col_new=col_spectrum("sub", col_r, col_g, col_b) elif char == "h": usage() else: print ("Unknown function or color out of range. Type 'q' to quit") col_b=col_new['col_b'] col_g=col_new['col_g'] col_r=col_new['col_r'] set_color(col_r, col_g, col_b) print("COLOR R:", col_r, "G:", col_g, "B:", col_b)Function func is used to capture input from keyboard.
Function col_adjust handles individual R, G and B color change.
Function col_spectrum uses simple algorithm to go through color spectrum. It has far from being perfect, but it's sufficient as a simple example. Following scheme demonstrates approximately how the colors are mixed up:
No comments:
Post a Comment