NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » Adding a delay to an PWM controlled LED

January 26, 2011
by kemil
kemil's Avatar

Hi guys,

i would like to add a delay to an led where its brigntness is being controlledby pwm. but im not sure how this could be implemented. ive taken some code from the servo squirter tutorial which i think is the part which controlls the brightness of the light. what i want to be able to do is flash the light on and off say every second but i when the light is on i dont necessarily want it to be on full brightness so i would like to controll its intensity using pwm.

ive added a first draft of some code which will need to be corrected for it to work but it kind of give a good indication of what i want to do.

so if anyone has any tips on how this could be done it it would be much apprciated.

kemil

void pwm_init() {
   // setup Timer1 for Fast PWM mode, 16-bit
   // COM1B1 -- for non-inverting output
   // WGM13, WGM12, WGM11, WGM10 -- for Fast PWM with OCR1A as TOP value
   // CS11 -- for CLK/8 prescaling

  OCR1A = 36864;    // sets PWM to repeat pulse every 20.0ms
 TCCR1A = (1<<COM1B1) | (1<<WGM11) | (1<<WGM10);
 TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS11);

}

int main(){

DDRC |= (1<<PB4);

while(1) {

PORTC |= (1<<PB4);
pwm_init();

delay_ms(1000);

// turn off LED
PORTC &= ~(1<<PC4);

//delay for 500 milliseconds to let the light stay off
delay_ms(500);

}
return 0;

}

January 26, 2011
by hevans
(NerdKits Staff)

hevans's Avatar

Hi kemil,

My suggestion on tackling this problem is to separate the two concerns and solve one problem at a time. First focus on getting an LED to light up to a desired brightness using PWM. You are sort of close with your code but you have the timer set up to do fast PWM with the TOP value set to OCR1A. This is fine, but this means you can't use OCR1A as an output compare register (since it is the top value and the counter goes back to 0 as soon as it hits OCR1A. What you could do is use OCR1B as your output compare register. You just have to set the proper bits to do that in TCCR1A. You will also need to move the LED to the OC1B pin (Output Compare 1 B).

There is also something strange the pins you are setting as outputs. You seem to be using pins on the PORTC register. To use the PWM pins they have to be the proper pins that are connected to the PWM and Timer/Counter module. I know this is a lot to take in, but if you take it slow I'm sure it will click in time. I referred to the Timer/Counter1 with PWM section of the datasheet starting on page 109 to look all this stuff up. I suggest you read through it even if it doesn't make too much sense for now.

Feel free to ask you have any questions.

Humberto

January 27, 2011
by kemil
kemil's Avatar

Hi humberto,

i have managed to set the brightness of the led whilst flashing it on and off. ive kind of just adjusted someone elses code until i got what i wanted. heres the code:

define F_CPU 14745600
#include <stdio.h>
#include <avr/io.h>
#include "../libnerdkits/delay.h"

int main(void)

 {

DDRB |= (1<<PB1);         //PortB 1 as output

for (;;) {
 TCCR1A = (1<<COM1A1)|(1<<1);   // OC1A to zero, 8-Bit PWM
 TCCR1B = 1;             //Start PWM
 OCR1AH = 0;
 OCR1AL = 100;
      //Change lowbyte of OCR1A

  delay_ms(1000);

 OCR1AL=0;

  delay_ms(1000);
 }
 return 0;
}

I now want to add a second led where the brightness is again controlled by pwm but does not flash, but im stuck on how to do this. I think i have to change, maybe turn on, some bits on the TCCR1A, TCCR1B registers but because im not 100% clear on what they are actually doing im lost on how do do this.

Thanks for your help

kemil

January 27, 2011
by hevans
(NerdKits Staff)

hevans's Avatar

Hi kemil,

Your code above is pretty confusing. I can see why it works as expected, but it is not exactly good coding practice.

You need to think of the timer modules and PWM as modules that have the ability to run outside of the code once you set them up properly and start them. That is part of what makes them so powerful, you can set a PWM to a 50% duty cycle, and then just leave it alone and it will keep doing it until you stop, which leaves your main() loop free to do other things. In your code above you are setting up the PWM and enabling it inside your main for() loop. This correctly starts the PWM module which turns on your LED using the PWM duty cycle. Then waits for one second in your delay function. Then loops back around and starts the PWM all over again. The more correct way of doing this is to set up the PWM once, and then look at the problem from a duty cycle perspective. When you want the light to be on, set the PWM duty cycle to some amount, when you want it to be off just set it 0.

Did you read over the parts of the datasheet I pointed you to yesterday. Those describe the functionality of the timer/counter module and explain what the registers do. If you are confused about specific parts of it I would be happy to explain it.

Humberto

January 28, 2011
by kemil
kemil's Avatar

Hi Humberto,

I had a little think and tried to decipher the data sheet. I am now able to independentally control to PWM on prots PB1 and PB2. in not sure if i have done it elegantly but it does what i want.

Further more, although i am not able to manipulate the pwm of both ports im not quite shure what the TCCR1B register is doing.

heres my code:

  int main(void)

{

DDRB |= (1<<PB1)|(1<<PB2);         
TCCR1A = (1<<COM1A1)|(1<<COM1B1)|(1<<1);   
TCCR1B = 1;

OCR1BH = 0;
OCR1BL = 5;

OCR1AH = 0;

while(1) {
OCR1AL = 5;

delay_ms(1000);

OCR1AL = 0;

delay_ms(1000);
}
return 0;
}

Thnaks

Kane

January 28, 2011
by kemil
kemil's Avatar

*sorry i am able to manipulate

February 18, 2011
by kemil
kemil's Avatar

Hi guys,

As you can see from above i have managed to control the light intensity of 2 LEDS on ports PB1 and PB2... as well as making one of them blink.

I would like to extend this further by adding 4 more LEDs to the other port B pins. But ifter skimming thought the data sheet im not sure if this is possible... if it is could any1 give me an insight into how this is done.

Idealy I want to have 6 leds, whose intensities are all controlled, and are blinking at different rates.

Thanks

kemil.

February 19, 2011
by hevans
(NerdKits Staff)

hevans's Avatar

Hi Kemil,

Adding more PWM outputs can be a bit tricky. Technically there are 3 timer/counter modules on board the chip, and each of them can control 2 PWM outputs. You have OC0A/B, OC1A/B, and OC2A/B, all controlled by Timer0, 1 and 2 respectively. This however would get pretty hairy to control since the timers are different and you would have to deal with all 3 differently. My suggestion is to redesign your project a little and use the the fact that you are time multiplexing anyway to your advantage. What I would do is use only one PWM output, and then round robin your multiple LEDs over time (same sort of trick we used in the LED Array and in the Valentines Day Heart). What you would do is connect all the anodes of the LEDs to the same output, and then connect all the cathodes to different digital inputs. Set all these cathode nodes to inputs (so that no current flows through them) except for one which you make a digital low (current sink), and turn on the LED for some amount of time. Then move on to the next one. Do this quickly enough and you will get the effect you want and have brightness control over multiple LEDs. Take a look at the Valentines Day Heart project where I did pretty much the exact same thing.

Humberto

February 20, 2011
by kemil
kemil's Avatar

Humberto,

Thanks for the advice i will try it out...

Could this be done if the LEDs i am using are high power 1W 80lm LEDs?

kemil

February 20, 2011
by hevans
(NerdKits Staff)

hevans's Avatar

Hi Kemil,

If your LEDs draw too much current it could damage your components but much more likely your LEDs are just not going to be as bright as you would expect them to be (because the MCU is current limiting you). If you are worried about drawing too much current you can add current limiting resistors.

Humberto

Post a Reply

Please log in to post a reply.

Did you know that you need to think about wires differently when you're transmitting signals more than a few inches? Learn more...