RGB-LED Lesson 1 – Creating Python Libraries (& Colours)
This lesson will introduce creating and using your own library to provide low level control of the GPIO, while hiding away the detail inside.
Plus, you can have a Disco and even touch the Rainbow!
If you don’t have the kit don’t worry since much of the information in this lesson can be applied to other GPIO control projects and using Python generally, you just miss out on the beautiful colours…
Set-up:
For details about the assumed hardware and software set-up, please see “Lesson 0” or the RGB-LED User Manual.
Be Structured:
When developing code it is useful to split your project into clear logical sections, so that you can easily separate and test each component individually before combining into a more complex and difficult to test system. Each component should be self-contained as much as possible, with clearly defined interfaces, so that the module can be used without needing to worry about the details contained within.

By structuring your system into logical layers, you can separate your application specific actions from your hardware implementation to aid development and testing.
Easy Testing:
When you have well designed components, it is easy to replace some of the modules with test versions, which can contain extra debugging messages, logging or even simulate hardware being attached. This can be particularly useful when writing code for development projects, where not all of the system is not available (still being developed) or when expensive hardware is being used.
As an example, we shall create the following script which will allow us to develop and test our RGB-LED python scripts without the hardware, and even develop them on a windows machine without any GPIO (if required).
Script: testRPiGPIO.py
#!/usr/bin/python BOARD = "board" BCM = "bcm" OUT = "out" IN = "in" def output(pin,value): print pin, ":", value def setmode(mode): print mode def setup(pin,value): print pin, ":", value def cleanup(): print "clean-up" #End
With the above script, we can replace the import of the RPi.GPIO library with this “test” library.
import RPi.GPIO as GPIO
with:
#import RPi.GPIO as GPIO #Use for Raspberry Pi GPIO import testRPiGPIO as GPIO #Use for Debugging GPIO
Using our previous script from lesson 0, we get the following result.
board 12 : out 16 : out 18 : out 22 : out 7 : out 11 : out 13 : out 15 : out 12 : 1 16 : 1 18 : 1 22 : 1 7 : 1 11 : 0 13 : 0 15 : 0 12 : 0 11 : 1 12 : 1 11 : 0 12 : 1 16 : 1 18 : 1 22 : 1 7 : 1 11 : 0 13 : 0 15 : 0 clean-up
While it may just look like a series of numbers, looking closer we can see the sequence of operations from our program from before.
Lines 1-9 – We setup the GPIO and output pins.
Lines 10-18 – We put the pins to their default values.
Lines 19-20 – We activate the RED LED.
Lines 21-22 – We deactivate the RED LED.
Lines 23-31 – Finally we set the pins to default and release the GPIO.
If you are using the Kit and a Raspberry Pi, just move the # mark to enable the RPi.GPIO and comment out the test library to access the GPIO again.
Creating Our Library:
We can make our previous rgbledtest.py script more useful by turning it into a library.
Take a copy of it and name it rgbled.py, this will be our new library. The file still contains the original main() function which runs some simple tests, we can keep this, but we do not want it to run if we import it into another file.
By adding the following line, before the call to main() our previous test code will now only be called if the script is run directly from the command line (like before).
if __name__=='__main__': main() #End
While we updating our file, we can tidy a few things up by adding a small function to clean up led_cleanup(), and move the call to led_clear() into led_setup().
def led_setup(): #Set up the wiring GPIO.setmode(GPIO.BOARD) # Setup Ports for val in LED: GPIO.setup(val, GPIO.OUT) for val in RGB: GPIO.setup(val, GPIO.OUT) led_clear() … … def led_cleanup(): led_clear() GPIO.cleanup() def main(): led_setup() led_activate(LED1,RGB_RED) time.sleep(5) led_deactivate(LED1,RGB_RED) led_cleanup()
Now, we can create a new file to use our library, instead of importing RPi.GPIO (for direct GPIO control) we now import rgbled.py (for GPIO control through our library).
rgbledcontrol.py:
#!/usr/bin/python # rgbledcontrol.py # Test program to show the use of libraries import time import rgbled as RGBLED def main(): print "Setup the RGB module" RGBLED.led_setup() print "Switch on LED1 RED" RGBLED.led_activate(RGBLED.LED1,RGBLED.RGB_RED) time.sleep(5) RGBLED.led_deactivate(RGBLED.LED1,RGBLED.RGB_RED) print "Finished" RGBLED.led_cleanup() main() #End
You may be thinking at this stage, why should we split the RGB-LED methods into another file, it worked fine as it was? Now imagine that we have 10 different programs which we want to run at different times or on different computers, so we have 10 different python files with each of our programs in. Now imagine we decide we want to change the wiring around, or perhaps we brought different RGB LEDs (common anode) – causing the LED_ENABLE and RGB_ENABLE to change. Because we have “abstracted” out all the low level detail, we would only need to update the library file while leaving all the other programs alone. This means we can do all our detailed tested focused on the one file we have changed, and only perform “integration” testing on the files we haven’t (to ensure nothing has been broken).
Improving Our Library:
We will now add some more functions to our library, so that any program which includes it has some extra functionality available. First we shall improve our led_activate() and led_deactivate() functions to provide some additional flexibility:
Add led_gpiocontrol() function to rgbled.py:
#This function will control the state of #a single or multiple pins in a list. def led_gpiocontrol(pins,state): #determine if "pins" is a single integer or not if isinstance(pins,int): #Single integer - reference directly GPIO.output(pins,state) else: #if not, then cycle through the "pins" list for i in pins: GPIO.output(i,state)
led_activate() and led_deactivate() can now be updated to use the function:
#Enable the selected led(s) and set the required colour(s) #Will accept single or multiple values def led_activate(led,colour): #Enable led led_gpiocontrol(led,LED_ENABLE) #Enable colour led_gpiocontrol(colour,RGB_ENABLE) #Deactivate the selected led(s) and set the required colour(s) #Will accept single or multiple values def led_deactivate(led,colour): #Disable led led_gpiocontrol(led,LED_DISABLE) #Disable colour led_gpiocontrol(colour,RGB_DISABLE)
We can also add a function led_time() to switch on an LED for a specific time period:
# Switch on the led and colour selected for the timeon period def led_time(led, colour, timeon): led_activate(led,colour) time.sleep(timeon) led_deactivate(led,colour)
The above code allows us to call the led_time()/led_activate()/led_deactivate() functions with either a single LED or COLOUR specified, or we can call using a list of values. This allows us to set one or more LEDs, and one or COLOURs using the same function. By running the file directly, we can also confirm we haven’t broken the previous functionality and any existing programs will work the same as before (as our “test” main function makes calls to these functions).
We can now add some new arrays (with the other defined arrays) to create some extra colours:
RGB_CYAN = [RGB_GREEN,RGB_BLUE] RGB_MAGENTA = [RGB_RED,RGB_BLUE] RGB_YELLOW = [RGB_RED,RGB_GREEN] RGB_WHITE = [RGB_RED,RGB_GREEN,RGB_BLUE]
Now we can update our control program rgbledcontrol.py to use the updated functions (and use some additional arrays – some_leds and sequence_leds):
# rgbledcontrol.py # Test program to show the use of libaries import time import rgbled as RGBLED some_leds = [RGBLED.LED1,RGBLED.LED3,RGBLED.LED5] sequence_leds = [RGBLED.LED1,RGBLED.LED2,RGBLED.LED3,RGBLED.LED4,RGBLED.LED5,RGBLED.LED4,RGBLED.LED3,RGBLED.LED2] def main(): print "Setup the RGB module" RGBLED.led_setup() print "Switch on LED1 RED" RGBLED.led_time(RGBLED.LED1,RGBLED.RGB_RED,1) time.sleep(0.5) print "Switch on LED2 MAGENTA" RGBLED.led_time(RGBLED.LED2,RGBLED.RGB_MAGENTA,1) time.sleep(0.5) print "Switch on 1,3,5 WHITE" RGBLED.led_time(some_leds,RGBLED.RGB_WHITE,1) print "Finished" RGBLED.led_cleanup() main() #End
Time for a D.I.S.C.O:
We can further demonstrate the extra functionality we have added, by creating another little function in rgbled.py called led_rgbrandom() and an array of colours RGB_LIST[] to pick from.
RGB_LIST = [RGB_RED,RGB_GREEN,RGB_BLUE,RGB_CYAN,RGB_MAGENTA,RGB_YELLOW,RGB_WHITE] # Light up the selected led, for period in seconds, in one of the possible colours. # The colours can be 1 to 3 for RGB, or 1-6 for RGB plus combinations, 1-7 includes white. # Anything over 7 will be determined as OFF (larger the number more chance of OFF). def led_rgbrandom(led,period,colours): value = randint(1,colours) if value < 8: led_time(led,RGB_LIST[value-1],period)
led_rgbrandom() allows us to specify an LED (or even several LEDs) and an on period, and a range of possible colours. It will randomly pick a colour from the list (randint() will pick a whole number between 1 and the given “colours”). The random number is then used to select a colour out of our table (remember arrays are always indexed starting with 0). We then light the LED for the required time (or if the value is beyond the colour range, we switch it off for that time period).
We now have our rgbled.py library ready to use:
#!/usr/bin/python import time from random import randint import RPi.GPIO as GPIO #Use real GPIO #import testRPiGPIO as GPIO #Use test GPIO # RGB LED Module (TEST) #Setup Active states #Common Cathode RGB-LEDs (Cathode=Active Low) LED_ENABLE = 0 LED_DISABLE = 1 RGB_ENABLE = 1 RGB_DISABLE = 0 #LED CONFIG - Set GPIO Ports LED1 = 12 #B4 LED2 = 16 #B18 LED3 = 18 #B23 LED4 = 22 #B24 LED5 = 7 #B25 LED = [LED1,LED2,LED3,LED4,LED5] RGB_RED = 11 #B22 RGB_GREEN = 13 #B21 Rev1 B27 Rev2 RGB_BLUE = 15 #B17 RGB = [RGB_RED,RGB_GREEN,RGB_BLUE] RGB_CYAN = [RGB_GREEN,RGB_BLUE] RGB_MAGENTA = [RGB_RED,RGB_BLUE] RGB_YELLOW = [RGB_RED,RGB_GREEN] RGB_WHITE = [RGB_RED,RGB_GREEN,RGB_BLUE] RGB_LIST = [RGB_RED,RGB_GREEN,RGB_BLUE,RGB_CYAN,RGB_MAGENTA,RGB_YELLOW,RGB_WHITE] #Setup the RGB-LED module pins and state. def led_setup(): #Set up the wiring GPIO.setmode(GPIO.BOARD) # Setup Ports for val in LED: GPIO.setup(val, GPIO.OUT) for val in RGB: GPIO.setup(val, GPIO.OUT) led_clear() #This function will control the state of #a single or multiple pins in a list. def led_gpiocontrol(pins,state): #determine if "pins" is a single integer or not if isinstance(pins,int): #Single integer - reference directly GPIO.output(pins,state) else: #if not, then cycle through the "pins" list for i in pins: GPIO.output(i,state) #Enable the selected led(s) and set the required colour(s) #Will accept single or multiple values def led_activate(led,colour): #Enable led led_gpiocontrol(led,LED_ENABLE) #Enable colour led_gpiocontrol(colour,RGB_ENABLE) #Deactivate the selected led(s) and set the required colour(s) #Will accept single or multiple values def led_deactivate(led,colour): #Disable led led_gpiocontrol(led,LED_DISABLE) #Disable colour led_gpiocontrol(colour,RGB_DISABLE) # Switch on the led and colour selected for the timeon peroid def led_time(led, colour, timeon): led_activate(led,colour) time.sleep(timeon) led_deactivate(led,colour) # Light up the selected led, for period in seconds, in one of the possible colours. # The colours can be 1 to 3 for RGB, or 1-6 for RGB plus combinations, 1-7 includes white. # Anything over 7 will be determined as OFF (larger the number more chance of OFF). def led_rgbrandom(led,period,colours): value = randint(1,colours) if value < 8: led_time(led,RGB_LIST[value-1],period) # Set the pins to default state. def led_clear(): for val in LED: GPIO.output(val, LED_DISABLE) for val in RGB: GPIO.output(val, RGB_DISABLE) # Reset pins to default state and release GPIO def led_cleanup(): led_clear() GPIO.cleanup() # Directly run test function. # This function will run if the file is executed directly. def main(): led_setup() led_activate(LED1,RGB_RED) time.sleep(5) led_deactivate(LED1,RGB_RED) led_cleanup() if __name__=='__main__': main() #End
Returning to our control program rgbledcontrol.py, we will now have the following:
#!/usr/bin/python # rgbledcontrol.py # Test program to show the use of libaries import time import rgbled as RGBLED some_leds = [RGBLED.LED1,RGBLED.LED3,RGBLED.LED5] sequence_leds = [RGBLED.LED1,RGBLED.LED2,RGBLED.LED3,RGBLED.LED4,RGBLED.LED5,RGBLED.LED4,RGBLED.LED3,RGBLED.LED2] def main(): print "Setup the RGB module" RGBLED.led_setup() print "Switch on LED1 RED" RGBLED.led_time(RGBLED.LED1,RGBLED.RGB_RED,1) time.sleep(0.5) print "Switch on LED2 MAGENTA" RGBLED.led_time(RGBLED.LED2,RGBLED.RGB_MAGENTA,1) time.sleep(0.5) print "Switch on 1,3,5 WHITE" RGBLED.led_time(some_leds,RGBLED.RGB_WHITE,1) print "Random RGB over all LEDs" for i in range(10): for j in sequence_leds: RGBLED.led_rgbrandom(j,0.1,3) #Select from R/G/B print "Finished" RGBLED.led_cleanup() main()
Extra Credit:
1. Try experimenting a little with your new led_rgbrandom() function, perhaps by changing the sequence or by increasing the colour value from 3 to 20 and observe the results.
2. As mentioned in the User Manual, we discussed using advanced control of the LEDs to allow us to produce different colours on different LEDs. The solution is to use high speed switching, to command several LEDs ON and OFF very quickly after another.
Now that we have our new led_time() function, we can easily achieve this in a loop (LED ON period of around 0.001 seconds seems to work nicely).
Therefore, we can recreate the 1st 5 colours of the Rainbow, according to the song we know they are:
Red, and Yellow, and Pink, and Green, Orange…
I will let you have a try to do this, if you have any problems then please let me know.
Once you start with this, you may wonder about “Orange” since we haven’t defined RGBLED.RGB_ORANGE in our files. However, with a little thought, I am sure you can produce Orange too!
Earn a Gold Star*!
If you are feeling real adventurous, you may even be able to get your RGB-LEDs to display the rest of the colours (or a smooth scale of colours) and scroll them across the LEDs.
This would look rather cool – so I will post a video from the first person to who manages it!
*Unfortunately you shall have to provide your own Gold Star (available from most supermarkets).
[…] RGB-LED Lesson 1 – Creating Python Libraries (& Colours) […]
[…] delal na nekem zelo učljivem dodatki za Pi. Njegov prikaz, kaj lahko naredite si lahko ogledate v tem vodiču, kjer boste ustvarili vašo Python knjižnico in jo uporabili pri upravljanju z GPIO pini. Za […]
[…] teaching add-ons for the Pi. He’s demonstrating what you can do with one of his little kits with this natty tutorial where you’ll be creating your own Python library, and using it to do some low-level control of […]
[…] This lesson will introduce creating and using your own library to provide low level control of the GPIO, while hiding away the detail inside. Plus, you can have a Disco and even touch the Rainbow! … […]
[…] teaching add-ons for the Pi. He’s demonstrating what you can do with one of his little kits with this natty tutorial where you’ll be creating your own Python library, and using it to do some low-level control of […]
[…] A nice little lesson in making python libraries – they’ll keep your code tidy and reusable, from MELTWATER’S RASPBERRY PI HARDWARE: […]
[…] RGB-LED Lesson 1 – Creating Python Libraries (& Colours) […]
[…] This lesson will introduce creating and using your own library to provide low level control of the GPIO, while hiding away the detail inside. Plus, you can have a Disco and even touch the Rainbow! … […]