In this sample, we will connect an RGB Controllable LED to a Raspberry Pi 2 and vary the intensity level of each color using a technique called Pulse Width Modulation (PWM).
The ability to control the level of intensity of each of the three colors on the LED will allow us to make an infinite number of color possibilities. How can we control the intensity? An LED's intensity can be controlled in one of two ways. The first way is to control the amount of current going to the LED. This approach is somewhat complex and requires additional hardware. The second way is through Pulse Width Modulation and can be done with a few basic parts and the right code (for a good explanation of what PWM is an how it works see this blog: "PWM - What is it, How does it work and how to detect it").
It is commonly known that the Raspberry Pi 2 only has only one pin for hardware based Pulse Width Modulation and therefore cannot be used to drive the three pins on the LED. To accommodate this, a software based PWM is needed. This sample will demonstrate how a software based PWM can control the intensity of the LED. The trade of between a hardware based PWM and a software based PWM is gong to be CPU overhead versus additional hardware. Although using a software based PWM has some limits it will get the job done!
Even though the GPIO APIs are only available on Windows IoT Core, this sample can run on your desktop but, of course, will not attach to the controller. This is because the sample uses the new meta data API's found in the Windows.Foundation.Metadata namespace to detect the presence of the GPIO Controller. This is useful to allow the code to be run on your desktop to help debug other aspects of the application.
Build the CircuitLet's start by constructing the simple circuit. In this example I use a small breadboard with a cobbler board and 40-pin ribbon cable to connect the Raspberry Pi 2 GPIO to the board (using a cobbler and ribbon cable is not required). If you do not have these components I have included a wiring diagram that shows you how to connect directly to the Raspberry Pi 2 pins. Note that the hardware list calls for male to male connectors when using the cobbler board. If you choose not to use the cobbler board you will need the same number of wires, but male to female instead.
When placing the cobbler board on the breadboard, I have positioned it so that the first pins are in row 1 which positions the four pins for 5V+, 5V-, 3V3+ and 3V3- into the second row. The pin farthest from the ribbon cable on the cobbler is in row 20. Having this exact positioning is not critical but will help you follow the wiring diagram in this sample. The pins that are used by the cobbler board are highlighted in the diagram below.
Start by placing the LED onto the breadboard. The red lead will go into position J26. The common cathode lead is inserted into J25. The green lead is inserted into J24 and the blue lead into J23. You will need to spread the leads out slightly to get them to insert at the same time into the these four positions on the breadboard.
Next you place the three 220 ohm resisters onto the breadboard. Place the first resistor between F23 and D23. Place the next resistor between F24 and D24. Place the last resistor between F26 and D26.
Last you will need to connect the four wires. The first wire, black, will be connected between pins F25 and 3V3-. The next wire, red, will be connected between D26 and D16 (GPIO pin 6). The next wire, green, will be connected between B24 and B15 (GPIO pin 5). The last wire, blue, will be connected between C23 and C8 (GPIO pin 22).
See the circuit diagrams at the bottom of this page.
That's it. Your circuit is built and ready to go!
This samples assumes you have followed the directions on windowsondevices.com to get your Raspberry Pi 2 up and running with Windows 10 IoT and your card is ready to go. If you have not done this yet, pause here and go get that done and then come back.
At this point I'll assume the following:
- Your Raspberry Pi 2 micro SD card is configured and installed in the device
- You have connected the proper power supply to your Raspberry Pi 2
- You have an HDMI cable connected to your Raspberry Pi 2 at one end and a monitor at the other
- You have an Ethernet cable connected to you Raspberry Pi 2 which is connected to your local network and the device has a valid IP address. If the device is powered up and the monitor is connected you will see the IP address on screen. Test your connection by typing the IP address in your browser.
- You have a mouse and keyboard attached to your Raspberry Pi 2
The last thing you need to do to get your circuit ready is to make sure you have connected the 40-pin ribbon cable between your cobbler and your Raspberry Pi. The cable is keyed (or notched) and can only go into to the connector one way.
Before you start make sure you have Visual Studio 2015 installed. If you do not have it, pause here and go to Microsoft and download the Community version and install it. You can find the download by going to msdn.microsoft.com and selecting Visual Studio from the Downloads links near the top of the page. You can get directly to the download page with this link:
Now it's time to get the source code. The code for this example is on GitHub. You can download the entire source code folder using this link (this will download a zip file).
See the bottom of the page for links to the GitHub repository
Save and extract this folder to your hard drive and open the code in Visual Studio 2015. Note that if you are familiar with GutHub you can install the extension in Visual Studio and clone the repository from within Visual Studio. There are plenty of sources online that will show you how to do this.
The source code is written in C# using the new Universal Application template in Visual Studio 2015.
Application OverviewMain View
The application has a single view (page) that has several controls for each LED. The application will allow you to adjust the intensity level for each color using a slider control that ranges from 0 (off) to 255 (full). This range was chosen to coincide with the value commonly used to specify a color in code. There is also a slider (one for each color) that allows the pulse frequency to be set. The application allows a pulse frequency between 100 Hz and 2000 Hz. The upper limit is based on how many Software based PWM's are running simultaneously and the power of your processor (as well as what other work it is doing). I chose 2000 Hz as the upper bound because values higher than this had little effect on the intensity of the LED. You can experiment with these values by changing the source code. In the code behind in the view you will find a set of constants that control the lower and upper limit for the controls on the page.
public static class Constants { ...
All of the controls (except the two buttons; they will use a click event) on the view are using the x:Bind feature for XAML which allows the controls to be bound to the code behind on the view. All of the code supporting these bindings can be found in the region titled 'Bindings'.
#region Bindings
The view's code behind is also setup to implement INotifyPropertyChanged to allow the view to track changes and update the UI. Normally I would develop this code using the MVVM pattern and create view models but for the sake of trying to keep this code somewhat simple I have implemented all of the view features in the code behind. To learn about MVVM see "Using the MVVM Pattern in Windows 8" or "WPF Apps With The Model-View-ViewModel Design Pattern".
GPIO Fluent API
This sample project includes a Fluent API (or Fluent Interface) for the GPIO to assist in setting up a GPIO pin. A fluent API is designed to make code more readable when object creation in code becomes complex or hard to read, especially when constructors with many parameters are involved. The use of a fluent API is mainly a style thing and is optional. When combined with the fluent API for the SoftPwmSharp library, it can be very useful. Here is an example of setting up a GPIO pin using the API:
GpioController gpio = GpioController.GetDefault(); GpioPin pin = gpio.OnPin(5).AsExclusive().Open();
This by itself does not provide much value over the current mannerin which a GPIO pin is initialized but when combined with the software based PWMthe code (in my opinion) will be more readable.
This library can be added to your project via NuGet:
PM> Install-Package IoT.FluentApi
Software PWM Library
Included in the source code is a Software based PWM library called SoftPwmSharp. This library makes it easy to setup Pulse Width Modulation on any GPIO pin. There are two main properties that drive the behavior of the SoftPwm. The first is the PulseFrequency which sets the number of times an LED is pulsed in 1 second (measured in hertz or Hz). The second property is the Value which sets the intensity of the LED (actually controls the amount of time in a single pulse that the output is High). The lowest value is 0 which keeps the pin out at Low. The highest value is configurable (set to 255 in the sample project). When the value property is set to the maximum value the out pin kept at a value of High.
The SoftPwmSharp library also includes a fluent API for configuring the SoftPwm in your code. The code below demonstrates how to use the API to create a new instance of SoftPwm.
SoftPwm pwm = gpio.OnPin(5).AsExclusive().Open().AssignSoftPwm().WithValue(50).WithPulseFrequency(800).Start();
This library can be added to your project via NuGet:
PM> Install-Package IoT.SoftPwm
Starting the ApplicationChoose Debug, ARM configuration and Remote Machine. Now right-click the project, and select Property and then click Debug tag. Next put the Raspberry Pi IP address in the Remote machine field, and uncheck Use authentication.
Press F5. The application will deploy to the device which may take a few minutes the first time.
The video below will walk through a demonstration the application:
View this video in You Tube using Theater mode for best quality.
Comments