AVR Freaks Forum Index

Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Author Message
youritronics
PostPosted: May 23, 2008 - 11:39 AM
Wannabe


Joined: May 15, 2008
Posts: 71


Hello, I'm new with AVR's and I'm learning C programing for AVR. I just finished my first project which is is a led chaser with my own pattern, so i can say i learned a bit how avr's work. Now i would like to experiment with PWM control over RGB LED's. I got myself an RGB led with 4 pins, and an AVR butterfly. I did a bit of research on the web and all of the projects for AVR i found were written in ASM, so my questions are:
1: Can a code written in ASM be converted to C ?
2: Can you give me a link to a project about pwm control on RGB LED written in C ?

thank you, Florin
 
 View user's profile Send private message  
Reply with quote Back to top
jayjay1974
PostPosted: May 23, 2008 - 12:03 PM
Raving lunatic


Joined: Oct 30, 2002
Posts: 3922
Location: The Netherlands

1. Yes, but in ASM tricks are possibly that have no direct equivalent in C. Timing critical stuff might be difficult it every single instruction counts; you never really know what the compiler generates.

2. No, I don't know any.

_________________
Free e-books
Modern Mechanix: Yesterday's Tommorow Today
 
 View user's profile Send private message  
Reply with quote Back to top
condemned
PostPosted: May 23, 2008 - 01:20 PM
Hangaround


Joined: Sep 04, 2007
Posts: 201
Location: Oxford (England)

Can I suggest that you read through some of the Tutorials, maybe the 'Newbie's guide to AVR Timers' and getting just a single LED under PWM control before moving to 3-channels (e.g. Red, Green and Blue).

When you run out of PWM timers (which you will do at some point) for controlling your multiple LEDs, then you're going to have to consider controlling them more directly.

I use the following method which isn't actually 'PWM', but it works very well for LEDs...
Take an 8-bit byte that holds the required intensity of the LED and turn on/off the LED in a timed pattern according to the binary value of that intensity.
E.g.
For an intensity value of 187 (binary 10111011)...
switch the LED with the following pattern:
ON for 128 ticks
OFF for 64 ticks
ON for 32 ticks
ON for 16 ticks
ON for 8 ticks
OFF for 4 ticks
ON for 2 ticks
ON for 1 tick

Whilst this might seem a little complex for a single-LED (certainly more so than just setting up a PWM output), it can scale very well to multiple LEDs.

I simply pre-calculate the pattern needed on each port/pin for each of the 8 time-slices. All the timer interrupt then needs to do is set the port-value and set the next interrupt delay. This means that the interrupt is quick and simple, hence the 'tick' timebase can be nice and short.
It can even be used to charlieplex/multiplex LEDs if neccesary; I've had 2 RGB LEDs hanging off a tiny13.

(Hopefully someone might move this to a more appropriate forum!)
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
bobgardner
PostPosted: May 23, 2008 - 03:11 PM
10k+ Postman


Joined: Sep 04, 2002
Posts: 13547
Location: Orlando Florida

That looks like an interesting variation of regular old 'software pwm' where you turn every thing off, set the loop counter to 0, then every loop check if the counter is up to the R value, turn on the R, counter = G value, turn on G, etc. If you count up to 64 (6 bits of adjustment range) 70 times a sec, the program should loop ~4000 times a sec

_________________
Imagecraft compiler user
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
youritronics
PostPosted: May 23, 2008 - 04:05 PM
Wannabe


Joined: May 15, 2008
Posts: 71


thx for your answers, and I'm waiting for more advices from you if possible Smile

sorry, i thought this category is right for my thread
 
 View user's profile Send private message  
Reply with quote Back to top
markus_b
PostPosted: May 23, 2008 - 04:11 PM
Posting Freak


Joined: Mar 20, 2001
Posts: 1031
Location: Switzerland

I've just done a software PWM for an RGB LED for a tiny15. I does not have memory, only registers and a hardware stack, so C is not practical Sad.

However, I set up a timer to fire with 25kHz. With an 8-Bit counter this gives a 100Hz PWM-interval. It decrements an 8-bit counter for each LED color and turns the LED off if the counter is zero. Every 256 interrupts it reloads the counters from the brightness setting and turns the LED's on.

The main routine is used to change the brightness settings to get interesting light changes.

Markus

_________________
Markus
 
 View user's profile Send private message Send e-mail  
Reply with quote Back to top
youritronics
PostPosted: May 23, 2008 - 04:13 PM
Wannabe


Joined: May 15, 2008
Posts: 71


Markus is your code written in C ? because i could use other AVR's

Florin
 
 View user's profile Send private message  
Reply with quote Back to top
JohanEkdahl
PostPosted: May 23, 2008 - 05:11 PM
Raving lunatic


Joined: Mar 27, 2002
Posts: 9648
Location: Lund, Sweden

Quote:

Markus is your code written in C ?

I don't think so as he hinted with this
Quote:

C is not practical [for an AVR that has no RAM]


I am not sure all compilers have difficulties with RAM-less AVRs, so don't take this as a statement from me that I agree with MArkus, but as a hint to the fact that he actually didn't use C for this.

Anyhow, PWMing LEDs does not require high PWM periods (frequencies) as your brain will integrate the blinking. 100 Hz might well be enough. And then you'd have little problem with exact timings, so generally speaking thois would be more than doable with C.

Why not start out with a single (eg one-colour) LED and master the PWM technique there? Then move on to three colours. After all, a RGB LED is only three LEDs of different colours in a monolithic housing...
 
 View user's profile Send private message  
Reply with quote Back to top
youritronics
PostPosted: May 23, 2008 - 05:14 PM
Wannabe


Joined: May 15, 2008
Posts: 71


ok, I'll take the advice and start with single LED, but still i need a C example project.
 
 View user's profile Send private message  
Reply with quote Back to top
bobgardner
PostPosted: May 23, 2008 - 05:32 PM
10k+ Postman


Joined: Sep 04, 2002
Posts: 13547
Location: Orlando Florida

State which AVR, what xtal speed, and which c compiler, maybe some kind soul will taior one of their existing projects for your specific example

_________________
Imagecraft compiler user
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
JohanEkdahl
PostPosted: May 23, 2008 - 05:45 PM
Raving lunatic


Joined: Mar 27, 2002
Posts: 9648
Location: Lund, Sweden

You can do the PWM either by using the PWM modes of timers (so read the timer tutorials in the tutorial forum) or you can "wiggle" a pin in PWM mode yourself but then you still need some basic timing tick (so read the timer tutorials in the tutorial forum).

For the latter approach:
You need to produce a PWM signal with a period of, say, 100 Hz (or more). Let's also assume that you want a PWM resolution of 100.

This means that you need to get some basic timer tick working at 100x100 Hz = 10 KHz. Use a timer for that. (Read the tutorials...).

Now every time the timer generates a tick you set a flag in the ISR.

Main loop in the program looks at the flag and holds a count of how many it has seen. You code so that this counter wraps to 0 at 100. Every time it wraps it sets the pin you are using for your PWM signal high. You also have a duty-cycle value you want to generate, and every time the count variable passes this value you set the PWM pin low.

Sketchy:
Code:

volatile int timerTick;

ISR(...) {
   // This ISR will fire with a frequency of 10KHz
   // (value not critical, could be a higher frequency)
   timerTick = 1;
}


int main()
{
   int tickCount;
   int dutyCycle = 42;

   //  Set up the timer here (as you have learned from the timer tutorials) to generate interrupts with 10 KHz or so

   while (1) {
      if (timerTick == 1) {
         tickCount++;
         timerTick = 0;

         if (tickCount >= 100) {
            // Wrap and set the pin high
            tickCount = 0;
            PORTx |= 1<<PWM_PIN;
         }
         else if (tickCount == dutyCycle) {
            // Set the pin low
            PORTx &= ~(1<<PWM_PIN);
         }
      }
   }
}


When this works you can move on to create code that generalizes this for n pins with a shared PWM frequency, but woith individual duty cycles.
 
 View user's profile Send private message  
Reply with quote Back to top
smileymicros
PostPosted: May 23, 2008 - 05:52 PM
Raving lunatic


Joined: Nov 17, 2004
Posts: 4578
Location: Great Smokey Mountains.

jayjay1974 wrote:
1. Yes, but in ASM tricks are possibly that have no direct equivalent in C. Timing critical stuff might be difficult it every single instruction counts; you never really know what the compiler generates.
I don't want to hijack the thread, but I will ask, what effect can you do with PWM for an LED that would be visible to a human and can't be done in C? I agree that if you push a particular AVR to its maximum that you can do things with asm that you cant do with C, but since we can't perceive lights flickering at greater than about 60 times per second, I can't imagine any visible effect that you couldn't do in C and have the AVR twiddling its thumbs most of the time.

Smiley

_________________
FREE TUTORIAL: 'Quick Start Guide for Using the WinAVR C Compiler with ATMEL's AVR Butterfly' AVAILABLE AT: http://www.smileymicros.com
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
jayjay1974
PostPosted: May 23, 2008 - 06:14 PM
Raving lunatic


Joined: Oct 30, 2002
Posts: 3922
Location: The Netherlands

I think nothing Wink More a general comment not specifically related to LED PWM.

I'd put all the PWM stuff inside the ISR, and do other modulation effects in the main loop.

_________________
Free e-books
Modern Mechanix: Yesterday's Tommorow Today
 
 View user's profile Send private message  
Reply with quote Back to top
theusch
PostPosted: May 23, 2008 - 06:15 PM
10k+ Postman


Joined: Feb 19, 2001
Posts: 19075
Location: Wisconsin USA

Smiley, do you remember who posted the holiday light project for Christmas 2006 IIRC? That was a fully-worked example for RGB driving, and in addition made a string of lights. IIRC it was in Off-Topic Forum.

Quote:
what effect can you do with PWM for an LED that would be visible to a human and can't be done in C?

That is always the interesting challenge. Evil or Very Mad IF the algorithm makes great use of Carry or Rotate (C has no concept of those), then I'll concede. Similarly, special arithmetic widths such as 24 bits--doesn't jesper's miniDDS use that? But in general one can almost always coerce C to get the job done, especially in a small contained app like this.

If there is a great advantage to using carry (say), then one can just drop into inline ASM for the critical sequence.

Lee
 
 View user's profile Send private message  
Reply with quote Back to top
theusch
PostPosted: May 23, 2008 - 06:31 PM
10k+ Postman


Joined: Feb 19, 2001
Posts: 19075
Location: Wisconsin USA

Quote:
Smiley, do you remember who posted the holiday light project for Christmas 2006 IIRC?

That was miamicanes. [No posts from him since the beginning of this year.] Forum search for "rgb christmas" leads to
http://www.avrfreaks.net/index.php?name ... torder=asc
http://www.avrfreaks.net/index.php?name ... +christmas

Hmmm--I thought the firmware was posted, but I can't seem to find it.

Lee
 
 View user's profile Send private message  
Reply with quote Back to top
glitch
PostPosted: May 23, 2008 - 07:06 PM
Raving lunatic


Joined: Jan 12, 2002
Posts: 7004
Location: Canada

not sure if miamicanes ever posted his code. but gmprops code is on that other thread thread (an early version of it) That code is not for the AVR's PWM though, it's for working with TLC5940 external LED pwm chips.
 
 View user's profile Send private message  
Reply with quote Back to top
youritronics
PostPosted: May 23, 2008 - 08:08 PM
Wannabe


Joined: May 15, 2008
Posts: 71


thx for all your help, I'll study a bit more and I'll come back if i have questions.

Florin
 
 View user's profile Send private message  
Reply with quote Back to top
bobgardner
PostPosted: May 23, 2008 - 08:49 PM
10k+ Postman


Joined: Sep 04, 2002
Posts: 13547
Location: Orlando Florida

if the part that is stumping you is the timer interrupt, this program is simple enough that the RG and B will get bright and dim just by running in a tight loop. You dont care if it runs at 70 times a sec or 700 or 7000 as long as it works.

_________________
Imagecraft compiler user
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
markus_b
PostPosted: May 24, 2008 - 12:48 AM
Posting Freak


Joined: Mar 20, 2001
Posts: 1031
Location: Switzerland

youritronics wrote:
Markus is your code written in C ? because i could use other AVR's


No, my code is in assembler. In fact, for the Software-PWM part, assembler does very nicely. But for the part where I'm trying to find nice algorithms to change the colors around C would be much better.

While some C compiler do work for the tiny15, gcc/winavr does not and I thought a tour with assembler only sharpens my mind Smile.

I you want I'll post the source.

Markus

_________________
Markus
 
 View user's profile Send private message Send e-mail  
Reply with quote Back to top
Levenkay
PostPosted: May 24, 2008 - 08:21 AM
Resident


Joined: Dec 20, 2007
Posts: 596
Location: Portland, Oregon, USA

JohanEkdahl wrote:
You can do the PWM either by using the PWM modes of timers (so read the timer tutorials in the tutorial forum) or you can "wiggle" a pin in PWM mode yourself but then you still need some basic timing tick (so read the timer tutorials in the tutorial forum).

For the latter approach:
You need to produce a PWM signal with a period of, say, 100 Hz (or more). Let's also assume that you want a PWM resolution of 100.

This means that you need to get some basic timer tick working at 100x100 Hz = 10 KHz. Use a timer for that. (Read the tutorials...).

Now every time the timer generates a tick you set a flag in the ISR.

Main loop in the program looks at the flag and holds a count of how many it has seen. You code so that this counter wraps to 0 at 100. Every time it wraps it sets the pin you are using for your PWM signal high. You also have a duty-cycle value you want to generate, and every time the count variable passes this value you set the PWM pin low.



This trick doesn't work quite as elegantly for a 100-count-resolution PWM, but it's pretty cute for an even-power-of-two resolution like 256:

Every sampling interval, you add the "duty cycle" setting to an accumulating total. Use the carry from this addition as your PWM signal.
 
 View user's profile Send private message  
Reply with quote Back to top
Display posts from previous:     
Jump to:  
All times are GMT + 1 Hour
Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Powered by PNphpBB2 © 2003-2006 The PNphpBB Group
Credits