In SX Microcontrollers, SX/B Compiler and SX-Key Tool, pljack wrote: This is something I have been wanting to do for some time now. Mixing colors with an RGB LED. So lets start at the beginning, The object is to vary the color of each red, green and blue LED to produce a different color. You can think of it as a standard 8 bit color palette. So lets say you wanted to produce the color purple. That would be full red, full blue and no green. Easy enough. But what if you wanted to produce a dark purple. This can be done by reducing the intensity of the blue LED. But how? The answer is in PWM (pulse width modulation). If you are new to PWM, then lets get one thing straight. You DO NOT control the color of an LED by blinking it at different speeds. Blinking is a byproduct of PWM. Controlling the color is a function of reducing the voltage that the LED sees. By reducing the voltage, you decrease the brightness. I will provide two examples. One I will just type at the end of this paragraph, the other is an attached file that will also be pasted to the end of this post. A simple example. The Red LED is connected to RB.0. Green connected to RB.1 and Blue connected to RB.2. Place the OUTPUT and PWM commands below into your SX/B Template: Start: ' initialization code here OUTPUT RB.0 OUTPUT RB.1 OUTPUT RB.2 Main: pwm RB.0, 255, 1 pwm RB.1, 0, 1 pwm RB.2, 255, 1 GOTO Main Please note that the color intensity comes from changing the DUTY cycle, not the duration. To create a dark purple you would set RB.2 (blue) to something like 180. There are a couple issues with the above approach. The first is that the duration of the PWM is too long. This destroys the POV (persistence of vision) effect. You can see this by looking at the LED and the quickly look up, or down or anywhere for that matter. You will see red, green and blue streaks coming from the LED. Very distracting to say the least. Bump up the duration from 1 to 5 to see the full effect. Another issue is that you are applying PWM to each LED one after the other. In other words the above code takes 3 milliseconds to PWM all three LEDs. You really need to PWM all three at the same time. The final issue is that pausing at a certain color is very problematic with the above method. The sample code provided solves all these issues. The code is pretty heavily commented so I will not reproduce it here. Basically it uses an INTERRUPT and some helper functions to produce some really pleasing results. Enjoy and have some fun this weekend. A more advanced method: [code] ' ========================================================================= ' ' Purpose... RBG LED Example ' Author.... PLJack ' E-mail.... kellylabs@fastmail.fm ' ' ========================================================================= ' ------------------------------------------------------------------------- ' Program Description: ' ' ------------------------------------------------------------------------- '--- Don't Forget: Zero is full brightness and 255 is off. '--- This example demonstrates the mixing of colors '--- using a RGB LED. '--- CAUTION: Be careful with bright LEDs while using '--- this code, staring at a bright LED for most of '--- the day can have undesirable results for your '--- eyes. '--- I find that surface mount LEDs work best for '--- color mixing. Most 5mm LEDs seem to have the '--- three LEDs too far apart for proper convergence '--- (mixing). '--- '--- General: '--- Basically there are several components to this '--- example. The first is an INTERRUPT that is '--- constantly monitoring the PWM lines for RGB. '--- There are three variables for the LED, RedVal, '--- GreenVal and BlueVal. You can change these '--- variables at any time. The interrupt will '--- automatically change the LED to the new value. '--- Because we are using an interrupt you can use the '--- PAUSE command and the LED will continue to emit '--- light. This makes it very easy to display a color '--- for a certain amount of time. '--- '--- Operation: '--- '--- Not much to it really. There are three main '--- functions for you to use. '--- '--- Diag: '--- '--- Used at startup. It will display the red, green '--- and blue LEDs in that order. This is useful to '--- determine that your LED is correctly connected to '--- the SX. '--- '--- '--- TransitColor [Num]: '--- '--- This function creates a random color. Then makes '--- a transition from the current LED color over to '--- the new color. It performs this transition in '--- 255 steps. You can provide and optional parameter '--- to pause for [Num] '--- milliseconds per step. '--- The max transition time is 255 steps X 255ms = 65 '--- seconds. '--- '--- '--- RandomPulse [Num]: '--- '--- This function actually creates some beautiful '--- results. It turns off the LED, creates a random '--- color then slowly raises the led to full '--- brightness and finally fades to off. '--- The great results come from the fact that it '--- increments the RGB colors by one. So if the color '--- has a lot of blue in it (strongest color) as it '--- fades blue will be the last led to fade. Thus '--- mixing with the red and green as those colors are '--- reduced. '--- This also has an optional parameter to pause for '--- [Num] milliseconds per step. Although the total '--- number of steps is unknown. It depends on the '--- value of the strongest color. '--- '--- And remember to have fun. '--- Please forgive my breaking of the Uppercase keyword convention. '--- After years of coding in PC languages, I just can't take '--- all those uppercase words. ' ------------------------------------------------------------------------- ' Device Settings ' ------------------------------------------------------------------------- DEVICE SX28, OSC4MHZ, TURBO, STACKX, OPTIONX FREQ 4_000_000 ID "SXB 1.50" ' ------------------------------------------------------------------------- ' IO Pins ' ------------------------------------------------------------------------- RedLED var RB.0 GreenLED var RB.1 BlueLED var RB.2 ' ------------------------------------------------------------------------- ' Constants ' ------------------------------------------------------------------------- '--- LED TYPE '--- Common anode - SX pins sink to ground. '--- Common Cathode - SX pins source the voltage. '--- Un-comment the correct type for your LED. '--- Common Anode 'LEDOn con 0 'LEDOff con 1 '--- Common Cathode LEDOn con 1 LEDOff con 0 '--- Color Clip '--- If your LED has a color that is over powering the others you can '--- clip its brightness here. Keep in mind this is not a global clip '--- because the color reduction is not proportional to the others. '--- But it will prevent a color from becoming too bright. '--- Zero is full strength. Increase number to reduce total brightness. '--- To do this properly you would need a variable resistor '--- on each LED. Run them at full brightness, then adjust '--- each VR for a perfect white. '--- You might have some luck performing a proportional adjust on '--- the fly via code, but I think rounding errors might cause more '--- trouble than it is worth. C_RedClip con 0 C_GreenClip con 0 C_BlueClip con 0 '--- Defaults if no parameter is provided C_DefaultTransitSpeed con 5 C_DefaultPulseSpeed con 15 '--- Just substitutes for 0 and 255 incase you should '--- ever want to change them. C_PwmMin con 0 C_PwmMax con 255 ' ------------------------------------------------------------------------- ' Variables ' ------------------------------------------------------------------------- '--- This is the value (duty cycle) given to each LED at each INTERRUPT. RedVal var Byte GreenVal var Byte BlueVal var Byte '--- Sometimes handy to store the above variables. RedValCopy var Byte GreenValCopy var Byte BlueValCopy var Byte '--- Used for the duty cycle inside the INTERRUPT. RpwmCounter var Byte GpwmCounter var Byte BpwmCounter var Byte '--- For use constructing loops. LoopIdx var Byte '--- Used to increase the time a loop takes to finish. FadeSpeed var Byte '--- For functions that return a Byte variable. ReturnVar var Byte '--- Always nice to have a few around. Always assume as volatile. UtilVar1 var Byte UtilVar2 var Byte UtilVar3 var Byte ' ------------------------------------------------------------------------- INTERRUPT 30000 ISR_Start: '--- Add one to pwm counters. '--- Note they will roll over to zero after 255. Inc RpwmCounter Inc GpwmCounter Inc BpwmCounter '--- Red LED PWM if RpwmCounter > RedVal then RedLED = LEDOn else RedLED = LEDOff endif '--- Green LED PWM if GpwmCounter > GreenVal then GreenLED = LEDOn else GreenLED = LEDOff endif '--- Blue LED PWM if BpwmCounter > BlueVal then BlueLED = LEDOn else BlueLED = LEDOff endif ISR_Exit: RETURNINT ' ========================================================================= PROGRAM Start ' ========================================================================= ' ------------------------------------------------------------------------- ' Subroutine Declarations ' ------------------------------------------------------------------------- TransitColor sub 0, 1 RandomPulse sub 0, 1 Diag sub 0 SeedVars sub 0 RandomColor sub 0 RandomUtilVar sub 0 RaiseStrongest sub 1 FadeStrongest sub 1 StoreColor sub 0 RestoreColor sub 0 GetStrongestColor sub 0 ' ------------------------------------------------------------------------- ' Program Code ' ------------------------------------------------------------------------- Start: '--- Set LEDs as outputs. OUTPUT RedLED OUTPUT GreenLED OUTPUT BlueLED '--- Un-comment to perform a quick diagnostic at start up. Diag 'Seed anything that the RANDOM command will use. SeedVars Main: TransitColor 255 ' RandomPulse Goto Main ' ------------------------------------------------------------------------- ' Subroutine Code ' ------------------------------------------------------------------------- ' ------------------------------------------------------------------------- RandomPulse: '--- Too few parameters, set to default. if __PARAMCNT <> 1 then FadeSpeed = C_DefaultPulseSpeed else FadeSpeed = __PARAM1 endif RandomColor '--- Bring color to full brightness. RaiseStrongest FadeSpeed '--- Now fade until off. FadeStrongest FadeSpeed return ' ------------------------------------------------------------------------- TransitColor: '--- Too few parameters, set to default. if __PARAMCNT <> 1 then FadeSpeed = C_DefaultTransitSpeed else FadeSpeed = __PARAM1 endif '--- Create a random color, only with the util vars this time. RandomUtilVar '--- Now bring the current LED values towards the new values. for loopIdx = C_PwmMin to C_PwmMax if RedVal <> UtilVar1 then if RedVal < UtilVar1 then inc RedVal else dec RedVal endif endif if GreenVal <> UtilVar2 then if GreenVal < UtilVar2 then inc GreenVal else dec GreenVal endif endif if BlueVal <> UtilVar3 then if BlueVal < UtilVar3 then inc BlueVal else dec BlueVal endif endif pause FadeSpeed next return ' ------------------------------------------------------------------------- FadeStrongest: FadeSpeed = __PARAM1 StoreColor UtilVar1 = GetStrongestColor '--- Find number of loops required to turn off color UtilVar2 = C_PwmMax - UtilVar1 '--- Bring down all colors. for loopIdx = C_PwmMin to UtilVar2 if RedVal < C_PwmMax then inc RedVal endif if GreenVal < C_PwmMax then inc GreenVal endif if BlueVal < C_PwmMax then inc BlueVal endif pause FadeSpeed next RestoreColor return ' ------------------------------------------------------------------------- RaiseStrongest: FadeSpeed = __PARAM1 UtilVar1 = GetStrongestColor UtilVar2 = C_PwmMax - UtilVar1 StoreColor '--- Set LEDs to off. RedVal = C_PwmMax GreenVal = C_PwmMax BlueVal = C_PwmMax '--- Bring up all colors. for loopIdx = C_PwmMin to UtilVar2 if RedVal > RedValCopy then dec RedVal endif if GreenVal > GreenValCopy then dec GreenVal endif if BlueVal > BlueValCopy then dec BlueVal endif pause FadeSpeed next RestoreColor return ' ------------------------------------------------------------------------- StoreColor: RedValCopy = RedVal GreenValCopy = GreenVal BlueValCopy = BlueVal return ' ------------------------------------------------------------------------- RestoreColor: RedVal = RedValCopy GreenVal = GreenValCopy BlueVal = BlueValCopy return ' ------------------------------------------------------------------------- RandomColor: random RedVal random GreenVal random BlueVal '--- If a color clip is set, honor it. if RedVal < C_RedClip then RedVal = C_RedClip endif if GreenVal < C_GreenClip then GreenVal = C_GreenClip endif if BlueVal < C_BlueClip then BlueVal = C_BlueClip endif return ' ------------------------------------------------------------------------- RandomUtilVar: '--- This is a bit of an odd ball function. '--- To perform the transition for the TransitColor function '--- we need a few random numbers. Here we just use the UtilVars '--- instead of wasting RAM for three one off variables. '--- random UtilVar1 random UtilVAr2 random UtilVar3 '--- If a color clip is set, honor it. if UtilVar1 < C_RedClip then UtilVar1 = C_RedClip endif if UtilVar2 < C_GreenClip then UtilVar2 = C_GreenClip endif if UtilVar3 < C_BlueClip then UtilVar3 = C_BlueClip endif return ' ------------------------------------------------------------------------- GetStrongestColor: '--- Assign strongest (low val) color to ReturnVal. if RedVal < GreenVal then ReturnVar = RedVal else ReturnVar = GreenVal endif if ReturnVar > BlueVal then ReturnVar = BlueVal endif return ReturnVar ' ------------------------------------------------------------------------- SeedVars: 'Seed anything that the RANDOM command will use. RedVal = 50 GreenVal = 100 BlueVal = 150 UtilVar1 = 150 UtilVar2 = 100 UtilVar3 = 50 return ' ------------------------------------------------------------------------- Diag: '--- A simple diagnostic to confirm that the LED is '--- connected to the SX correctly and is working properly. RedVal = C_PwmMax GreenVal = C_PwmMax BlueVal = C_PwmMax RedVal = C_PwmMin Pause 500 RedVal = C_PwmMax GreenVal = C_PwmMin Pause 500 GreenVal = C_PwmMax BlueVal = C_PwmMin Pause 500 BlueVal = C_PwmMax for loopIdx = C_PwmMin to C_PwmMax RedVal = LoopIdx pause 2 next for loopIdx = C_PwmMin to C_PwmMax GreenVal = LoopIdx pause 2 next for loopIdx = C_PwmMin to C_PwmMax BlueVal = LoopIdx pause 2 next for loopIdx = C_PwmMin to C_PwmMax RedVal = LoopIdx BlueVal = LoopIdx GreenVal = LoopIdx pause 4 next return ' ------------------------------------------------------------------------- ' ========================================================================= ' User Data ' ========================================================================= Pgm_ID: DATA "SX/B RGB LED Example", 0 ' [/code] ---------- End of Message ---------- You can view the post on-line at: http://forums.parallax.com/forums/default.aspx?f=7&p=1&m=156930 Need assistance? Send an email to the Forum Administrator at forumadmin@parallax.com The Parallax Forums are powered by dotNetBB Forums, copyright 2002-2006 (http://www.dotNetBB.com)