Author Topic: Why is my blinky not stable?  (Read 10996 times)

0 Members and 1 Guest are viewing this topic.

Offline mortos360Topic starter

  • Regular Contributor
  • *
  • Posts: 89
  • Country: at
Why is my blinky not stable?
« on: March 23, 2014, 10:23:30 pm »
I know that arduino is not very welcome here, but thats what I started with and teached myself so far.
But my question is not arduino related... I just use it for this test.

I made a simple blinky program that runs a pin 20ms ON then 20ms OFF... basically 25Hz... but its not stable, and I don't understand why?!
By not stable, I mean that the frequency that I am measuring is jumping between 25.08 Hz and 25.07 Hz or so... why is that?
I know that crystals can have very big difference in stability//accuracy, but we are talking about Hz here... a 16MHz crystal should have that a bit more stable then what I am measuring... or am I missing here something?   ...or measuring it wrong?   for the measurement I am using a DG4102 function gen. from rigol.. its has a build in counter. I don't have a real counter yet...

Is it normal that a MC with cheap crystal has such an inaccuracy or am I doing something wrong here... and if its normal, how do I get a stable frequency?

« Last Edit: March 23, 2014, 10:37:38 pm by mortos360 »
 

Offline madires

  • Super Contributor
  • ***
  • Posts: 7765
  • Country: de
  • A qualified hobbyist ;)
Re: Why is my blinky not stable?
« Reply #1 on: March 23, 2014, 10:45:21 pm »
I think we need a few details about your blinky project to be able to answer your question. Are you using an ATmega with an external 16MHz crystal? Please post the code!
 

Offline mortos360Topic starter

  • Regular Contributor
  • *
  • Posts: 89
  • Country: at
Re: Why is my blinky not stable?
« Reply #2 on: March 23, 2014, 10:50:57 pm »
I think we need a few details about your blinky project to be able to answer your question. Are you using an ATmega with an external 16MHz crystal? Please post the code!

Yes, its a simple ATmega2560 with a 16MHz crystal.

The code is just a loop:
digitalWrite(output, HIGH)
delay(20)
digitalWrite(output, LOW)
delay(20)

 

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2803
  • Country: nz
Re: Why is my blinky not stable?
« Reply #3 on: March 23, 2014, 11:20:57 pm »
How are you "delaying" for 20ms? is it acheived through a h/w timer, or running instructions that take 20ms of CPU cycles?

Arduino uses a timer to count milliseconds, so if you are delaying through executing clock cycles then every 1ms or so a few cycles will be stolen for timer interrupt processing, and this could be causing your jitter.

If this is the case on a O'scope with infinite persistance you should see two distinct edges (as long as you have resolution to distinguish them!)

Try something like this, which does reference back to the internal H/W timer - I haven't tested it, but you should get the idea that rather than waiting for 20ms, it is watching for 20ms to pass by checking the timer. It also has a bug when mills() rolls over, but that will take a while!

int led = 13;
void setup() {               
  pinMode(led, OUTPUT);     
}

void loop() {
   static unsigned int now = 0;
   static char led_state = 0;
   int newNow = millis() /20;

   if(now != newNow) {
     now = newNow;
     led_state = !led_state;
     digitalWrite(led, led_state ? HIGH : LOW);
  }
}
Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Offline matkar

  • Regular Contributor
  • *
  • Posts: 153
  • Country: si
  • Sixty percent of the time it works EVERY time.
Re: Why is my blinky not stable?
« Reply #4 on: March 23, 2014, 11:53:09 pm »
Your frequency measurement is jumping on the last digit? You can't judge crystal accuracy with your measurement. For what we know your clock might jump from 25.0799999999 to 25.08000000000.
Use timer interrupts to get exact periods.
 

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2803
  • Country: nz
Re: Why is my blinky not stable?
« Reply #5 on: March 24, 2014, 12:00:38 am »
Your frequency measurement is jumping on the last digit? You can't judge crystal accuracy with your measurement. For what we know your clock might jump from 25.0799999999 to 25.08000000000.
Use timer interrupts to get exact periods.

But it looks like it should be 25.00Hz - so it is out by about 0.3%...
Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Offline mariush

  • Super Contributor
  • ***
  • Posts: 5029
  • Country: ro
  • .
Re: Why is my blinky not stable?
« Reply #6 on: March 24, 2014, 01:35:12 am »
The delay function in the Arduino is not accurate. Those 20ms are not really 20ms and there can be a slight difference between delays.

If you want to do it right, use assembly to get around the crud Arduino adds.. see this thread: https://www.eevblog.com/forum/microcontrollers/a-more-efficient-blink-for-avr-processors/?topicseen

There's even a video link in that thread, which shows an arduino program written in arduino doing exactly that, blinking a led.
 

Offline kizzap

  • Supporter
  • ****
  • Posts: 477
  • Country: au
Re: Why is my blinky not stable?
« Reply #7 on: March 24, 2014, 01:50:36 am »
are we all also going to ignore the fact that instructions are not immediate, and take time? assuming a 16MHz crystal, a single instruction cycle will take 62.5ns

when you also consider that the digitalWrite function is more then just a simple write to port function (at least a read, XOR, write function on the whole port I would suspect), and the fact that the delay as others have said is not the most accurate thing, I am surprised that the output frequency is close :)

also what are you measuring the frequency with?

Might be best to ditch the arduino code, and delve down into the assembly realm

-kizzap
<MatCat> The thing with aircraft is murphy loves to hang out with them
<Baljem> hey, you're the one who apparently pronounces FPGA 'fuhpugger'
 

Offline Rick Law

  • Super Contributor
  • ***
  • Posts: 3442
  • Country: us
Re: Why is my blinky not stable?
« Reply #8 on: March 24, 2014, 02:09:48 am »
Using a delay function involves more inaccuracy than just the delay.  If you do
loop() {
  flipOnOff();
  delay(20);
}
Even if that delay is exactly 20ms, you went back to caller (Operating System) and now waited for it to call you back.  Once you go back to the caller, the caller (Operating System) would have other house keeping stuff to do and wont call you back until all the house keeping work is finished.  How long the house-keeping stuff take depends on how much house-keeping awaits and that changes.  If you have a serial print in action, or serial data coming in, the OS will have more (or less) work to do from call to call.

A better way is:

#define waitTimeLed 20 // 20ms waiting time
long lastTimeLedFlipped=0;

loop() {
    long currentMS=millis();
   if ((currentMS-lastTimeLedFlipped)>=waitTimeLed) { // waited longer than 20ms
      lastTimeLedFlipped= currentMS;
      flipLedOnOff(); // however you turn it on or off
   }
} // now go back to the OS

With this "is it time to do it yet" approach, you eliminated most of the other issues.  Another benefit is now you can have multiple time dependent items.  You can see one can insert another timer to say turn off the music:

#define waitTimeLed 20 // 20ms waiting time
long lastTimeLedFlipped=0;

#define waitTimeBuzzer 100
long buzzerOnTime=0;

loop() {
    long currentMS=millis();
   if ((currentMS-lastTimeLedFlipped)>=waitTimeLed) { // waited longer than 20ms
      lastTimeLedFlipped= currentMS;
      flipLedOnOff(); // however you turn it on or off
   }
   if ((currentMS-buzzerOnTime)>=waitTimeBuzzer) { // time to turn on the buzzer
      buzzerOnTime=currentMS;
      goTurnBuzzerOnOrOff();
   }
}

Switch to this approach, you should see the timer being more stable.
 

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2803
  • Country: nz
Re: Why is my blinky not stable?
« Reply #9 on: March 24, 2014, 08:23:45 am »
I just had to look a little bit more...

Here is a grab of the of the jitter in calling "delay(20);" on an Arduino Uno.

Looks to be about 10us of jitter, and takes about 0.06mS longer than you would believe from looking at the source (which might be the duration of the digialWrite() call).
Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Offline mortos360Topic starter

  • Regular Contributor
  • *
  • Posts: 89
  • Country: at
Re: Why is my blinky not stable?
« Reply #10 on: March 24, 2014, 10:17:24 am »
Just to make that clear... I don't care if I get 25Hz or 25.5Hz, i know that different commands will have different execution timings and that it ads up... what disturbs me is the jitter.
I still don't understand why the frequency is jumping so much.  (I am measuring 25.07X.XXX so the last 4 digits are all over the place)

It looks like the loop has a different number on cycles each run... which is impossible, or?
Each instruction needs x amount of cycles and when you loop it, it should always be the same... or am I wrong here?

 

Offline TMM

  • Frequent Contributor
  • **
  • Posts: 471
  • Country: au
Re: Why is my blinky not stable?
« Reply #11 on: March 24, 2014, 11:14:04 am »
It's because there are interrupts being executed in the background that provide the functionality for arduino functions like delay() in the first place.

Using a chinese made Arduino Nano with the default blink sketch adjusted to delay(20); i get a frequency stable to +/-100uHz with a 10second gate time on a DG4062. About 5uS jitter.

If you need more exact timing, run your code from a timer interrupt:
http://www.instructables.com/id/Arduino-Timer-Interrupts/

i.e. you set it up so ISR(TIMER[0/1]_COMPA_vect) gets called every 20us, and you have that code turn on the LED every second time, and turn it off every other time. 

edit:
Code: [Select]
int led = 13; //led pin
long Fs = 50; //sampling rate (twice the desired frequency)
boolean led_status = false; //state logic for toggling led

void setup() {               
  //TIMER INTERRUPT SETUP
  cli();
  TCCR1A = 0; //normal mode
  TCCR1B = 0; //clear TCCR1B
  TCCR1B |= (1 << WGM12); //CTC mode
  TCCR1B |= (1 << CS11) | (1 << CS10); //prescaler = 64
  OCR1A = (16000000/(Fs*64))-1; //set required interrupt delay for timer1a
  TIMSK1 |= (1 << OCIE1A); //enable timer1a interrupt
  sei();//reenable interrupts
 
  pinMode(led, OUTPUT);
}

void loop() {
  while(1); //do nothing!
}

ISR(TIMER1_COMPA_vect) //timer 1 interrupt
{
  if(led_status)
  {
    digitalWrite(led, LOW);
    led_status=false;
  }
  else
  {
    digitalWrite(led, HIGH);
    led_status=true;
  } 
}
Jitter is less than 100ns. Frequency stability better than 10uHz.
« Last Edit: March 24, 2014, 11:38:54 am by TMM »
 

Offline mortos360Topic starter

  • Regular Contributor
  • *
  • Posts: 89
  • Country: at
Re: Why is my blinky not stable?
« Reply #12 on: March 24, 2014, 11:36:15 am »
It's because there are interrupts being executed in the background that provide the functionality for arduino functions like delay() in the first place.

Using a chinese made Arduino Nano with the default blink sketch adjusted to delay(20); i get a frequency stable to +/-100uHz with a 10second gate time on a DG4062. About 5uS jitter.

If you need more exact timing, run your code from a timer interrupt:
http://www.instructables.com/id/Arduino-Timer-Interrupts/

i.e. you set it up so ISR(TIMER[0/1]_COMPA_vect) gets called every 20us, and you have that code turn on the LED every second time, and turn it off every other time. 

edit:
Code: [Select]
int led = 13; //led pin
long Fs = 50; //sampling rate (twice the desired frequency)
boolean led_status = false; //state logic for toggling led

void setup() {               
  //TIMER INTERRUPT SETUP
  cli();
  TCCR1A = 0; //normal mode
  TCCR1B = 0; //clear TCCR1B
  TCCR1B |= (1 << WGM12); //CTC mode
  TCCR1B |= (1 << CS11) | (1 << CS10); //prescaler = 64
  OCR1A = (16000000/(Fs*64))-1; //set required interrupt delay for timer1a
  TIMSK1 |= (1 << OCIE1A); //enable timer1a interrupt
  sei();//reenable interrupts
 
  pinMode(led, OUTPUT);
}

void loop() {
  while(1); //do nothing!
}

ISR(TIMER1_COMPA_vect) //timer 1 interrupt
{
  if(led_status)
  {
    digitalWrite(led, LOW);
    led_status=false;
  }
  else
  {
    digitalWrite(led, HIGH);
    led_status=true;
  } 
}
Jitter is less than 100ns.

Thanks!!
I will give it a try in the evening.

 

Offline amyk

  • Super Contributor
  • ***
  • Posts: 8275
Re: Why is my blinky not stable?
« Reply #13 on: March 24, 2014, 01:32:42 pm »
...and if you want really exact timing, forget about all the Arduino cruft and write it all in Asm.
 

Offline zapta

  • Super Contributor
  • ***
  • Posts: 6190
  • Country: us
Re: Why is my blinky not stable?
« Reply #14 on: March 24, 2014, 03:43:13 pm »
If you want really accurate time, use one of the spare timers of your Arduino.  It will give you a rock stable frequency, and will free your cpu to do other things.
 

Offline matts-uk

  • Contributor
  • Posts: 37
  • Country: gb
  • select * from user where clue = null
Re: Why is my blinky not stable?
« Reply #15 on: March 24, 2014, 03:51:39 pm »
I just had to look a little bit more...

Just for kicks, I wondered whether delayMicros() could do any better;

Using digitalWrite
Code: [Select]
#define LED_PIN 13
//...
void loop()
{
delayMicroseconds(10000);
delayMicroseconds(9870);
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
}

Direct to the Port
Code: [Select]
#define bitCheck(var,pos) ((var) & (1<<(pos)))
const uint8_t ledPin = 5;
//...
void loop()
{
delayMicroseconds(10000);
delayMicroseconds(9870);

bitClear(DDRB, ledPin);
if(bitCheck(PINB, ledPin) ) {
bitSet(DDRB, ledPin);
bitClear(PORTB, ledPin);
}
else {
bitSet(DDRB, ledPin);
bitSet(PORTB, ledPin);
}
}

 

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2803
  • Country: nz
Re: Why is my blinky not stable?
« Reply #16 on: March 24, 2014, 08:34:12 pm »
...and if you want really exact timing, forget about all the Arduino cruft and write it all in Asm.

... and if you want really really exact timing, forget about all the Asm cruft and do it with descrete logic

... and if you want really really really exact timing, forget about all the descrete logic cruft and do it all in a FPGA

... and if you want really really really really exact timing, forget about all the FPGA cruft and do it all in custom silicon

It IS turtles all the way down.... the problem is where to stop. Here is my rules of thumb for platform to different response times to changing inputs

* 10ms - PCs / General purpose computers with general-purpose OS (without H/W assist)
* 1ms or so - Micro controllers (without H/W assist, interrupts enabled, multiple things to manage), PC with RTOS
* 100us or so - Micro controllers (without H/W assist, interrupts enabled, single tasks), maybe PC with RTOS
* 10us or so - Micro controllers (without H/W assist, interrupts disabled, single tasks)
* 1us or so - PC or slow Micro, with H/W assistance or hand-optimised code (e.g. timer/counter),
* 100us or so - fast Micro, with H/W assistance or hand-optimised code
* 10ns or so - low end FGPA
* 1ns or so - implemented in silicon
* less than 1ns - you must be kidding.






Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Offline miguelvp

  • Super Contributor
  • ***
  • Posts: 5550
  • Country: us
Re: Why is my blinky not stable?
« Reply #17 on: March 24, 2014, 10:27:58 pm »

It IS turtles all the way down.... the problem is where to stop. Here is my rules of thumb for platform to different response times to changing inputs

* 1us or so - PC or slow Micro, with H/W assistance or hand-optimised code (e.g. timer/counter),

Not saying to use a PC to blink a light but the Query Performance counter (using the Time Stamp Counter with RDTSC) on a processor is very accurate. My old PC with a 6600 dual core running at 2.40GHz means each count is 0.416666(6) nanoseconds. But I agree with you, having a good timer is one thing, using the signal to do something is another :)

I wonder if the Galileo has a performance counter, it should since it's a pentium right?
But at 400MHz the CPU tick is 2.5ns, so that should be good for 10ns or so.

http://en.wikipedia.org/wiki/Time_Stamp_Counter
Note that the Intel Atom does support it, and even the AVR32 has a Performance Clock Counter based on CPU cycles.

You might need to code the CPUID to decide on the behavior of the counter.
CPUID opcode (0x0fa2)
RDTSC opcode (0x0f31)

I might need to pick myself a Galileo after all, looks like a beast of a processor, and I don't have an Arduino and this is Uno R3 compatible for shields.

A quick search reveals the Intel Quark X1000 might not have RDTSC but newer chips (X1010 and X1020D) have them.
http://www.cpu-world.com/news_2014/2014031301_Intel_expands_Quark_family_with_new_products.html

But the doc here says it does
https://communities.intel.com/docs/DOC-21826

Quote
12.2.5.3 RDTSC
Description
Loads the current value of the processor’s time-stamp counter (a 64-bit MSR) into the
EDX:EAX registers. The EDX register is loaded with the high-order 32 bits of the MSR
and the EAX register is loaded with the low-order 32 bits. (On processors that support
the Intel 64 architecture, the high-order 32 bits of each of RAX and RDX are cleared.)
The processor monotonically increments the time-stamp counter MSR every clock cycle
and resets it to 0 whenever the processor is reset.
When in protected or virtual 8086 mode, the time stamp disable (TSD) flag in register
CR4 restricts the use of the RDTSC instruction as follows. When the TSD flag is clear,
the RDTSC instruction can be executed at any privilege level; when the flag is set, the
instruction can only be executed at privilege level 0. (When in real-address mode, the
RDTSC instruction is always enabled.)
The time-stamp counter can also be read with the RDMSR instruction, when executing
at privilege level 0.

But I will trust Intel more than pc-world for info on their own products.
 

Offline Rick Law

  • Super Contributor
  • ***
  • Posts: 3442
  • Country: us
Re: Why is my blinky not stable?
« Reply #18 on: March 25, 2014, 03:35:52 am »
... (using the Time Stamp Counter with RDTSC) on a processor is very accurate. My old PC with a 6600 dual core running at 2.40GHz means each count is 0.416666(6) nanoseconds. But I agree with you, having a good timer is one thing, using the signal to do something is another :)

I wonder if the Galileo has a performance counter, it should since it's a pentium right?
But at 400MHz the CPU tick is 2.5ns, so that should be good for 10ns or so.


But have you taken into account the crystal that created the 2.4GHz signal.  The crystal would likely limit you to 0.5% accuracy even if temperature is relatively constant.
 

Offline miguelvp

  • Super Contributor
  • ***
  • Posts: 5550
  • Country: us
Re: Why is my blinky not stable?
« Reply #19 on: March 25, 2014, 01:41:40 pm »

But have you taken into account the crystal that created the 2.4GHz signal.  The crystal would likely limit you to 0.5% accuracy even if temperature is relatively constant.

That's true, I forgot to mention that you'll need to use an accurate external oscillator to count how many ticks per second your MCU ticks at. But once you measure it, you can use that oscillator for other things.
 

Offline Rick Law

  • Super Contributor
  • ***
  • Posts: 3442
  • Country: us
Re: Why is my blinky not stable?
« Reply #20 on: March 29, 2014, 05:55:28 am »

But have you taken into account the crystal that created the 2.4GHz signal.  The crystal would likely limit you to 0.5% accuracy even if temperature is relatively constant.

That's true, I forgot to mention that you'll need to use an accurate external oscillator to count how many ticks per second your MCU ticks at. But once you measure it, you can use that oscillator for other things.

My favorite desktop clock used to try to impress me on how hard it works - it ticks at least once more than it needs to every day.  But, after it joined the union, it quit running after 5pm until 8am the next day.

What is really really annoying is, typical clock chips like DS1307 doesn't allow for compensation (like specifying exactly how many crystal ticks per 1000 second).  I can see the 16MHz MCU (or 2.4GHz CPU) being uncompensated since 1% faster/slower CPU/MCU is a non-issue, but a crystal at 20ppm (0.002%) you are off 1.73 seconds a day, or about a minute a month just for the crystal alone.

So, typical battery clock means everyone is in their own time zone.  However undesirable, that is reality.  Reality however doesn't make it less annoying when one has to adjust clocks all the time.
 

Offline miguelvp

  • Super Contributor
  • ***
  • Posts: 5550
  • Country: us
Re: Why is my blinky not stable?
« Reply #21 on: March 29, 2014, 08:13:49 pm »
My favorite desktop clock used to try to impress me on how hard it works - it ticks at least once more than it needs to every day.  But, after it joined the union, it quit running after 5pm until 8am the next day.

What is really really annoying is, typical clock chips like DS1307 doesn't allow for compensation (like specifying exactly how many crystal ticks per 1000 second).  I can see the 16MHz MCU (or 2.4GHz CPU) being uncompensated since 1% faster/slower CPU/MCU is a non-issue, but a crystal at 20ppm (0.002%) you are off 1.73 seconds a day, or about a minute a month just for the crystal alone.

So, typical battery clock means everyone is in their own time zone.  However undesirable, that is reality.  Reality however doesn't make it less annoying when one has to adjust clocks all the time.

If you really want accurate then go for a RTC/TCXO (Real Time Clock/Temperature Compensated Crystal Oscillator) that allows for additional compensation. For example the PCF2127AT/2Y will add ~$3 to your BOM but if you set it to run at 16384 Hz or even down to 1Hz to get your performance counter timing. It has even aging compensation.

That's the cheapest I found, you can always spend more to get something a bit better that is accurate at 32768 Hz (this one in particular can be set to that, but it falls into a 60:40 duty cycle, so not good for that frequency. More expensive ones allow for more adjusting parameters.

But like you said, for a CPU that is fast and provides a Time Stamp Counter or Performance Counter, I would't even worry about compensating it.

 

Offline Rick Law

  • Super Contributor
  • ***
  • Posts: 3442
  • Country: us
Re: Why is my blinky not stable?
« Reply #22 on: March 30, 2014, 04:39:41 am »
My favorite desktop clock used to try to impress me on how hard it works - it ticks at least once more than it needs to every day.  But, after it joined the union, it quit running after 5pm until 8am the next day.

What is really really annoying is, typical clock chips like DS1307 doesn't allow for compensation (like specifying exactly how many crystal ticks per 1000 second).  I can see the 16MHz MCU (or 2.4GHz CPU) being uncompensated since 1% faster/slower CPU/MCU is a non-issue, but a crystal at 20ppm (0.002%) you are off 1.73 seconds a day, or about a minute a month just for the crystal alone.

So, typical battery clock means everyone is in their own time zone.  However undesirable, that is reality.  Reality however doesn't make it less annoying when one has to adjust clocks all the time.

If you really want accurate then go for a RTC/TCXO (Real Time Clock/Temperature Compensated Crystal Oscillator) that allows for additional compensation. For example the PCF2127AT/2Y will add ~$3 to your BOM but if you set it to run at 16384 Hz or even down to 1Hz to get your performance counter timing. It has even aging compensation.

That's the cheapest I found, you can always spend more to get something a bit better that is accurate at 32768 Hz (this one in particular can be set to that, but it falls into a 60:40 duty cycle, so not good for that frequency. More expensive ones allow for more adjusting parameters.

But like you said, for a CPU that is fast and provides a Time Stamp Counter or Performance Counter, I would't even worry about compensating it.

Yeah, I know there are a few high accuracy clock chips with internal compensation at a few bucks more.  I am just annoyed that I got a couple of projects already build with the uncompensated DS1307 and wanted to rant a bit.

I actually logged some data after the rant I made.  After about 20 hours of run, using my PC clock as reference (not to say that my PC clock is accurate), my MCU is fast by 53ms/hour, and my DS1307 is fast by 2.7 times that.  Which is ironic because I got the DS1307 to get a more accurate time for data logging - inexperience always hurts and I just learned from that.

When I have some time, I think I may actually experiment around and see if I can use the MCU to do compensation just for the hell of it.  Every 3600.053 seconds on the MCU millis() is actually 1hour on a more accurate clock, so in theory it should work.

It is impractical of course, since I will have to verify every MCU board as each would need a different compensation factor, and I may have an MCU on a board that has far less reliable millis() because of noise and board layout.  But trying to make it work should be educational and fun.
 

Offline miguelvp

  • Super Contributor
  • ***
  • Posts: 5550
  • Country: us
Re: Why is my blinky not stable?
« Reply #23 on: March 30, 2014, 05:08:50 am »
PC's RTCs are not that accurate, good thing most PCs sync time every week.
Typical drift on a PC's RTC is around 5 seconds per day, that's 208ms per hour.
Some PC's can be off by up to 20 seconds per day. The problem is not with the RTC chip but how the interrupt might be handled.

So part of the problem with using that as a reference is that the reference is broken. Use a real stop watch if you really want to measure time. Not sure about cell phones, so try to find a real time keeping piece, i.e. wristwatch with a chronograph :)

Edit: Or use your Oscilloscope to measure the timer signal, that's probably as good as it can get.
« Last Edit: March 30, 2014, 05:26:05 am by miguelvp »
 

Offline miguelvp

  • Super Contributor
  • ***
  • Posts: 5550
  • Country: us
Re: Why is my blinky not stable?
« Reply #24 on: March 30, 2014, 06:39:58 am »
Here is how unstable a PC RTC is compared to the QueryPerformanceCounter

The first number is number of microseconds that is off in the current tick
the second number is the average.
So in a thousand seconds it's 55 milliseconds off.
in a hundred thousand seconds it's 5.5 seconds off.

so in 27.777777777777777777777777777778 hours is 5.5 seconds off.
That' 1 day 3 hours 46 minutes and 40 seconds to drift 5.5 seconds.

Per day would be, 27.7(7) is to 5.5 like 24 is to X so, X = 24*5.5/27.7(7) = 4.752 seconds per day drift.

And look at how the seconds fluctuate (first value) it's horrible!
my PC seems to actually run slow on the RTC

Code: [Select]
second drift = -0.000055, total drift = -0.000055
second drift = -0.000056, total drift = -0.000055
second drift = -0.000055, total drift = -0.000055
second drift = -0.000054, total drift = -0.000055
second drift = -0.000055, total drift = -0.000055
second drift = -0.000055, total drift = -0.000055
second drift = -0.000056, total drift = -0.000055
second drift = -0.000054, total drift = -0.000055
second drift = -0.000056, total drift = -0.000055
second drift = -0.000055, total drift = -0.000055
second drift = -0.000054, total drift = -0.000055
second drift = -0.000056, total drift = -0.000055
second drift = -0.000055, total drift = -0.000055
second drift = -0.000031, total drift = -0.000053
second drift = -0.000079, total drift = -0.000055
second drift = -0.000056, total drift = -0.000055
second drift = -0.000054, total drift = -0.000055
second drift = -0.000055, total drift = -0.000055
second drift = -0.000056, total drift = -0.000055
second drift = -0.000048, total drift = -0.000055
second drift = -0.000062, total drift = -0.000055
second drift = -0.000051, total drift = -0.000055
second drift = -0.000059, total drift = -0.000055
second drift = -0.000052, total drift = -0.000055
second drift = -0.000060, total drift = -0.000055
second drift = -0.000046, total drift = -0.000055
second drift = -0.000063, total drift = -0.000055
second drift = -0.000055, total drift = -0.000055
second drift = -0.000054, total drift = -0.000055
second drift = -0.000057, total drift = -0.000055
second drift = -0.000043, total drift = -0.000055
second drift = -0.000067, total drift = -0.000055
second drift = -0.000055, total drift = -0.000055
second drift = -0.000055, total drift = -0.000055
second drift = -0.000055, total drift = -0.000055
second drift = -0.000055, total drift = -0.000055
second drift = -0.000056, total drift = -0.000055
second drift = -0.000055, total drift = -0.000055
second drift = -0.000055, total drift = -0.000055
second drift = -0.000056, total drift = -0.000055
second drift = -0.000030, total drift = -0.000055
second drift = -0.000080, total drift = -0.000055
second drift = -0.000054, total drift = -0.000055
second drift = -0.000056, total drift = -0.000055
second drift = -0.000054, total drift = -0.000055
second drift = -0.000055, total drift = -0.000055
second drift = -0.000057, total drift = -0.000055
second drift = 0.000122, total drift = -0.000051
second drift = -0.000232, total drift = -0.000055
second drift = -0.000055, total drift = -0.000055
second drift = -0.000055, total drift = -0.000055
second drift = -0.000055, total drift = -0.000055
second drift = -0.000055, total drift = -0.000055
second drift = -0.000055, total drift = -0.000055
second drift = -0.000056, total drift = -0.000055
second drift = -0.000055, total drift = -0.000055
second drift = -0.000056, total drift = -0.000055
second drift = -0.000054, total drift = -0.000055
second drift = -0.000056, total drift = -0.000055
second drift = -0.000050, total drift = -0.000055
second drift = -0.000060, total drift = -0.000055
second drift = -0.000055, total drift = -0.000055
second drift = -0.000043, total drift = -0.000055
second drift = -0.000067, total drift = -0.000055
second drift = -0.000055, total drift = -0.000055
second drift = -0.000054, total drift = -0.000055
second drift = -0.000056, total drift = -0.000055

Edit: granted, that jumping per second is probably due to aliasing due to the interrupt system that maintains the clock, but in any event the average clock is still off by 55 microseconds per second average.

Edit2: And thinking about it it might be that both are off, meaning the QPC and the RTC, the thing is the QPC keeps real time (even if a wrong time) the RTC oscillates a lot.
I could adjust the QPC to match the average RTC easily if that was giving a good clock in the long run. But I tend to trust the QueryPerformanceFrequency to actually give me the CPU clock, so I guess I would have to spend a full day with a chrono to check if the RTC is right or the QPC is right, or both are wrong!

No matter what, the average of the RTC is consistent with the QPC so there is hope!
I had the program running for almost 3 hours and the average is still 55 micro seconds per second

Edit3: So QueryPerformanceFrequency claims my CPU is 2,400,050,000 Hz (weird number because it's way too round).

If I adjust for the -0.000055 seconds per second and trust the average of the RTC then my CPU frequency is really: 2,399,917,997.25 Hz for a 2.4GHz rated system.

That looks more plausible, But no matter what the QPC doesn't jump up and down like the RTC. I will have to investigate further to see where in between the true time lies upon.

In the past I always used the average of the RTC to determine the actual frequency of the CPU when using the RDTSC, but since the introduction of the QueryPerformanceCounter and QueryPerformanceFrequency I did rely on that frequency instead. Maybe I should not.
« Last Edit: March 30, 2014, 08:47:47 am by miguelvp »
 

Offline miguelvp

  • Super Contributor
  • ***
  • Posts: 5550
  • Country: us
Re: Why is my blinky not stable?
« Reply #25 on: March 30, 2014, 09:02:26 am »
So changing to trust the RTC, here is the output, but I still have to determine how off the RTC is

2nd number is the average drift kept by the QPC, the first one is still the deviation per second of the RTC and is still horrible.

So after computing the real frequency of the CPU I can have a clock with no drift by using the QPC.
But I will have to investigate where the frequency of the CPU really is at between 2,400,050,000 Hz and 2,399,917,997 Hz.

Code: [Select]
Frequency MHz = 2399.917997
second drift = -0.000001, average drift/s = -0.000001
second drift = 0.000000, average drift/s = -0.000000
second drift = -0.000001, average drift/s = -0.000001
second drift = -0.000000, average drift/s = -0.000000
second drift = 0.000001, average drift/s = -0.000000
second drift = -0.000001, average drift/s = -0.000000
second drift = -0.000000, average drift/s = -0.000000
second drift = 0.000000, average drift/s = -0.000000
second drift = -0.000001, average drift/s = -0.000000
second drift = -0.000000, average drift/s = -0.000000
second drift = -0.000001, average drift/s = -0.000000
second drift = -0.000000, average drift/s = -0.000000
second drift = 0.000001, average drift/s = -0.000000
second drift = -0.000002, average drift/s = -0.000000
second drift = 0.000001, average drift/s = -0.000000
second drift = 0.000000, average drift/s = -0.000000
second drift = -0.000001, average drift/s = -0.000000
second drift = -0.000001, average drift/s = -0.000000
second drift = -0.000001, average drift/s = -0.000000
second drift = 0.000001, average drift/s = -0.000000
second drift = -0.000001, average drift/s = -0.000000
second drift = -0.000001, average drift/s = -0.000000
second drift = 0.000001, average drift/s = -0.000000
second drift = -0.000001, average drift/s = -0.000000
second drift = 0.000001, average drift/s = -0.000000
second drift = -0.000002, average drift/s = -0.000000
second drift = -0.000001, average drift/s = -0.000000
second drift = 0.000001, average drift/s = -0.000000
second drift = -0.000002, average drift/s = -0.000000
second drift = 0.000001, average drift/s = -0.000000
second drift = -0.000000, average drift/s = -0.000000
second drift = -0.000001, average drift/s = -0.000000
second drift = -0.000002, average drift/s = -0.000000
second drift = 0.000001, average drift/s = -0.000000
second drift = -0.000007, average drift/s = -0.000001
second drift = 0.000006, average drift/s = -0.000000
second drift = -0.000001, average drift/s = -0.000000
second drift = 0.000000, average drift/s = -0.000000
second drift = -0.000001, average drift/s = -0.000000
second drift = 0.000000, average drift/s = -0.000000
second drift = -0.000000, average drift/s = -0.000000
second drift = -0.000001, average drift/s = -0.000000
second drift = -0.000000, average drift/s = -0.000000
second drift = -0.000000, average drift/s = -0.000000
second drift = -0.000001, average drift/s = -0.000000
second drift = -0.000001, average drift/s = -0.000000
second drift = 0.000000, average drift/s = -0.000000
second drift = -0.000000, average drift/s = -0.000000
second drift = -0.000001, average drift/s = -0.000000
second drift = -0.000001, average drift/s = -0.000000
second drift = 0.000000, average drift/s = -0.000000
second drift = 0.000000, average drift/s = -0.000000
second drift = -0.000001, average drift/s = -0.000000
second drift = 0.000000, average drift/s = -0.000000
second drift = 0.000000, average drift/s = -0.000000
second drift = -0.000000, average drift/s = -0.000000
second drift = -0.000000, average drift/s = -0.000000
second drift = 0.000040, average drift/s =  0.000000
second drift = -0.000042, average drift/s = -0.000000
second drift = 0.000000, average drift/s = -0.000000
second drift = -0.000001, average drift/s = -0.000000
second drift = 0.000001, average drift/s = -0.000000
second drift = -0.000000, average drift/s = -0.000000
second drift = 0.000000, average drift/s = -0.000000
second drift = -0.000001, average drift/s = -0.000000
second drift = 0.000000, average drift/s = -0.000000
second drift = 0.000000, average drift/s = -0.000000
second drift = -0.000001, average drift/s = -0.000000
second drift = -0.000001, average drift/s = -0.000000
second drift = 0.000000, average drift/s = -0.000000
second drift = -0.000000, average drift/s = -0.000000
second drift = -0.000002, average drift/s = -0.000000
second drift = 0.000000, average drift/s = -0.000000
second drift = -0.000001, average drift/s = -0.000000
second drift = 0.000000, average drift/s = -0.000000
second drift = 0.000000, average drift/s = -0.000000
second drift = -0.000001, average drift/s = -0.000000
 

Offline miguelvp

  • Super Contributor
  • ***
  • Posts: 5550
  • Country: us
Re: Why is my blinky not stable?
« Reply #26 on: March 30, 2014, 07:00:29 pm »
So I ran a program overnight to compute my true CPU frequency based on the RTC clock.
I used the brute force approach, because I didn't want to deal with signal processing of both clocks so I averaged 8 hours worth of it.
Otherwise I will have to sample the RTC with respect the QPC and viceversa and with some math get the number, but it was late so brute force it is.

So the speed of the CPU's performance counter according to the RTC is 2399913708.04589784 Hz.
Note the decimal part is because we are dealing with two signals of different periods, so that is the frequency taking away the time discreet offset of the RTC.

Having that calibration data I can preload the average of 8 hours worth of data and run my program.

With that frequency value I have a 1ns precise clock (based on the average second of the RTC over 8 hours)

The first value is the second variaton of the RTC with respect of the performance counter per second.
The second value is the average mean time according to the performance counter. (pretty much absorbing the waveform from the RTC being sampled at random discreet points.

Code: [Select]
Frequency MHz = 2399.913708
second drift = -0.000006850, average drift/s = -0.000000000
second drift = 0.000006455, average drift/s = -0.000000000
second drift = -0.000000276, average drift/s = -0.000000000
second drift = 0.000000286, average drift/s = -0.000000000
second drift = 0.000000043, average drift/s = -0.000000000
second drift = 0.000000991, average drift/s =  0.000000000
second drift = -0.000000261, average drift/s =  0.000000000
second drift = -0.000006809, average drift/s = -0.000000000
second drift = 0.000006549, average drift/s =  0.000000000
second drift = 0.000000834, average drift/s =  0.000000000
second drift = -0.000001701, average drift/s = -0.000000000
second drift = -0.000000164, average drift/s = -0.000000000
second drift = 0.000001659, average drift/s =  0.000000000
second drift = 0.000000200, average drift/s =  0.000000000
second drift = -0.000000385, average drift/s =  0.000000000
second drift = -0.000000490, average drift/s =  0.000000000
second drift = -0.000000299, average drift/s = -0.000000000
second drift = 0.000000568, average drift/s =  0.000000000
second drift = 0.000000264, average drift/s =  0.000000000
second drift = -0.000000239, average drift/s =  0.000000000
second drift = 0.000001205, average drift/s =  0.000000000
second drift = -0.000000359, average drift/s =  0.000000000
second drift = -0.000000048, average drift/s =  0.000000000
second drift = -0.000000963, average drift/s =  0.000000000
second drift = 0.000002439, average drift/s =  0.000000000
second drift = -0.000000310, average drift/s =  0.000000000
second drift = -0.000000569, average drift/s =  0.000000000
second drift = -0.000000340, average drift/s =  0.000000000
second drift = -0.000006100, average drift/s = -0.000000000
second drift = 0.000006703, average drift/s =  0.000000000
second drift = 0.000000200, average drift/s =  0.000000000
second drift = 0.000000946, average drift/s =  0.000000000
second drift = -0.000001308, average drift/s =  0.000000000
second drift = 0.000000774, average drift/s =  0.000000000
second drift = -0.000000839, average drift/s =  0.000000000
second drift = 0.000000358, average drift/s =  0.000000000
second drift = -0.000005879, average drift/s = -0.000000000
second drift = 0.000006286, average drift/s =  0.000000000
second drift = 0.000002079, average drift/s =  0.000000000
second drift = -0.000000846, average drift/s =  0.000000000
second drift = -0.000000895, average drift/s =  0.000000000
second drift = 0.000023038, average drift/s =  0.000000000
second drift = -0.000022031, average drift/s =  0.000000000
second drift = -0.000000205, average drift/s =  0.000000000
second drift = -0.000000003, average drift/s =  0.000000000
second drift = 0.000000440, average drift/s =  0.000000000
second drift = -0.000001143, average drift/s =  0.000000000
second drift = 0.000001111, average drift/s =  0.000000000
second drift = 0.000000564, average drift/s =  0.000000000
second drift = -0.000001690, average drift/s =  0.000000000
second drift = 0.000000616, average drift/s =  0.000000000
second drift = 0.000000440, average drift/s =  0.000000000
second drift = -0.000000145, average drift/s =  0.000000000
second drift = 0.000000530, average drift/s =  0.000000000
second drift = -0.000000636, average drift/s =  0.000000000
second drift = 0.000001153, average drift/s =  0.000000000
second drift = -0.000001064, average drift/s =  0.000000000
second drift = 0.000000575, average drift/s =  0.000000000
second drift = 0.000000628, average drift/s =  0.000000000
second drift = -0.000000483, average drift/s =  0.000000000
second drift = 0.000000268, average drift/s =  0.000000000
second drift = -0.000000115, average drift/s =  0.000000000
second drift = -0.000000370, average drift/s =  0.000000000
second drift = 0.000000440, average drift/s =  0.000000000
second drift = 0.000024925, average drift/s =  0.000000000
second drift = -0.000024716, average drift/s =  0.000000000
second drift = -0.000000269, average drift/s =  0.000000000
second drift = 0.000001423, average drift/s =  0.000000000
second drift = -0.000000318, average drift/s =  0.000000000
second drift = 0.000002330, average drift/s =  0.000000000
second drift = -0.000002838, average drift/s =  0.000000000
second drift = 0.000001966, average drift/s =  0.000000000
second drift = -0.000001476, average drift/s =  0.000000000
second drift = 0.000000020, average drift/s =  0.000000000
second drift = 0.000000598, average drift/s =  0.000000000
second drift = 0.000000155, average drift/s =  0.000000000
second drift = 0.000000219, average drift/s =  0.000000000
second drift = -0.000001004, average drift/s =  0.000000000
second drift = 0.000000425, average drift/s =  0.000000000
second drift = 0.000000249, average drift/s =  0.000000000
second drift = 0.000000024, average drift/s =  0.000000000
second drift = -0.000000025, average drift/s =  0.000000000
second drift = -0.000000625, average drift/s =  0.000000000
second drift = -0.000000104, average drift/s =  0.000000000
second drift = 0.000002435, average drift/s =  0.000000000
second drift = -0.000001634, average drift/s =  0.000000000
second drift = -0.000001053, average drift/s =  0.000000000
second drift = 0.000000635, average drift/s =  0.000000000
second drift = 0.000000159, average drift/s =  0.000000000
second drift = -0.000000063, average drift/s =  0.000000000
second drift = 0.000000380, average drift/s =  0.000000000
second drift = -0.000000179, average drift/s =  0.000000000
second drift = 0.000000538, average drift/s =  0.000000000
second drift = 0.000000129, average drift/s =  0.000000000
second drift = -0.000000693, average drift/s =  0.000000000
second drift = 0.000000264, average drift/s =  0.000000000
second drift = -0.000000914, average drift/s =  0.000000000
second drift = 0.000001531, average drift/s =  0.000000000
second drift = -0.000001079, average drift/s =  0.000000000
second drift = 0.000000174, average drift/s =  0.000000000
second drift = 0.000000609, average drift/s =  0.000000000
second drift = 0.000000980, average drift/s =  0.000000000
second drift = -0.000000078, average drift/s =  0.000000000
second drift = -0.000000884, average drift/s =  0.000000000
second drift = 0.000000489, average drift/s =  0.000000000
second drift = -0.000000745, average drift/s =  0.000000000

I'm going to start it again and let it run for a long time.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf