Welcome, Guest
Username: Password: Secret Key Remember me

TOPIC: Swordfish Program - Red Green Blue (RGB) LED

Re: Swordfish Program - Red Green Blue (RGB) LED 10 years 3 months ago #15358

Red Green Blue (RGB) LED's are a marvel to watch in action, and I have got to say, they are worth the effort to play around with. The programming side of things does take a little thought, primarily because you need to control 3 different Pulse Width Modulated (PWM) signals to control the brightness of each LED (Red Green and Blue).

{youtube}ZZW-aAAFFxQ{/youtube}


RGB LED's have 4 pins, 3 of them are for a specific colour (either Red Green or Blue), and the forth is a common anode or cathode. I prefer to use the common anode devices, as I like to use the ULN2003 to drive the LED's. This way I can hook up many LED's in parallel to get some very powerful and amazing lighting effects.


The LED's I am using are Common Anode so that I can use the ULN2003 to drive many in parallel. I brought them from www.core-electronics.com.au and I'm very impressed by the vivid colour and extreme brightness of these LED's! Below is the pin-out;



Note the PIC's power supply/oscillator are not shown



The above diagram utilises the ULN2003 to drive much higher current devices then what the PIC can handle so with this design, you could put a lot of RGB LED's in parallel for some really stunning lighting effects.


The RGB LED's from Core Electronics have a forward voltage drop of about 2 Volts for the Red LED, and 3.5 Volts for both the Green and Blue LED's. To ensure that I am running them at full brightness (20mA for each colour), I can calculate the resistance required for each resistor by the following equation;


R = (V - Vf - Vce) / I


Where R = Resistance in ohms, V = Supply Voltage, Vf = LED Forward Bias Voltage, Vce = ULN2003 voltage drop, I = Current


To get the maximum brightness from your LED's, replace the resistors with the following (increase the current if more LED's

are used in parallel);

Red resistor = (5 - 2 - 0.9) / 0.020 = 105 ohm or greater

Green resistor = (5 - 3.5 - 0.9) / 0.020 = 30 ohm or greater

Blue resistor = (5 - 3.5 - 0.9) / 0.020 = 30 ohm or greater


The Program


Because the program is interrupt driven, I want to take as little time as possible to service the interrupt. One way is to minimise the code, another is to maximise the clock speed, so I chose a little of both.


The reason why I chose an Interrupt driven routine, is so that once the registers and interrupt is setup, you can do anything you want in the main program, and not worry about the performance of the RGB LED. In the circuit above, I use the 18F4550 with a 20Mhz Crystal Oscillator and PLL enabled (a couple of config settings) to achieve 48Mhz CPU Clock speed, handy.


The program has to incorporate the control of three different PWM signals (one for each colour). I wanted to maintain as much brightness control as possible, and decided to make the Duty Cycle editable from 0 t0 100% by simply editing a register from 0 to 255.


In the example below, I am using the 18F4550 with a 20Mhz external oscillator, and with a few PLL config settings, the CPU will operate at 48Mhz (12 million instructions per second). The Timer 2 interrupt will be serviced every 50uS, that is 20Khz. With this in mind, as each complete PWM signal takes 256 timer cycles, this means that a PWM pulse will be driven 20000 / 256 = 78.125 Hz. Anything above 25Hz will look fluent to the human eye!


This might not be the most efficient way to create three PWM signals, but it allows complete diversity in the fact that you can control the brightness of each LED colour component on the fly while doing anything else! The program also uses the random number user  library to create random numbers from 0 to 255.


The 19mS delay between increments/decrements of the colours is to control the time it takes going from one extreme to the other, in this case, 19mS ensures it takes just under 5 seconds for all 256 brightness levels to change.



Device = 18F4550
Clock = 48
Config PLLDIV = 5,
       CPUDIV = OSC1_PLL2,
       USBDIV = 2,
       FOSC = HSPLL_HS
 
Include "RandGen.bas"
 
Dim TMR2IE As PIE1.1,         // TMR2 interrupt enable
    TMR2IF As PIR1.1,         // TMR2 overflow flag
    TMR2ON As T2CON.2,        // Enables TMR2 to begin incrementing
    Signal_Pin As PORTB.0     // Signal output to frequency meter
 
Dim Red_Pin As PORTC.0,
    Green_Pin As PORTC.1,
    Blue_Pin As PORTC.2,
    Red_Duty As Byte,
    Green_Duty As Byte,
    Blue_Duty As Byte,
    Red_DutyVal As Byte,
    Green_DutyVal As Byte,
    Blue_DutyVal As Byte,
    RandomVal As Byte
 
Dim uS As Word,
    mS As Word           
 
Interrupt TMR2_Interrupt()
    High(Signal_Pin)
    Save(0)                   // Back up system variables   
    If TMR2IF = 1 Then        // Check if the interrupt was from TMR2   
        TMR2IF = 0            // Clear the TMR2 interrupt flag
        uS = uS + 50
        If uS >= 1000 Then
            uS = uS - 1000
            Inc(mS)
        EndIf       
        Inc(Red_DutyVal)
        Inc(Green_DutyVal)
        Inc(Blue_DutyVal)
        If Red_DutyVal > Red_Duty or red_Duty = 0 Then
            Red_Pin = 0
        Else
            Red_Pin = 1
        EndIf
        If Green_DutyVal > Green_Duty or Green_Duty = 0 Then
            Green_Pin = 0
        Else
            Green_Pin = 1
        EndIf
        If Blue_DutyVal > Blue_Duty or Blue_Duty = 0 Then
            Blue_Pin = 0
        Else
            Blue_Pin = 1
        EndIf               
    EndIf                     //
    Restore                   // Restore system variables
    Low(Signal_Pin)
End Interrupt
 
Private Sub TMR2_Initialize()
    TMR2ON = 0                // Disable TMR2
    TMR2IE = 0                // Turn off TMR2 interrupts   
 
    PR2 = 149                 // TMR2 Period register PR2
    T2CON = %00000001         // T2CON 0:1 = Prescale
                              //        00 = Prescale is 1:1
                              //        01 = Prescale is 1:4
                              //        1x = Prescale is 1:16                                 
                              //      3:6 = Postscale              
                              //     0000 = 1:1 postscale
                              //     0001 = 1:2 postscale
                              //     0010 = 1:3 postscale...
                              //     1111 = 1:16 postscale
 
    TMR2 = 0                  // Reset TMR2 Value   
    TMR2IE = 1                // Enable TMR2 interrupts
    TMR2ON = 1                // Enable TMR2 to increment
    Enable(TMR2_Interrupt)
End Sub
 
// Start Of Program...
Low(Red_Pin)
Low(Green_Pin)
Low(Blue_Pin)
Red_Duty = 0
Green_Duty = 0
Blue_Duty = 0
Red_DutyVal = 0
Green_DutyVal = 0
Blue_DutyVal = 0
 
uS = 0
mS = 0
 
RandGen.Initialize(128)       // Initialize the Random Number generator
TMR2_Initialize               // Setup and enable TMR2
 
While True                    // Create an infinite loop
    RandomVal = RandGen.Rand  // Grab a random number from 0 to 255 
     Select RandomVal         // Find out what colour to increase/decrease
        Case 0 To 42
            While Red_duty < 255
                mS = 0
                Repeat
                Until mS = 19
                inc(Red_Duty)
            Wend
        Case 43 To 84
            While Red_duty > 0
                mS = 0
                Repeat
                Until mS = 19
                dec(Red_Duty)
            Wend
        Case 84 To 127
            While Green_duty < 255
                mS = 0
                Repeat
                Until mS = 19
                inc(Green_Duty)
            Wend
        Case 128 To 170
            While Green_duty > 0
                mS = 0
                Repeat
                Until mS = 19
                dec(Green_Duty)
            Wend
        Case 170 To 212
            While Blue_duty < 255
                mS = 0
                Repeat
                Until mS = 19
                inc(Blue_Duty)
            Wend
        Case 212 To 255
            While Blue_duty > 0
                mS = 0
                Repeat
                Until mS = 19
                dec(Blue_Duty)
            Wend
     End Select           
Wend





Simulation of the program
{youtube}CV6wkeFRXUM{/youtube}

RandGen
Read full article...
Time to create page: 0.231 seconds