0% duty cycle not working properly

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

Hi,

I'm working on a circuit using an attiny2313 to control 3, 3W RGB LEDs.

I'm using 3 outputs from Timer0 and Timer1 to switch on the red, green and blue color channels. I have them set up in fast PWM mode, so that I can set the brightness of each color channel with the duty cycle of the timers.

This works fine at changing the intensity, but my problem is when the duty cycle should be 0% (OCRXX = 0) the LEDs are still on, when they should be off (at least in my thinking).

I've tested this with just a small 5mm LED on one of the PWM outputs, and it also faintly glows, so I'm fairly certain this is some kind of software issue and not something wrong with the hardware.

Here's what it looks like:

That LED should be completely off, but it isn't. The other LED is off because it's common anode is disconnected.

This is the schematic:
https://www.circuitlab.com/circuit/734hqw/3-x-1-watt-rgb-led-driver/

The transistors and resistor values are all wrong in that schematic, but that's how it's hooked up.

This is how I've set up one of the timers:

	TCCR0A |= (1<<COM0A1) | (1<<WGM01) | (1<<WGM00); // fast PWM
	TCCR0B |= (1<<CS02); // clk / 256
	OCR0A = 0;

If anyone could point me in the right direction here, I would really appreciate it. Thanks!

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

This is a hardware issue (a hardware design flaw IMO, but others disagree). Setting fast PWM to 0 will still produce a slight output glitch, which is what you are seeing. Phase correct PWM does not have that issue/flaw. Or you can reverse the sense of the PWM so 0 is full-on and 255 is full off (inelegant IMO), or special-case a 0 output and turn off the output pin.

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

Quote:

Or you can reverse the sense of the PWM so 0 is full-on and 255 is full off (inelegant IMO),

OK, I'll bite. :twisted: Why would this simple change be "inelegant"?
Quote:

0 is full-on

AFAIK, the same issue remains with inverted PWM. However, while the 1/256 will often/usually make the LED glow which is undesirable, the inverted "full on" of 0 is actually 255/256 which would be unnoticeable for LED work.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

As a further demonstration of my oafishness (lack of elegance), I happen to have a current app with two dimming "channels". I thought I'd share...

//
// **************************************************************************
// *
// *		_ L E V E L
// *
// **************************************************************************
//
// Backlight and indicator LED brightness handling
//	-- Master system sends a level 0-255 for off-full on
//	-- Don't allow indicator level to be full off.
//	-- Timer2 (backlight) is run in inverted PWM to allow easy full-off with an OCR value of 255.
//	-- Timer0 (indicator) value cannot be greater than 0x46, so divide the commanded value by 4.
//
unsigned char				set_backlight_level	(unsigned char setpoint)
{
// Inverted PWM, 255 (full off) to 0 (nearly full on)
	return (255 - setpoint);
}
unsigned char				set_indicator_level	(unsigned char setpoint)
{
unsigned char work;

// Do not allow 0 level.  Limit to ~64 max by a /4
	work = setpoint/4;
	work++;	// changes 0 into 1, and 255 into 64 for near max
	return work;
}
...
// Change to inverted PWM in order to get full-off for the backlight
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: 3686.400 kHz
// Mode: Fast PWM top=0xFF
// OC2A output: Disconnected
// OC2B output: Inverted PWM
// Timer Period: 0.069444 ms
// Output Pulse(s):
// OC2B Period: 0.069444 ms Width: 0.032407 ms
ASSR=(0<<EXCLK) | (0<<AS2);
TCCR2A=(0<<COM2A1) | (0<<COM2A0) | (1<<COM2B1) | (1<<COM2B0) | (1<<WGM21) | (1<<WGM20);
TCCR2B=(0<<WGM22) | (0<<CS22) | (0<<CS21) | (1<<CS20);
TCNT2=0x00;
OCR2A=0x00;
OCR2B=0x88;
...
// OCR registers for LED backlight and indicators
#define	LEVEL_BACKLIGHT		OCR2B
#define	LEVEL_INDICATORS	OCR0B
...
					// Set backlight and indicator levels to new values
					LEVEL_BACKLIGHT = set_backlight_level (commo_buf[1]);
					LEVEL_INDICATORS = set_indicator_level (commo_buf[2]);
...

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Thanks for the tips guys! I set it up in phase correct PWM mode and 0% works fine, but now I have a new issue. Timer1 A/B control the blue and green channels, and in phase correct mode I can't control the individual channels. I can only turn blue/green on at the same time.

Is there some way to fix that? I can always do the inverted fast PWM trick, but if there's a way to get this to work I'd prefer to. Thanks again for your time :)

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

Whoops! my problem was one of the resistors touching where it shouldn't have been. The circuit works fine now, thanks for solving my problem so quickly!

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

0% duty cycle is possible. Just stop the timer.

Sid

Life... is a state of mind

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

Amazing how fast we found that short for you!

The largest known prime number: 282589933-1

It's easy to stop breaking the 10th commandment! Break the 8th instead. 

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

theusch wrote:
Quote:

Or you can reverse the sense of the PWM so 0 is full-on and 255 is full off (inelegant IMO),

OK, I'll bite. :twisted: Why would this simple change be "inelegant"?
Quote:

0 is full-on

AFAIK, the same issue remains with inverted PWM. However, while the 1/256 will often/usually make the LED glow which is undesirable, the inverted "full on" of 0 is actually 255/256 which would be unnoticeable for LED work.

Right, which is one reason why it's inelegant - it's still not giving you full off and full on. Nobody will ever notice it, but it's the kind of thing that gnaws at me. The other is just an aesthetic judgement, that mapping 0 to 255 and 255 to 0 is very much programming in the solution domain rather than the problem domain, and that's always inelegant.