Searching \ for '[PIC] fading a LED with 16F917' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: www.piclist.com/techref/displays.htm?key=led
Search entire site for: 'fading a LED with 16F917'.

Exact match. Not showing close matches.
PICList Thread
'[PIC] fading a LED with 16F917'
2007\01\23@083804 by Balthasar Indermuehle

picon face
Hi all,

I just received my PicKit2 today featuring a 16F917, and despite never
having programmed a PIC before I made rapid progress switching LED's on and
off (I've been practising with a simulator for the past few days). I then
searched the archives for information on how to fade in/out those LED's, but
unfortunately I do not understand how that is supposed to work.

Can someone explain to me in hardware newbie terms, how I can use the pulse
width modulation method on the LED's connected to PORTD (TRISD)? Some sample
code would be of great help, too.

Thanks!

- Balt

2007\01\23@091410 by Chris Piclist

flavicon
face
Hi Balt,

Welcome to the world of pics! They are great devices and a lot of fun to
experiment with.

One of my favorite things to do is make led and robot projects for my
daughter. She really enjoys helping me make things and likes it when I
make her little circuits. I do a lot of led projects using RGB leds and
pwm.

I've experimented and created many types of pwm code using bit banging
and the pwm modules that some pics have. My favorite piece of code and
the one I now use as the foundation for most of my led work was written
by Scott Datalo. I've pasted a few code snippets here for you to look
at. None of them are 100% complete so you will need to add code of your
own. If you are interested, I would be happy to zip up a simple
nightlight project I created and post it on my website or here on
Piclist.

Hope this helps.

-Chris

; ----------------------------------------------------
; Here is a piece of sample code from Scott.
; be sure to visit his web site for more info. The
; link is below.
; ----------------------------------------------------
       list    P=pic16f84

       #include p16f84.inc
   

; ----------------------------------------------------
;Variables - Adjust for your pic and for absolute
; or relative mode.
; ----------------------------------------------------
 cblock 0x0020

  ;
  ; The duty cycle for each PWM  is stored here:
  ;

       pwm0,pwm1,pwm2,pwm3
       pwm4,pwm5,pwm6,pwm7

  ;
  ; The counters are compared to the duty cycles
  ; to determine when the pulse should be turned off
  ;

       pwm0_cntr,pwm1_cntr,pwm2_cntr,pwm3_cntr
       pwm4_cntr,pwm5_cntr,pwm6_cntr,pwm7_cntr

  ;
  ; When rhe "rising_edge" counter rolls over, all
  ; pwms are driven high
  ;
       rising_edge

       pwm_state
 endc

#define PWM_PORT        PORTB


       org     0

       goto    Start
   
       org     4

;------------------------------------------------------------
;pwm_multiple
;
;  The purpose of this routine is to generate 8 pulse width
;modulated waveforms. The algorithm consists of 9 counters
;that change the state of the pwm bits whenever they roll over.
;One of the counters, rising_edge, will drive the pwm bits
;high when it rolls over. The other 8 counters pwm0-pwm7 will
;drive their corresponding bits low when they roll over.
;
; The technique can be understood with an example for one
; counter. (This was taken from my web page:
; http://www.dattalo.com/technical/theory/pwm.html )
;
; In Psuedo-code:
;
;// Initialize
;
;PWM_output = 1;
;rising_edge = 0;                         // Rising edge counter
;falling_edge = MAX_COUNT - duty_cycle;   // Falling edge counter
;
;// Loop forever:
;
;while(1) {
;
;  // If the rising_edge counter rolls over, make the output high
;
;  if(rising_edge++ > MAX_COUNT) {
;    rising_edge = 0;
;    PWM_output = 1;
;  }
;
;
;  // If the falling_edge counter rolls over, make the output low
;
;  if(falling_edge++ > MAX_COUNT) {
;    falling_edge = 0;
;    PWM_output = 0;
;  }
;
;}
;    
;
;In this un-optimized example, we start the PWM output in the high
;state and initialize the falling edge counter with the desired
;duty cycle (or actually MAX_COUNT - duty_cycle, since the
;algorithm increments the counters). When the counters reach their
;maximum count, they're cleared back to zero and the PWM output is
;updated. Perhaps a simple picture illustrates it better:
;
;
;RE  |---------|---------|---------|---------|---------
;    01234567890123456789012345678901234567890123456789
;
;FE  ----|---------|---------|---------|---------|-----
;    67890123456789012345678901234567890123456789012345
;
;PWM ----______----______----______----______----______
;
;  
;
;RE = Rising Edge counter
;
;FE = Falling Edge counter
;
;PWM = PWM output
;
;In this example, the counters roll over after 10 counts. In the
;beginning, the rising edge counter is cleared and the output is
;driven high. Also, the duty cycle is 4 so the falling edge
;counter is initialized to (10 - 4) = 6. When the rising edge
;counter counts from 9 to 10, it is "rolled over" back to zero and
;the output is driven high. Similarly, the falling edge counter
;drives the output low when it rolls over.
;
;Perhaps one thing to notice is that the difference (modulo 10)
;between the two counters is always equal to the duty cycle. That's
;no coincidence. In fact that's why this technique is called the
; "Phase Shifted Counters".
;
;The modulo arithmetic gets *much* simpler when MAX_COUNT = 2^N.
;
;
;RAM:
; pwm0-pwm7 - pwm counters
; rising_edge - rising edge counter
; pwm_state - current state of the pwm outputs.
;ROM
; 38 instructions
;Execution time
; 23 cycles

pwm_multiple

                               ;
       DECFSZ  rising_edge,F   ;If the rising edge counter has not
rolled
        GOTO   pwm_update      ;over, then go update the PWM counters
                               ;
pwm_rising_edge:                ;
                               ;
       MOVF    pwm0,W          ;Update each counter with the latest
       MOVWF   pwm0_cntr       ;pwm value
                               ;
       MOVF    pwm1,W          ;
       MOVWF   pwm1_cntr       ;
                               ;
       MOVF    pwm2,W          ;
       MOVWF   pwm2_cntr       ;
                               ;
       MOVF    pwm3,W          ;
       MOVWF   pwm3_cntr       ;
                               ;
       MOVF    pwm4,W          ;
       MOVWF   pwm4_cntr       ;
                               ;
       MOVF    pwm5,W          ;
       MOVWF   pwm5_cntr       ;
                               ;
       MOVF    pwm6,W          ;
       MOVWF   pwm6_cntr       ;
                               ;
       MOVF    pwm7,W          ;
       MOVWF   pwm7_cntr       ;
                               ;
       MOVLW   0xff            ;Turn on all of the PWM's.
       GOTO    pwm_exit        ;

pwm_update:
       CLRW                    ;Build the bit mask for turning
                               ;off the PWM outputs. Assume that
                               ;all of the outputs will be turned
                               ;off.
                               ;
       DECFSZ  pwm0_cntr,F     ;If the first counter has not reached 0
        IORLW  b'00000001'     ;then we don't want to turn it off.
                               ;
       DECFSZ  pwm1_cntr,F     ;Same for the second one
        IORLW  b'00000010'     ;
                               ;
       DECFSZ  pwm2_cntr,F     ;and so on...
        IORLW  b'00000100'     ;
                               ;
       DECFSZ  pwm3_cntr,F     ;
        IORLW  b'00001000'     ;
                               ;
       DECFSZ  pwm4_cntr,F     ;
        IORLW  b'00010000'     ;
                               ;
       DECFSZ  pwm5_cntr,F     ;
        IORLW  b'00100000'     ;
                               ;
       DECFSZ  pwm6_cntr,F     ;
        IORLW  b'01000000'     ;
                               ;
       DECFSZ  pwm7_cntr,F     ;
        IORLW  b'10000000'     ;
                               ;
                               ;
                               ;
                               ;
       ANDWF   pwm_state,W     ; Clear all of those pwm outputs
                               ;that have reached zero.
pwm_exit:                       ;
       MOVWF   PWM_PORT        ;Update the outputs
       MOVWF   pwm_state       ;Save the state

       RETURN


Start
       BSF     STATUS,RP0
       CLRF    PWM_PORT
       BCF     STATUS,RP0

       MOVLW   0
       MOVWF   pwm0

       MOVLW   0x10
       MOVWF   pwm1

       MOVLW   0x20
       MOVWF   pwm2

       MOVLW   0x30
       MOVWF   pwm3

       MOVLW   0x40
       MOVWF   pwm4

       MOVLW   0x50
       MOVWF   pwm5

       MOVLW   0x60
       MOVWF   pwm6

       MOVLW   0x70
       MOVWF   pwm7

loop
       CALL    pwm_multiple
       goto    loop
 end



; ----------------------------------------------------
; Below are some routines from one of my nightlight
; projects. You can see how I am using Scott's code
; to PWM modulate the RGB led. I control brightness
; which lets me change colors and overall intensity.
;
; *** NOTE *** This code is not complete. I left out
; a lot of setup and other irrelivent stuff to try
; and keep it simple.
;
; ----------------------------------------------------
;MAIN CODE
;
; The PWMLevelTable contains entries
; for bright, medium and dim led levels.
; It is used when the user changes the
; maximum brightness level of the
; nightlight.
;
; The table has 4 entries for each
; brightness level. The entries are:
;        MaxDutyCycle        - The new maximum duty cycle
;        RedStart                - Starting red duty cycle
;        GreenStart                - Starting green duty cycle
;        BlueStart                - Starting blue duty cycle
;
; USAGE: Call the table subroutine with the
; offset you want in W
;
; *** NOTE *** I did not put any error checking or
; 256 byte boundary management code in here. Make
; sure table is in first 256 bytes or write better code.
;
PWMLevelTable
       addwf PCL,f
       ; Bright
       dt 0xf0, 0x09, 0xa5, 0xe0        ; Start offset 0x0
       ; Medium
       dt 0x20, 0x15, 0x05, 0x1e        ; Start offset 0x4
       ; Dim
       dt 0x09, 0x05, 0x03, 0x02        ; Start offset 0x8

; -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
; *** Main program loop
; -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
; PWM the RGB leds
Main
PWM
       ; check for light adjust button press
       btfsc LTBtnPressed
       goto LTAdjBtnHandler

       ; Check for time adjust button press
       btfsc TMBtnPressed
       goto TMAdjBtnHandler
       
       ; Check for TimeToSleep
       btfsc TimeToSleep
       goto Shutdown

       ; Time to change colors by adjusting duty cycles?        
       btfsc ChangeColor                        
       goto ColorCycle
         
; ----------------------------------------------------
; This is Scott's code - modified for my project
; ----------------------------------------------------

       decfsz risingEdge,f                        ; Rising edge == 0?
(time to start over)
       goto PWMUpdate                                ;        NO - Update each
pwm count down
       
PWMRisingEdge        
       movfw redPwm                                ; Set each color's duty
cycle
       movwf redPwmCtr

       movfw greenPwm
       movwf greenPwmCtr

       movfw bluePwm
       movwf bluePwmCtr
               
       movlw RLED|GLED|BLED                ; turn on all pwm ports
       goto PWMExit
       
PWMUpdate
       ; build bit mask for turning off pwm's
       ; who's counters are zero
       clrw                                                ; Clear WREG.
It's the mask register.
       
       decfsz redPwmCtr,f                        ; Is it time to turn off
this led?
       iorlw RLED                                        ;        NO - set
mask to keep this led on.

       decfsz greenPwmCtr,f
       iorlw GLED

       decfsz bluePwmCtr,f
       iorlw BLED
       
       andwf pwmState,w                        ; clear all outpus that
reached zero
PWMExit
       movwf PORTC                                        ; Update pwm
outputs
       movwf pwmState                                ; Save state for next
pass through
       goto PWM                                        ; repeat
;-----------------------------------------------------------------------
------

; ----------------------------------------------------
; This routine is a cut and paste from my nightlight.
;
; It shows one way to change duty cycle and cycle
; led colors/brightness.
; ----------------------------------------------------
;
;
; ColorCycle is responsible for incrementing the
; duty cycle for each of the colors in the RGB led.
;
; It does this by adding 0x01 or 0xFF to each
; color's duty cycle. Adding 0xFF is the same
; as subtracting 0x01.
;
; When a duty cycle reaches the maximum
; or minimum value, it's increment register
; is changed from 0x01 to 0xFF or from 0xFF to 0x01.
; This causes the duty cycle to count in the
; opposite direction.
;
; Each led cycles back and forth between its
; minimum and maximum brightness level.
;
; When the three led's are mixed, all kinds
; of cool colors come out.
;
; NOTE - ColorCycle is called by the main line
; code whenever ChangeColor is high. ChangeColor
; is set every 32 mS in the TMR0 interrupt.
; Adjust the TMR0 interrupt interval to change
; the cycle speed AND/OR add a counter here
; to only change values every X calls.
; ----------------------------------------------------
ColorCycle
; *** Automatic color cycle the pwms - test version 1        
       movfw redInc                        ; Increment/decrement duty
cycles
       addwf redPwm,f
       movfw greenInc
       addwf greenPwm,f
       movfw blueInc
       addwf bluePwm,f
       
       ; Check each duty cycle for min value. If it's at
       ; the minimun, invert the incrementer.
CheckRed        
       ; min check
       movf redPwm,w                        ; Check for minimum value
       subwf pwmMin,w
       btfss STATUS,Z                        ; Need to invert?
       goto CheckRedMax                ;        NO, Check for max invert
       goto RedInvert                        ;        YES, Invert
       
CheckRedMax
       ; max check
       movf redPwm,w                        ; Check for maximum value
       subwf pwmMax,w
       btfss STATUS,Z                        ; Need to invert?
       goto CheckGreen                        ;        NO, Check next color

RedInvert        
       movlw 0xff                                ; Toggle incrementer
between
       btfsc redInc,7                        ; 0xFF and 0x01. This causes it
       movlw 0x01                                ; to increment or
decrement duty
       movwf redInc                        ; cycle when added to a
register.
       
CheckGreen
       ; min check        
       movf greenPwm,w
       subwf pwmMin,w
       btfss STATUS,Z        
       goto CheckGreenMax
       goto GreenInvert
       
CheckGreenMax
       ; max check
       movf greenPwm,w
       subwf pwmMax,w
       btfss STATUS,Z
       goto CheckBlue        

GreenInvert        
       movlw 0xff
       btfsc greenInc,7
       movlw 0x01
       movwf greenInc
       
CheckBlue        
       ; min check
       movf bluePwm,w
       subwf pwmMin,w
       btfss STATUS,Z
       goto CheckBlueMax
       goto BlueInvert
       
CheckBlueMax
       ; max check
       movf bluePwm,w
       subwf pwmMax,w
       btfss STATUS,Z
       goto ColorCycleDone
       
BlueInvert                
       movlw 0xff
       btfsc blueInc,7
       movlw 0x01
       movwf blueInc

ColorCycleDone
       bcf ChangeColor                        ; Clear the color change flag.
       goto PWM
;-----------------------------------------------------------------------
------

2007\01\23@091720 by Richard Seriani, Sr.

picon face

----- Original Message -----
From: "Balthasar Indermuehle" <spam_OUTbindermuehleTakeThisOuTspamgmail.com>
To: <.....piclistKILLspamspam@spam@mit.edu>
Sent: Tuesday, January 23, 2007 8:37 AM
Subject: [PIC] fading a LED with 16F917


> Hi all,
>
> I just received my PicKit2 today featuring a 16F917, and despite never
> having programmed a PIC before I made rapid progress switching LED's on
and
> off (I've been practising with a simulator for the past few days). I then
> searched the archives for information on how to fade in/out those LED's,
but
> unfortunately I do not understand how that is supposed to work.
>
> Can someone explain to me in hardware newbie terms, how I can use the
pulse
> width modulation method on the LED's connected to PORTD (TRISD)? Some
sample
> code would be of great help, too.
>
> Thanks!
>
> - Balt
>
> --

2007\01\23@094529 by Wouter van Ooijen

face picon face
> Can someone explain to me in hardware newbie terms, how I can
> use the pulse
> width modulation method on the LED's connected to PORTD
> (TRISD)?

PWM: Switch the LED on and off rapidly, whith the ration of on and off
times determining the amount of LED light. Your PIC might have some
hardware PWM modules that can do this for you, but that will limit the
number of LEDs and force you to use specific pins. It is not that hard
to do in software.

Wouter van Ooijen

-- -------------------------------------------
Van Ooijen Technische Informatica: http://www.voti.nl
consultancy, development, PICmicro products
docent Hogeschool van Utrecht: http://www.voti.nl/hvu


2007\01\23@094542 by M. Adam Davis

face picon face
PWM is pulse width modulation.  This means that the signal goes high
and low, and the high pulses are sometimes longer than low pulses and
vice versa.

If the high pulses are longer than the low pulses (assuming your LED
is on when the pin is high) then the LED is brighter.

If the low pulses are longer than the high pulses then they LED is dimmer.

A very simple and fairly easy way to make the LED dim in and out is to
do something like this (fake code, haven't tested, let me know if you
need tested code):

x=0;
y=0;

:label1
Turn the LED on.
y=0
Loop here and count y up until y = x;  (call delay each count up)
Turn LED off.
y=255;
Loop here and count y down until y = x;  (call delay each count up)
x=x+1
goto label1

:delay
z = 0
count up until z = 255
return

When x is small, the LED will be dim, because it will be off for
longer than it is on.

When x is large it will be bright because it is on for longer than it is off.

You can comment out the "x=x+1" and just set x at the start to set a
particular brightness.

If the PIC is running at 8 MHz, then the LED will go from off to on
over about 8 to 10 seconds and then restart at off.

I hope this makes sense - if not, ask more questions!

-Adam


On 1/23/07, Balthasar Indermuehle <bindermuehlespamKILLspamgmail.com> wrote:
{Quote hidden}

> -

2007\01\23@200712 by Balthasar Indermuehle

picon face
Hi Chris and all others who responded so diligently to my question!

Thanks for all your excellent help so far. I'm reading, learning and
experimenting at this point (not successful yet, but it's starting to look
good). I might have some more questions in regards to an individual
response. Is it customary to respond privately in that case or to the list?

Cheers

- Balt

> {Original Message removed}

2007\01\24@115400 by Mike Hord

picon face
It is always appropriate to respond to the list instead of the individual.
That keeps the information on the list.

The point of the PICList is less to provide a forum for YOU to get
help with YOUR problem, and more to provide a way for people to
observe problems and solutions of others, so we can all learn from
these experiences.  It's a way to disseminate experience and
information as widely as possible- moving discussion off-list when
it has technical content does not serve that interest.

Mike H.

On 1/23/07, Balthasar Indermuehle <.....bindermuehleKILLspamspam.....gmail.com> wrote:
{Quote hidden}

> > {Original Message removed}

More... (looser matching)
- Last day of these posts
- In 2007 , 2008 only
- Today
- New search...