PDA

View Full Version : How to make an LED gradually and slowly get brighter and dimmer?



keithv
- 29th September 2016, 23:30
I need to make an LED very slowly get brighter and then dimmer and repeat. I do not need to make the LED "blink" on and off. I need to make the LED start at completely off and then slowly and gradually get brighter. Once it reaches full brightness, I need to make it slowly and gradually get dimmer until it's all the way off.

I've used PWM and HPWM. These go too fast. I need it to go slower. I've asked this question before, and people have suggested I need to use the CCP module and/or interrupts, but I'm fairly new to this, and I don't know what to do with the CCP module. Can someone please give me some example code of how to make an LED slowly and gradually get brighter and dimmer?

mark_s
- 30th September 2016, 00:15
Use the HPWM command. Can't write the code for you, but one way is to use a counter and slowly ramp the duty cycle up and then down. Play with the pause times to get the effect you want. It will look better with 10bit PWM, try this first. Also search MBAM on the forum this works good for leds.



Duty var byte
Main:

For Duty = 0 to 255 ' Gets brighter
pause 100
HPWM 1, Duty, 1000
Next Duty

For Duty = 254 to 0 step -1 'Gets dimmer
pause 100
HPWM 1, Duty, 1000
Next Duty
Goto Main

richard
- 30th September 2016, 00:21
I've asked this question before, and people have suggested I need to use the CCP module and/or interrupts, but I'm fairly new to this, and I don't know what to do with the CCP module. Can someone please give me some example code of how to make an LED slowly and gradually get brighter and dimmer?

you were given some working examples last time
what don't you understand ?
what have you tried ?

Scampy
- 30th September 2016, 08:56
the problem with using the pause statement is that it effectively halts the execution of the rest of the code until the period has elapsed.

How many LEDs do you want to fade up and down? There are dedicated LED controllers that use i2c to communicate with the PIC, that can handle multiples of 16 LEDs, and means that once you have sent the value off to the chip, the PIC can the perform other functions.

Post up what code you have and more details on what you are hoping to achieve and I'm sure you'll get some suggestions

HenrikOlsson
- 30th September 2016, 09:23
Oh, for crying out loud, this was discussed in detail in the other thread. When you use HPWM you ARE using the CCP module. The frequency of the PWM signal has nothing to do with how fast or slow you fade the LED - as was discussed previously.

The example posted by mark_s does exactly what you ask for, can't you at least try that.

And PAUSE doesn't affect HPWM since HPWM uses the CCP module, ie it generates the PWM signal in hardware so in this case it does exactly what was asked.

Scampy
- 30th September 2016, 17:33
Oh, for crying out loud, this was discussed in detail in the other thread. When you use HPWM you ARE using the CCP module. The frequency of the PWM signal has nothing to do with how fast or slow you fade the LED - as was discussed previously.

The example posted by mark_s does exactly what you ask for, can't you at least try that.

Having a bad groundhog day Henrik ? :-)

HenrikOlsson
- 30th September 2016, 19:20
Ah, not really but please accept my apologies.

I just don't understand what the problem here, the issue was discussed in depth in the other thread but apparently there's some detail that doesn't make sense - and that's fine - but instead of asking about that detail we get a new thread with the same topic.

And, regarding PAUSE, you're of course 100% correct with that comment but it doesn't really pertain to the HPWM command and may just make thing more confusing.

Anyway, I'm sorry for being harsh, not my intention, shame on me.

/Henrik.

picster
- 3rd October 2016, 15:39
Yup, for sure HPWM is the way to go unless you've already used those pins up, in which case you can go SPWM, but that chews up processing time. HPWM isn't "slow or fast" like Henrik says, you just change your duty cycle as quickly or slowly as you want to, you can test it with a pause loop, and then implement via a timed interrupt routine (which obviously has less overhead).

keithv
- 3rd October 2016, 21:53
you were given some working examples last time
what don't you understand ?
what have you tried ?

Thanks, Richard. Here is the code you gave me last time:


'************************************************* ***************
'* Name : fader.BAS *
'* Author : [select VIEW...EDITOR OPTIONS] *
'* Notice : Copyright (c) 2016 [select VIEW...EDITOR OPTIONS] *
'* : All Rights Reserved *
'* Date : 6/30/2016 *
'* Version : 1.0 *
'* Notes : pic16f1825 *
'* : *
'************************************************* ***************


#CONFIG
__config _CONFIG1, _FOSC_INTOSC & _CP_OFF & _WDTE_ON & _PWRTE_ON & _MCLRE_ON & _CLKOUTEN_OFF
__config _CONFIG2, _PLLEN_ON & _LVP_OFF
#ENDCONFIG


DEFINE OSC 32



goto overpwm

my_pwm:
;100 step 1.35 gamma curve
@ dW 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
@ dW 1, 1, 1, 1, 1, 1, 2, 2, 2, 2
@ dW 2, 2, 2, 2, 2, 3, 3, 3, 3, 3
@ dW 3, 4, 4, 4, 4, 5, 5, 5, 6, 6
@ dW 6, 7, 7, 8, 8, 9, 9, 10, 11, 11
@ dW 12, 13, 14, 15, 16, 17, 18, 20, 21, 23
@ dW 24, 26, 28, 30, 33, 35, 38, 41, 44, 47
@ dW 51, 55, 59, 64, 69, 74, 80, 86, 93,101
@ dW 109,118,128,138,150,162,176,190,206,224
@ dW 243,263,286,310,337,366,398,433,471,511



ASM
;---[Returns the Address of a Label as a Word]------------------------------
GetAddress macro Label, Wout
CHK?RP Wout
movlw low Label ; get low byte
movwf Wout
; movlw High Label ; get high byte MPLAB 8.53 killed high
movlw Label >> 8 ; get high byte
movwf Wout + 1
endm
endasm
overpwm:

OSCCON=$70
ANSELA=0
ANSELC=0
paddress var word
pw var word
pl var byte
pl2 var word
inc var word
t2con=5
TRISA = %111110
TRISC = %11010011 ' set PORTC I/O
led1 var portc.3 ; 10 bit straight pwm
led2 var portc.5 ; 10 bit 100 step gamma corrected pwm


@ GetAddress _my_pwm,_paddress
pl2 =0
pl=100

main:
inc=1
while pl
pl=pl-1
gosub setpwm
pause 50
wend
inc=-1
while pl < 99
pl=pl+1
gosub setpwm
pause 50
wend
goto main

setpwm:
readcode paddress+pl ,pw
CCPR1L = PW>>2;
ccp1con=12|((PW&3)<<4); led2
pl2 =pl2 +inc
if pl2 >1023 then pl2 =0
CCPR2L = Pl2>>2; led1
ccp2con=12|((Pl2&3)<<4);
return


The first problem is that I'm using a 16F886 and I can't seem to get this code to work with it. I've done some reconfiguring, and PBP will compile it for the 16F886, but I get an error message when I actually try to program the chip, so I'm clearly not doing something correctly.

Also, I really don't fully understand what is going on. I understand what the code is doing, but I don't understand the CCP module well enough to understand what setpwm is doing. Although the line "while pl" doesn't make any sense to me. Doesn't there need to be some sort of statement like "while pl < 99"?

CCPR1L = PW>>2;
ccp1con=12|((PW&3)<<4); led2

CCPR2L = Pl2>>2; led1
ccp2con=12|((Pl2&3)<<4);

Could you please explain what these lines are doing? I'm reading over the datasheet. It's starting to make a little more sense, but I'm not completely there yet. Am I correct in assuming the the LEDs need to physically connect to specific pins on the MCU, i.e., the CCP1 and CCP2 pins?

keithv
- 3rd October 2016, 21:58
Oh, for crying out loud, this was discussed in detail in the other thread. When you use HPWM you ARE using the CCP module. The frequency of the PWM signal has nothing to do with how fast or slow you fade the LED - as was discussed previously.

The example posted by mark_s does exactly what you ask for, can't you at least try that.

And PAUSE doesn't affect HPWM since HPWM uses the CCP module, ie it generates the PWM signal in hardware so in this case it does exactly what was asked.

I started a new thread because I didn't really get anything that helped me last time, and I thought that was because I wasn't asking my questions correctly. There seemed to be some confusion about what I was trying to do, so rather than possible cause more confusion, I thought it was best to try again with a new thread and ask my question in a different way.

richard
- 3rd October 2016, 23:36
The first problem is that I'm using a 16F886 and I can't seem to get this code to work with it. I've done some reconfiguring, and PBP will compile it for the 16F886, but I get an error message when I actually try to program the chip, so I'm clearly not doing something correctly.

firstly there is not much point reposting my code , you need to post what you are using , my example is for a pic16f1825
for a 16f886 things will be different
osc is different, ccp1 and 2 pins are different , ansel settings are different, config word is different tris ..........



Also, I really don't fully understand what is going on. I understand what the code is doing, but I don't understand the CCP module well enough to understand what setpwm is doing. Although the line "while pl" doesn't make any sense to me. Doesn't there need to be some sort of statement like "while pl < 99"?

in nearly all computer languages false=0 anything else is true

so "while pl" means while pl is true ie anything but 0



CCPR1L = PW>>2;
ccp1con=12|((PW&3)<<4); led2

CCPR2L = Pl2>>2; led1
ccp2con=12|((Pl2&3)<<4);

10 bit pwm is high 8 bits =CPRxL , LOW 2 bits = CCPxCON bits 4,5

so our 10 bit pwm value "PW" is deconstructed CCPR1L = PW>>2 moves high 8 bits into CCPR1L

and with [ccp1con=12|((PW&3)<<4)] the low two bits "PW&3" are shifted to bit 4,5 posn and or(ed) into ccp1con

keithv
- 4th October 2016, 18:25
Thank you for clarifying that, Richard.

I'm using mark_s's suggestion and it's working well so far. I think the problem I had last time I experimented with pulse width modulation is that I thought hpwm was the same as pwm where I could assign the output to whichever pin I wanted. I wasn't aware that hpwm is like adcin - there are specific channels on specific pins.