PIC and PWM

Status
Not open for further replies.

Termike

New Member
Hi, I am new on this forum so here's my problem.

I wrote a program in my pic because I want to build a home made desklight. I'm using leds which are adjustable in intensity, this using PWM ofcourse.
Now there are 2 kind of leds, one with high brightness leds, and one with large angle leds. The intensity is set for the both. Not independant. THe program works. S2 switches between only the first set of leds, or the second set of leds, or both. The first 2 options work perfect with the PWM commando. Now with the third option doesn't work well with the pwm commando. This is because the PIC pwms the first set of leds, then leaves them black, and then pwms the second set of leds. I want them both at the same time, with the same intensity ofcourse. Now what I actually need is a replacement commando for PWM. Something with for next loops perhaps?

Thanks already for your help.
Greetings
Robin

Code:
DEVICE 16F628A                                                      ;Using the 16F628A
CONFIG INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF    ;Fuses instellen
ALL_DIGITAL TRUE                                                    ;All info is digital
Dim Duty as byte
Dim main_switch as byte

SYMBOL LED0 = PORTA.0                                               
SYMBOL LED1 = PORTA.1                                              
SYMBOL LED2 = PORTA.2  
SYMBOL LED3 = PORTA.3                                               
SYMBOL S0   = PORTB.0                                               
SYMBOL S1   = PORTB.1                                               
SYMBOL S2   = PORTB.2                                              
        ;76543210
PORTA = %00000000                                                   ;Port A low
PORTB = %00000000                                                   ;Port B low
TRISA = %00000000                                                   ;All output
TRISB = %00000111                                                   ;ports 0-2 input

PORTB_PULLUPS ON
LED3 = 1
Duty = 255
main_switch = 1
Loop:                       ;start mainloop
While 1 = 1
Select case main_switch
    Case 1
        PWM LED0, Duty, 10 
        Call readaction
    Case 2
        PWM LED1, Duty, 10
        Call readaction    
    Case 3
        PWM LED0, Duty, 10
        PWM LED1, Duty, 10
        Call readaction
End Select
Wend                                             ;End mainloop

readaction:
    Select Case 0
        Case S0
            If Duty = 30 then
                Duty = 30
            else
                Duty = Duty - 25
            End if
            while S0 = 0 : wend
        Case S1
            If Duty = 255 then
                Duty = 255
            else
                Duty = Duty + 25
            End if
            while S1 = 0 : wend
        Case S2
            If main_switch = 3 then
                main_switch = 1
            Else
                main_switch = main_switch + 1
            End if
            while S2 = 0 : wend
    End select            
return

END                           ;End program
 
there's lots of basic code examples out there for interrupt driven PWM - usually you'll get 8 or more duty adjustable pwms.

alternately you can go with a chip that has two (or more) dedicated hardware pwm generators (CCP modules), and that'll leave the chip open to doing other things.
 
I can't seem to find a replacement code for the PWM command. I know it has to be something like a for next loop but I can't seem to figure it out...
 
I was going to suggest searching picbasic.org/forum, but I see that Les has funked up the search feature with an almost impossible to read captcha - so much for that idea.

I can't find the interrupt driven PWM example right now - but what you might want to try:

1. shorten the pwm period for your colors, use only 1-3 cycles instead of the 10 you're using now. this will make the pic update each color faster, so it your eye can't see them being updated separately. this will dim them somewhat, so compensate with more drive current.

2. place the soft pwm calls in a hard loop, and handle your interface (switches) using interrupts. taking the button-checking out of the pwm loop will speed up the rate at which the pic can update the pwm values.
 
justDIY said:
I was going to suggest searching picbasic.org/forum, but I see that Les has funked up the search feature with an almost impossible to read captcha - so much for that idea...

I wrote this, but it doesn't do what I want it to do. It shocks too much. And that's why i inserted a second for next loop. But that doesn't help.
PS, I have never worked with interrupts. I first want to make 2 leds adjustable in intensity. At the same time ofcouse. Interrupts I can insert later on right?

This is the code, that actually doesn't work very well
Code:
For I = 0 to 255
    For J = 0 to 10
        led0 = 1
        LED1 = 1
        delayms I / 15
        led0 = 0
        LED1 = 0
        delayms (255 - I) / 15
    Next J
Next I
 
if you have two led (or groups of leds), grab a chip with hardware pwm and make life easy on yourself.

the 16F873A has two pwm generators, you can use the basic HPWM command. No need to calculate any delay loops or know any interrupts.

just this easy:
' set CCP1 to 50% duty cycle, 1 khz frequency
HPWM 1, 128, 1024

' set CCP2 to 75% duty cycle, 1 khz frequency
HPWM 2, 192, 1024

you only issue the command once, and it stays that way until you want to change it - no need to call the command again and again
 
Yes I know, but don't any of you here use home made pwm codes, in stead of the PWM or HPWM command? I think there should be a way to do this with a simple 16F628A, after all they say this is the most commonly used PIC, and the thing I want it to do can't be too difficult for that PIC now can't it?
 
Have a look at TMR2 and how it works. It is a very low maintenance Timer Interrupt, and very easy to use once you know how to set it up.


**broken link removed**


That example will create a uS, mS, S counter that will increment once every 200uS. Now you might be able to get away with something a little slower (say 1mS)

Just on that, the longer the delay, the more your program can "do in between" Interrupts, generally, 1mS is plenty

Now you can create simple counters that check if a pre-determined amount of time has passed, perform an action (in this case TOGGLE Pin) and reset the counter. Pie

 
Interrupts really are a better way to go. That said, you might try something like this 'soft' PWM routine (below). There are 64 discrete PWM steps in this example and you should set the RedLED, GrnLED, and BluLED variables in MAIN to some value between 0 (off) and 63 (full brightness). The interrupt driver simply compares each LED setting to a master counter [0..63) and turns off the LED bit in a shadow register on a match. The PORT B output bits are updated from the shadow variable at the end of the interrupt code so there's no update jitter.

Code:
Dim 
    Shadow As Byte,
    PWM_ctr As Byte,
    RedLED, GrnLED, BluLED As Byte

interrupt TMR2_interrupt()
    PIR1.1 = 0              // clear Timer 2 interrupt flag
    Inc (PWM_ctr)           // increment our 0..63 PWM counter
    If PWM_ctr = 64 Then    // if end of 64 step cycle then
        PWM_ctr = 0         // reset to 0 and
        Shadow = 0          // turn on all LED bits in shadow
    EndIf
    
    If RedLED = PWM_ctr Then
        Shadow = Shadow Or %00000001    // turn off Red LED
    EndIf
    
    If GrnLED = PWM_ctr Then
        Shadow = Shadow Or %00000010    // turn off Grn LED
    EndIf
    
    If BluLED = PWM_ctr Then
        Shadow = Shadow Or %00000100    // turn off Blu LED
    EndIf
    
    PORTB = Shadow          // update LED output pins
 
Last edited:
I read the entire document, a few times actually. And some other things too. But I don't see how I can use this in my project. I don't know how to implement it into my code...
 
Termike said:
I read the entire document, a few times actually. And some other things too. But I don't see how I can use this in my project. I don't know how to implement it into my code...


Mike posted a good example above, my example was more of a generic one, explaining how to set up and use TMR2, how you want to proceed from their is entirely up to you
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…