reading 1000ths of a seconds from a pcf8583 rtc

I am looking at enorporating a pcf8583 into my project so I can measure in hundredth of a second accurately. All the librays only mention seconds is it possible to read the hundredth of a second from the chip ? or is there a better way of measuring time accurately I have discovered milli has a drift of 4ms over 60 seconds and I need it to be lower.

Thanks in advance

That chip uses the I2C bus. The bus only runs at 100KHz so you can not get that sort of accuracy from it.

what is the maximum time you want to measure ?
60 seconds?
The error of 4 millis on 60 seconds is under the 1/100 you want for accuracy…?

You could use one of the hardware timers with appropriate pre-scaling …

What is the max I2C speed the chip can handle?

The datasheet for the chip says it can generate a 32768Hz interrupt or it has a pre-scaler which can divide the 32768Hz down by a factor of up to 100. However, the RTC is only as accurate as the 32768Hz crystal that you provide and it probably won't be any better than what you'd get if you used the Arduino Timer intterupt. A DS3231 RTC is more accurate and can generate a 1Hz, 1kHz, 4kHz or 8kHz interrupt.

Pete

The chip has a register for hundredths of a second (datasheet, p8), so it certainly ought to be possible.

If there isn't a library that addresses it, modify an existing library or write a new one. If you really meant thousandths of a second as in the subject line, I'd say you're out of luck.

The problem is that the stock Arduino Uno uses a ceramic resonator instead of a crystal. The best resonator tolerance on Mouser is 0.1%, which is 1000 ppm. A good crystal, on the other hand, will have a few tens of ppm accuracy tolerance.

My recommendation would be to make a barebones Arduino on a breadboard with a crystal instead of a ceramic resonator if you really need accuracy. Then you can use millis() and it will be much more accurate.

Jiggy-Ninja: The problem is that the stock Arduino Uno uses a ceramic resonator instead of a crystal. The best resonator tolerance on Mouser is 0.1%, which is 1000 ppm. A good crystal, on the other hand, will have a few tens of ppm accuracy tolerance.

My recommendation would be to make a barebones Arduino on a breadboard with a crystal instead of a ceramic resonator if you really need accuracy. Then you can use millis() and it will be much more accurate.

All true but if an external RTC is used then its accuracy is the critical factor. And most will be a few tens of ppm or the ones with TCXOs will be maybe an order of magnitude better.

OP also needs to define "accurate" ... 1000 ppm, 100 ppm, 50 ppm, 10 ppm, or something else?

The chip has a register for hundredths of a second

Dunno how I missed that :blush:
Looks like it can be set up to interrupt at 100Hz which would make the timing easy if 100ths of a sec are what are required. But the required accuracy of the RTC is still the main issue.

Pete

Rather than read every “millisecond” from the RTC perhaps you could just use it to update a correction factor to use with millis()

For example if you read millis() and the RTC in setup() and later if you read millis() and the RTC you may find that the millis() count has fallen behind by (say) 3. So you store the value 3 into your correction and everytime you use millis() add the correction to it. Later the correction might have grown to 7 or 3572 (if it is running a long time).

…R

I might have got my ms/seconds 1000ths mixed up. This is what I have to work to:

-the timing system shall display the time down to at least the hundredth of a second (xxx.xx) to 2 decimal points - the timing system shall be accurate to within 3ms over 60 seconds (50 ppm) - the timing system shall provide the same timing for both lanes to within 2ms over 60 seconds

Thanks for all your answers.

crazynight:

  • the timing system shall provide the same timing for both lanes to within 2ms over 60 seconds

This sounds like it might be for a slot-car system.

One Arduino used to measure the time for two separate things will probably give relative measurements with an accuracy of a few microseconds indefinitely because whatever error exists is applied equally to both things. In other words one can be quite sure that A was faster than B by X milliseconds if the winning margin is small (less than 5 minutes?) regardless of how long the “race” might be.

It is only if timings need to be correct in an absolute sense (for example to compare results (lap times?) from two different systems) that you will need an RTC. And then it may be sufficient just to use the RTC to calibrate millis().

…R

crazynight:
-the timing system shall display the time down to at least the hundredth of a second (xxx.xx) to 2
decimal points

  • the timing system shall be accurate to within 3ms over 60 seconds (50 ppm)
  • the timing system shall provide the same timing for both lanes to within 2ms over 60 seconds

Good, this describes both the accuracy and the resolution needed. But, the 3rd point is redundant and somewhat conflicting. The 2nd point says accurate to 3ms, the 3rd point says 2ms. Not exactly sure what the words “shall provide” mean, especially given the requirement to display to 0.01 second.

I am aware of several RTCs with 0.01 sec resolution but none that provide 0.001. Since time of day is not needed, as pointed out above, one solution would be a custom Arduino-compatible board with a decent crystal, say 20ppm. I’ve designed and built several of these and they do indeed run within spec. Then one of the internal timers could be set up to give interrupts at 1000Hz, which would provide the time base. Use the external interrupts for the start and stop for each lane.

If a custom board isn’t an option, then an external oscillator with the required accuracy will be needed, as an Arduino’s ceramic resonator isn’t good enough. This most likely will not be an RTC; while many can provide various frequency square waves, the frequencies are usually powers of two. (Although I suppose computational games could be played to come close enough, similar to the way millis() works.)

this is the code I am using it flops over at 60000000micro's later but it flops at 60000004micro's later??

can anyone explain it?

// Variables will change:
long interval = 60000000L;
void setup() {
Serial.begin(19200);
Serial.println("please wait");
delay(1000);
Serial.println("lets start");

} 
   
void loop()
{
//unsigned long currentmicros = micros();
//long starttime = micros();
long starttime;
long timeout;
long exittime;
cli();  // disable interrupts
starttime = micros();
sei();  // enable interrupts
timeout = starttime + interval;
while(timeout >= starttime){
  cli();  // disable interrupts
  starttime = micros(); 
  sei();  // enable interrupts
  } 
  cli();  // disable interrupts
  exittime = micros(); 
  sei();  // enable interrupts
Serial.print(timeout - starttime);
Serial.print(" micro sec out running for ");
Serial.print(exittime - starttime + interval); 
Serial.println("micro sec ");    
}

NOte that the granularity of micros() is 4 uSec not 1 uSec!

try this simplified variation.

// Variables will change:
unsigned long interval = 60000000UL;  // Unsigned Long

void setup() 
{
  Serial.begin(19200);  // 115200 is a bit faster...
  Serial.println("please wait");
  delay(1000);
  Serial.println("lets start");
} 
   
void loop()
{
  unsigned long start = micros();

  while(micros() - starttime < interval);
  unsigned long stop = micros(); 

  Serial.println(stop - start);
}

Why the extensive use of sei() and cli() ?

crazynight: this is the code I am using it flops over at 60000000micro's later but it flops at 60000004micro's later??

can anyone explain it?

Sure can, read this, third sentence: http://arduino.cc/en/Reference/Micros

PS: Also note that micros() returns an unsigned long, so variables like starttime, timeout, exittime should also be unsigned long.

[quote author=Jack Christensen link=topic=260126.msg1839030#msg1839030 date=1407790662] Sure can, read this, third sentence: http://arduino.cc/en/Reference/Micros

PS: Also note that micros() returns an unsigned long, so variables like starttime, timeout, exittime should also be unsigned long.

[/quote]

Silly beginner mistake - so am I right in thinking the best timing a arduino can do is 4 microseconds then.

crazynight: so am I right in thinking the best timing a arduino can do is 4 microseconds then.

Given a 16MHz system clock (Uno, et al.), one clock cycle is then 62.5 ns. The internal hardware timers can be configured to count at this rate. Of course there are tradeoffs (e.g. the counter will overflow rather quickly, being only 8 or 16 bits). The input capture unit can be a nice approach in many applications. Basically an external signal causes the current timer count to be captured in another register, and this event can trigger an interrupt, etc.

you have lost me am reading about prescaler but all double dutch will need to improve my knowledge further.

crazynight: you have lost me am reading about prescaler but all double dutch will need to improve my knowledge further.

Timers are pretty neat, and even fairly straightforward once you get them figured out a bit.

There's a tutorial here that really helped me get started: http://www.fourwalledcubicle.com/AVRArticles.php

And of course Nick Gammon's site: http://www.gammon.com.au/forum/?id=11504