Need PWM help PLZ

Go To Last Post
24 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi all

I have been playing with this for a few days and not getting anywhere.

All i am trying to do is get a little bit a code working to just dull an LED. I have looked through the forums, internet and what books i have but i am lost now.

This is the code i have ended up with and it has changed greatly with different samples i have found.

I am using an STK500 and ATMega16 and just trying to get something to work.

Any help would be appreciated.

#include  

int main (void) 
{ 
  
   // Port D5 as output 
   DDRB   |= (1 << 3); 
    
  
   // Set on match, clear on TOP 
   	TCCR0 |= ((1 << COM01) | (1 << COM00) | (1<<WGM01)); 
   	TCCR0 |= ((1<<CS02) );

	//where is the desired brightness 
     OCR0= 125; 
   

   for (;;) 
		{
		}    
    

}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You dont want to set (1 << COM01) but just (1 << COM00) to "Toggle OC0 on compare match". See page 82 of data sheet.

John Samperi

Ampertronics Pty. Ltd.

https://www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,
With WGM01=1 WGM00=0 the timer is in CTC mode.
This mode produces allways duty cycle 50/50, so you cannot change the brightnes of a led.
Choose FAST PWM mode.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok thx guys,

Will try that and see how i go. It has been very hard to find a basic PWM example. I have search the forum and internet but everyone goes off in different direction so i was just getting more confused.

Regards

Craig

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

It has been very hard to find a basic PWM example.

What? You mean like the one in the manual for the compiler you are using that is almost certainly sitting on your hard drive if you installed WinAVR?

Take a look at:

http://www.nongnu.org/avr-libc/u...

Probably also in c:\winavr\doc\avr-libc\examples\demo

Last Edited: Mon. Oct 12, 2009 - 08:45 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,
Sometimes looking at datasheet may be a faster way than searching for examples.

In datasheet see table "Waveform Generation Mode Bit Description" in Timer0 section.
Fast Pwm mode is set with
WGM0=1
WGM1=1

Then look at table "Compare Output Mode, Fast PWM Mode".
Choose setting of COM00 , COM01.

You can change the frequency with timer0 prescaler and duty cycle with OCR0.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok thanks very much for that.

I didn't even realize that there were examples with WinAvr.

I have read the tutorial on timers but it stopped short of explaining about PWM so i wasn't sure.

I decided to use Timer0 as there were less options but i still got lost in the data sheets.

It's too late now but will look at it in the morning and go back through the datasheet when i get it working to ensure I understand everything i have enable and the things i have not.

Thanks again.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok got the PWM working on Timer0 and Timer1. I have a 10K hooked up to the ADC0 and can vary an RGB LED on the 2 channels and get a mix of 2 colors.

My question now is can Timer1 be used as an 8 Bit timer the same as the other 2 timers?

If so i am having troubles trying to work out how to mix the 3 colors to get the blend right.

I am not looking to get 16 Million colors or anything that grand but using the 10k pot on the ADC just be able to go from one extreme to the other.

I can work out how to do it using 3 different pots on the ADC.

Here's my code so far

#include  

int main (void) 
{ 
  
	// ADC setup for Pin A0

   	ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // Set ADC prescalar to 128 - 125KHz sample rate @ 16MHz 

   	ADMUX |= (1 << REFS0); // Set ADC reference to AVCC 
   	ADMUX |= (1 << ADLAR); // Left adjust ADC result to allow easy 8 bit reading 

   	// No MUX values needed to be changed to use ADC0 

   	ADCSRA |= (1 << ADATE);  // Set ADC to Free-Running Mode 
   	ADCSRA |= (1 << ADEN);  // Enable ADC 
   	ADCSRA |= (1 << ADSC);  // Start A2D Conversions 
   
   
   // PWM Channel set as outputs. 
   	
	DDRB   |= (1 << 3); 
    DDRD   |= ((1 << 7) | (1<<5));
  
   // Timer0 Setup
   	TCCR0 |= ( (1<<COM01) | (1<<WGM00) | (1<<WGM01)); 
   	TCCR0 |= ((1<<CS01) | (1<<CS00));

// Timer1 Set up
   	//TCCR1A |= ( (1<<COM01) | (1<<WGM00) | (1<<WGM01));  //not sure if correct setup
   	//TCCR1A |= (1<<CS01) | (1<<COM00);
  
   // Timer2 Set up
   	TCCR2 |= ( (1<<COM01) | (1<<WGM00) | (1<<WGM01)); 
   	TCCR2 |= ((1<<CS01) | (1<<COM00) | (1<<COM01));




   	for (;;) 
		{
		int j;
	  	j = ADCH;
		OCR2 = j;
		OCR0 = j;
		
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
My question now is can Timer1 be used as an 8 Bit timer the same as the other 2 timers?

Mode 5.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks very much for that i now have an output out of OC1B but am unable to vary the PWM.

Here is my set up

/

 Timer1 Set up
   	TCCR1B |= ( (1<<WGM10) | (1<<WGM11) | (1<<CS11));  	//Set to 8 Bit Fast PWM, Clock source set to /64
   	TCCR1A |= (1<<COM1A1) | (1<<COM1A0);				//Set Set on compare match

i am starting to think that the TOP is not adjustable in this mode though. Not sure.

Anyone know for sure.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
      TCCR1B |= ( (1<<WGM10) | (1<<WGM11) | (1<<CS11));   

This does not set mode 5. In fact, niether WGM10 nor WGM11 are in TCCR1B. You need to set WGM10 in TCCR1A and WGM12 in TCCR1B.

Quote:
thanks very much for that i now have an output out of OC1B

I'm not sure how you did that since you haven't set OC1B as output, you have set OC1A as output.
Quote:
i am starting to think that the TOP is not adjustable in this mode though

You don't need TOP to be adjustable, you need the duty cycle to be adjustable.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi cwilson,
Maybe this could help.

PWM setting
------------------------------------------------------------------
1. Choose mode. Each timer has its own PWM mode table (Waveform Generation Mode Bit Description).

2. Set WGM bits. Each timer has its own WGM bits. Inspect datasheet in which registers these bits sit.

3. Set COMnn bits. Each timer has its own three tables for this (Compare Output Mode non-pwm, fast-pwm and phase-correct-pwm). Here you choose what will happen with pwm-output-pin at compare match.

4. Set pwm-output-pin as output.
For timer0 it is pin OC0 (Portb.3 for Atmega16)
For timer2 it is pin OC2

5. Set duty cycle for timer0 with OCR0, for timer2 with OCR2 register.

------------------------------------------------------------------------------

In timer1 there are two compare units A and B.
You can use either, in some modes both of them.

3. For unit A:
Set COM1An bits, set duty cycle with OCR1A, set pwm-output-pin OC1A as output

For unit B:
Set COM1Bn bits, set duty cycle with OCR1B, set pwm-output-pin OC1B as output

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks very much for the help it is much appreciated. I have got it working now. I have the 3 timers controlling an RGB LED.
I have been trying to work out a way to control the color of the LED with the 10K pot on ADC0 but are coming up with a problem with every solution i think will work.
Does anyone have any ideas? I am starting to run out with my knowledge of the AVR (limited).
I am just trying to use a pot to scan through the color range. It doesn't have to be a perfect transition just so a color can be selected and left at it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What part are you having problems with, reading the ADC or using the value to set a color?

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Using the value to set the color. I can have 256 values for each PWM channel. I don't need nowhere near that much color but not sure how to use 1 ADC channel to control the 3 different PWM channels.

My last sort of idea was to have a switch which would scroll through the 3 PWM channels and adjust each one individually with the one ADC channel.

Does this sound like a feasible idea or not??

I was going to hook the switch up to one of the interupts, so when pushed would go to an interupt routine and toggle through the color select then use the pot ADC to adjust and then store the value before going to the next color.

Let me know if this sounds ok or i am going about it the wrong way.

Regards

Craig

PS I am not looking for someone to do this for me i just need some ideas and then maybe a little hand when i stuff it up. :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
My last sort of idea was to have a switch which would scroll through the 3 PWM channels and adjust each one individually with the one ADC channel.

That would either limit you to only a few colors, or give you a very big switch statement.
I would use a lookup table (or three, one for each channel).

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Steve,

I have never used a lookup table before what would the keyword i would put into google to search to find info in this?

Thanks,

Craig

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You could have a very wild LED show with a setup like this:

array[256][3]={{R, G, B},{R, G, B} ... };

You would then use the (8-bit in this case) ADC value as index to first dimension to find out which subset of R, G, and B values to apply to PWM outputs. The downside is that you would have to type 256 * 3 RGB values yourself or generate the table with some routine, not to mention the considerable size of it.

You can always scale the ADC value down to 8 different values and use array[8][3].

Something like:

PWM1dutycycle = array[ADCvalue][0];
PWM2dutycycle = array[ADCvalue][1];
PWM3dutycycle = array[ADCvalue][2];

I hope this helps.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

what would the keyword i would put into google to search to find info in this?

Without looking see if you can guess what the very top link will be if you simply Google for "lookup table" ;-)

hint: the name starts with a W

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson,
sorry for being new to the AVR and not a guru like you. If you are sick of answering new peoples questions then don't,
I don't need the smart arse comments everytime you respond to one of my posts.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Most good programming textbooks should have references to lookup tables. I note that textbooks are not much in favour these days. The modern philosphy seems to be
"if it can't be done with a keyboard, it can't be done!" and "If it doesn't come up on a Google search it doesn't exist"
I would have thought that those who turn to Google first, should also know how to use it.
I know 7 year olds & 70 year olds who do know how to use Google & you don't have to be a
AVR guru to do so. I don't believe the comment to Clawson is deserved.

Quote:
PS I am not looking for someone to do this for me i just need some ideas and then maybe a little hand when i stuff it up.

And you will get that, along with some "humour" perhaps even some sarcasm from time to time! Life is like that! :)

Incidentily, if I want to know if a textbook contains a reference to "lookup tables",
what do you think I should look up in the index. You guessed it...."lookup tables"! Google is no different! :D

Charles Darwin, Lord Kelvin & Murphy are always lurking about!
Lee -.-
Riddle me this...How did the serpent move around before the fall?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

cwilson wrote:
clawson,
sorry for being new to the AVR and not a guru like you. If you are sick of answering new peoples questions then don't,
I don't need the smart arse comments everytime you respond to one of my posts.

Did someone miss the smiley I put in that post then?Apologies if I upset you but Wikipedia really does have a good explanation of "lookup table". Google or Wikipedia really should be your first port of call if there's something you need explained.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok clawson i apologies for my reply. It is just a bit frustrating finding info around the net. I would prefer to use text books as they run through the topic from start to finish and usually a bit more indepth, but with text books usually starting at about $80aus they get very expensive really quick.

Ok i am really sorry for my outburst and will think before reponding next time.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm probably late to this discussion but understand that clawson is not trying to give you the answer but show you how you can get it for yourself. And believe me, there are a lot of other groups that would tear you apart for having no idea what you're doing.

The focus at AVR freaks is to help people help themselves. They're more likely to show you where to look or what to do than to do the code for you.

Ever heard: "Give a man a fish and he'll eat for a day. Teach a man to fish and he'll eat for a lifetime" ?

So yeah, I've been new at the AVR stuff and it can be rough to start but it gets easier. Check out the tutorials section as it's a really good place to learn a lot of this stuff (it's where I learned how to use PWM). When you learn something, the best thing to do is to find out where it came from. Go back to the chip's datasheet and find out where it talks about the section (though that's a good place to start, too). Eventually, you'll learn where to look to find a lot of this stuff.

I hope this helps and good luck, man!