Saturday, 25 May 2013

Controlling a RGB LED with a Raspberry Pi

You can use the General Purpose IO pins on a Raspberry Pi to easily control an LED. If you choose a three colour red-green-blue (RGB) LED you can mix these colours to create a wide range of colours, in the same way a pixel on your screen does.

I used a common cathode RGB LED, wiring the cathode to the ground pin on the Pi. Then the three legs are each wired to a GPIO pin on the board. In this case red to 12, green to 16 and blue to 18.

From the datasheet and the GPIO outputs I'd calculated the following resistances were needed between the LED and the GPIO's 3.3V supply. If you're using different LEDs check their current draw and typical forward voltage and use Ohm's law to calculate the resistor you need (or use the handy LED Resistor Calculator).

Assuming a 20mA current draw per leg:

Colour Typical Fwd Voltage Internal  Additional Commonly Available
Red
1.9V
95Ω
70Ω
68Ω
Green
3.3V
165Ω
-
Blue
3.2V
160Ω
10Ω

But using these resulted in the green and blue were much brighter than the red, so when all the colours were on at the same time to create a 'white' light, it was distinctly blue. The yellow (red and green mixed) also came out very green.

After some experimenting with different resistor values and measuring with a multi-meter I managed to achieve an even white colour with the values below.

Colour Resistor Used Measured Voltage   Drop   
Red 1.88V
Green 220Ω 2.66V
Blue 100Ω 2.69V





I used the Python GPIO library that comes with Raspbian, which recently added an experimental Pulse Width Modulation (PWM) feature , so make sure you follow the update instructions to make sure you have version 0.5.2a or later.

I included a small function that cycles through each colour at different speeds so the colour changes, creating an effect similar to Mitch Altman's Trippy RGB Waves Kit that I saw a couple of weeks ago at the Bristol Hackspace
 #!/usr/bin/python3  
 #Controlling a RGB LED with built in PWM.  
 #Mostly copied from GPIO PWM example:  
 #http://code.google.com/p/raspberry-gpio-python/wiki/PWM  
   
 import time  
 import RPi.GPIO as GPIO  
 import math  
   
   
 GPIO.setmode(GPIO.BOARD)  
 red = 12 #pin numbers to match LED legs  
 green = 16  
 blue = 18  
   
 GPIO.setup(red, GPIO.OUT) #setup all the pins  
 GPIO.setup(green, GPIO.OUT)  
 GPIO.setup(blue, GPIO.OUT)  
   
 Freq = 100 #Hz  
   
 #setup all the colours  
 RED = GPIO.PWM(red, Freq) #Pin, frequency  
 RED.start(0) #Initial duty cycle of 0, so off  
 GREEN = GPIO.PWM(green, Freq)    
 GREEN.start(0)   
 BLUE = GPIO.PWM(blue, Freq)  
 BLUE.start(0)  
   
 def colour(R, G, B, on_time):  
   #colour brightness range is 0-100  
   RED.ChangeDutyCycle(R)  
   GREEN.ChangeDutyCycle(G)  
   BLUE.ChangeDutyCycle(B)  
   time.sleep(on_time)  
   
   #turn everything off  
   RED.ChangeDutyCycle(0)  
   GREEN.ChangeDutyCycle(0)  
   BLUE.ChangeDutyCycle(0)  
   
 def PosSinWave(amplitude, angle, frequency):  
   #angle in degrees  
   #creates a positive sin wave between 0 and amplitude*2  
   return amplitude + (amplitude * math.sin(math.radians(angle)*frequency) )  
   
 try:  
     
   while 1:  
     for i in range(0, 720, 5):  
       colour( PosSinWave(50, i, 0.5),  
           PosSinWave(50, i, 1),  
           PosSinWave(50, i, 2),  
           0.1 )  
       
 except KeyboardInterrupt:  
   pass  
   
 #Stop all the PWM objects  
 RED.stop()  
 GREEN.stop()  
 BLUE.stop()  
   
 #Tidy up and remaining connections.  
 GPIO.cleanup()