+ Reply to Thread
Page 1 of 3
1 2 3 Last
Results 1 to 15 of 31

Thread: Blinking LED using PWM - PIC18f4520

  1. #1
    Ecappp Newbie
    Join Date
    Apr 2009
    Posts
    16

    Default Blinking LED using PWM - PIC18f4520

    Specifications:
    Microcontroller: PIC18f4520
    Crystal: 4 MHz
    Language: C Programming (not assembly codes)

    Basically I'm trying to blink a LED using PWM to enable the on-time to be variable. However, I can't seem to blink the LED without using the LED toggle and delay functions. By using the toggle function, I have found that the on-time cannot be changed.

    May anyone give me an idea on what I can do to go around this?
    Last edited by Ecappp; 13th April 2009 at 04:05 AM.


  2. #2
    Help us help you blueroomelectronics Excellent blueroomelectronics Excellent blueroomelectronics Excellent blueroomelectronics Excellent blueroomelectronics Excellent blueroomelectronics Excellent blueroomelectronics Excellent blueroomelectronics Excellent blueroomelectronics Excellent blueroomelectronics Excellent
    Join Date
    Jan 2007
    Location
    Toronto, Canada
    Posts
    10,696
    Blog Entries
    5

    Default

    Post your code, and compiler version.

    At 4MHz the PWM is going to be pretty fast. How slow do you want it to blink?
    Bill
    Smart Kits build Smart People

    http://www.blueroomelectronics.com/

  3. #3
    Ecappp Newbie
    Join Date
    Apr 2009
    Posts
    16

    Default

    Compiler: MPLAB C18 C Compiler (MCC18)

    I don't exactly have a specific speed that I want the LED to blink (duty cycle interchangeable). I just need to be able to see the speed of the blinking clearly on the hardware. The crystal can't be changed because it is built-in into the hardware.

    Code:

    #include <p18f4520.h>

    void main ( )
    {

    TRISB = 0;
    TRISC = 0b11111011; // RC2 as output
    T2CON = 0b00000101; // Timer 2 On, postscale = 1:1, prescale = 1:4
    PR2 = 64; // Set PR2 = 64 for 52 ?s
    CCPR1L = 0b00001101; // CCPR1L:CCP1CON<5:4> = 52
    CCP1CON = 0b00001111; // DC1B1 & DC1B0 = 0, PWM mode
    PORTBbits.RB1 = PORTCbits.RC2; //blinking LED according to PWM
    while(1);

    }

  4. #4
    Help us help you blueroomelectronics Excellent blueroomelectronics Excellent blueroomelectronics Excellent blueroomelectronics Excellent blueroomelectronics Excellent blueroomelectronics Excellent blueroomelectronics Excellent blueroomelectronics Excellent blueroomelectronics Excellent blueroomelectronics Excellent
    Join Date
    Jan 2007
    Location
    Toronto, Canada
    Posts
    10,696
    Blog Entries
    5

    Default

    What do you figure your PWM speed is? Anything faster than 30Hz may be impossible to see as a flash.

    Code:
    PORTBbits.RB1 = PORTCbits.RC2;     //blinking LED according to PWM
      while(1);
    
    Do you see anything wrong here? How will RB1 change?
    Last edited by blueroomelectronics; 13th April 2009 at 04:26 AM.
    Bill
    Smart Kits build Smart People

    http://www.blueroomelectronics.com/

  5. #5
    Ecappp Newbie
    Join Date
    Apr 2009
    Posts
    16

    Default

    Well, regarding the code you quoted, I do know there is something wrong there. I was trying to link the LED to the PWM but it obviously failed.

    If I were to try configuring the speed as less than 30Hz, how may I get the PR2 value to be less than 255? I don't know of a way to bring it lower than that.

  6. #6
    be80be Excellent be80be Excellent be80be Excellent be80be Excellent be80be Excellent be80be Excellent
    Join Date
    Aug 2008
    Location
    morristown,tn
    Posts
    2,000

    Default

    Internal oscillator support - 31 kHz to 8 MHz, up to 32 MHz with 4X PLL
    looks like you could set that for any thing you would want
    Burt

  7. #7
    Ecappp Newbie
    Join Date
    Apr 2009
    Posts
    16

    Default

    If the oscillator used is big, does the PR2 value increase as well? Is the crystal oscillator and the internal oscillator support two different things?

    Code:
    PORTBbits.RB1 = PORTCbits.RC2;     //blinking LED according to PWM
      while(1);
    
    By the way, can anyone tell me what is wrong (I know it's wrong) with this statement and how do I rewrite it?
    Last edited by Ecappp; 13th April 2009 at 05:13 AM.

  8. #8
    tresca Good tresca Good
    Join Date
    Apr 2004
    Location
    Canada
    Posts
    194

    Default

    You need to toggle that bit

    It should be more like
    Code:
    PORTBbits.RB1 ^= 1;     //blinking LED according to PWM
      while(1);
    
    This will toggle the RB1 each time this line is executed.

  9. #9
    tresca Good tresca Good
    Join Date
    Apr 2004
    Location
    Canada
    Posts
    194

    Default

    If the oscillator used is big, does the PR2 value increase as well? Is the crystal oscillator and the internal oscillator support two different things?
    The value does not increase but the time it takes to overflow does. Each clock cycle, the value of PR2 increases. Thats all the timer does. But if you clock is at 4MHz, then each increment of PR2 occurs in 1us. If you change your clock frequency to say 8Mhz, then each increment of PR2 occurs 500ns. So if you are looking for a specific PWM frequency, your PR2 value needs to be updated to account for the clock frequency.

    Make sense ?

  10. #10
    be80be Excellent be80be Excellent be80be Excellent be80be Excellent be80be Excellent be80be Excellent
    Join Date
    Aug 2008
    Location
    morristown,tn
    Posts
    2,000

    Default

    I'm not good with C but the osc can be change the Internal oscillator clock from 8mhz 4mhz 2mhz 1 mhz and lower down to 32khz which would give you real slow pwm and if your using a CRYSTAL/CERAMIC RESONATOR your can turn it off and use Internal oscillator
    Burt

  11. #11
    arhi Excellent arhi Excellent arhi Excellent arhi Excellent arhi Excellent arhi Excellent
    Join Date
    Apr 2008
    Location
    Belgrade, .rs
    Posts
    832

    Default

    Code:
     while(1); 

    What is the intention of this?! while(1); does "loop in one spot" it will never change / set / do anything .. the app will just "stand still" at that position....

    disregarding the config bits etc ..
    Code:
    #include <p18f4520.h>
    
    void main ( )
    {
      TRISB = 0;
      TRISC = 0b11111011; // RC2 as output
      T2CON = 0b00000101; // Timer 2 On, postscale = 1:1, prescale = 1:4
      PR2 = 64; // Set PR2 = 64 for 52 us
      CCPR1L = 0b00001101; // CCPR1L:CCP1CON<5:4> = 52
      CCP1CON = 0b00001111; // DC1B1 & DC1B0 = 0, PWM mode
      while(1){
        PORTBbits.RB1 = PORTCbits.RC2; //blinking LED according to PWM
      }
    }
    
    In theory this will blink B1 almost the same time as RC2
    RC2 is "blinked" by hardware ccp (pwm) module.

    if you only need to blink the RC2 then you do not need the b1 part
    Code:
    #include <p18f4520.h>
    
    void main ( )
    {
      TRISB = 0;
      TRISC = 0b11111011; // RC2 as output
      T2CON = 0b00000101; // Timer 2 On, postscale = 1:1, prescale = 1:4
      PR2 = 64; // Set PR2 = 64 for 52 us
      CCPR1L = 0b00001101; // CCPR1L:CCP1CON<5:4> = 52
      CCP1CON = 0b00001111; // DC1B1 & DC1B0 = 0, PWM mode
      while(1); // DO NOTHING - hw pwm module will blink led
    }
    


    I do not see the config here but if you are running it at 4MHz the speed of the pwm will be too fast and there is no way you can see the blinking with naked eye .. if you want blinking that you can see, you have to forget about pwm as you cannot make pwm go that slow (max that you can notice is about 100Hz and even that is almost impossible to tell ... the 15Hz is kinda max for "noticeable" blink) and PWM usually do not go under few KHz because:

    PWM Period = [(PR2) + 1] • 4 • TOSC • (TMR2 Prescale Value)

    your TOSC is 1/4000000, max TMR2 prescale is 16, max PR2 is 255 so max period is

    256 * 4 * (1/4000000) * 16 = 0.004096 => 1/0.004096 = 244.14Hz

    So with 4MHz the lowest you can go is 244Hz - there is NO WAY you can see that with naked eye. not to mention that you are using 1:4 prescale and not 1:16 so your led is blinking at almost 1KHz

    If you need to be able to see the led blink, use the delay function

    Code:
    #include <p18f4520.h>
    
    void main ( )
    {
      TRISB = 0;
      TRISC = 0b11111011; // RC2 as output
      LATBbits.LATB1 = 0;
      LATCbits.LATC2 = 0;
    
      while(1){
        LATBbits.LATB1 ^= 1;
        LATCbits.LATC2 ^= 1;
        Delay10KTCYx(200); //wait 2000000 cycles
      }
    }
    
    Last edited by arhi; 13th April 2009 at 08:02 AM. Reason: added comment

  12. #12
    arhi Excellent arhi Excellent arhi Excellent arhi Excellent arhi Excellent arhi Excellent
    Join Date
    Apr 2008
    Location
    Belgrade, .rs
    Posts
    832

    Default

    btw, you are probably trying:

    Code:
    #include <p18f4520.h>
    
    void main ( )
    {
      unsigned char dcycle;
      TRISB = 0;
      TRISC = 0b11111011; // RC2 as output
      T2CON = 0b00000101; // Timer 2 On, postscale = 1:1, prescale = 1:4
      PR2 = 64; // Set PR2 = 64 for 52 us
      CCPR1L = 0b00001101; // CCPR1L:CCP1CON<5:4> = 52
      CCP1CON = 0b00001111; // DC1B1 & DC1B0 = 0, PWM mode
    
       // the led is now pwm'd with 1KHz on RC2
    
      dcycle = 0;
      while(1){ // loop forever
         // change the brightness of the LED by changing PWM DC
         // PWM Duty Cycle = (CCPRXL:CCPXCON<5:4>) • TOSC • (TMR2 Prescale Value)
         CCPR1L = dcycle++;
         Delay10KTCYx(20); //wait 200000 cycles
      }
    }
    
    this will change the brightness of your led on RC2 every 200ms (only 8bit resolution - 10 bit resolution is possible but not needed for this example) 256 times and then will start from scratch

  13. #13
    arhi Excellent arhi Excellent arhi Excellent arhi Excellent arhi Excellent arhi Excellent
    Join Date
    Apr 2008
    Location
    Belgrade, .rs
    Posts
    832

    Default

    and .. if you want to blink and not to smoothly light more :

    Code:
    #include <p18f4520.h>
    
    void main ( )
    {
      TRISB = 0;
      TRISC = 0b11111011; // RC2 as output
      T2CON = 0b00000101; // Timer 2 On, postscale = 1:1, prescale = 1:4
      PR2 = 64; // Set PR2 = 64 for 52 us
      CCPR1L = 0b00001101; // CCPR1L:CCP1CON<5:4> = 52
      CCP1CON = 0b00001111; // DC1B1 & DC1B0 = 0, PWM mode
      // the led is now pwm'd with 1KHz on RC2
    
      while(1){ // loop forever
         //LED ON
         CCPR1L = 0xFF;
         Delay10KTCYx(20); //wait 200000 cycles
         //LED OFF
         CCPR1L = 0;
         Delay10KTCYx(20); //wait 200000 cycles
      }
    }
    

  14. #14
    arhi Excellent arhi Excellent arhi Excellent arhi Excellent arhi Excellent arhi Excellent
    Join Date
    Apr 2008
    Location
    Belgrade, .rs
    Posts
    832

    Default

    and .. for the end of mine involvement .. if you are using C18 why don't you use available libraries ... there's pwm library .. :

    Function prototypes
    #include <pwm.h>
    void OpenPWMx ( char PR2 ); // Configure PWM channel x.
    void SetDCPWMx ( unsigned int dutycycle ); // Write a new duty cycle value to PWM channel x.
    void ClosePWMx ( void ); // Disable PWM channel x.

    Notes:

    1. PR2 can be any value from 0x00 to 0xff. This value determines the PWM frequency by using the following formula:
    PWM period =[(PR2) + 1] x 4 x TOSC x TMR2 prescaler

    2. The value of dutycycle can be any 10-bit number. Only the lower 10-bits of dutycycle are written into the duty cycle registers. The duty cycle determines the high time of the PWM waveform.

    3. PWM uses TIMER2 for time base. In addition to opening the PWM, TIMER2 must also be opened with an OpenTimer2(...) statement before the PWM will operate. See the other manual for the timer functions.

    4. TIMER2 postscaler is not used in the determination of the PWM frequency. TIMER2 postscaler could be used to generate TMR2 interrupts at a different frequency than the PWM output.

  15. #15
    Ecappp Newbie
    Join Date
    Apr 2009
    Posts
    16

    Default

    Quote Originally Posted by arhi View Post
    and .. if you want to blink and not to smoothly light more :

    Code:
      while(1){ // loop forever
         //LED ON
         CCPR1L = 0xFF;
         Delay10KTCYx(20); //wait 200000 cycles
         //LED OFF
         CCPR1L = 0;
         Delay10KTCYx(20); //wait 200000 cycles
      }
    
    May i know why is CCPR1L = 0xFF instead of my desired CCPR1L value?

    I've tried changing the value of CCPR1L to different values and i noticed that has effect for buzzer tone. However, the blinking of the LED looks the same. How do I know if PWM has any effect on the LED?
    Last edited by Ecappp; 15th April 2009 at 03:55 AM.

+ Reply to Thread
Page 1 of 3
1 2 3 Last

Similar Threads

  1. I2C in PIC18F4520
    By hmk in forum Electronic Projects Design/Ideas/Reviews
    Replies: 3
    Latest: 18th February 2009, 12:12 PM
  2. New To Pic18f4520
    By sokalpunx in forum Micro Controllers
    Replies: 3
    Latest: 7th November 2008, 08:08 PM
  3. Pic18F4520
    By jster28 in forum Micro Controllers
    Replies: 2
    Latest: 3rd December 2007, 08:49 PM
  4. PIC18f4520
    By lihsheng in forum Micro Controllers
    Replies: 1
    Latest: 20th November 2007, 09:27 AM
  5. help with pic18f4520
    By MenessFreak in forum Micro Controllers
    Replies: 8
    Latest: 24th November 2006, 06:04 AM

Tags for this Thread