Log in

PWM LED Fading - Goldtronics [entries|archive|friends|userinfo]

[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

PWM LED Fading [Sep. 25th, 2008|03:44 pm]

At work we have these orbs from Ambient Devices (http://www.ambientdevices.com/cat/orb/orborder.html) which connect to the serial port and you can make it "display" almost anything you want, from the weather to stock prices. For one hundred fifty frickin dollars. All it contains is a few red, green, and blue LEDs and a 16F or 18F series PIC. The colors change and pulse up and down. I guess it's expensive because it also has a wireless "pager" receiver on the 929.6625 MHz band. But not worth $150.

Four bytes are sent to it... a start byte letting it know valid data is coming next, followed by a mode byte, and then color and pulse rate. More info about it is in the developer section of the site (http://www.ambientdevices.com/developer/).

When I opened it up and saw how simple it was, I realized I could build my own. Also, it gave me a good excuse to play with LEDs, and learn about the PWM functionality of the PIC 16F series microcontrollers.

To test the PWM, I wrote a program that fades an LED on and off, using the hardware PWM and one of the hardware timers in the microcontroller. The micro runs on an internal 4MHz clock, which produced 1MHz instruction cycles. It uses a PWM period of approximately 1ms. The fading effect is created by modifying the duty cycle to change the intensity of the LED.

The following is the core of the code. The main loop calls fadeU to turn the brightness of the LED up by adding the variable 'step' (which I set to 0x04) to the duty cycle register (CCPR1L). It then pauses for a very short time (about 16.384 ms) by calling T0ov which waits for Timer0 to overflow. I set the Timer0 prescaler to 64 (it divides the 1MHz clock by 64. 1000000 / 64 = 15625. 256/15625 = 16.384 ms). It then checks to see if there would be an overflow of the CCPR1L register by adding 'step' to it again, but this time it puts the result in W and checks the carry flag in the status register. If there's no carry, then it can continue to increment, otherwise, it clears the carry flag and returns to the main loop. The fadeD function does the same thing, but uses subtraction.

I used a 16F767.



    call fadeU		;fade up
    call fadeD		;fade down
    goto LOOP         	;repeat forever

    movlw step            ;increment duty cycle
    addwf CCPR1L,F        ;
    call T0ov             ;pause
    addwf CCPR1L,W        ;add step to duty cycle to
    btfss STATUS,C        ;check for overflow
    goto fadeU            ;fade up more if no overflow
    bcf STATUS,C          ;clear carry flag
    return                ;done fading up

    movlw step            ;decrement duty cycle
    subwf CCPR1L,F        ;
    call T0ov             ;pause
    subwf CCPR1L,W        ;subtract step from duty cycle to
    btfsc STATUS,C        ;check for overflow
    goto fadeD            ;fade down more if no borrow
    bcf STATUS,C          ;clear carry flag
    return                ;done fading up

T0ov        ;rather than using Pause, check TMR0 
    btfss INTCON,TMR0IF    ;check T0 overflow flag
    goto T0ov              ;wait for T0 to overflow
    bcf INTCON,TMR0IF      ;clear overflow flag


The next thing I would like to do is use an 18F series PIC with USB capabilities and use RBG LEDs.

From: bgd_90
2011-07-09 11:23 pm (UTC)


Very nice work out there!
Can you please post a complete source code and perhaps a schematic?I desperately need it!
(Reply) (Thread)
[User Picture]From: goldtronics
2011-07-11 08:27 pm (UTC)

Re: Hello!

The source code is on some old computer I have. I never made a schematic.
(Reply) (Parent) (Thread)