0
Offline
Full Member
Karma: 2
Posts: 109
ArduiYES!
|
 |
« Reply #15 on: December 19, 2010, 05:26:36 pm » |
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
Jr. Member
Karma: 1
Posts: 70
If you can't fix it with a hammer, it must be an electrical problem.
|
 |
« Reply #16 on: December 19, 2010, 05:58:20 pm » |
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
Faraday Member
Karma: 6
Posts: 6226
Have fun!
|
 |
« Reply #17 on: December 20, 2010, 03:02:26 am » |
|
|
|
|
|
Logged
|
|
|
|
|
nr Bundaberg, Australia
Offline
Tesla Member
Karma: 73
Posts: 6841
Scattered showers my arse -- Noah, 2348BC.
|
 |
« Reply #18 on: December 20, 2010, 03:33:04 am » |
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. 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
|
|
|
|
|
SF Bay Area (USA)
Offline
Faraday Member
Karma: 78
Posts: 5455
Strongly opinionated, but not official!
|
 |
« Reply #19 on: December 20, 2010, 03:38:44 am » |
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. 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
Jr. Member
Karma: 1
Posts: 70
If you can't fix it with a hammer, it must be an electrical problem.
|
 |
« Reply #20 on: December 20, 2010, 11:59:45 am » |
Thanks for all of the responses so far. 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
Edison Member
Karma: 8
Posts: 1988
|
 |
« Reply #21 on: December 20, 2010, 12:43:12 pm » |
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
Faraday Member
Karma: 78
Posts: 5455
Strongly opinionated, but not official!
|
 |
« Reply #22 on: December 20, 2010, 03:22:08 pm » |
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: 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
Edison Member
Karma: 6
Posts: 1215
Arduino Ninja
|
 |
« Reply #23 on: December 20, 2010, 05:40:45 pm » |
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
|
|
|
|
|
USA
Offline
Jr. Member
Karma: 1
Posts: 70
If you can't fix it with a hammer, it must be an electrical problem.
|
 |
« Reply #24 on: December 24, 2010, 08:27:38 pm » |
Running a 7-segment display directly with the following code solved my timing issues. // //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.htmlthanks for everyone's help.
|
|
|
|
« Last Edit: December 24, 2010, 08:28:25 pm by JimEli »
|
Logged
|
|
|
|
|
0
Offline
Jr. Member
Karma: 0
Posts: 92
|
 |
« Reply #25 on: December 24, 2010, 10:20:22 pm » |
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
Tesla Member
Karma: 73
Posts: 6841
Scattered showers my arse -- Noah, 2348BC.
|
 |
« Reply #26 on: December 24, 2010, 10:34:56 pm » |
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
|
|
|
|
|
0
Offline
Jr. Member
Karma: 0
Posts: 92
|
 |
« Reply #27 on: December 24, 2010, 10:58:55 pm » |
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
Shannon Member
Karma: 120
Posts: 10201
|
 |
« Reply #28 on: December 24, 2010, 11:19:50 pm » |
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
Edison Member
Karma: 8
Posts: 1988
|
 |
« Reply #29 on: December 25, 2010, 03:37:55 am » |
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
|
|
|
|
|
|