Timer Counter accuracy. I am over 5% out on my timings accorinding to my oscilloscope!!!!

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

Greetings,

 

I have configured a noddy timercounter to get a project up and running to generate a 125KHz (8us) tick so I can update a DAC with a sinewave at 125 samples per cycle (giving a 1ms sinewave cycle).

 

I have set up the internal 32MHz clock and set up the Timer Counter for TCC0. I have my tick and I have a sinewave... however when I scope up the tick (toggle of a pin), I get 7.52us not the 8us I am expecting.

 

I have changed the divisor and PER to see if it was a function of the code but each gave the same tick time. I even removed the code in the ISR that updates the DAC with a new value but with no change to the timer. The thing is, I kind of expected that the tick would be "slower" as there may be other stuff the micro is doing but I stripped the code down to the bare bones.

 

I have even tried two other oscilloscopes. The same innacuracy.

 

TCC0.CTRLA = TC_CLKSEL_DIV2_gc;
TCC0.PER = 127;

TCC0.CTRLA = TC_CLKSEL_DIV4_gc;
TCC0.PER = 63;

TCC0.CTRLA = TC_CLKSEL_DIV8_gc;
TCC0.PER = 31;

TCC0.CTRLA = TC_CLKSEL_DIV64_gc;
TCC0.PER = 3;

TCC0.CTRLA = TC_CLKSEL_DIV128_gc;
TCC0.PER = 1;

 

I looked at the datasheet to see that the factory error is +/-1.5%.... if you do the maths on 7.52us i am over 5% out!!!!!  One way to get a 1ms sinewave is to do a use a divisor of 2 and set PER to 135. But as this is so out of specification, how can I trust other MCU's when it goes into production?

 

Ok so it doesnt have to be bang on an interger divisor 32MHz but I did expect it to be within the spec.

 

This is the initialisation and interrupt routine code

void initCLK(void)
{
    OSC.CTRL |= OSC_RC32MEN_bm ;
    while ((OSC.STATUS & OSC_RC32MRDY_bm) == 0);
    uint8_t clkctrl;
    clkctrl = (CLK.CTRL & (~CLK_SCLKSEL_gm)) | CLK_SCLKSEL_RC32M_gc;
    CCP = CCP_IOREG_gc;
    CLK.CTRL = clkctrl;
    OSC.CTRL &= ~(OSC_RC2MEN_bm | OSC_XOSCEN_bm | OSC_PLLEN_bm);
}

void initTIMER(void)
{
    //TIMER 0
    TCC0.CTRLA = TC_CLKSEL_DIV;
    TCC0.CTRLB = 0x00;
    TCC0.PER = 127;
    TCC0.CNT = 0x00;
    nterrupt for timer
    TCC0.INTCTRLA = 0b00000011;
}

ISR(TCC0_OVF_vect)
{
    //while(!(DACB_STATUS & DAC_CH0DRE_bm));
    //DACB_CH0DATA = sineTable[i++];
    PORTA.DIRTGL = TC;
    if(i > 124)
    {
        i=0;
    }
}

Am I doing something silly. Is there something obvious I have not done????

 

please help :)

 

 Pep

 

This topic has a solution.
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You have

PORTA.DIRTGL = TC;

don't you mean

PORTA.OUTTGL = TC;

?

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

I'm not an Xmega person but I'll describe a common gotcha for tiny/mega and you see if it fits:

 

When using timers in tiny/mega if you want to generate accurate width pulses it is usual to use a timer in "clear timer on compare" (CTC) mode. In this mode the timer counter TCNT counts up until it matches some compare value and when it does the hardware instantly resets TCNt back to 0 and generates the "event".

 

The "gotcha" is that 0 is a valid "tick". So if you want the timer to count to 8 then reset you actually set the compare register to 7 so it counts the ticks: 0,1,2,3,4,5,6,7 then resets and counts 0,1,2,3,4,5,6,7 again and so on. The temptation when you want 8 "ticks" in the sequence is to set the compare register to 8 but as you can see 0,1,2,3,4,5,6,7 *is* 8 timers periods not just 7 and so the compare register is set to 7. More generally it's always set to N-1. So if you want 125 ticks you set it to 124 and so on.

 

Does this have any relevance to the way you are using the Xmega timer I wonder?

 

(having said that I note you are "under" not over - so maybe not?).

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

Fair point snigelen, I looked at the datasheet and saw where I went wrong. Still getting to grips with the automatic definition list as one types. So I did make the change and.... no change.. still an error.

 

clawson, I understand your point.. However if you look in the ISR I am toggling when the interrupt fires. The calculation to get the Match Compare is PER = ( ( MCUclk / (N * REQUIRED_FREQ)) - 1).

 

The DAC output waveform cycle period of 1ms could go wrong but that is why I have put >124 to then reset my volatile variable i back to 0 to repeat the const uint8_t[125] data array.

 

 

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

I've not seen an Xmega with 5% clock error, but I only use small numbers of them, nothing in production.

 

Several thought's:

 

What level priority interrupt is your DAC interrupt?

 

Is there a higher priority interrupt interfering with it?

 

Which Xmega are you using?

 

Know that you can route a buffered clock signal to an I/O pin on the Xmegas, and feed this to your O'scope of Freq counter, and directly measure the uC's clock.

This totally eliminates any software issues being a factor int he clock / measurement / etc.

 

Does your PCB have an external Xtal?

If so, have you tried checking the uC's freq against the Xtal?

Is it spot on? (As expected)

 

Note, also, that one could again validate the clock error with a simple loop:

setup pin as output

set pin high

delay 1000 mSec

toggle pin

loop

 

This should also give a 5% error if the source of the problem is truly the uC's clock, (just another way to verify the source of the problem).

 

Finally, you need a plan B:

The Xmegas have several clock sources, including an internal 32.whatever kHz clock Xtal, which can be used to calibrate the 32 Mhz clock.

Make sure you use the correct 32 kHz clock to do this, not the inaccurate ultra low power one.

 

 

Also, one could put pads for an external Xtal and two caps on the PCB, and not populate unless needed, as a last resort.

 

I think the first step is just to route the clock signal to an I/O pin and measure it.

 

JC

 

 

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

JC,

 

The DAC was disabled when I stripped down the code. I must say again that the time less than 8us rather than more (which would of lead me to think it was something else with higher priority).

 

The part is the XMEGA-A3BU-Xplained PCB and my prototype has gone out for fabrication. On previous MEGA designs I did use an external clock. There was no room on the XMEGA PCB for an external clock (believe me on that one!!!!). OK I shall do the little experiment in the morning routing the clock to an IO. Thanks and I shall get back to you on that one. But a quick thought on that one...

 

There may be an issue with measuring 32MHz clock on an oscilloscope... the time period is so close together, that the inaccuracy of moving the cursors wont give me the resolution... More to the point... Can the IO pins work that fast???? SET/CLR within half of 0.03125us????? (at 32MHz)!!

 

By the way, I used a simple _delay_ms(1) routine in a while loop and toggled the same pin and the delay was on par with my timer counter results!!! within about 20ppm

 

Pep

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

There is absolutely no need or requirement to measure the clock output.

 

If you count 1 second blinks for 100 seconds against your wristwatch,   it will be plenty good enough.

Likewise,  you can start a counter at a specific time on your watch.    And read the counter one hour later if you want more accurate resolution.

 

In my experience the Xmega RC is plenty reliable for UART.    Obviously a crystal is needed for RTC accuracy.

 

David.

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

pep4130 wrote:

I have set up the internal 32MHz clock and set up the Timer Counter for TCC0. I have my tick and I have a sinewave... however when I scope up the tick (toggle of a pin), I get 7.52us not the 8us I am expecting.

 

I looked at the datasheet to see that the factory error is +/-1.5%.... if you do the maths on 7.52us i am over 5% out!!!!!  One way to get a 1ms sinewave is to do a use a divisor of 2 and set PER to 135.

But as this is so out of specification, how can I trust other MCU's when it goes into production?

It sure looks to be a little out of spec, - you could try a 32Mhz Xtal or external oscillator to confirm.

 

If you do not have a Frequency Counter, then generate a Sine wave in the Audio range & use a Sound card Frequency Counter.

A prescaler tap may allow you to scale in a way that does not change your code.

( eg http://www.daqarta.com/)

Sound Cards are within a couple of hundred ppm, and can resolve to single digit ppm on a clean sine wave using a fit algorithm.

 

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

I can quite understand the advantage of an oscilloscope to examine complex waveforms.

 

Since you want to measure the 32MHz RC clock,   setting the Timer to 1Hz blinks is all that you need.

Mind you,  a simple _delay_ms(500) would be just as effective.

 

Yes,  it is possible that your Xmega is badly calibrated.    But unlikely.

 

Likewise,  you can check the 2MHz RC and the 32kHz RC.    I am sceptical that there would be a problem.

 

Yes,  if you need 50ppm accuracy,   a HF or LF crystal will provide it.    If you need the power saving,   you just use the crystal to calibrate an RC (or all the RCs).

 

David.

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

Thankyou Mr Resident,

 

I never thought there is software that will change a sound card into a frequency counter or other neat tool. I shall give it a go sometime. Before that I will need to look at voltage levels etc before I go like a bull in a china shop. My 1Khz sinewave I originally had should do the trick, however, reading everyones feedback I am leaning towards using an external clock source (like i did with my Mega designs).

 

I shall certainly keep daquarta up my sleeve to when I really need it.

 

Pep

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

And my reply to you David,

 

Yes, what I have is perfectly acceptable for USART and I will be using it at 9600BAUD to communicate with an ATTINY841. Your 500ms tick experiment I allready did but with a _delay_ms(1) and I was on par with my timer counter tick. The reason that I need 1KHz is to induce an AC current (via a loop transformer) into "something!!!". 1KHz +/-100Hz would do the trick in the analogue domain if I am honest with you (as long as the frequency doesnt change significanlty over time). But when it comes down to the specification of the electronics I am designing, less that +/-10% percent error would be alarming. +/-2% seemed reasonable as I saw the XMega datasheet had +/-1.5%. this was why I moved to XMEGA because of the built in DAC. My SPI DAC on the Mega wasnt quick enough at the 125KHz update rate.

 

Taking in everybodies input l will have a go at calibrating the 32MHz clock but as a back up I will sqeeze an external XTAL or osciilator for the production run.

 

But before I go... If there is anyone out there kicking their heels for 30mins or so and they happen to have an XMEGA and an oscilloscope to hand right next to them, hook up the timer and see what you get. No DAC, just a pin toggle. Even a _delay_ms(1) may do. Simples. I will be very interested to see what you get. happy oscilloscoping. :)

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

pep4130 wrote:
... the XMega datasheet had +/-1.5%. this was why I moved to XMEGA

The 5% error that you are seeing is to be expected.  The 1.5% error applied to the factory calibration point, and the factory calibration is at 85°C, as shown below.

 

The plot below shows that at 25°C, the frequency will be about 4.7% higher, which you are observing from your board.

 

To solve this, you don't need to add an external crystal or oscillator, just calibrate the 32MHz internal oscillator as part of the production process.

 

 

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

... devil  or load up the device until the T=85C is reached devil

 

Ross McKenzie ValuSoft Melbourne Australia

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

The 32 MHz oscillator is not accurate, unless you got lucky.  The 32 kHz RC osc. is accurate, usually within 0.3%.  Using DFLL will make the 32 MHz osc as accurate as the 32kHz osc.

 

You should check the clocks.  You can export the RTC clock (32 kHz clock / 32) on pin C6 by flipping a couple of bits on most Xmegas, but maybe not on the A3BU.

 

The A3BU is an oddball Xmega with a battery backup and RTC32 instead of the usual RTC.  It may take more than the 2 bit flips, I don't remember.  The Xplained board has a 32 kHz crystal so I'm not sure which clock I'm measuring on C6.  I see exactly 1024 Hz but I may be looking at the crystal osc.  I think when I have it set up with the RC osc., I see 1026 on this board.

 

 

 

 

Last Edited: Thu. Feb 5, 2015 - 01:43 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Chuck99 wrote:

The 5% error that you are seeing is to be expected.  The 1.5% error applied to the factory calibration point, and the factory calibration is at 85°C, as shown below.

The plot below shows that at 25°C, the frequency will be about 4.7% higher, which you are observing from your board.

 

Well spotted, I had forgotten many Calibrate at 85'C because they test for leakage at that point, and it just takes too long to cool a device down.

 

Chuck99 wrote:

To solve this, you don't need to add an external crystal or oscillator, just calibrate the 32MHz internal oscillator as part of the production process.

 

The OP simply wants a SW delay, so they can apply a correction for the thermal curve you included, they only have to recalibrate if they cannot Value-adjust for the curve.

 

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

I am going to look for that graph right NOW in the datasheet!!!!! Not that I dont trust you, Chuck99.

 

OK.. so I now have a sinking moment. Wait while I beat myself up over this. As Homer would say.. DOH

 

Interestingly, the graph below it in the datasheet of the calibrated 32MHz clock looks optimised for 3.3V operation.

 

Thanks you guys

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

Well spotted,

+1

 

I understand the point about the chip being hot but why can't they reorder the factory testing so they calibrate before they cook it?

 

Surely 95% of all devices are going to operate in a 10..30°C environment so calibrating for 20°C would seem to be a whole lot more useful!

 

A look at a 48/88/168/328 datasheet shows them to be calibrated at 25°C so I think a lot of us would have assumed the Xmega would have been the same?

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

I don't really see the problem. If you need accuracy, you must use DFLL to the internal 32K. If even that is not enough, you must use DFLL to an external 32K or just use an external oscillator for 32 MHz clock. What is the problem with using DFLL?

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes DFLL is the way to go.  The A3BU Xplained board has a 32 kHz crystal on it which can be used for DFLL if extreme accuracy is wanted.

 

The internal 32 kHz osc, and of course the crystal, also have less frequency drift with temperature changes, compared to the internal 32Mhz RC osc.