go_away

Author Topic: LED dimmer (PWM) and timer program on AtMega8?  (Read 14569 times)

0 Members and 1 Guest are viewing this topic.

Offline corrado33Topic starter

  • Supreme Robot
  • *****
  • Posts: 611
  • Helpful? 11
LED dimmer (PWM) and timer program on AtMega8?
« on: March 31, 2010, 09:10:45 AM »
Hey guys, long time no post.  I've gotten really busy writing my thesis and with some of my other projects.  Anyway, I'm trying to build something with parts I have available, and I want to use my AtMega8.  Basically what I want to do is build a lighting fixture if you will.  (It's actually a "moonlight" for a fish tank).  Anyway, I've already built one, but it is very simple.  Here's my plan for a better one.  

Keep in mind, I've had very limited experience programming microcontrollers.  I can do PWM, but only with that webbot lib thing, and that doesn't fit on an AtMega8.

Features I want.
  • Universal "dimming" dial. (Controlled by a potentiometer probably, which regulates the overall PWM, maybe a factor in mathematical equation
  • Timer (More on this later)
  • Time controlled dimming (moon moves across the sky, as would the lighting in this fixture.  The leftmost ones would get bright first, then start dimming and at the same time ones to the right would be getting brighter, so the brightest light would "move" from left to right.
  • Modular.  Basically I'd have ports in the back to add more LEDs, then a multiposition switch to tell the micro controller how many LEDs were plugged in.  The micro controller would then take into account those extra LEDs in the "moon moving" algorithim.  (Meaning the LEDs would be lit for shorter amounts of time, since there are more of them)
  • Time controlled On/Off switch (Turn on at night, off during day)
  • Universal Voltage control (Some LEDs are 2.5v, some are 3.7.  I don't know if controlling each one individually would be possible, but I think if I was able to just regulate the voltage applied to all LEDs that are used, I'd be good, cause most people would use the same LEDs throughout their lighting. So all LED output would either be 2.5 or 3.7, not a mix of both for example.  I thought of doing this with a <1k pot and a variable voltage controller, but I think using the microcontroller would be easier.)

It's a really cool idea, and I'm actually gunna try to build one for a friend of mine.  I realize I have to try to start small, but as I said earlier, this entire thing is based on PWM, which I don't know how to do.  Yes I've read the tutorial on here, but I'm still lost.  

Does anyone have a simple PWM program for an ATMega8?  Maybe for one port?  If I had that, I'd be able to do a ton.
Does anyone have a simple timer program for an ATMega8?  Would I have to use a crystal?

Thanks in advance!  I know I'm pretty much asking for you guys to show me examples and write code for me, but for someone who really knows what they're doing, this would be a very quick program, and I heartily thank anybody who is willing to help me with this.  Generally I learn by seeing examples, they manipulating those examples to do what I want.

EDIT:  Found this tutorial on timers... seems to be very good.  http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=50106&highlight=timers+tutorial
EDIT 2:  I'm a great programmer, the part that confuses me about programming the microcontrollers is the initial set up part.  I can program all day, but I don't know how to set up the microcontroller to output on certain ports.   :-\
« Last Edit: March 31, 2010, 09:29:38 AM by corrado33 »

Offline chelmi

  • Supreme Robot
  • *****
  • Posts: 496
  • Helpful? 15
Re: LED dimmer (PWM) and timer program on AtMega8?
« Reply #1 on: March 31, 2010, 09:41:08 AM »
Take a look at the Procyon AVRlib:
http://www.mil.ufl.edu/~chrisarnold/components/microcontrollerBoard/AVR/avrlib/docs/html/index.html

However, if you just want to use hardware pwm, you are limited to 3 leds (The atmega8 has only 3 pwm channels).
But you could always implement pwm in software since you mcu doesn't have much to do beside controlling the leds.

Regarding the time controlled on/off, you could use an external RTC like this one: http://www.futurlec.com/Mini_DS1307.shtml

Chelmi.

Offline corrado33Topic starter

  • Supreme Robot
  • *****
  • Posts: 611
  • Helpful? 11
Re: LED dimmer (PWM) and timer program on AtMega8?
« Reply #2 on: March 31, 2010, 11:16:38 AM »
Cool, both links were really cool.  I knew the ATMega8 was limited to 3 PWM outputs.  I kinda forgot you could do software PWM.  What's the difference anyway?  I read somewhere that timers are seperate circuits within mcus.  Is this correct?  

Then assuming that those PWMs are directly controlled by the timers, I can see why the PWM outputs are limited.  Software PWM works simply by using a timer, but using the software to turn the light on and off, instead of the timer doing it directly I'm guessing?  

EDIT:  Anyone have any great tutorials on setting up ports to do certain things?
« Last Edit: March 31, 2010, 11:23:22 AM by corrado33 »

Offline chelmi

  • Supreme Robot
  • *****
  • Posts: 496
  • Helpful? 15
Re: LED dimmer (PWM) and timer program on AtMega8?
« Reply #3 on: March 31, 2010, 11:56:14 AM »
Cool, both links were really cool.  I knew the ATMega8 was limited to 3 PWM outputs.  I kinda forgot you could do software PWM.  What's the difference anyway?  I read somewhere that timers are seperate circuits within mcus.  Is this correct? 

Then assuming that those PWMs are directly controlled by the timers, I can see why the PWM outputs are limited.  Software PWM works simply by using a timer, but using the software to turn the light on and off, instead of the timer doing it directly I'm guessing? 

Yep that's it.

Offline Soeren

  • Supreme Robot
  • *****
  • Posts: 4,672
  • Helpful? 227
  • Mind Reading: 0.0
Re: LED dimmer (PWM) and timer program on AtMega8?
« Reply #4 on: March 31, 2010, 05:50:17 PM »
Hi,

However, if you just want to use hardware pwm, you are limited to 3 leds (The atmega8 has only 3 pwm channels).
That should be enough. If every third LED in the "sky" is connected to the same one, then _which_ one is on can be selected by other outputs.
Regards,
Søren

A rather fast and fairly heavy robot with quite large wheels needs what? A lot of power?
Please remember...
Engineering is based on numbers - not adjectives

Offline corrado33Topic starter

  • Supreme Robot
  • *****
  • Posts: 611
  • Helpful? 11
Re: LED dimmer (PWM) and timer program on AtMega8?
« Reply #5 on: March 31, 2010, 10:27:41 PM »
Hi,
That should be enough. If every third LED in the "sky" is connected to the same one, then _which_ one is on can be selected by other outputs.


Can you elaborate?  I see what you are saying that I really only NEED 3 outputs.  I'd only have 3 LEDs on at any one time anyway.  Are you thinking that I could use transistors?  Use the switch (aka port on mcu) to tell the transistor to send the PWM signal through to the LED?  Or is there a much easier thing that I'm not thinking of?  If I could get the ports on the mcu to act as grounds it'd be easy, just connect the other end of the LED to the mcu, but I don't think I can do that.
« Last Edit: March 31, 2010, 10:29:25 PM by corrado33 »

Offline Soeren

  • Supreme Robot
  • *****
  • Posts: 4,672
  • Helpful? 227
  • Mind Reading: 0.0
Re: LED dimmer (PWM) and timer program on AtMega8?
« Reply #6 on: April 01, 2010, 10:40:48 AM »
Hi,

Can you elaborate?  I see what you are saying that I really only NEED 3 outputs.

Something like this.
The slanted/diagonal lines (p2) divides the groups (1, 2, ...5, 1, etc.) that are on in any instant (by an NPN low side transistor). The A, B and C groups are catered for by the high side (PNP) transistors.
It's not a mature idea and I haven't specified the values of the LED resistors - the transistors needs base resistors 2, at the very least and depending on voltage requirement of the LEDs, it might be best to drive the PNPs with (ground referenced) NPNs.
One little caveat is the need to drive one group with one transistor while driving another with another (concurrently), so either they need to be multiplexed or the entire idea should be churned around the mill one more time, but it is the best way to do it IMO ;D
Regards,
Søren

A rather fast and fairly heavy robot with quite large wheels needs what? A lot of power?
Please remember...
Engineering is based on numbers - not adjectives

Offline corrado33Topic starter

  • Supreme Robot
  • *****
  • Posts: 611
  • Helpful? 11
Re: LED dimmer (PWM) and timer program on AtMega8?
« Reply #7 on: April 01, 2010, 02:36:12 PM »
Thanks Soeren.  I had pretty much the same thought in my head when you mentioned I only needed 3 PWM outputs.  I also see why I wouldn't be able to have LEDs 2,3, and 4 on without having LED 1 on as well.  Hmm... I'll look at it for a while and see if I can come up with anything that'll solve that problem.  If not, I'll just work around it.  It's not the end of the world or anything.  Thanks for the idea, I really appreciate it.

I think I figured it out.  Since I wouldn't be using many of the MCUs outputs, I could simply have two LEDs between each "group" controlled by software PWM.  These LEDs would be connected to the MCU output, then to ground (basically.)  Then as the lights would get ready to move from one "group" to another, the two LEDs in the middle would be sort of a buffer.  When the last LED in the first group turns off, the first LED in the second group turns on. 

That's the best I can think of...
« Last Edit: April 01, 2010, 11:04:46 PM by corrado33 »

Offline Soeren

  • Supreme Robot
  • *****
  • Posts: 4,672
  • Helpful? 227
  • Mind Reading: 0.0
Re: LED dimmer (PWM) and timer program on AtMega8?
« Reply #8 on: April 02, 2010, 09:17:19 AM »
Hi,

I think I figured it out.  Since I wouldn't be using many of the MCUs outputs, I could simply have two LEDs between each "group" controlled by software PWM.  These LEDs would be connected to the MCU output, then to ground (basically.)  Then as the lights would get ready to move from one "group" to another, the two LEDs in the middle would be sort of a buffer.  When the last LED in the first group turns off, the first LED in the second group turns on. 

Here's a solution.
Each timer can control more than one output and having 2 outputs from each makes it possible to switch cleanly.

This schematic shows that approach.
Output A and D (from the controller) is different output pins, but controlled by the same timer, likewise with B/E and C/F.
You alternate between A and D (B/E and C/F), so first run, A lets the output from counter1 and then, when it is faded out, next time round it's D that lets counter1 through.
(Just use a flag that specifies which pin is the present output at the start of each /\ period and then toggled when the period finishes).
Something like:
Code: [Select]
...
Period_begin:
  Output_AD = Flag_AD   ;Where Flag_AD is a Boolean
...
Period_done:
 Flag_AD = NOT Flag_AD
...

I have added one more group, as I got my brain into thinking it should run in rings, but in your application, an even number of groups are not needed - if you have spare I/O, you can easily extend it further if needs be.

To get more light, you could double the number of LEDs (and resistors!) and run them in parallel.

To go from LED3 to LED4, just have both "1" and "2" on, as they have different high side controller outputs, it will cause no problems with light in wrong LEDs.
Regards,
Søren

A rather fast and fairly heavy robot with quite large wheels needs what? A lot of power?
Please remember...
Engineering is based on numbers - not adjectives

Offline corrado33Topic starter

  • Supreme Robot
  • *****
  • Posts: 611
  • Helpful? 11
Re: LED dimmer (PWM) and timer program on AtMega8?
« Reply #9 on: April 02, 2010, 10:23:03 PM »
Hi,

Here's a solution.
Each timer can control more than one output and having 2 outputs from each makes it possible to switch cleanly.


So basically I'm still using only the 3 hardware PWM, except I'm splitting each signal.  (Kinda like a Y adapter for RCA cables).  Then I have more transistors to let the signal go to one place or the other?  Makes sense, I don't see why I didn't think of that...  Now... if I just knew how to set up the pins on the MCU... I have yet to find an all inclusive tutorial that says "If you want to do this with a certain pin, you have to look up this bit value in the datasheet and write some code like this..." etc. etc...

Offline Soeren

  • Supreme Robot
  • *****
  • Posts: 4,672
  • Helpful? 227
  • Mind Reading: 0.0
Re: LED dimmer (PWM) and timer program on AtMega8?
« Reply #10 on: April 03, 2010, 08:23:52 AM »
Hi,

So basically I'm still using only the 3 hardware PWM, except I'm splitting each signal.  (Kinda like a Y adapter for RCA cables). 

Yes, more or less. You do have to alternate the outputs though.


Now... if I just knew how to set up the pins on the MCU... I have yet to find an all inclusive tutorial that says "If you want to do this with a certain pin, you have to look up this bit value in the datasheet and write some code like this..." etc. etc...

I don't think you'll find a tut that has got all the bits you need in one go, but reading a couple might give you a better understanding of the stuff, as each writer will probably have a different angle.

This (pdf) tutorial may be helpfull if you can live with the poor English and the strange web linking in some places of the background.

This is a short example as well.

Newbie's Guide to AVR Timers and PWM tutorial.

If you get through these documents, you should understand the concept and be able to make the Moonlight "scanner".


About the "features" you want.

Quote
Universal "dimming" dial. (Controlled by a potentiometer probably, which regulates the overall PWM, maybe a factor in mathematical equation

Yes, a factor will be the best approach here.


Quote
Modular.  Basically I'd have ports in the back to add more LEDs, then a multiposition switch to tell the micro controller how many LEDs were plugged in.  The micro controller would then take into account those extra LEDs in the "moon moving" algorithim.  (Meaning the LEDs would be lit for shorter amounts of time, since there are more of them)

I doubt that it's worth it, but you could set all the possible pins to input and scan them. If you have a weak pull ups/downs on each, you'd be able to see which pins are connected.


Quote
Time controlled On/Off switch (Turn on at night, off during day)

You could add an RTC or make an equivalent in software, but a much easier approach is to use an LDR mounted so it can sense outside light and let it start when it gets to a certain level of darkness.


Quote
Universal Voltage control (Some LEDs are 2.5v, some are 3.7.  I don't know if controlling each one individually would be possible, but I think if I was able to just regulate the voltage applied to all LEDs that are used, I'd be good, cause most people would use the same LEDs throughout their lighting. So all LED output would either be 2.5 or 3.7, not a mix of both for example.  I thought of doing this with a <1k pot and a variable voltage controller, but I think using the microcontroller would be easier.)

LEDs are current controlled devices and the simplest way of controlling this current is with a resistor (as you see it in the schematic).
If you used LEDs with different voltage drops, you would go with individual constant current devices.
Regards,
Søren

A rather fast and fairly heavy robot with quite large wheels needs what? A lot of power?
Please remember...
Engineering is based on numbers - not adjectives

Offline corrado33Topic starter

  • Supreme Robot
  • *****
  • Posts: 611
  • Helpful? 11
Re: LED dimmer (PWM) and timer program on AtMega8?
« Reply #11 on: April 03, 2010, 12:19:04 PM »
Hi,

This (pdf) tutorial may be helpfull if you can live with the poor English and the strange web linking in some places of the background.



Pretty much exactly what I needed, but one question...

In the tutorial, there is "Step 2: Enable PWM:"
Then it says "For this you need to write COM1A10=0 and COM1A11=1"
The code for this is TCCR1A=0xA1;

How did that code come from those things?  I can understand the 1A in all of them (it's timer/counter 1A, there are two counters on "1", A and B.), but why did setting TCCR1A to 0xA1 make the two things above it the required numbers... Can you maybe point me to a place in the tutorial(which contains a lot of the datasheet), or ATMega8 datasheet itself where it would tell you to do that?

EDIT:  I figured it out.  TCCR1A contains both COM1A10 and COM1A11.  The 0xA1 sets many values including the two that needed to be changed.  Basically, each HEX digit corresponds to a certain... bit?  I think I'm saying that right.  The only thing is, I've used two different online converters, and I can't figure out what A1 actually is.  I think it's 10100001.  Right?  Cause it contains 8 digits?

So according to this table...


He really set the COM1A1 to 1, COM1A0 to 0, COM1B1 to 1, COM1B0 to 0, ect ect. right?  Where is the extra 1 coming from?  Ex. he has COM1A10 where in reality it's COM1A0, and he has COM1A11 where really it's COM1A1, is this just a typo?



About the "features" you want.

Quote
Time controlled On/Off switch (Turn on at night, off during day)

You could add an RTC or make an equivalent in software, but a much easier approach is to use an LDR mounted so it can sense outside light and let it start when it gets to a certain level of darkness.


I like that idea.  The moonlights are so dim that they wouldn't be seen without complete darkness in the room anyway, so I might as well have a light sensor.  

Quote
Quote
Universal Voltage control (Some LEDs are 2.5v, some are 3.7.  I don't know if controlling each one individually would be possible, but I think if I was able to just regulate the voltage applied to all LEDs that are used, I'd be good, cause most people would use the same LEDs throughout their lighting. So all LED output would either be 2.5 or 3.7, not a mix of both for example.  I thought of doing this with a <1k pot and a variable voltage controller, but I think using the microcontroller would be easier.)

LEDs are current controlled devices and the simplest way of controlling this current is with a resistor (as you see it in the schematic).
If you used LEDs with different voltage drops, you would go with individual constant current devices.


So you're saying that I should only regulate the voltage to say 4 V, then use resistors to get the leds to work?  Won't the resistors get really hot depending on how much current is gong through them?  I thought it was more "efficient" and "safer" (heat wise) to use voltage controllers...?  Please correct me if I'm wrong.  

Other wise, thanks so much.  That first tutorial basically told me everything I need to know.  I can just copy and paste a couple times, change a few numbers, and I'd be good.  
« Last Edit: April 03, 2010, 04:12:31 PM by corrado33 »

Offline Webbot

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 2,132
  • Helpful? 108
Re: LED dimmer (PWM) and timer program on AtMega8?
« Reply #12 on: April 03, 2010, 06:56:13 PM »
The '1' is there to set bit WGM11 = 0 and WGM10=1
these are 2 of the 4 bits that set the waveform generation mode.
The other 2 bits are in TCCR1B

Go to this page of my tutorial http://www.societyofrobots.com/member_tutorials/node/233 and download the ATMega8 reference sheet.
Or read the whole tutorial.
Webbot Home: http://webbot.org.uk/
WebbotLib online docs: http://webbot.org.uk/WebbotLibDocs
If your in the neighbourhood: http://www.hovinghamspa.co.uk

Offline corrado33Topic starter

  • Supreme Robot
  • *****
  • Posts: 611
  • Helpful? 11
Re: LED dimmer (PWM) and timer program on AtMega8?
« Reply #13 on: April 04, 2010, 05:29:42 PM »
The '1' is there to set bit WGM11 = 0 and WGM10=1
these are 2 of the 4 bits that set the waveform generation mode.
The other 2 bits are in TCCR1B


Thanks for the input, but that's not exactly what I meant.  I know the 1010001 applies to all eight of the boxes in the pic above, I just didn't feel like writing out WGM11 = 0 and WGM10=1 lol that's why I put etc. etc..  What I meant was he wrote COM1A11 where on the data sheet it's COM1A1 and the same for COM1A10, on the datasheet it's COM1A0.  There is an extra "1" in both of those things that he wrote.  Is it just a typo?

Offline Webbot

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 2,132
  • Helpful? 108
Re: LED dimmer (PWM) and timer program on AtMega8?
« Reply #14 on: April 04, 2010, 07:12:02 PM »
Yep its a typo
Webbot Home: http://webbot.org.uk/
WebbotLib online docs: http://webbot.org.uk/WebbotLibDocs
If your in the neighbourhood: http://www.hovinghamspa.co.uk

Offline corrado33Topic starter

  • Supreme Robot
  • *****
  • Posts: 611
  • Helpful? 11
Re: LED dimmer (PWM) and timer program on AtMega8?
« Reply #15 on: April 07, 2010, 06:01:05 PM »
Hey guys, I'm back!  I have a PWM program running on my AtMega8!  Yay!  It honestly wasn't that hard, even though I think I blew up part of my programmer...  ;)   Anyway, the program I'm using right now uses phase correct PWM.  It achieves this using this chart...



and these settings


Don't mind the link thingy, it's 0001. 

Anyway I want to use fast PWM, as I don't think LEDs care whether it's phase correct or not (now motors do).  And I can achieve faster frequencies with fast PWM. (Hence the name)

My first question, why so many different types of PWM?  Is it just so that if you are using the flag TRV1 and you want it to go off at certain times?  Since I'm not using it does it matter to me? 

Why is there 8, 9 and 10 bit PWM?  (I think it's to get more accurate (I.E. higher resolution) timings, 10 bit is slower than 8 bit?, since TOP is the number of clock cycles per time period of PWM, as top increases the PWM slows down but gets more accurate?) 

Correct me if I'm wrong, but could I use the 5 row down, 0101, for my application? 

Why are there different TOP values?  (I understand the different values for 8,9,and 10 bit pwm, but what about the other ones?)  Do I have to set the different top values? (Or is it assumed with the setting of the registers in the above chart?)  EDIT:  From further research, it seems that modifying the TOP value changes the frequency at which the PWM... works?  So if I wanted to set a custom TOP value, would I use one of the rows that had OCR1A or ICR1 as the TOP value, then set those registers to the TOP value I wanted to use?

I DO have to set OCR, which defines the duty cycle.  But what does this do for me, in an LED dimming application?

How do I actually change the dimming of the LED, is it simply changing the duty cycle?  Or is it changing the frequency at which it blinks?  (Former is easier, correct?)

As for the resistors in Soeren's diagram, I can calculate the value by using this formula... R = (Vs - Vl)/I  I did it for mine, and got a value of roughly 100.  R=(5-2.5)/.025  I was guessing for the voltage and current, as the LEDs didn't come with a data sheet.  (I know the stats for the ones I'm using).  Does this sound right? 

That's all for now... Thanks!
« Last Edit: April 07, 2010, 06:32:53 PM by corrado33 »

Offline Webbot

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 2,132
  • Helpful? 108
Re: LED dimmer (PWM) and timer program on AtMega8?
« Reply #16 on: April 07, 2010, 06:56:00 PM »
My first question, why so many different types of PWM?

There are some modes that effect top like the 8, 9 and 10 bit modes. In these modes the frequency is set by the clock and the prescaler. The prescaler can only have certain values. So you don't have very fine control over the frequency but you can adjust the duty cycle.

Other modes like phase/frequency correct tend to need a 16 bit timer and use an ICR register (along with prescaler) to set top. This gives you precise control over the frequency as well as the duty cycle. The difference between them is quite subtle and, as you've said, only tend to make a difference when controlling (precisely) DC motors.

But congratulations by the way
Webbot Home: http://webbot.org.uk/
WebbotLib online docs: http://webbot.org.uk/WebbotLibDocs
If your in the neighbourhood: http://www.hovinghamspa.co.uk

Offline corrado33Topic starter

  • Supreme Robot
  • *****
  • Posts: 611
  • Helpful? 11
Re: LED dimmer (PWM) and timer program on AtMega8?
« Reply #17 on: April 07, 2010, 07:37:35 PM »
Other modes like phase/frequency correct tend to need a 16 bit timer and use an ICR register (along with prescaler) to set top. This gives you precise control over the frequency as well as the duty cycle. The difference between them is quite subtle and, as you've said, only tend to make a difference when controlling (precisely) DC motors.

Ok so I'm going to use Phase/Frequency correct PWM.  I'm going to use row 11 in the table I posted.  I used a prescaler of 8, to get a frequency of 100 (I have the 16 MHz atmega8).  To do that, I set OCR1A to 10000.  The frequency was found using this formula Freq = Clock Speed/(2*Prescaler*TOP)  So I did 100 = 16000000/(2*8*x) and got 10000 for my TOP value.  So I set OCR1A to 10000.  However, I don't notice a dimming of the LED.  I then tried a TOP value of 20000 to get a freq of 50 Hz.  I still didn't notice any difference.  What am I doing wrong?

Offline Soeren

  • Supreme Robot
  • *****
  • Posts: 4,672
  • Helpful? 227
  • Mind Reading: 0.0
Re: LED dimmer (PWM) and timer program on AtMega8?
« Reply #18 on: April 07, 2010, 07:58:28 PM »
Hi,

Why is there 8, 9 and 10 bit PWM?  (I think it's to get more accurate (I.E. higher resolution) timings, 10 bit is slower than 8 bit?, since TOP is the number of clock cycles per time period of PWM, as top increases the PWM slows down but gets more accurate?) 
You got it. Sometimes you need fast and resolution is not a big concern and sometimes you need high resolution, or like a servo pulse where the period is 20ms and the pulse is varied from 1ms to 2ms - which is from 5% to 10% and in this (10%-5%=) 5% you need a resolution that gives you at least say 60 steps.
An  8 bit PWM will give you steps of 78.1µs (12.8 step/ms)
An  9 bit PWM will give you steps of 39.1µs (25.6 steps/ms)
An 10 bit PWM will give you steps of 19.5µs (51.2 steps/ms) = almost useable (depending on purpose of course)
A 16 bit PWM will give you steps of 305ns (3,277 step/ms) = Way more resolution than needed, but 8, 16 and 32 bit are the common width for timers, so just adapt one that has got the needed (or higher) resolution.


Correct me if I'm wrong, but could I use the 5 row down, 0101, for my application? 
Sorry, but I haven't done any serious AVR programming in a decade, so this kind of detail there'll be others more suited to answer that.


How do I actually change the dimming of the LED, is it simply changing the duty cycle?  Or is it changing the frequency at which it blinks?  (Former is easier, correct?)
You select a suitable frequency once (say 200Hz to 1kHz) and let it rip, then you change the duty cycle to reflect the amount of light you want.
When you want to do the overall dampening, just use a multiplier between 0.00 and 1.00 - since you won't be doing floating point, scale the multiplier up to eg. 0..100 (then you have it as a percentage, which we are accustomed to) and scale down after rounding.
You could use 0..487 if you like, but percentages are more intuitively handled by our grey matter.


As for the resistors in Soeren's diagram, I can calculate the value by using this formula... R = (Vs - Vl)/I  I did it for mine, and got a value of roughly 100.  R=(5-2.5)/.025  I was guessing for the voltage and current, as the LEDs didn't come with a data sheet.  (I know the stats for the ones I'm using).  Does this sound right? 
About right.
If you want it as precise as possible, you need to subtract the voltage drops over the transistors, i.e. 2 x U_ce as well.

R_LED = (U_sup - U_LED - 2 x U_ce) / I_LED

Assuming a white LED with a drop of 3.6V, a 5.0V supply, an U_ce of 0.1V and you want 30mA through the diode when at max. (99.99% PWM), the calc looks like:
 R_LED = (5 - 3.6 - 0.2) / 0.03 = 40 Ohm

Closest standard resistor is 39 Ohm
 I_LED = (5 - 3.6 - 0.2) / 39 = 30,77mA (2.6% higher than wanted - no big deal).


Measure the LEDs you have with either a new 9V battery and a 470R series resistor or a 12V supply and a 1k series resistor.
Connect resistor and LED and measure over the LED alone. the voltage drop of an LED won't change much from 5mA to 30mA, so you can rely on that voltage drop (and use it in above formula) without knowing the exact current.
If you want to measure the voltage drops of the transistors, you need to draw the max. current to get it right (be it 20mA, 30mA or 100mA if your LED's will handle that), but it should end up as something around 0.05V to 0.2 V total for 2 transistors.

Overcurrent in LEDs
An LED spec'd to 20mA but used at 30mA will shorten the life of the LED. How much varies from manuf. to manuf., but about one third to half the lifetime, will not be too far off for a 50% overcurrent.
LEDs are usually spec'd to 100,000 hours, so let's err on the safe side and say 30,000 hours. that's around 3½ year (of constant light, 24/7/365).

And the lifetime of an LED is spec'd to the point where the light output is reduced to 50% of the value as new, not as a measure where it goes out completely.
It's not like it suddenly goes to 50% of course, it's a gradual process over its entire lifetime (past the 100,000 hours as well), so if it takes 3½ years to 50%, it will likely take another 3½ years to get down to 25% and so on, much like the reduction time on nuclear stuff.

The small key ring LED lamps that's nothing more than an LED and 2 CR2032s and a resistor (when they don't just rely on the internal resistance of the button cells) is putting a high current through the LED, that's why they appear so bright, but since you use it briefly every now and then (and probably looses it before the battery needs a change, costing more than the entire lamp did), they can pull it off with very few failing.

Think about it... An LED operated within specs in a flashlight used for 1h each day around the year (unthinkable I guess) will still have 50% of its light output after more than 270 years...
 "And you my son shall inherit this flashlight that your great great great great great great great great grandfather bought when he met your great great great great great great great great grandmother".

(Ohh Gee, I guess I just revealed the opto-geek inside me ;D)
Regards,
Søren

A rather fast and fairly heavy robot with quite large wheels needs what? A lot of power?
Please remember...
Engineering is based on numbers - not adjectives

Offline Webbot

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 2,132
  • Helpful? 108
Re: LED dimmer (PWM) and timer program on AtMega8?
« Reply #19 on: April 07, 2010, 08:42:23 PM »
You also need to Google 'perceived intensity brightness' - ie a linear change to your duty cycle does not result in a linear change in brightness as far as your eye is concerned. This also varies depending on the color of LED you are using.
Webbot Home: http://webbot.org.uk/
WebbotLib online docs: http://webbot.org.uk/WebbotLibDocs
If your in the neighbourhood: http://www.hovinghamspa.co.uk

Offline corrado33Topic starter

  • Supreme Robot
  • *****
  • Posts: 611
  • Helpful? 11
Re: LED dimmer (PWM) and timer program on AtMega8?
« Reply #20 on: April 07, 2010, 09:10:04 PM »
Quote
An  8 bit PWM will give you steps of 78.1µs (12.8 step/ms)
An  9 bit PWM will give you steps of 39.1µs (25.6 steps/ms)
An 10 bit PWM will give you steps of 19.5µs (51.2 steps/ms) = almost useable (depending on purpose of course)


So if I choose one of those modes, I'm stuck with a certain frequency, but I can change the duty cycle.  But if I use the mode where OCR1A is the TOP value, I can change the frequency, but not the duty cycle... (In the datasheet it says that if OCR1A is used as the TOP value, it runs at a 50% duty cycle).  So I'm assuming you'd say go with the 10 bit pwm? 

Quote
You also need to Google 'perceived intensity brightness' - ie a linear change to your duty cycle does not result in a linear change in brightness as far as your eye is concerned. This also varies depending on the color of LED you are using.


If using PWM doesn't change brightness that we can notice with our eyes, then how do people make the percieved brightness change in videos like this...

ATMega32 PWM LED Dimmer

Offline Soeren

  • Supreme Robot
  • *****
  • Posts: 4,672
  • Helpful? 227
  • Mind Reading: 0.0
Re: LED dimmer (PWM) and timer program on AtMega8?
« Reply #21 on: April 07, 2010, 09:38:57 PM »
Hi,

So if I choose one of those modes, I'm stuck with a certain frequency, but I can change the duty cycle.  But if I use the mode where OCR1A is the TOP value, I can change the frequency, but not the duty cycle... (In the datasheet it says that if OCR1A is used as the TOP value, it runs at a 50% duty cycle).  So I'm assuming you'd say go with the 10 bit pwm? 
Oh, I was referring to servos and their rather special case of PWM there.
You can change the frequency as well as the duty cycle, but you have no reason to change the frequency, as long as you keep it high enough to not perceive the flashing. If you need a number, let's say 500Hz.

To change the brightness, you change the duty cycle.


Quote
You also need to Google 'perceived intensity brightness' - ie a linear change to your duty cycle does not result in a linear change in brightness as far as your eye is concerned. This also varies depending on the color of LED you are using.

If using PWM doesn't change brightness that we can notice with our eyes, then how do people make the percieved brightness change in videos like this...
What an expensive way of doing it ;D

What Webbot said was just that your perception of brightness doesn't follow a linear scale.

I don't think the effect will be visible at all though, as the fading up/down of more than one LED will result in a steady sum of light that's just "moving" and your eyes will perceive the sum of light, hence a constant brightness.
Regards,
Søren

A rather fast and fairly heavy robot with quite large wheels needs what? A lot of power?
Please remember...
Engineering is based on numbers - not adjectives

Offline corrado33Topic starter

  • Supreme Robot
  • *****
  • Posts: 611
  • Helpful? 11
Re: LED dimmer (PWM) and timer program on AtMega8?
« Reply #22 on: April 07, 2010, 09:50:50 PM »
I've successfully dimmed an LED using a freq of 1000 Hz (actually 977.5 Hz), a 10 bit Phase correct PWM, and a prescaler of 8.  I had to take the duty cycle down to 7% to actually "see" some dimming.  I'm sure I can configure it some other way so I get more duty cycle to play with, if you know what I mean.  (Maybe if I lower the frequency?)


Quote
What Webbot said was just that your perception of brightness doesn't follow a linear scale.

This puzzles me.  So basically even though we're linearly adjusting the parameters that affect brightness, the brightness change won't LOOK linear?  (I'm guessing it falls off toward the low and high end, so we have to adjust more to get the same amount of brightness "change")

If I am correct, I agree with you soeren, it's not really going to matter. 

EDIT:  Yes webbot I googled, but it's late, and I didn't see any result that jumped out at me, and I didn't feel like reading papers, so I just decided to guess :)

EDIT 2:  I just remembered that there are two 8 bit timers and one 16 bit timer.  I've been using the 16 bit timer, and I used 10 of those bits in the timer I used.  I'm going to have to use the 8 bit timer to make the PWM on all three channels similar.  I'll figure it out tomorrow...
« Last Edit: April 07, 2010, 10:10:45 PM by corrado33 »

Offline Soeren

  • Supreme Robot
  • *****
  • Posts: 4,672
  • Helpful? 227
  • Mind Reading: 0.0
Re: LED dimmer (PWM) and timer program on AtMega8?
« Reply #23 on: April 07, 2010, 10:10:36 PM »
Hi,

I've successfully dimmed an LED using a freq of 1000 Hz (actually 977.5 Hz), a 10 bit Phase correct PWM, and a prescaler of 8.  I had to take the duty cycle down to 7% to actually "see" some dimming.  I'm sure I can configure it some other way so I get more duty cycle to play with, if you know what I mean.  (Maybe if I lower the frequency?)
Strange, but keep on experimenting - best way to learn (at least some of it).


This puzzles me.  So basically even though we're linearly adjusting the parameters that affect brightness, the brightness change won't LOOK linear?  (I'm guessing it falls off toward the low and high end, so we have to adjust more to get the same amount of brightness "change")
Yes, like most biological changes it follows an S-shaped curve (also called a biological curve).
Back in the seventies, there was a very popular touch dimmer IC (S576A..C) that swept up and down linearly when the sensor was "touched", but you'd perceive it as going fast through the middle part and slower through each end of the range.
Regards,
Søren

A rather fast and fairly heavy robot with quite large wheels needs what? A lot of power?
Please remember...
Engineering is based on numbers - not adjectives

Offline Webbot

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 2,132
  • Helpful? 108
Re: LED dimmer (PWM) and timer program on AtMega8?
« Reply #24 on: April 08, 2010, 07:37:56 AM »
EDIT:  Yes webbot I googled, but it's late, and I didn't see any result that jumped out at me, and I didn't feel like reading papers, so I just decided to guess :)


It was discussed at length in this post: http://www.societyofrobots.com/robotforum/index.php?topic=5834.0
Webbot Home: http://webbot.org.uk/
WebbotLib online docs: http://webbot.org.uk/WebbotLibDocs
If your in the neighbourhood: http://www.hovinghamspa.co.uk

Offline corrado33Topic starter

  • Supreme Robot
  • *****
  • Posts: 611
  • Helpful? 11
Re: LED dimmer (PWM) and timer program on AtMega8?
« Reply #25 on: April 08, 2010, 11:12:02 AM »
Ok, I this time I used a phase correct, 8 bit PWM, and no prescaler to dim the LED.  It works fine.  I set OCR1A (which defines the duty cycle) to 25, so I had a duty cycle of about 10%.  ((25/255) or (OCR1A/TOP) is roughly .10 or 10%).  I tried to create a program that varies OCR1A from 1 to 255, then back down.  I think I'm missing the whole idea of the interrupts and timers.  Here's the code I used (I know it's not great, but I wrote it in a few minutes).

Code: [Select]
int main()
{
unsigned int i,j; 
DDRB|=(1<<PORTB1);  //Define port B1 as output
TCCR1A=0xA1;        //Set B1 as PWM and set 2 of 4 registers for PWM type
OCR1A=25;           //Set duty cycle (OCR1A/TOP)= Duty cycle, which changes brightness
TCCR1B=0x01;        //Set 2 of 4 registers for PWM type and 3 registers for prescaler
for(j=1;j<10;j++) //My infinite loop
{
for(i=1;i<200;i++)
{
OCR1A=i; //Loop to increase LED brightness  (This doesn't work)
pause();
}
for(i=200;i>1;i--)
{
OCR1A=i; //Loop to decrease LED brightness  (This doens't work)
pause();
}
j=j-1; //This keeps my j For loop infinite
}
}

However the LED just stayed at one brightness.  I think I have to use an interrupt?  In the table I posted before, it said that the OCR1x is updated on TOP.  Therefore when the timer reaches top, which is 255 in this case, it'll update OCR1A.  However, with the program I have written... actually I don't know why it's not working, that's why I'm asking.    ;)

EDIT: The for loop with J is my endless loop.  I couldn't get a while loop to work.  I like for loops anyway...  Don't worry about the PAUSE, I tried it with and without it and I had the same result.

EDIT2:  I know that because I'm using a hardware PWM, the PWM and program run at the same time.  They technically aren't linked anywhere.  So even if this is true, the program IS changing OCR1A, and the PWM IS updating OCR1A... however OCR1A might not actually be implemented into the PWM everytime it's changed.  I just don't understand why it's not changing at all, and how I should CORRECTLY implement the change.

EDIT3:  I believe I have to use the TOV1 Flag...
« Last Edit: April 08, 2010, 11:36:31 AM by corrado33 »

Offline corrado33Topic starter

  • Supreme Robot
  • *****
  • Posts: 611
  • Helpful? 11
Re: LED dimmer (PWM) and timer program on AtMega8?
« Reply #26 on: April 08, 2010, 03:17:28 PM »
Got an update... I figured I'd make a new post, and I have new code so here it is.

This WORKS!
Code: [Select]
int main()
{
unsigned int i,j; 
DDRB|=(1<<PORTB1);  //Define port B1 as output
DDRB|=(1<<PORTB2); //Define port B2 as output
TCCR1A=0xA1;        //Set B1 and B2 as PWM and set 2 of 4 registers for PWM type
OCR1A=200;      //Set duty cycle (OCR1A/TOP)= Duty cycle, which changes brightness
OCR1B=2;
TCCR1B=0x01;    //Set 2 of 4 registers for PWM type and 3 registers for prescaler
for(i=1;i<50000;i++)//Pauses for a second or so
pause();
OCR1A=2; //Switches the brightness of the two LEDs
OCR1B=200;

}

This does NOT WORK!
Code: [Select]
int main()
{
unsigned int i,j; 
DDRB|=(1<<PORTB1);  //Define port B1 as output
DDRB|=(1<<PORTB2); //Define port B2 as output
TCCR1A=0xA1;        //Set B1 as PWM and set 2 of 4 registers for PWM type
for(j=1;j<10;j++) //Repeat the brightness switch 9 times
{
OCR1A=200;      //Set duty cycle (OCR1A/TOP)= Duty cycle, which changes brightness
OCR1B=2;
TCCR1B=0x01;    //Set 2 of 4 registers for PWM type and 3 registers for prescaler
for(i=1;i<50000;i++)//Pause for a second or so
pause();
OCR1A=2;
OCR1B=200; //Switch the brightness of the two LEDs
}

}

I don't understand why...  I would think that it would simply switch the brightness of the LEDs 9 times... but it doesn't.  It doesn't even switch them once?  Can I not use nested for loops?

EDIT:  This works as well, it seems as if nested for loops could be the problem.
Code: [Select]
int main()
{
unsigned int i,j; 
DDRB|=(1<<PORTB1);  //Define port B1 as output
DDRB|=(1<<PORTB2); //Define port B2 as output
TCCR1A=0xA1;        //Set B1 as PWM and set 2 of 4 registers for PWM type
OCR1A=200;      //Set duty cycle (OCR1A/TOP)= Duty cycle, which changes brightness
OCR1B=2;
TCCR1B=0x01;    //Set 2 of 4 registers for PWM type and 3 registers for prescaler
pause2();
OCR1A=2;
OCR1B=200; //Switch the brightness of the two LEDs

for(i=1;i<200;i++)
{
OCR1A=i;
OCR1B=200-i; //Dim one LED and brighten other LED
pause2();
}

}
« Last Edit: April 08, 2010, 03:32:30 PM by corrado33 »

Offline Webbot

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 2,132
  • Helpful? 108
Re: LED dimmer (PWM) and timer program on AtMega8?
« Reply #27 on: April 08, 2010, 04:53:21 PM »
you don't give the code for your 'pause' or 'pause2' routines.

if all these do is something like:
for( int p =0; p < 1000; p++);

and you are compiling with optimisation enabled then the compiler will realize that these for loops don't actually achieve anything - and will remove them. ie all of your pauses get auto-deleted.
Webbot Home: http://webbot.org.uk/
WebbotLib online docs: http://webbot.org.uk/WebbotLibDocs
If your in the neighbourhood: http://www.hovinghamspa.co.uk

Offline corrado33Topic starter

  • Supreme Robot
  • *****
  • Posts: 611
  • Helpful? 11
Re: LED dimmer (PWM) and timer program on AtMega8?
« Reply #28 on: April 08, 2010, 07:47:59 PM »
Code: [Select]
void pause()
{
unsigned int k;
for(k=1;k<20000;k++)
{
k++;
k--;
}
for(k=1;k<20000;k++)
{
k++;
k--;
}
for(k=1;k<20000;k++)
{
k++;
k--;
}
}

I have no idea how to compile with optimization on... but my pauses do work, because I've changed the numbers around to get different lengths of pauses. 

EDIT: UPDATE!!

LED Dimmer with AtMega8

Here's a vid of me using all three PWM channels on the AtMega8.  It doesn't look like it, but here's how the LEDs light up.  The first one goes to half brightness, then the second one starts.  The first one goes to full brightness, and the second is at half brightness, the third starts.  The first goes to half brightness, the second goes to full brightness, and the third goes to half brightness.  The First goes to off, the second goes to half brightness, and the third goes to full brightness.  The second goes to zero, the third goes to half brightness.  The third goes to zero.  It's supposed to look like a "wave".  But because of non-linear perceived LED brightness, it doesn't look like it. 

Here's the code...
Code: [Select]
int main()
{
unsigned int i; 
setup_pwm();

for(i=1;i<1000;i++)
{
if (i<=200) //LED1 brightness up
OCR1A++;
else if ((i>200) && (i<=400))                 //LED1 brightness down
OCR1A--;
if ((i>100) && (i<=300))                 //LED2 brightness up
OCR1B++;
else if ((i>300) && (i<=500))              //LED2 brightness down
OCR1B--;
if ((i>200) && (i<=400))                 //LED3 brightness up
OCR2++;
else if ((i>400) && (i<=600))                 //LED3 brightness down
OCR2--;
if (i == 600) //Makes this loop go on forever
i = 0;
pause2(); //Pause so that I can actually see the dimming
}
}

Geeze the code indenting gets messed up when you put it in those tags...

EDIT2:  Yeah yeah I didn't include the setup_pwm and pause2 functions, the code is all on this page, I just rearranged it. 

EDIT3:  The weird thing is, when I step through the program, OCR2 only gets up to 23... I have no idea why, but it works?  I know that OCR2 is an 8 bit value, and OCR1A and OCR1B are 16 bit, but why does OCR2 act weird like that?
« Last Edit: April 08, 2010, 10:41:31 PM by corrado33 »

Offline corrado33Topic starter

  • Supreme Robot
  • *****
  • Posts: 611
  • Helpful? 11
Re: LED dimmer (PWM) and timer program on AtMega8?
« Reply #29 on: April 09, 2010, 07:03:19 PM »
Quote
The weird thing is, when I step through the program, OCR2 only gets up to 23... I have no idea why, but it works?  I know that OCR2 is an 8 bit value, and OCR1A and OCR1B are 16 bit, but why does OCR2 act weird like that?

I guess I'll answer my own question...  ;)  It's the simulator's fault.  OCR2 when using Phase correct PWM only updates on TOP (when the timer reaches TOP).  The program runs faster than the frequency of the PWM, so OCR2 is being incremented multiple times per PWM period.  Since OCR2 is only updated ONCE per PWM period, if OCR2 is currently at 6, and I add 1 to it, then the program comes around again, and again, and adds 1 to OCR2, which is STILL 6 because it was never updated after the last time I added 1.  Get it?  But you say "But why does OCR1A and OCR1B act fine?  The 16 bit timers act weird (aka wrong) when being simulated, especially when using PWM.  So really they would be doing the same thing, except the simulator gets it wrong. 

BUT you say "Then why do the LEDs light up correctly when you actually use the program?"  Well, see that "pause()" function?  I comment it out when I simulate it, cause it makes the simulation take forever.  Since I pause every time around the loop when I actually program it, the PWM completes it's current period (and probably a few more), so the next time OCR2 is incremented, the PWM has time to catch up before OCR2 is incremented again. 

With that resolved... I've implemented a potentiometer and I've used the analog to digital converter with it's corresponding interrupt to dim one of the LEDs (specifically LED3) manually.  It was... weird at first, and running the ADC constantly (free run mode) slowed down my dimming considerably, so I ran it once every 10 times through my loop.  It still works fine.  Here's the code...

Code: [Select]
int main()
{
unsigned int i; 
setup_pwm();

ADMUX= 0x21;
ADCSRA= 0xC8;
SREG=0x80;


for(i=1;i<1000;i++)
{
if (i<=200) //LED1 brightness up
OCR1A++;
else if ((i>200) && (i<=400)) //LED1 brightness down
OCR1A--;
if ((i>100) && (i<=300)) //LED2 brightness up
OCR1B++;
else if ((i>300) && (i<=500)) //LED2 brightness down
OCR1B--;
// if ((i>200) && (i<=400)) //LED3 brightness up
// OCR2++;
// else if ((i>400) && (i<=600)) //LED3 brightness down
// OCR2--;
if (i == 600) //Makes this loop go on forever
i = 0;
pause2(); //Pause so that I can actually see the dimming
if (i%10==0)
ADCSRA |= 0x40;
}


}


ISR(ADC_vect)
{
int valu;
valu = ADCH;
OCR2 = valu;
}

Critique is welcome!
« Last Edit: April 09, 2010, 07:05:43 PM by corrado33 »

 


Get Your Ad Here