Pages: 1 [2] 3   Go Down
Author Topic: millis (crystal) accuracy & thoughts  (Read 3862 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Full Member
***
Karma: 2
Posts: 109
ArduiYES!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

pushing data on spi and putting things on the serial will need interrupts.
interrupts are "robbed time".
are you sure your timekeeping is not bothered by these
interrupts ?
Logged

USA
Offline Offline
Jr. Member
**
Karma: 4
Posts: 92
If you can't fix it with a hammer, it must be an electrical problem.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I can tell you that here in the future, we expect proper data, just as they did back in 2010 (and 1910 and 1810, etc.)
Proper data has an explanation for each line. Does your list represent readings at 1min, 2min, etc?  Then say so. Even back in 2010, not doing so was called "unlabeled".
Proper data is concise. It does not include the same number represented as seconds and milliseconds. Even back in 2010 repeating values was called "redundant".

Your responses have become redundantly useless.

I'll try the same test with an LCD hooked up via parallel (eliminating spi) and report back.

I promise to post concise labeled unredundant proper data in the future.
Logged


London
Offline Offline
Tesla Member
***
Karma: 10
Posts: 6255
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If you want to include an accurate RTC in your tests you could try this one: http://macetech.com/store/index.php?main_page=product_info&cPath=5&products_id=8&zenid=fbf0c0760af1303010f94d69e70a8661
Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 129
Posts: 8601
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

As I see it the bottom line is that even the crappiest crystal is good for an accuracy of about 100ppm and most are a lot better.  

Surely this is accurate enough, and if so the problem must be in the code.

Quote
I'm thinking of using a DS3231 (like a chronodot) to create an accurate 1Hz interrupt on the Arduino.
I gather then that you're timing a long event, not a drag race.

The RTCs with inbuilt TXCOs can be calibrated to about 2ppm and even uncalibrated are very good.

A couple of questions.

Is this a start-time-stop application?
How many things are being timed?
Do you need to display the time while the timer is running?
How long is the event being timed?
What accuracy do you need?


______
Rob

« Last Edit: December 20, 2010, 03:33:42 am by graynomad » Logged

Rob Gray aka the GRAYnomad www.robgray.com

SF Bay Area (USA)
Offline Offline
Tesla Member
***
Karma: 137
Posts: 6792
Strongly opinionated, but not official!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The methodology looks OK to me.  The internal millis() timer shouldn't be subject to drift because of other code, but it seems that that his arduino are drifting about 1.3 s over 10 minutes (600s.)  That's only 0.2% error, not completely "unreasonable" for a resonator, though better would be ... better.

Quote
I'm seeing unacceptable timing errors for anything more accurate than an egg timer.
0.2% error is unacceptable?  I guess it would be nicer if it looked more regular...
« Last Edit: December 20, 2010, 03:42:35 am by westfw » Logged

USA
Offline Offline
Jr. Member
**
Karma: 4
Posts: 92
If you can't fix it with a hammer, it must be an electrical problem.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for all of the responses so far.

Quote
Is this a start-time-stop application?
How many things are being timed?
Do you need to display the time while the timer is running?
How long is the event being timed?
What accuracy do you need?

I am making a split timer, where the timer will run continuously with intervals tripped by an electronic switch.

One individual is timed over several intervals. The overall event could be from 15 minutes to several hours, with the splits lasting in the range of 1-10 minutes long.

I need to display the interval times.

I want at least a tenth-of-second accuracy, hundredths would be better.

Man, it looks like I was having a conversation with myself?
Logged


Lancashire, UK
Offline Offline
Edison Member
*
Karma: 9
Posts: 1991
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Even my crappy Uno with a resonator is good to 4 seconds a day (72 seconds fast after 20 days) .  As I've said before my Duemilanoves (even my Chinese knockoff) are much better.  The secret is not to count millis between it doing something but to work just with the big number since it was started.  
Logged


SF Bay Area (USA)
Offline Offline
Tesla Member
***
Karma: 137
Posts: 6792
Strongly opinionated, but not official!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

 
Quote
The secret is not to count millis between it doing something but to work just with the big number since it was started.
Yes, but he's been doing that all along.  From the first message:
Code:
void loop(void) {
  //main loop
  while(1) {
    //update display
    current_time = (millis() - millis_offset)/100;
    DisplayTime();
}

Note that the divide by 100 is throwing away relatively important precision, and probably explains some of the non-linearity in the times reported in your first post.
Logged

SF Bay Area
Offline Offline
Edison Member
*
Karma: 11
Posts: 1244
Arduino Ninja
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

If you need  1/10 or 1/100 accuracy, then you don't want a 1pps time source. You would use the 32KHz output on the ChronoDot or other RTC chips. I think the Arduino hardware interrupt pins would be able to handle it. Or set up one of the timers with the external clock option and set up an overflow at the appropriate time. The only difficulty is that an external RTC designed for timekeeping is not going to have a frequency evenly divisible by 10 or 100, so you'll have to just get close and live with some inaccuracy. For 1/100 you would see maybe +/- 0.3% of one count error.
Logged

Unique RGB LED Modules and Arduino shields: http://www.macetech.com/store

USA
Offline Offline
Jr. Member
**
Karma: 4
Posts: 92
If you can't fix it with a hammer, it must be an electrical problem.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Running a 7-segment display directly with the following code solved my timing issues.

Code:
//
//7 segment timer test
//
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 16000000
#include <avr/delay.h>

// SBI and CBI to set bits
#define sbi(port_name, pin_number)   (port_name |= 1<<pin_number)
#define cbi(port_name, pin_number)   ((port_name) &= (uint8_t)~(1 << pin_number))

int d[10];
//wiring millis value
extern volatile unsigned long timer0_millis;

void setup() {
  /* 7-segment pin alignment
   LCD - Arduino
    1  -  A0
    2  -  A1
    6  -  A2
    8  -  A3
    13 -  D0
    15 -  D1
    12 -  D2
    3  -  D3
    5  -  D4
    10 -  D5
    14 -  D6
  */
  DDRC = DDRC | 0b0111111;      // Set data direction for port C (DIG1,...DP)
  PORTC = PORTC | 0b0011111;      // Initialize all digits off
  DDRD = DDRD | 0b11111110;      // Set data direction for port D (A,B,...,G)
  PORTD = PORTD | 0b00000000;      // Initialize all digits off
}

void loop() {
  // Main loop: update display
  int i;
  
  while(1) {
    ExtractDigits(timer0_millis);
    for (i=0; i<4; i++) {
      //total time per loop ~5.5ms@16MHz
      display(d[5 - i], i);
      //this delay controls individual segment on-time/brightness, longer = brighter
      _delay_us(100);
      //clear display
      PORTC = PORTC | 0b0011111;;
      PORTD = 0;
    }  
    //this delay controls all segments off-time/brightness, shorter = brighter
    _delay_ms(5);
  }
}

void ExtractDigits(unsigned long num) {
  int i;
  
  i = 0;
  while(num > 0) {
    d[i++] = (int)num%10;
    num /= 10;
  }
}

// Output number to digit 0,1,2, or 3, 4 to display dots
void display(int number, int digit) {
  cbi(PORTC, digit);      // Turn on corresponding digit
  switch(number) {      // Set PORTD, display pins, to correct output
    case 0:
      PORTD = 0b01111110;
      break;
    case 1:
      PORTD = 0b00001100;
      break;
    case 2:
      PORTD = 0b10110110;
      break;
    case 3:
      PORTD = 0b10011110;
      break;
    case 4:
      PORTD = 0b11001100;
      break;
    case 5:
      PORTD = 0b11011010;
      break;
    case 6:
      PORTD = 0b11111010;
      break;
    case 7:
      PORTD = 0b00001110;
      break;
    case 8:
      PORTD = 0b11111110;
      break;
    case 9:
      PORTD = 0b11011110;
      break;
    default:
      PORTD = 0b01111110;  //0
      break;
  }
}

I think I found the issue. It appears to be in the sparkfun serial 7-segment display. The problem is outlined here: http://bleaklow.com/2010/08/28/sparkfun_are_less_than_electrifying.html

thanks for everyone's help.
« Last Edit: December 24, 2010, 08:28:25 pm by JimEli » Logged


0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 92
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The reason isn't too mysterious.  

for a 16Mhz clock (assuming it is EXACTLY accurate) you get 64 clocks per timer tick (as set by the arduino's init() code) and 256 ticks per interrupt (overflow).

So thats: 16000000/64/256 = 976.5625 timer interrupts per second

but this number is used in integer math so that comes out to 976.  So even with a perfectly precise clock you get error.  You can see all this by reading wiring.c

This is why many microcontollers accept TWO clocks one CPU clock at say 16 MHz and another at 32768Hz (=2^15) watch crystal.  Checking the datasheet the timer2 can be run by a watch crystal (at least in the mega 2560).

if we do the same math with a 32768Hz clock we get
32768/64/256=2  (or 128 if you don't prescale the clock)
which gives no loss of precision!  

So, if you want good timing you should probably attach a watch crystal and use timer 2.



Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 129
Posts: 8601
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Well researched mspguy, I assumed the millis actually meant millis.

So one may wonder why they didn't /250 by using an output compare interrupt? Or is that used for PWM?

______
Rob

« Last Edit: December 24, 2010, 10:46:36 pm by graynomad » Logged

Rob Gray aka the GRAYnomad www.robgray.com

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 92
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

EDIT:  I totally misread the above post.  

I think /250 can be done with timer 2 using clear timer on compare match mode.
« Last Edit: December 24, 2010, 11:05:58 pm by cnt » Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 210
Posts: 13036
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Or is that used for PWM?
Yes.  Timer 0 is used to drive millis / micros and provide PWM on two pins.
Logged

Lancashire, UK
Offline Offline
Edison Member
*
Karma: 9
Posts: 1991
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

If there is an automatic error of 576ppm (52 seconds a day)( due to the integer maths. why are all my Arduinos so accurate ?.  The worst is the Uno at 4 seconds a day.  

One of my Duemilanoves  made the period between 08:00 24th July and 0800 11th September  (7 weeks, 49 days) to be 4233620357 Milliseconds an error of only 20357 milliseconds giving it better than 5 ppm against the NTP controlled host computer.  It keeps better time than the Casio on my wrist.  

The chinese knockoff is good to just over 2 seconds aday  and my other real Duemilanove good to a second a day. They do vary slightly with temperature as you would expect of a crystal.
« Last Edit: December 25, 2010, 03:51:44 am by stephen_t » Logged


Pages: 1 [2] 3   Go Up
Jump to: