Timer OCR pin initial state glitch

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

When I setup timer 3 on my 1284p in the following way (and many, many others) I get a unpredictable start state. The OCR3A pin always ideals at 0 since I set both TCCRA and B to 0 when the timer is off. FOC3A does not work in any of the PWM modes, which I need. It also does not produce the desired outcome in CTC mode, but that's another issue for another day.

After the following code is executed I get a short pulse, about 200ns wide, then the output is off for the correct period and on for the correct period and everything behaves as expected. Where is this pulse coming from and how do I get ride of it? I want the timer to start low every time.

Please keep in mind I need this to execute quickly so setting several different modes just to make some inaccessible pin toggle register happy may not an option.

		ICR3=(PW);	//cycle pulse width
		OCR3A=(PW/2);	//output PW off time
		TCNT3=40;   //set timer 3 start value
		TCCR3A =(0<<COM3A0)|(1<<COM3A1)//clr compare match b.6
		TCCR3B =(1<<WGM33)|(1<<CS30);//tmr3-clk/1, P/F PWM

Any ideas?

Last Edited: Mon. Feb 10, 2014 - 03:31 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Explain exactly what behaviour that you want.

You select PWM mode#8 with an output mode which starts high, and goes low on match.
If you want to start low, you could set TCNT3 = OCR3A to force an immediate match.

You may change duty cycle but otherwise most PWM runs continuously. The behaviour of the first cycle is insignificant. e.g. does it matter if the first cycle is 'short'?

David.

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

I am looking for predictable start up.

The behavior is present regardless of clear or set on match. I have tried setting TCNT3=OCR3A with no change. Anything I can look at?

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

You can reset the timer so that it starts from zero. And,for some prescalers, you can reset the prescaler, also. Won't this give you a known start state?

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

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

I reset both TCCR A and B to zero, which effectivly resets the timer and prescaler, and establish a start value for TCNT. This results in a known state for the timer, but not the fist pulse out of the OCR3A pin.

Thanks for the efforts so far guys. I still haven't found a solution. A side note - I've been using google to search this forum since for some reason I can't get the forums own search to work.

Aron

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

hvguy0 wrote:
I reset both TCCR A and B to zero, which effectivly resets the timer and prescaler
It does more than that, it also sets mode 0 for the timer. The mode is set whether or not the timer is running. In timer mode 0, compare output modes are different than they are in mode 8.

hvguy0 wrote:
I am looking for predictable start up.
But:
Quote:
After the following code is executed I get a short pulse, about 200ns wide, then the output is off for the correct period and on for the correct period and everything behaves as expected.
Are you saying:
- this 200 ns pulse doesn't happen consistently?
- this pulse is undesirable?
- both?

A couple of things I can think of that might be biting you:
- You set ICR3 before switching from mode 0 to mode 8, so activity on ICP3 can update ICR3.
- You set the compare output mode before you set the timer mode...
- ... and compare output mode behaviour is different for timer mode 0 than it is for timer mode 8 (as mentioned above)

What frequency is the mcu running at? 200 ns represents 3 clock cycles at about 16 MHz. I'd take a stab that you are running at 16 MHz, and that the 200 ns you're seeing is the three clock cycles it takes between writing TCCR3A and writing TCCR3B.

Just some ideas, but if you're seeing undesired compare output pulses (whether spurious or consistent) when you configure the timer, then control the order in which you configure the timer:

GTCCR = (1<<TSM) | (1<<PSRSYNC);  // hold prescaler
TCCR3B = (1<<WGM33) | (1<<CS30);  // mode 8, clk/1
TCNT3 = 40;           // start value
ICR3 = PW;            // top
OCR3A = PW / 2;       // ~50% duty
TCCR3A = (1<<COM3A);  // non-inverting mode
GTCCR = 0;            // release prescaler to start

A couple of notes:
- Datasheet not clear w.r.t effect of PSRSYNC on TIMER3
- The minimum resolution allowed is 2-bit (ICR3 set to 0x0003)
- Writes to TCNT3 will block compare matches on the next timer tick, so if OCR3A == TCNT3 (or TCNT3 + 1?), a compare match may be missed.

JJ

///////////////////////////////////////////////////////////////////////////////

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

Thanks JJ. Unfortunately, that didn't get it. Yes, the pulse does not happen consistently, and I do not want it there. I understand your reasoning for rearranging the register setting sequence. No doubt that will be useful in the future, but the problem persists for now, even with a cut and paste of your code example.

I believe the unpredictable start state is a result of, maybe, the toggle FF on that pin retaining it's final state when the timer in turned off. When I turn it back on it just starts in what ever state that FF was left in. But, aside from resetting the entire part, I can't see a way to reset it.

Aron

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

hvguy0 wrote:
Thanks JJ. Unfortunately, that didn't get it. Yes, the pulse does not happen consistently, and I do not want it there. I understand your reasoning for rearranging the register setting sequence. No doubt that will be useful in the future, but the problem persists for now, even with a cut and past of your code example.

Aron

If you can isolate exactly when that pulse occurs in relation to the lines of code that configure the timer, it might help to discover the root cause and a solution. Insert a while(1) before the last step. If the glitch is unchanged, the line before the while is not likely to be implicated. Move the while back by one line and test again.

Is there a placement for the while which causes the glitch to disappear? Does PWM stop as well? Does the glitch become 'frozen in time' as a permanent high level on OC3A? If not then it may indeed be an artefact of the internal logic of the timer and be unavoidable.

You can also confirm whether or not TIMER3 is affected by PSRSYNC by omitting GTCCR = 0. If the timer still runs, TIMER3's prescaler cannot be reset or stopped.

In that case, a different approach might work:

TCCR3B = (1<<WGM33);  // mode 8, stopped
TCNT3 = 40;           // start value
ICR3 = PW;            // top
OCR3A = PW / 2;       // ~50% duty
TCCR3A = (1<<COM3A);  // non-inverting mode
TCCR3B = (1<<WGM33) | (1<<CS30);  // mode 8, clk/1

Finally, you may try setting the compare mode last. Since you are pre-loading TCNT3 with a value that (presumably?) places it far away from the next compare match, it should result in normal glitch-free operation. If the glitch persists, I'm out of ideas ;)

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

Well, I tried rearranging things as you mentioned, still no luck :-( Maybe the below will help?

More information:

The test code is as follows (20MHz clk):

ICR3=(200);									
OCR3A=(100);				
TCNT3=0;								
PORTD&=~(1<<5);
TCCR3A =(1<<COM3A0)|(1<<COM3A1);				
TCCR3B =(1<<WGM33)|(1<<CS30);

If (1<<COM3A1) and (1<<COM3A0), I get the glitch, shown below as the blue trace, the green trace is the falling edge of PORTD5 used for ref trigger.

If (1<<COM3A1), I get the incorrect first PW of *exactly* half what it should be, shown below as the blue trace, the green trace is the falling edge of PORTD5 used for ref trigger.

So the goal is an img like the second pic, but with the right pulse width, which remains the same until the timer is terminated, or I change it.

I hope this helps...

Aron

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

hvguy0 wrote:
The test code is as follows (20MHz clk):
That is not the test code I suggested.

With your test code as posted, you are still switching compare output modes before switching timer modes.

Set the mode of the timer first, keeping it stopped. See my previous post.

You may also try setting the compare output mode last.

Have you determined if PSRSYNC affects TIMER3?

JJ

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

Quote:

Set the mode of the timer first, keeping it stopped.

Also, clear the match flag(s) before starting the timer in case they were already set.

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

Just as a silly point, why not separate your two traces?

I am sure that Joey is on the right track. i.e. set your SFRs in the correct sequence.

If you want to eliminate a glitch, you could disable DDR until later in the sequence.
Obviously this only works if you have pull-up or pull-down on the OC3 pin.

David.

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

david.prentice wrote:
If you want to eliminate a glitch, you could disable DDR until later in the sequence.
Obviously this only works if you have pull-up or pull-down on the OC3 pin.
I had just that thought on my way home for lunch :)

If the OP needs to idle both low and high at different points in the app, this could be achieved with a high-value (1Mohm) pulldown on OC3A, and the internal pullup on another otherwised unused GPIO pin.

It would be a (slightly) interesting finding if there turns out to be no software-only remedy to this glitch. I'd be curious if it can be reproduced with the other compare output, and with the other timers. I'd also be curious if it can be reproduced on other devices.

JJ

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

JJ - As the data sheet would seem to vaguely indicate, PSRSYNC had no effect of timer 3. Also, I tried every conceivable arrangement of the registers with no change in output. Though it does seem different arrangements execute more efficiently than others.

theusch - I cleared the flags to no avail.

David - Personal preference, i'm one of those people that likes to have my traces on top of each other ;-) Manipulating DDR did the trick! I'm still not sure why this behavior exists with the timer, and I intend to test it on other parts/timers. See working code below.

JJ - Had the DDR fix not done it I was working on several hardware fixes, yours included.

DDRB&=~(1<<DDB6);
TCNT3=((PW/2)-3);	
//as long as TCNT is less than PW/2 it works for controlling timer phase
ICR3=(PW);
OCR3A=(PW/2);                  																    TCCR3A =(0<<COM3A0)|(1<<COM3A1);					
TCCR3B =(1<<WGM33)|(1<<CS30);
while (TCNT3<=OCR3A);
DDRB = (1<<DDB6);

Thanks for all the help guys, I'm glad this one is fixed, even if we didn't figure out the cause. I will need to port this to an AT90PWM in the future, it will be interesting to see if the problem persists.

Aron

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

hvguy0 wrote:
yours included.
Well, David had the idea first ;)

The datasheet gives a hint that this is the correct approach anyway:

Quote:
The design of the Output Compare pin logic allows initialization of the OCnx state before the output is enabled.

BTW:

Quote:
If (1<<COM3A1), I get the incorrect first PW of *exactly* half what it should be, shown below as the blue trace, the green trace is the falling edge of PORTD5 used for ref trigger.
This is not incorrect. It is exactly consistent with the advertised behaviour of the timer.

Remember that you'd specified mode 8, a phase and frequency correct PWM mode which is a dual-slope mode. In this mode OCnx will change on a compare match with OCRnx and nowhere else (in contrast to single-slope modes where OCnx can change at 0x0000 and OCRnx).

The timer ping-pongs between 0 and TOP, passing OCRnx in each direction. For non-inverting mode (as you had selected) an up-counting compare match clears OCnx, while a down-counting compare match sets OCnx. In other words the OCnx output is high for 2*OCRnx timer ticks. In your case that's 200 timer ticks.

For the test in question, you preloaded TCNT3 with 0 and initiated the dual-slope mode. The timer started up-counting and reached OCR3A, clearing OCnx exactly 100 timer ticks after you initiated mode 8.

Your second capture perfectly reflects this.

Your first capture of inverting mode also demonstrates the expected half-duty initial pulse low before the first up-counting compare match that sets OC3A. The mystery remains as to why the compare match output unit spits out a high level for the first few timer ticks.

I'd guess that the logic which handles the initialisation of the compare output units always starts off with the output high when you change compare output modes. It must take a few timer ticks to synchronise the output to the current state of the counter (value and direction).

In that sense the 'glitch' is there in non-inverting mode as well, but you can't see it because the natural state of the output under your test conditions (TCNT3 = 0) is high.

There are several questions I posed which you haven't answered. I'm most curious what you would see with this:

ICR3=(200);                           
OCR3A=(100);            
TCNT3=0;                        
PORTD&=~(1<<5);
TCCR3A =(1<<COM3A0)|(1<<COM3A1);            
while(1);

Does the OC3A 'glitch' stay high forever? Or does it still last about 200 ns even though the timer is never started?

Quote:
See working code below
It's still unclear what exactly you are trying to accomplish.

You've selected non-inverting mode. Do you want to trigger the PWM and have the OC3A start high or low? Whichever it is, do you want the full duration of that part of the duty cycle to elapse before the first change?

Based on your latest code I'd guess you want to start low for the full off time of the configured duty cycle.

If this is the case, your choice of a dual-slope mode, and further of non-inverting mode, makes that difficult as I've shown above. It means you have to preload TCNTn with a value above (or near) OCRnx.

Why can't you use fast PWM? It would be much easier to work with, and might not even suffer from the glitch at all.

JJ

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]